root/opal/mca/pmix/pmix4x/pmix/src/event/pmix_event.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
   2 /*
   3  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
   4  *                         University Research and Technology
   5  *                         Corporation.  All rights reserved.
   6  * Copyright (c) 2004-2006 The University of Tennessee and The University
   7  *                         of Tennessee Research Foundation.  All rights
   8  *                         reserved.
   9  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
  10  *                         University of Stuttgart.  All rights reserved.
  11  * Copyright (c) 2004-2005 The Regents of the University of California.
  12  *                         All rights reserved.
  13  * Copyright (c) 2015-2018 Intel, Inc. All rights reserved.
  14  * $COPYRIGHT$
  15  *
  16  * Additional copyrights may follow
  17  *
  18  * $HEADER$
  19  */
  20 
  21 #ifndef PMIX_EVENT_H
  22 #define PMIX_EVENT_H
  23 
  24 #include <src/include/pmix_config.h>
  25 #include "src/include/types.h"
  26 #include PMIX_EVENT_HEADER
  27 
  28 #include <pmix_common.h>
  29 #include "src/class/pmix_list.h"
  30 #include "src/util/output.h"
  31 
  32  BEGIN_C_DECLS
  33 
  34 #define PMIX_EVENT_ORDER_NONE       0x00
  35 #define PMIX_EVENT_ORDER_FIRST      0x01
  36 #define PMIX_EVENT_ORDER_LAST       0x02
  37 #define PMIX_EVENT_ORDER_BEFORE     0x04
  38 #define PMIX_EVENT_ORDER_AFTER      0x08
  39 #define PMIX_EVENT_ORDER_PREPEND    0x10
  40 #define PMIX_EVENT_ORDER_APPEND     0x20
  41 
  42 /* define an internal attribute for marking that the
  43  * server processed an event before passing it up
  44  * to its host in case it comes back down - avoids
  45  * infinite loop */
  46 #define PMIX_SERVER_INTERNAL_NOTIFY   "pmix.srvr.internal.notify"
  47 
  48 
  49 /* define a struct for tracking registration ranges */
  50 typedef struct {
  51     pmix_data_range_t range;
  52     pmix_proc_t *procs;
  53     size_t nprocs;
  54 } pmix_range_trkr_t;
  55 
  56 /* define a common struct for tracking event handlers */
  57 typedef struct {
  58     pmix_list_item_t super;
  59     char *name;
  60     size_t index;
  61     uint8_t precedence;
  62     char *locator;
  63     pmix_proc_t source;  // who generated this event
  64     /* When registering for events, callers can specify
  65      * the range of sources from which they are willing
  66      * to receive notifications - e.g., for callers to
  67      * define different handlers for events coming from
  68      * the RM vs those coming from their peers. We use
  69      * the rng field to track these values upon registration.
  70      */
  71     pmix_range_trkr_t rng;
  72     /* For registration, we use the affected field to track
  73      * the range of procs that, if affected by the event,
  74      * should cause the handler to be called (subject, of
  75      * course, to any rng constraints).
  76      */
  77     pmix_proc_t *affected;
  78     size_t naffected;
  79     pmix_notification_fn_t evhdlr;
  80     void *cbobject;
  81     pmix_status_t *codes;
  82     size_t ncodes;
  83 } pmix_event_hdlr_t;
  84 PMIX_CLASS_DECLARATION(pmix_event_hdlr_t);
  85 
  86 /* define an object for tracking status codes we are actively
  87  * registered to receive */
  88 typedef struct {
  89     pmix_list_item_t super;
  90     pmix_status_t code;
  91     size_t nregs;
  92 } pmix_active_code_t;
  93 PMIX_CLASS_DECLARATION(pmix_active_code_t);
  94 
  95 /* define an object for housing the different lists of events
  96  * we have registered so we can easily scan them in precedent
  97  * order when we get an event */
  98 typedef struct {
  99     pmix_object_t super;
 100     size_t nhdlrs;
 101     pmix_event_hdlr_t *first;
 102     pmix_event_hdlr_t *last;
 103     pmix_list_t actives;
 104     pmix_list_t single_events;
 105     pmix_list_t multi_events;
 106     pmix_list_t default_events;
 107 } pmix_events_t;
 108 PMIX_CLASS_DECLARATION(pmix_events_t);
 109 
 110 /* define an object for chaining event notifications thru
 111  * the local state machine. Each registered event handler
 112  * that asked to be notified for a given code is given a
 113  * chance to "see" the reported event, starting with
 114  * single-code handlers, then multi-code handlers, and
 115  * finally default handlers. This object provides a
 116  * means for us to relay the event across that chain
 117  */
 118 typedef struct pmix_event_chain_t {
 119     pmix_list_item_t super;
 120     pmix_status_t status;
 121     pmix_event_t ev;
 122     bool timer_active;
 123     bool nondefault;
 124     bool endchain;
 125     pmix_proc_t source;
 126     pmix_data_range_t range;
 127     /* When generating events, callers can specify
 128      * the range of targets to receive notifications.
 129      */
 130     pmix_proc_t *targets;
 131     size_t ntargets;
 132     /* the processes that we affected by the event */
 133     pmix_proc_t *affected;
 134     size_t naffected;
 135     /* any info provided by the event generator */
 136     pmix_info_t *info;
 137     size_t ninfo;
 138     size_t nallocated;
 139     pmix_info_t *results;
 140     size_t nresults;
 141     pmix_event_hdlr_t *evhdlr;
 142     pmix_op_cbfunc_t final_cbfunc;
 143     void *final_cbdata;
 144 } pmix_event_chain_t;
 145 PMIX_CLASS_DECLARATION(pmix_event_chain_t);
 146 
 147 /* prepare a chain for processing by cycling across provided
 148  * info structs and translating those supported by the event
 149  * system into the chain object*/
 150 pmix_status_t pmix_prep_event_chain(pmix_event_chain_t *chain,
 151                                     const pmix_info_t *info, size_t ninfo,
 152                                     bool xfer);
 153 
 154 /* invoke the error handler that is registered against the given
 155  * status, passing it the provided info on the procs that were
 156  * affected, plus any additional info provided by the server */
 157 void pmix_invoke_local_event_hdlr(pmix_event_chain_t *chain);
 158 
 159 bool pmix_notify_check_range(pmix_range_trkr_t *rng,
 160                              const pmix_proc_t *proc);
 161 
 162 bool pmix_notify_check_affected(pmix_proc_t *interested, size_t ninterested,
 163                                 pmix_proc_t *affected, size_t naffected);
 164 
 165 
 166 /* invoke the server event notification handler */
 167 pmix_status_t pmix_server_notify_client_of_event(pmix_status_t status,
 168                                                  const pmix_proc_t *source,
 169                                                  pmix_data_range_t range,
 170                                                  const pmix_info_t info[], size_t ninfo,
 171                                                  pmix_op_cbfunc_t cbfunc, void *cbdata);
 172 
 173 void pmix_event_timeout_cb(int fd, short flags, void *arg);
 174 
 175 #define PMIX_REPORT_EVENT(e, p, r, f)                                                   \
 176     do {                                                                                \
 177         pmix_event_chain_t *ch, *cp;                                                    \
 178         size_t n, ninfo;                                                                \
 179         pmix_info_t *info;                                                              \
 180         pmix_proc_t proc;                                                               \
 181                                                                                         \
 182         ch = NULL;                                                                      \
 183         /* see if we already have this event cached */                                  \
 184         PMIX_LIST_FOREACH(cp, &pmix_globals.cached_events, pmix_event_chain_t) {        \
 185             if (cp->status == (e)) {                                                    \
 186                 ch = cp;                                                                \
 187                 break;                                                                  \
 188             }                                                                           \
 189         }                                                                               \
 190         if (NULL == ch) {                                                               \
 191             /* nope - need to add it */                                                 \
 192             ch = PMIX_NEW(pmix_event_chain_t);                                          \
 193             ch->status = (e);                                                           \
 194             ch->range = (r);                                                            \
 195             PMIX_LOAD_PROCID(&ch->source, (p)->nptr->nspace,                            \
 196                              (p)->info->pname.rank);                                    \
 197             PMIX_PROC_CREATE(ch->affected, 1);                                          \
 198             ch->naffected = 1;                                                          \
 199             PMIX_LOAD_PROCID(ch->affected, (p)->nptr->nspace,                           \
 200                              (p)->info->pname.rank);                                    \
 201             /* if I'm a client or tool and this is my server, then we don't */          \
 202             /* set the targets - otherwise, we do */                                    \
 203             if (!PMIX_PROC_IS_SERVER(pmix_globals.mypeer) &&                            \
 204                 !PMIX_CHECK_PROCID(&pmix_client_globals.myserver->info->pname,          \
 205                                   &(p)->info->pname)) {                                 \
 206                 PMIX_PROC_CREATE(ch->targets, 1);                                       \
 207                 ch->ntargets = 1;                                                       \
 208                 PMIX_LOAD_PROCID(ch->targets, (p)->nptr->nspace, PMIX_RANK_WILDCARD);   \
 209             }                                                                           \
 210             /* if this is lost-connection-to-server, then we let it go to */            \
 211             /* the default event handler - otherwise, we don't */                       \
 212             if (PMIX_ERR_LOST_CONNECTION_TO_SERVER != (e) &&                            \
 213                 PMIX_ERR_UNREACH != (e)) {                                              \
 214                 ch->ninfo = 1;                                                          \
 215                 ch->nallocated = 3;                                                     \
 216                 PMIX_INFO_CREATE(ch->info, ch->nallocated);                             \
 217                 /* mark for non-default handlers only */                                \
 218                 PMIX_INFO_LOAD(&ch->info[0], PMIX_EVENT_NON_DEFAULT, NULL, PMIX_BOOL);  \
 219             } else {                                                                    \
 220                 ch->nallocated = 2;                                                     \
 221                 PMIX_INFO_CREATE(ch->info, ch->nallocated);                             \
 222             }                                                                           \
 223             ch->final_cbfunc = (f);                                                     \
 224             ch->final_cbdata = ch;                                                      \
 225             /* cache it */                                                              \
 226             pmix_list_append(&pmix_globals.cached_events, &ch->super);                  \
 227             ch->timer_active = true;                                                    \
 228             pmix_event_assign(&ch->ev, pmix_globals.evbase, -1, 0,                      \
 229                               pmix_event_timeout_cb, ch);                               \
 230             PMIX_POST_OBJECT(ch);                                                       \
 231             pmix_event_add(&ch->ev, &pmix_globals.event_window);                        \
 232         } else {                                                                        \
 233             /* add this peer to the array of sources */                                 \
 234             pmix_strncpy(proc.nspace, (p)->nptr->nspace, PMIX_MAX_NSLEN);               \
 235             proc.rank = (p)->info->pname.rank;                                          \
 236             ninfo = ch->nallocated + 1;                                                 \
 237             PMIX_INFO_CREATE(info, ninfo);                                              \
 238             /* must keep the hdlr name and return object at the end, so prepend */      \
 239             PMIX_INFO_LOAD(&info[0], PMIX_PROCID,                                       \
 240                            &proc, PMIX_PROC);                                           \
 241             for (n=0; n < ch->ninfo; n++) {                                             \
 242                 PMIX_INFO_XFER(&info[n+1], &ch->info[n]);                               \
 243             }                                                                           \
 244             PMIX_INFO_FREE(ch->info, ch->nallocated);                                   \
 245             ch->nallocated = ninfo;                                                     \
 246             ch->info = info;                                                            \
 247             ch->ninfo = ninfo - 2;                                                      \
 248             /* reset the timer */                                                       \
 249             pmix_event_del(&ch->ev);                                                    \
 250             PMIX_POST_OBJECT(ch);                                                       \
 251             pmix_event_add(&ch->ev, &pmix_globals.event_window);                        \
 252         }                                                                               \
 253     } while(0)
 254 
 255 
 256  END_C_DECLS
 257 
 258 #endif /* PMIX_EVENT_H */

/* [<][>][^][v][top][bottom][index][help] */