root/opal/mca/pmix/base/pmix_base_hash.c

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

DEFINITIONS

This source file includes following definitions.
  1. proc_data_construct
  2. proc_data_destruct
  3. lookup_keyval
  4. lookup_proc
  5. opal_pmix_base_hash_init
  6. opal_pmix_base_hash_finalize
  7. opal_pmix_base_store
  8. opal_pmix_base_fetch
  9. opal_pmix_base_remove

   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
   2 /*
   3  * Copyright (c) 2010-2016 Cisco Systems, Inc.  All rights reserved.
   4  * Copyright (c) 2004-2011 The University of Tennessee and The University
   5  *                         of Tennessee Research Foundation.  All rights
   6  *                         reserved.
   7  * Copyright (c) 2011-2014 Los Alamos National Security, LLC.  All rights
   8  *                         reserved.
   9  * Copyright (c) 2014-2015 Intel, Inc. All rights reserved.
  10  * Copyright (c) 2014      Research Organization for Information Science
  11  *                         and Technology (RIST). All rights reserved.
  12  * $COPYRIGHT$
  13  *
  14  * Additional copyrights may follow
  15  *
  16  * $HEADER$
  17  *
  18  */
  19 
  20 #include "opal_config.h"
  21 #include "opal/constants.h"
  22 
  23 #include <time.h>
  24 #include <string.h>
  25 
  26 #include "opal_stdint.h"
  27 #include "opal/class/opal_hash_table.h"
  28 #include "opal/class/opal_pointer_array.h"
  29 #include "opal/dss/dss_types.h"
  30 #include "opal/util/error.h"
  31 #include "opal/util/output.h"
  32 #include "opal/util/proc.h"
  33 #include "opal/util/show_help.h"
  34 
  35 #include "opal/mca/pmix/base/base.h"
  36 #include "opal/mca/pmix/base/pmix_base_hash.h"
  37 
  38 /**
  39  * Data for a particular opal process
  40  * The name association is maintained in the
  41  * proc_data hash table.
  42  */
  43 typedef struct {
  44     /** Structure can be put on lists (including in hash tables) */
  45     opal_list_item_t super;
  46     bool loaded;
  47     /* List of opal_value_t structures containing all data
  48        received from this process, sorted by key. */
  49     opal_list_t data;
  50 } opal_pmix_proc_data_t;
  51 static void proc_data_construct(opal_pmix_proc_data_t *ptr)
  52 {
  53     ptr->loaded = false;
  54     OBJ_CONSTRUCT(&ptr->data, opal_list_t);
  55 }
  56 
  57 static void proc_data_destruct(opal_pmix_proc_data_t *ptr)
  58 {
  59     OPAL_LIST_DESTRUCT(&ptr->data);
  60 }
  61 OBJ_CLASS_INSTANCE(opal_pmix_proc_data_t,
  62                    opal_list_item_t,
  63                    proc_data_construct,
  64                    proc_data_destruct);
  65 
  66 /**
  67  * Find data for a given key in a given proc_data_t
  68  * container.
  69  */
  70 static opal_value_t* lookup_keyval(opal_pmix_proc_data_t *proc_data,
  71                                    const char *key)
  72 {
  73     opal_value_t *kv;
  74 
  75     OPAL_LIST_FOREACH(kv, &proc_data->data, opal_value_t) {
  76         if (0 == strcmp(key, kv->key)) {
  77             return kv;
  78         }
  79     }
  80     return NULL;
  81 }
  82 
  83 /**
  84  * Find proc_data_t container associated with given
  85  * opal_process_name_t.
  86  */
  87 static opal_pmix_proc_data_t* lookup_proc(opal_proc_table_t *ptable,
  88                                           opal_process_name_t id, bool create)
  89 {
  90     opal_pmix_proc_data_t *proc_data = NULL;
  91 
  92     opal_proc_table_get_value(ptable, id, (void**)&proc_data);
  93     if (NULL == proc_data && create) {
  94         proc_data = OBJ_NEW(opal_pmix_proc_data_t);
  95         if (NULL == proc_data) {
  96             opal_output(0, "pmix:hash:lookup_proc: unable to allocate proc_data_t\n");
  97             return NULL;
  98         }
  99         opal_proc_table_set_value(ptable, id, proc_data);
 100     }
 101 
 102     return proc_data;
 103 }
 104 
 105 
 106 static opal_proc_table_t ptable;
 107 
 108 /* Initialize our hash table */
 109 void opal_pmix_base_hash_init(void)
 110 {
 111     OBJ_CONSTRUCT(&ptable, opal_proc_table_t);
 112     opal_proc_table_init(&ptable, 16, 256);
 113 }
 114 
 115 void opal_pmix_base_hash_finalize(void)
 116 {
 117     opal_pmix_proc_data_t *proc_data;
 118     opal_process_name_t key;
 119     void *node1, *node2;
 120 
 121     /* to assist in getting a clean valgrind, cycle thru the hash table
 122      * and release all data stored in it
 123      */
 124     if (OPAL_SUCCESS == opal_proc_table_get_first_key(&ptable, &key,
 125                                                       (void**)&proc_data,
 126                                                       &node1, &node2)) {
 127         if (NULL != proc_data) {
 128             OBJ_RELEASE(proc_data);
 129         }
 130         while (OPAL_SUCCESS == opal_proc_table_get_next_key(&ptable, &key,
 131                                                             (void**)&proc_data,
 132                                                             node1, &node1,
 133                                                             node2, &node2)) {
 134             if (NULL != proc_data) {
 135                 OBJ_RELEASE(proc_data);
 136             }
 137         }
 138     }
 139     OBJ_DESTRUCT(&ptable);
 140 }
 141 
 142 
 143 
 144 int opal_pmix_base_store(const opal_process_name_t *id,
 145                          opal_value_t *val)
 146 {
 147     opal_pmix_proc_data_t *proc_data;
 148     opal_value_t *kv;
 149     int rc;
 150 
 151     opal_output_verbose(1, opal_pmix_base_framework.framework_output,
 152                         "%s pmix:hash:store storing data for proc %s",
 153                         OPAL_NAME_PRINT(OPAL_PROC_MY_NAME), OPAL_NAME_PRINT(*id));
 154 
 155     /* lookup the proc data object for this proc */
 156     if (NULL == (proc_data = lookup_proc(&ptable, *id, true))) {
 157         /* unrecoverable error */
 158         OPAL_OUTPUT_VERBOSE((5, opal_pmix_base_framework.framework_output,
 159                              "%s pmix:hash:store: storing data for proc %s unrecoverably failed",
 160                              OPAL_NAME_PRINT(OPAL_PROC_MY_NAME), OPAL_NAME_PRINT(*id)));
 161         return OPAL_ERR_OUT_OF_RESOURCE;
 162     }
 163 
 164     /* see if we already have this key in the data - means we are updating
 165      * a pre-existing value
 166      */
 167     kv = lookup_keyval(proc_data, val->key);
 168 #if OPAL_ENABLE_DEBUG
 169     char *_data_type = opal_dss.lookup_data_type(val->type);
 170     OPAL_OUTPUT_VERBOSE((5, opal_pmix_base_framework.framework_output,
 171                          "%s pmix:hash:store: %s key %s[%s] for proc %s",
 172                          OPAL_NAME_PRINT(OPAL_PROC_MY_NAME),
 173                          (NULL == kv ? "storing" : "updating"),
 174                          val->key, _data_type, OPAL_NAME_PRINT(*id)));
 175     free (_data_type);
 176 #endif
 177 
 178     if (NULL != kv) {
 179         opal_list_remove_item(&proc_data->data, &kv->super);
 180         OBJ_RELEASE(kv);
 181     }
 182     /* create the copy */
 183     if (OPAL_SUCCESS != (rc = opal_dss.copy((void**)&kv, val, OPAL_VALUE))) {
 184         OPAL_ERROR_LOG(rc);
 185         return rc;
 186     }
 187     opal_list_append(&proc_data->data, &kv->super);
 188 
 189     return OPAL_SUCCESS;
 190 }
 191 
 192 int opal_pmix_base_fetch(const opal_process_name_t *id,
 193                          const char *key, opal_list_t *kvs)
 194 {
 195     opal_pmix_proc_data_t *proc_data;
 196     opal_value_t *kv, *knew;
 197     int rc;
 198 
 199     OPAL_OUTPUT_VERBOSE((5, opal_pmix_base_framework.framework_output,
 200                          "%s pmix:hash:fetch: searching for key %s on proc %s",
 201                          OPAL_NAME_PRINT(OPAL_PROC_MY_NAME),
 202                          (NULL == key) ? "NULL" : key, OPAL_NAME_PRINT(*id)));
 203 
 204     /* lookup the proc data object for this proc */
 205     if (NULL == (proc_data = lookup_proc(&ptable, *id, true))) {
 206         OPAL_OUTPUT_VERBOSE((5, opal_pmix_base_framework.framework_output,
 207                              "%s pmix_hash:fetch data for proc %s not found",
 208                              OPAL_NAME_PRINT(OPAL_PROC_MY_NAME),
 209                              OPAL_NAME_PRINT(*id)));
 210         return OPAL_ERR_NOT_FOUND;
 211     }
 212 
 213     /* if the key is NULL, that we want everything */
 214     if (NULL == key) {
 215         /* must provide an output list or this makes no sense */
 216         if (NULL == kvs) {
 217             OPAL_ERROR_LOG(OPAL_ERR_BAD_PARAM);
 218             return OPAL_ERR_BAD_PARAM;
 219         }
 220         OPAL_LIST_FOREACH(kv, &proc_data->data, opal_value_t) {
 221             /* copy the value */
 222             if (OPAL_SUCCESS != (rc = opal_dss.copy((void**)&knew, kv, OPAL_VALUE))) {
 223                 OPAL_ERROR_LOG(rc);
 224                 return rc;
 225             }
 226             OPAL_OUTPUT_VERBOSE((5, opal_pmix_base_framework.framework_output,
 227                                  "%s pmix:hash:fetch: adding data for key %s on proc %s",
 228                                  OPAL_NAME_PRINT(OPAL_PROC_MY_NAME),
 229                                  (NULL == kv->key) ? "NULL" : kv->key,
 230                                  OPAL_NAME_PRINT(*id)));
 231 
 232             /* add it to the output list */
 233             opal_list_append(kvs, &knew->super);
 234         }
 235         return OPAL_SUCCESS;
 236     }
 237 
 238     /* find the value */
 239     if (NULL == (kv = lookup_keyval(proc_data, key))) {
 240         OPAL_OUTPUT_VERBOSE((5, opal_pmix_base_framework.framework_output,
 241                              "%s pmix_hash:fetch key %s for proc %s not found",
 242                              OPAL_NAME_PRINT(OPAL_PROC_MY_NAME),
 243                              (NULL == key) ? "NULL" : key,
 244                              OPAL_NAME_PRINT(*id)));
 245         return OPAL_ERR_NOT_FOUND;
 246     }
 247 
 248     /* if the user provided a NULL list object, then they
 249      * just wanted to know if the key was present */
 250     if (NULL == kvs) {
 251         return OPAL_SUCCESS;
 252     }
 253 
 254     /* create the copy */
 255     if (OPAL_SUCCESS != (rc = opal_dss.copy((void**)&knew, kv, OPAL_VALUE))) {
 256         OPAL_ERROR_LOG(rc);
 257         return rc;
 258     }
 259     /* add it to the output list */
 260     opal_list_append(kvs, &knew->super);
 261 
 262     return OPAL_SUCCESS;
 263 }
 264 
 265 int opal_pmix_base_remove(const opal_process_name_t *id, const char *key)
 266 {
 267     opal_pmix_proc_data_t *proc_data;
 268     opal_value_t *kv;
 269 
 270     /* lookup the specified proc */
 271     if (NULL == (proc_data = lookup_proc(&ptable, *id, false))) {
 272         /* no data for this proc */
 273         return OPAL_SUCCESS;
 274     }
 275 
 276     /* if key is NULL, remove all data for this proc */
 277     if (NULL == key) {
 278         while (NULL != (kv = (opal_value_t *) opal_list_remove_first(&proc_data->data))) {
 279             OBJ_RELEASE(kv);
 280         }
 281         /* remove the proc_data object itself from the jtable */
 282         opal_proc_table_remove_value(&ptable, *id);
 283         /* cleanup */
 284         OBJ_RELEASE(proc_data);
 285         return OPAL_SUCCESS;
 286     }
 287 
 288     /* remove this item */
 289     OPAL_LIST_FOREACH(kv, &proc_data->data, opal_value_t) {
 290         if (0 == strcmp(key, kv->key)) {
 291             opal_list_remove_item(&proc_data->data, &kv->super);
 292             OBJ_RELEASE(kv);
 293             break;
 294         }
 295     }
 296 
 297     return OPAL_SUCCESS;
 298 }

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