Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-22 10:47:20

0001 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
0002 /*
0003  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
0004  *                         University Research and Technology
0005  *                         Corporation.  All rights reserved.
0006  * Copyright (c) 2004-2006 The University of Tennessee and The University
0007  *                         of Tennessee Research Foundation.  All rights
0008  *                         reserved.
0009  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
0010  *                         University of Stuttgart.  All rights reserved.
0011  * Copyright (c) 2004-2005 The Regents of the University of California.
0012  *                         All rights reserved.
0013  * Copyright (c) 2015-2020 Intel, Inc.  All rights reserved.
0014  * Copyright (c) 2020      IBM Corporation.  All rights reserved.
0015  * Copyright (c) 2021-2022 Nanook Consulting.  All rights reserved.
0016  * $COPYRIGHT$
0017  *
0018  * Additional copyrights may follow
0019  *
0020  * $HEADER$
0021  */
0022 
0023 #ifndef PMIX_EVENT_H
0024 #define PMIX_EVENT_H
0025 
0026 #include "src/include/pmix_config.h"
0027 #include "src/include/pmix_types.h"
0028 #include <event.h>
0029 
0030 #include "pmix_common.h"
0031 #include "src/class/pmix_list.h"
0032 #include "src/mca/bfrops/bfrops_types.h"
0033 #include "src/util/pmix_output.h"
0034 
0035 BEGIN_C_DECLS
0036 
0037 #define PMIX_EVENT_ORDER_NONE          0x00
0038 #define PMIX_EVENT_ORDER_FIRST         0x01
0039 #define PMIX_EVENT_ORDER_LAST          0x02
0040 #define PMIX_EVENT_ORDER_BEFORE        0x04
0041 #define PMIX_EVENT_ORDER_AFTER         0x08
0042 #define PMIX_EVENT_ORDER_PREPEND       0x10
0043 #define PMIX_EVENT_ORDER_APPEND        0x20
0044 #define PMIX_EVENT_ORDER_FIRST_OVERALL 0x40
0045 #define PMIX_EVENT_ORDER_LAST_OVERALL  0x80
0046 
0047 /* define an internal attribute for marking that the
0048  * server processed an event before passing it up
0049  * to its host in case it comes back down - avoids
0050  * infinite loop */
0051 #define PMIX_SERVER_INTERNAL_NOTIFY "pmix.srvr.internal.notify"
0052 
0053 /* define a struct for tracking registration ranges */
0054 typedef struct {
0055     pmix_data_range_t range;
0056     pmix_proc_t *procs;
0057     size_t nprocs;
0058 } pmix_range_trkr_t;
0059 
0060 #define PMIX_RANGE_TRKR_STATIC_INIT     \
0061 {                                       \
0062     .range = PMIX_RANGE_UNDEF,          \
0063     .procs = NULL,                      \
0064     .nprocs = 0                         \
0065 }
0066 
0067 
0068 /* define a common struct for tracking event handlers */
0069 typedef struct {
0070     pmix_list_item_t super;
0071     char *name;
0072     size_t index;
0073     uint8_t precedence;
0074     bool oneshot;
0075     char *locator;
0076     pmix_proc_t source; // who generated this event
0077     /* When registering for events, callers can specify
0078      * the range of sources from which they are willing
0079      * to receive notifications - e.g., for callers to
0080      * define different handlers for events coming from
0081      * the RM vs those coming from their peers. We use
0082      * the rng field to track these values upon registration.
0083      */
0084     pmix_range_trkr_t rng;
0085     /* For registration, we use the affected field to track
0086      * the range of procs that, if affected by the event,
0087      * should cause the handler to be called (subject, of
0088      * course, to any rng constraints).
0089      */
0090     pmix_proc_t *affected;
0091     size_t naffected;
0092     pmix_notification_fn_t evhdlr;
0093     void *cbobject;
0094     pmix_status_t *codes;
0095     size_t ncodes;
0096 } pmix_event_hdlr_t;
0097 PMIX_CLASS_DECLARATION(pmix_event_hdlr_t);
0098 
0099 #define PMIX_EVENT_HDLR_STATIC_INIT         \
0100 {                                           \
0101     .super = PMIX_LIST_ITEM_STATIC_INIT,    \
0102     .name = NULL,                           \
0103     .index = SIZE_MAX,                      \
0104     .precedence = UINT8_MAX,                \
0105     .locator = NULL,                        \
0106     .source = PMIX_PROC_STATIC_INIT,        \
0107     .rng = PMIX_RANGE_TRKR_STATIC_INIT,     \
0108     .affected - NULL,                       \
0109     .naffected = 0,                         \
0110     .evhdlr = NULL,                         \
0111     .cbobject = NULL,                       \
0112     .codes = NULL,                          \
0113     .ncodes = 0                             \
0114 }
0115 
0116 /* define an object for tracking status codes we are actively
0117  * registered to receive */
0118 typedef struct {
0119     pmix_list_item_t super;
0120     pmix_status_t code;
0121     size_t nregs;
0122 } pmix_active_code_t;
0123 PMIX_CLASS_DECLARATION(pmix_active_code_t);
0124 
0125 /* define an object for housing the different lists of events
0126  * we have registered so we can easily scan them in precedent
0127  * order when we get an event */
0128 typedef struct {
0129     pmix_object_t super;
0130     size_t nhdlrs;
0131     pmix_event_hdlr_t *first;
0132     pmix_event_hdlr_t *last;
0133     pmix_list_t actives;
0134     pmix_list_t single_events;
0135     pmix_list_t multi_events;
0136     pmix_list_t default_events;
0137 } pmix_events_t;
0138 PMIX_CLASS_DECLARATION(pmix_events_t);
0139 
0140 #define PMIX_EVENTS_STATIC_INIT                     \
0141 {                                                   \
0142     .super = PMIX_OBJ_STATIC_INIT(pmix_object_t),   \
0143     .nhdlrs = 0,                                    \
0144     .first = NULL,                                  \
0145     .last = NULL,                                   \
0146     .actives = PMIX_LIST_STATIC_INIT,               \
0147     .single_events = PMIX_LIST_STATIC_INIT,         \
0148     .multi_events = PMIX_LIST_STATIC_INIT,          \
0149     .default_events = PMIX_LIST_STATIC_INIT         \
0150 }
0151 
0152 /* define an object for chaining event notifications thru
0153  * the local state machine. Each registered event handler
0154  * that asked to be notified for a given code is given a
0155  * chance to "see" the reported event, starting with
0156  * single-code handlers, then multi-code handlers, and
0157  * finally default handlers. This object provides a
0158  * means for us to relay the event across that chain
0159  */
0160 typedef struct pmix_event_chain_t {
0161     pmix_list_item_t super;
0162     pmix_status_t status;
0163     pmix_event_t ev;
0164     bool timer_active;
0165     bool nondefault;
0166     bool endchain;
0167     bool cached;
0168     pmix_proc_t source;
0169     pmix_data_range_t range;
0170     /* When generating events, callers can specify
0171      * the range of targets to receive notifications.
0172      */
0173     pmix_proc_t *targets;
0174     size_t ntargets;
0175     /* the processes that we affected by the event */
0176     pmix_proc_t *affected;
0177     size_t naffected;
0178     /* any info provided by the event generator */
0179     pmix_info_t *info;
0180     size_t ninfo;
0181     size_t nallocated;
0182     pmix_status_t interim_status;
0183     pmix_info_t *results;
0184     size_t nresults;
0185     pmix_info_t *interim;
0186     size_t ninterim;
0187     pmix_event_hdlr_t *evhdlr;
0188     pmix_op_cbfunc_t opcbfunc;
0189     void *cbdata;
0190     pmix_op_cbfunc_t final_cbfunc;
0191     void *final_cbdata;
0192 } pmix_event_chain_t;
0193 PMIX_CLASS_DECLARATION(pmix_event_chain_t);
0194 
0195 /* prepare a chain for processing by cycling across provided
0196  * info structs and translating those supported by the event
0197  * system into the chain object*/
0198 PMIX_EXPORT pmix_status_t pmix_prep_event_chain(pmix_event_chain_t *chain, const pmix_info_t *info,
0199                                                 size_t ninfo, bool xfer);
0200 
0201 /* invoke the error handler that is registered against the given
0202  * status, passing it the provided info on the procs that were
0203  * affected, plus any additional info provided by the server */
0204 PMIX_EXPORT void pmix_invoke_local_event_hdlr(pmix_event_chain_t *chain);
0205 
0206 PMIX_EXPORT bool pmix_notify_check_range(pmix_range_trkr_t *rng, const pmix_proc_t *proc);
0207 
0208 PMIX_EXPORT bool pmix_notify_check_affected(pmix_proc_t *interested, size_t ninterested,
0209                                             pmix_proc_t *affected, size_t naffected);
0210 
0211 PMIX_EXPORT pmix_status_t pmix_deregister_event_hdlr(size_t event_hdlr_ref,
0212                                                      pmix_buffer_t *msg);
0213 
0214 /* invoke the server event notification handler */
0215 PMIX_EXPORT pmix_status_t pmix_server_notify_client_of_event(pmix_status_t status,
0216                                                              const pmix_proc_t *source,
0217                                                              pmix_data_range_t range,
0218                                                              const pmix_info_t info[], size_t ninfo,
0219                                                              pmix_op_cbfunc_t cbfunc, void *cbdata);
0220 PMIX_EXPORT pmix_status_t pmix_notify_server_of_event(pmix_status_t status, const pmix_proc_t *source,
0221                                                       pmix_data_range_t range, const pmix_info_t info[],
0222                                                       size_t ninfo, pmix_op_cbfunc_t cbfunc, void *cbdata,
0223                                                       bool dolocal);
0224 
0225 PMIX_EXPORT void pmix_event_timeout_cb(int fd, short flags, void *arg);
0226 
0227 #define PMIX_REPORT_EVENT(e, p, r, f)                                                          \
0228     do {                                                                                       \
0229         pmix_event_chain_t *ch, *cp;                                                           \
0230         size_t _n;                                                                             \
0231                                                                                                \
0232         ch = NULL;                                                                             \
0233         /* see if we already have this event cached */                                         \
0234         PMIX_LIST_FOREACH (cp, &pmix_globals.cached_events, pmix_event_chain_t) {              \
0235             if (cp->status == (e)) {                                                           \
0236                 ch = cp;                                                                       \
0237                 break;                                                                         \
0238             }                                                                                  \
0239         }                                                                                      \
0240         if (NULL == ch) {                                                                      \
0241             /* nope - need to add it */                                                        \
0242             ch = PMIX_NEW(pmix_event_chain_t);                                                 \
0243             ch->status = (e);                                                                  \
0244             ch->range = (r);                                                                   \
0245             PMIX_LOAD_PROCID(&ch->source, (p)->nptr->nspace, (p)->info->pname.rank);           \
0246             PMIX_PROC_CREATE(ch->affected, 1);                                                 \
0247             ch->naffected = 1;                                                                 \
0248             PMIX_LOAD_PROCID(ch->affected, (p)->nptr->nspace, (p)->info->pname.rank);          \
0249             /* if this is lost-connection-to-server, then we let it go to */                   \
0250             /* the default event handler - otherwise, we don't */                              \
0251             if (PMIX_ERR_LOST_CONNECTION != (e) && PMIX_ERR_UNREACH != (e)) {                  \
0252                 ch->ninfo = 1;                                                                 \
0253                 ch->nallocated = 3;                                                            \
0254                 PMIX_INFO_CREATE(ch->info, ch->nallocated);                                    \
0255                 /* mark for non-default handlers only */                                       \
0256                 PMIX_INFO_LOAD(&ch->info[0], PMIX_EVENT_NON_DEFAULT, NULL, PMIX_BOOL);         \
0257             } else {                                                                           \
0258                 ch->nallocated = 2;                                                            \
0259                 PMIX_INFO_CREATE(ch->info, ch->nallocated);                                    \
0260             }                                                                                  \
0261             ch->final_cbfunc = (f);                                                            \
0262             ch->final_cbdata = ch;                                                             \
0263             /* cache it */                                                                     \
0264             pmix_list_append(&pmix_globals.cached_events, &ch->super);                         \
0265             ch->timer_active = true;                                                           \
0266             pmix_event_assign(&ch->ev, pmix_globals.evbase, -1, 0, pmix_event_timeout_cb, ch); \
0267             PMIX_POST_OBJECT(ch);                                                              \
0268             pmix_event_add(&ch->ev, &pmix_globals.event_window);                               \
0269         } else {                                                                               \
0270             /* add this peer to the array of sources */                                        \
0271             pmix_proc_t proc_tmp;                                                              \
0272             pmix_info_t *info_tmp;                                                             \
0273             size_t ninfo_tmp;                                                                  \
0274             pmix_strncpy(proc_tmp.nspace, (p)->nptr->nspace, PMIX_MAX_NSLEN);                  \
0275             proc_tmp.rank = (p)->info->pname.rank;                                             \
0276             ninfo_tmp = ch->nallocated + 1;                                                    \
0277             PMIX_INFO_CREATE(info_tmp, ninfo_tmp);                                             \
0278             /* must keep the hdlr name and return object at the end, so prepend */             \
0279             PMIX_INFO_LOAD(&info_tmp[0], PMIX_PROCID, &proc_tmp, PMIX_PROC);                   \
0280             for (_n = 0; _n < ch->ninfo; _n++) {                                               \
0281                 PMIX_INFO_XFER(&info_tmp[_n + 1], &ch->info[_n]);                              \
0282             }                                                                                  \
0283             PMIX_INFO_FREE(ch->info, ch->nallocated);                                          \
0284             ch->nallocated = ninfo_tmp;                                                        \
0285             ch->info = info_tmp;                                                               \
0286             ch->ninfo = ninfo_tmp - 2;                                                         \
0287             /* reset the timer */                                                              \
0288             if (ch->timer_active) {                                                            \
0289                 pmix_event_del(&ch->ev);                                                       \
0290             }                                                                                  \
0291             PMIX_POST_OBJECT(ch);                                                              \
0292             ch->timer_active = true;                                                           \
0293             pmix_event_add(&ch->ev, &pmix_globals.event_window);                               \
0294         }                                                                                      \
0295     } while (0)
0296 
0297 END_C_DECLS
0298 
0299 #endif /* PMIX_EVENT_H */