/*
 * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
 *                         University Research and Technology
 *                         Corporation.  All rights reserved.
 * Copyright (c) 2004-2006 The University of Tennessee and The University
 *                         of Tennessee Research Foundation.  All rights
 *                         reserved.
 * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
 *                         University of Stuttgart.  All rights reserved.
 * Copyright (c) 2004-2005 The Regents of the University of California.
 *                         All rights reserved.
 * Copyright (c) 2015-2020 Intel, Inc.  All rights reserved.
 * Copyright (c) 2021-2026 Nanook Consulting  All rights reserved.
 * $COPYRIGHT$
 *
 * Additional copyrights may follow
 *
 * $HEADER$
 */

#include "src/include/pmix_config.h"

#include <stdio.h>
#ifdef HAVE_UNISTD_H
#    include <unistd.h>
#endif

#include "src/include/pmix_globals.h"
#include "src/util/pmix_argv.h"
#include "src/util/pmix_error.h"

#include "src/mca/ptl/base/base.h"

bool pmix_ptl_base_peer_is_earlier(pmix_peer_t *peer, uint8_t major, uint8_t minor, uint8_t release)
{
    if (0 == PMIX_PEER_MAJOR_VERSION(peer)) {
        /* the peer's version was never assigned. This happens
         * when the application never calls PMIx_Init - we
         * cannot assign the version because the client never
         * told us what they are using. Normally, this indicates
         * that the application is not a PMIx one. All we can do
         * is assume the peer is NOT earlier
         */
        return false;
    }

    /* if they don't care, then don't check */
    if (PMIX_MAJOR_WILDCARD != major) {
        if (PMIX_PEER_MAJOR_VERSION(peer) == PMIX_MAJOR_WILDCARD) {
            /* we don't know what it is - assume earlier */
            return true;
        }
        if (PMIX_PEER_MAJOR_VERSION(peer) > major) {
            return false;
        }
        if (PMIX_PEER_MAJOR_VERSION(peer) < major) {
            return true;
        }
    }
    /* major value must be equal, so check minor */
    if (PMIX_MINOR_WILDCARD != minor) {
        if (PMIX_PEER_MINOR_VERSION(peer) == PMIX_MINOR_WILDCARD) {
            /* we don't know what it is - assume earlier */
            return true;
        }
        if (PMIX_PEER_MINOR_VERSION(peer) > minor) {
            return false;
        }
        if (PMIX_PEER_MINOR_VERSION(peer) < minor) {
            return true;
        }
    }
    /* major and minor must be equal - check release */
    if (PMIX_RELEASE_WILDCARD != release) {
        if (PMIX_PEER_REL_VERSION(peer) == PMIX_RELEASE_WILDCARD) {
            /* we don't know what it is - assume earlier */
            return true;
        }
        if (PMIX_PEER_REL_VERSION(peer) > release) {
            return false;
        }
        if (PMIX_PEER_REL_VERSION(peer) < release) {
            return true;
        }
    }
    /* must be equal */
    return false;
}

pmix_status_t pmix_ptl_base_set_notification_cbfunc(pmix_ptl_cbfunc_t cbfunc)
{
    pmix_ptl_posted_recv_t *req;

    /* post a persistent recv for the special 0 tag so the client can recv
     * error notifications from the server */
    req = PMIX_NEW(pmix_ptl_posted_recv_t);
    if (NULL == req) {
        return PMIX_ERR_NOMEM;
    }
    req->tag = 0;
    req->cbfunc = cbfunc;
    pmix_output_verbose(5, pmix_ptl_base_framework.framework_output,
                        "posting notification recv on tag %d", req->tag);
    /* add it to the list of recvs - we cannot have unexpected messages
     * in this subsystem as the server never sends us something that
     * we didn't previously request */
    pmix_list_prepend(&pmix_ptl_base.posted_recvs, &req->super);
    return PMIX_SUCCESS;
}
