This source file includes following definitions.
- opal_hash_table_construct
- opal_hash_table_destruct
- opal_hash_round_capacity_up
- opal_hash_table_init2
- opal_hash_table_init
- opal_hash_table_remove_all
- opal_hash_grow
- opal_hash_table_remove_elt_at
- opal_hash_hash_elt_uint32
- opal_hash_table_get_value_uint32
- opal_hash_table_set_value_uint32
- opal_hash_table_remove_value_uint32
- opal_hash_hash_elt_uint64
- opal_hash_table_get_value_uint64
- opal_hash_table_set_value_uint64
- opal_hash_table_remove_value_uint64
- opal_hash_hash_key_ptr
- opal_hash_destruct_elt_ptr
- opal_hash_hash_elt_ptr
- opal_hash_table_get_value_ptr
- opal_hash_table_set_value_ptr
- opal_hash_table_remove_value_ptr
- opal_hash_table_get_next_elt
- opal_hash_table_get_first_key_uint32
- opal_hash_table_get_next_key_uint32
- opal_hash_table_get_first_key_ptr
- opal_hash_table_get_next_key_ptr
- opal_hash_table_get_first_key_uint64
- opal_hash_table_get_next_key_uint64
- opal_proc_table_construct
- opal_proc_table_destruct
- opal_proc_table_init
- opal_proc_table_remove_all
- opal_proc_table_get_value
- opal_proc_table_set_value
- opal_proc_table_remove_value
- opal_proc_table_get_first_key
- opal_proc_table_get_next_key
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 
  25 #include "opal_config.h"
  26 
  27 #include <string.h>
  28 #include <stdlib.h>
  29 
  30 #include "opal/util/output.h"
  31 #include "opal/class/opal_hash_table.h"
  32 #include "opal/constants.h"
  33 
  34 
  35 
  36 
  37 
  38 
  39 
  40 
  41 
  42 
  43 
  44 
  45 
  46 
  47 
  48 
  49 
  50 
  51 
  52 
  53 
  54 
  55 
  56 
  57 
  58 
  59 
  60 
  61 
  62 
  63 
  64 
  65 
  66 
  67 
  68 
  69 
  70 
  71 
  72 
  73 
  74 
  75 
  76 
  77 
  78 
  79 
  80 
  81 
  82 
  83 
  84 
  85 
  86 
  87 
  88 #define HASH_MULTIPLIER 31
  89 
  90 
  91 
  92 
  93 
  94 struct opal_hash_element_t {
  95     int         valid;          
  96     union {                     
  97         uint32_t        u32;
  98         uint64_t        u64;
  99         struct {
 100             const void * key;
 101             size_t      key_size;
 102         }       ptr;
 103     }           key;
 104     void *      value;          
 105 };
 106 typedef struct opal_hash_element_t opal_hash_element_t;
 107 
 108 struct opal_hash_type_methods_t {
 109     
 110 
 111 
 112 
 113     void        (*elt_destructor)(opal_hash_element_t * elt);
 114     
 115     uint64_t    (*hash_elt)(opal_hash_element_t * elt);
 116 };
 117 
 118 
 119 
 120 static void opal_hash_table_construct(opal_hash_table_t* ht);
 121 static void opal_hash_table_destruct(opal_hash_table_t* ht);
 122 
 123 OBJ_CLASS_INSTANCE(
 124     opal_hash_table_t,
 125     opal_object_t,
 126     opal_hash_table_construct,
 127     opal_hash_table_destruct
 128 );
 129 
 130 static void
 131 opal_hash_table_construct(opal_hash_table_t* ht)
 132 {
 133   ht->ht_table = NULL;
 134   ht->ht_capacity = ht->ht_size = ht->ht_growth_trigger = 0;
 135   ht->ht_density_numer = ht->ht_density_denom = 0;
 136   ht->ht_growth_numer = ht->ht_growth_denom = 0;
 137   ht->ht_type_methods = NULL;
 138 }
 139 
 140 static void
 141 opal_hash_table_destruct(opal_hash_table_t* ht)
 142 {
 143     opal_hash_table_remove_all(ht);
 144     free(ht->ht_table);
 145 }
 146 
 147 
 148 
 149 
 150 
 151 static size_t
 152 opal_hash_round_capacity_up(size_t capacity)
 153 {
 154     
 155     return ((capacity+29)/30*30 + 1);
 156 }
 157 
 158 
 159 
 160 int                             
 161 opal_hash_table_init2(opal_hash_table_t* ht, size_t estimated_max_size,
 162                       int density_numer, int density_denom,
 163                       int growth_numer, int growth_denom)
 164 {
 165     size_t est_capacity = estimated_max_size * density_denom / density_numer;
 166     size_t capacity = opal_hash_round_capacity_up(est_capacity);
 167     ht->ht_table = (opal_hash_element_t*) calloc(capacity, sizeof(opal_hash_element_t));
 168     if (NULL == ht->ht_table) {
 169         return OPAL_ERR_OUT_OF_RESOURCE;
 170     }
 171     ht->ht_capacity       = capacity;
 172     ht->ht_density_numer  = density_numer;
 173     ht->ht_density_denom  = density_denom;
 174     ht->ht_growth_numer   = growth_numer;
 175     ht->ht_growth_denom   = growth_denom;
 176     ht->ht_growth_trigger = capacity * density_numer / density_denom;
 177     ht->ht_type_methods   = NULL;
 178     return OPAL_SUCCESS;
 179 }
 180 
 181 int                             
 182 opal_hash_table_init(opal_hash_table_t* ht, size_t table_size)
 183 {
 184     
 185     return opal_hash_table_init2(ht, table_size, 1, 2, 2, 1);
 186 }
 187 
 188 int                             
 189 opal_hash_table_remove_all(opal_hash_table_t* ht)
 190 {
 191     size_t ii;
 192     for (ii = 0; ii < ht->ht_capacity; ii += 1) {
 193         opal_hash_element_t * elt = &ht->ht_table[ii];
 194         if (elt->valid && ht->ht_type_methods && ht->ht_type_methods->elt_destructor) {
 195             ht->ht_type_methods->elt_destructor(elt);
 196         }
 197         elt->valid = 0;
 198         elt->value = NULL;
 199     }
 200     ht->ht_size = 0;
 201     
 202     
 203     ht->ht_type_methods = NULL;
 204     return OPAL_SUCCESS;
 205 }
 206 
 207 static int                      
 208 opal_hash_grow(opal_hash_table_t * ht)
 209 {
 210     size_t jj, ii;
 211     opal_hash_element_t* old_table;
 212     opal_hash_element_t* new_table;
 213     size_t old_capacity;
 214     size_t new_capacity;
 215 
 216     old_table    = ht->ht_table;
 217     old_capacity = ht->ht_capacity;
 218 
 219     new_capacity = old_capacity * ht->ht_growth_numer / ht->ht_growth_denom;
 220     new_capacity = opal_hash_round_capacity_up(new_capacity);
 221 
 222     new_table    = (opal_hash_element_t*) calloc(new_capacity, sizeof(new_table[0]));
 223     if (NULL == new_table) {
 224         return OPAL_ERR_OUT_OF_RESOURCE;
 225     }
 226 
 227     
 228 
 229 
 230 
 231 
 232 
 233 
 234 
 235     for (jj = 0; jj < old_capacity; jj += 1) {
 236         opal_hash_element_t * old_elt;
 237         opal_hash_element_t * new_elt;
 238         old_elt =  &old_table[jj];
 239         if (old_elt->valid) {
 240             for (ii = (ht->ht_type_methods->hash_elt(old_elt)%new_capacity); ; ii += 1) {
 241                 if (ii == new_capacity) { ii = 0; }
 242                 new_elt = &new_table[ii];
 243                 if (! new_elt->valid) {
 244                     *new_elt = *old_elt;
 245                     break;
 246                 }
 247             }
 248         }
 249     }
 250     
 251     ht->ht_table = new_table;
 252     ht->ht_capacity = new_capacity;
 253     ht->ht_growth_trigger = new_capacity * ht->ht_density_numer / ht->ht_density_denom;
 254     free(old_table);
 255     return OPAL_SUCCESS;
 256 }
 257 
 258 
 259 
 260 
 261 
 262 static int                      
 263 opal_hash_table_remove_elt_at(opal_hash_table_t * ht, size_t ii)
 264 {
 265     size_t jj, capacity = ht->ht_capacity;
 266     opal_hash_element_t* elts = ht->ht_table;
 267     opal_hash_element_t * elt;
 268 
 269     elt = &elts[ii];
 270 
 271     if (! elt->valid) {
 272         
 273         return OPAL_ERROR;
 274     }
 275 
 276     elt->valid = 0;
 277     if (ht->ht_type_methods->elt_destructor) {
 278         ht->ht_type_methods->elt_destructor(elt);
 279     }
 280 
 281     
 282     
 283 
 284 
 285 
 286 
 287 
 288 
 289 
 290 
 291     for (ii = ii+1; ; ii += 1) { 
 292         if (ii == capacity) { ii = 0; }
 293         elt = &elts[ii];
 294         if (! elt->valid) {
 295             break;              
 296         }
 297         
 298         for (jj = ht->ht_type_methods->hash_elt(elt)%capacity; ; jj += 1) {
 299             if (jj == capacity) { jj = 0; }
 300             if (jj == ii) {
 301                 
 302                 break;
 303             } else if (! elts[jj].valid) {
 304                 
 305                 elts[jj] = elts[ii];
 306                 elts[ii].valid = 0;
 307                 break;
 308             } else {
 309                 
 310             }
 311         }
 312     }
 313     ht->ht_size -= 1;
 314     return OPAL_SUCCESS;
 315 }
 316 
 317 
 318 
 319 
 320 static uint64_t
 321 opal_hash_hash_elt_uint32(opal_hash_element_t * elt)
 322 {
 323   return elt->key.u32;
 324 }
 325 
 326 static const struct opal_hash_type_methods_t
 327 opal_hash_type_methods_uint32 = {
 328     NULL,
 329     opal_hash_hash_elt_uint32
 330 };
 331 
 332 int                             
 333 opal_hash_table_get_value_uint32(opal_hash_table_t* ht, uint32_t key, void * *value)
 334 {
 335     size_t ii, capacity = ht->ht_capacity;
 336     opal_hash_element_t * elt;
 337 
 338 #if OPAL_ENABLE_DEBUG
 339     if(capacity == 0) {
 340         opal_output(0, "opal_hash_table_get_value_uint32:"
 341                     "opal_hash_table_init() has not been called");
 342         return OPAL_ERROR;
 343     }
 344     if (NULL != ht->ht_type_methods &&
 345         &opal_hash_type_methods_uint32 != ht->ht_type_methods) {
 346         opal_output(0, "opal_hash_table_get_value_uint32:"
 347                     "hash table is for a different key type");
 348             return OPAL_ERROR;
 349     }
 350 #endif
 351 
 352     ht->ht_type_methods = &opal_hash_type_methods_uint32;
 353     for (ii = key%capacity; ; ii += 1) {
 354         if (ii == capacity) { ii = 0; }
 355         elt = &ht->ht_table[ii];
 356         if (! elt->valid) {
 357             return OPAL_ERR_NOT_FOUND;
 358         } else if (elt->key.u32 == key) {
 359             *value = elt->value;
 360             return OPAL_SUCCESS;
 361         } else {
 362             
 363         }
 364     }
 365 
 366 }
 367 
 368 int                             
 369 opal_hash_table_set_value_uint32(opal_hash_table_t * ht, uint32_t key, void * value)
 370 {
 371     int rc;
 372     size_t ii, capacity = ht->ht_capacity;
 373     opal_hash_element_t * elt;
 374 
 375 #if OPAL_ENABLE_DEBUG
 376     if(capacity == 0) {
 377         opal_output(0, "opal_hash_table_set_value_uint32:"
 378                    "opal_hash_table_init() has not been called");
 379         return OPAL_ERR_BAD_PARAM;
 380     }
 381     if (NULL != ht->ht_type_methods &&
 382         &opal_hash_type_methods_uint32 != ht->ht_type_methods) {
 383         opal_output(0, "opal_hash_table_set_value_uint32:"
 384                     "hash table is for a different key type");
 385             return OPAL_ERROR;
 386     }
 387 #endif
 388 
 389     ht->ht_type_methods = &opal_hash_type_methods_uint32;
 390     for (ii = key%capacity; ; ii += 1) {
 391         if (ii == capacity) { ii = 0; }
 392         elt = &ht->ht_table[ii];
 393         if (! elt->valid) {
 394             
 395             elt->key.u32 = key;
 396             elt->value = value;
 397             elt->valid = 1;
 398             ht->ht_size += 1;
 399             if (ht->ht_size >= ht->ht_growth_trigger) {
 400                 if (OPAL_SUCCESS != (rc = opal_hash_grow(ht))) {
 401                     return rc;
 402                 }
 403             }
 404             return OPAL_SUCCESS;
 405         } else if (elt->key.u32 == key) {
 406             
 407             elt->value = value;
 408             return OPAL_SUCCESS;
 409         } else {
 410             
 411         }
 412     }
 413 }
 414 
 415 int
 416 opal_hash_table_remove_value_uint32(opal_hash_table_t * ht, uint32_t key)
 417 {
 418     size_t ii, capacity = ht->ht_capacity;
 419 
 420 #if OPAL_ENABLE_DEBUG
 421     if(capacity == 0) {
 422         opal_output(0, "opal_hash_table_get_value_uint32:"
 423                     "opal_hash_table_init() has not been called");
 424         return OPAL_ERROR;
 425     }
 426     if (NULL != ht->ht_type_methods &&
 427         &opal_hash_type_methods_uint32 != ht->ht_type_methods) {
 428         opal_output(0, "opal_hash_table_remove_value_uint32:"
 429                     "hash table is for a different key type");
 430             return OPAL_ERROR;
 431     }
 432 #endif
 433 
 434     ht->ht_type_methods = &opal_hash_type_methods_uint32;
 435     for (ii = key%capacity; ; ii += 1) {
 436         opal_hash_element_t * elt;
 437         if (ii == capacity) ii = 0;
 438         elt = &ht->ht_table[ii];
 439         if (! elt->valid) {
 440             return OPAL_ERR_NOT_FOUND;
 441         } else if (elt->key.u32 == key) {
 442             return opal_hash_table_remove_elt_at(ht, ii);
 443         } else {
 444             
 445         }
 446     }
 447 }
 448 
 449 
 450 
 451 
 452 
 453 static uint64_t
 454 opal_hash_hash_elt_uint64(opal_hash_element_t * elt)
 455 {
 456   return elt->key.u64;
 457 }
 458 
 459 static const struct opal_hash_type_methods_t
 460 opal_hash_type_methods_uint64 = {
 461     NULL,
 462     opal_hash_hash_elt_uint64
 463 };
 464 
 465 int                             
 466 opal_hash_table_get_value_uint64(opal_hash_table_t * ht, uint64_t key, void * *value)
 467 {
 468     size_t ii;
 469     size_t capacity = ht->ht_capacity;
 470     opal_hash_element_t * elt;
 471 
 472 #if OPAL_ENABLE_DEBUG
 473     if(capacity == 0) {
 474         opal_output(0, "opal_hash_table_get_value_uint64:"
 475                    "opal_hash_table_init() has not been called");
 476         return OPAL_ERROR;
 477     }
 478     if (NULL != ht->ht_type_methods &&
 479         &opal_hash_type_methods_uint64 != ht->ht_type_methods) {
 480         opal_output(0, "opal_hash_table_get_value_uint64:"
 481                     "hash table is for a different key type");
 482             return OPAL_ERROR;
 483     }
 484 #endif
 485 
 486     ht->ht_type_methods = &opal_hash_type_methods_uint64;
 487     for (ii = key%capacity; ; ii += 1) {
 488         if (ii == capacity) { ii = 0; }
 489         elt = &ht->ht_table[ii];
 490         if (! elt->valid) {
 491             return OPAL_ERR_NOT_FOUND;
 492         } else if (elt->key.u64 == key) {
 493             *value = elt->value;
 494             return OPAL_SUCCESS;
 495         } else {
 496             
 497         }
 498     }
 499 
 500 }
 501 
 502 int                             
 503 opal_hash_table_set_value_uint64(opal_hash_table_t * ht, uint64_t key, void * value)
 504 {
 505     int rc;
 506     size_t ii, capacity = ht->ht_capacity;
 507     opal_hash_element_t * elt;
 508 
 509 #if OPAL_ENABLE_DEBUG
 510     if(capacity == 0) {
 511         opal_output(0, "opal_hash_table_set_value_uint64:"
 512                    "opal_hash_table_init() has not been called");
 513         return OPAL_ERR_BAD_PARAM;
 514     }
 515     if (NULL != ht->ht_type_methods &&
 516         &opal_hash_type_methods_uint64 != ht->ht_type_methods) {
 517         opal_output(0, "opal_hash_table_set_value_uint64:"
 518                     "hash table is for a different key type");
 519             return OPAL_ERROR;
 520     }
 521 #endif
 522 
 523     ht->ht_type_methods = &opal_hash_type_methods_uint64;
 524     for (ii = key%capacity; ; ii += 1) {
 525         if (ii == capacity) { ii = 0; }
 526         elt = &ht->ht_table[ii];
 527         if (! elt->valid) {
 528             
 529             elt->key.u64 = key;
 530             elt->value = value;
 531             elt->valid = 1;
 532             ht->ht_size += 1;
 533             if (ht->ht_size >= ht->ht_growth_trigger) {
 534                 if (OPAL_SUCCESS != (rc = opal_hash_grow(ht))) {
 535                     return rc;
 536                 }
 537             }
 538             return OPAL_SUCCESS;
 539         } else if (elt->key.u64 == key) {
 540             elt->value = value;
 541             return OPAL_SUCCESS;
 542         } else {
 543             
 544         }
 545     }
 546 }
 547 
 548 
 549 int                             
 550 opal_hash_table_remove_value_uint64(opal_hash_table_t * ht, uint64_t key)
 551 {
 552     size_t ii, capacity = ht->ht_capacity;
 553 
 554 #if OPAL_ENABLE_DEBUG
 555     if(capacity == 0) {
 556         opal_output(0, "opal_hash_table_get_value_uint64:"
 557                     "opal_hash_table_init() has not been called");
 558         return OPAL_ERROR;
 559     }
 560     if (NULL != ht->ht_type_methods &&
 561         &opal_hash_type_methods_uint64 != ht->ht_type_methods) {
 562         opal_output(0, "opal_hash_table_remove_value_uint64:"
 563                     "hash table is for a different key type");
 564             return OPAL_ERROR;
 565     }
 566 #endif
 567 
 568     ht->ht_type_methods = &opal_hash_type_methods_uint64;
 569     for (ii = key%capacity; ; ii += 1) {
 570         opal_hash_element_t * elt;
 571         if (ii == capacity) { ii = 0; }
 572         elt = &ht->ht_table[ii];
 573         if (! elt->valid) {
 574             return OPAL_ERR_NOT_FOUND;
 575         } else if (elt->key.u64 == key) {
 576             return opal_hash_table_remove_elt_at(ht, ii);
 577         } else {
 578             
 579         }
 580     }
 581 }
 582 
 583 
 584 
 585 
 586 
 587 static uint64_t
 588 opal_hash_hash_key_ptr(const void * key, size_t key_size)
 589 {
 590     uint64_t hash;
 591     const unsigned char *scanner;
 592     size_t ii;
 593 
 594     hash = 0;
 595     scanner = (const unsigned char *)key;
 596     for (ii = 0; ii < key_size; ii += 1) {
 597         hash = HASH_MULTIPLIER*hash + *scanner++;
 598     }
 599     return hash;
 600 }
 601 
 602 
 603 
 604 static void
 605 opal_hash_destruct_elt_ptr(opal_hash_element_t * elt)
 606 {
 607     elt->key.ptr.key_size = 0;
 608     void * key = (void *) elt->key.ptr.key; 
 609     if (NULL != key) {
 610         elt->key.ptr.key = NULL;
 611         free(key);
 612     }
 613 }
 614 
 615 static uint64_t
 616 opal_hash_hash_elt_ptr(opal_hash_element_t * elt)
 617 {
 618     return opal_hash_hash_key_ptr(elt->key.ptr.key, elt->key.ptr.key_size);
 619 }
 620 
 621 static const struct opal_hash_type_methods_t
 622 opal_hash_type_methods_ptr = {
 623     opal_hash_destruct_elt_ptr,
 624     opal_hash_hash_elt_ptr
 625 };
 626 
 627 int                             
 628 opal_hash_table_get_value_ptr(opal_hash_table_t * ht,
 629                               const void * key, size_t key_size,
 630                               void * *value)
 631 {
 632     size_t ii, capacity = ht->ht_capacity;
 633     opal_hash_element_t * elt;
 634 
 635 #if OPAL_ENABLE_DEBUG
 636     if(capacity == 0) {
 637         opal_output(0, "opal_hash_table_get_value_ptr:"
 638                    "opal_hash_table_init() has not been called");
 639         return OPAL_ERROR;
 640     }
 641     if (NULL != ht->ht_type_methods &&
 642         &opal_hash_type_methods_ptr != ht->ht_type_methods) {
 643         opal_output(0, "opal_hash_table_get_value_ptr:"
 644                     "hash table is for a different key type");
 645             return OPAL_ERROR;
 646     }
 647 #endif
 648 
 649     ht->ht_type_methods = &opal_hash_type_methods_ptr;
 650     for (ii = opal_hash_hash_key_ptr(key, key_size)%capacity; ; ii += 1) {
 651         if (ii == capacity) { ii = 0; }
 652         elt = &ht->ht_table[ii];
 653         if (! elt->valid) {
 654             return OPAL_ERR_NOT_FOUND;
 655         } else if (elt->key.ptr.key_size == key_size &&
 656                    0 == memcmp(elt->key.ptr.key, key, key_size)) {
 657             *value = elt->value;
 658             return OPAL_SUCCESS;
 659         } else {
 660             
 661         }
 662     }
 663 }
 664 
 665 int                             
 666 opal_hash_table_set_value_ptr(opal_hash_table_t * ht,
 667                               const void * key, size_t key_size,
 668                               void * value)
 669 {
 670     int rc;
 671     size_t ii, capacity = ht->ht_capacity;
 672     opal_hash_element_t * elt;
 673 
 674 #if OPAL_ENABLE_DEBUG
 675     if(capacity == 0) {
 676         opal_output(0, "opal_hash_table_set_value_ptr:"
 677                    "opal_hash_table_init() has not been called");
 678         return OPAL_ERR_BAD_PARAM;
 679     }
 680     if (NULL != ht->ht_type_methods &&
 681         &opal_hash_type_methods_ptr != ht->ht_type_methods) {
 682         opal_output(0, "opal_hash_table_set_value_ptr:"
 683                     "hash table is for a different key type");
 684             return OPAL_ERROR;
 685     }
 686 #endif
 687 
 688     ht->ht_type_methods = &opal_hash_type_methods_ptr;
 689     for (ii = opal_hash_hash_key_ptr(key, key_size)%capacity; ; ii += 1) {
 690         if (ii == capacity) { ii = 0; }
 691         elt = &ht->ht_table[ii];
 692         if (! elt->valid) {
 693             
 694             void * key_local = malloc(key_size);
 695             memcpy(key_local, key, key_size);
 696             elt->key.ptr.key      = key_local;
 697             elt->key.ptr.key_size = key_size;
 698             elt->value = value;
 699             elt->valid = 1;
 700             ht->ht_size += 1;
 701             if (ht->ht_size >= ht->ht_growth_trigger) {
 702                 if (OPAL_SUCCESS != (rc = opal_hash_grow(ht))) {
 703                     return rc;
 704                 }
 705             }
 706             return OPAL_SUCCESS;
 707         } else if (elt->key.ptr.key_size == key_size &&
 708                    0 == memcmp(elt->key.ptr.key, key, key_size)) {
 709             
 710             elt->value = value;
 711             return OPAL_SUCCESS;
 712         } else {
 713             
 714         }
 715     }
 716 }
 717 
 718 int                             
 719 opal_hash_table_remove_value_ptr(opal_hash_table_t * ht,
 720                                  const void * key, size_t key_size)
 721 {
 722     size_t ii, capacity = ht->ht_capacity;
 723 
 724 #if OPAL_ENABLE_DEBUG
 725     if(capacity == 0) {
 726         opal_output(0, "opal_hash_table_get_value_ptr:"
 727                     "opal_hash_table_init() has not been called");
 728         return OPAL_ERROR;
 729     }
 730     if (NULL != ht->ht_type_methods &&
 731         &opal_hash_type_methods_ptr != ht->ht_type_methods) {
 732         opal_output(0, "opal_hash_table_remove_value_ptr:"
 733                     "hash table is for a different key type");
 734             return OPAL_ERROR;
 735     }
 736 #endif
 737 
 738     ht->ht_type_methods = &opal_hash_type_methods_ptr;
 739     for (ii = opal_hash_hash_key_ptr(key, key_size)%capacity; ; ii += 1) {
 740         opal_hash_element_t * elt;
 741         if (ii == capacity) { ii = 0; }
 742         elt = &ht->ht_table[ii];
 743         if (! elt->valid) {
 744             return OPAL_ERR_NOT_FOUND;
 745         } else if (elt->key.ptr.key_size == key_size &&
 746                    0 == memcmp(elt->key.ptr.key, key, key_size)) {
 747             return opal_hash_table_remove_elt_at(ht, ii);
 748         } else {
 749             
 750         }
 751     }
 752 }
 753 
 754 
 755 
 756 
 757 static int                      
 758 opal_hash_table_get_next_elt(opal_hash_table_t *ht,
 759                              opal_hash_element_t * prev_elt, 
 760                              opal_hash_element_t * *next_elt)
 761 {
 762   opal_hash_element_t* elts = ht->ht_table;
 763   size_t ii, capacity = ht->ht_capacity;
 764 
 765   for (ii = (NULL == prev_elt ? 0 : (prev_elt-elts)+1); ii < capacity; ii += 1) {
 766     opal_hash_element_t * elt = &elts[ii];
 767     if (elt->valid) {
 768       *next_elt = elt;
 769       return OPAL_SUCCESS;
 770     }
 771   }
 772   return OPAL_ERROR;
 773 }
 774 
 775 int                             
 776 opal_hash_table_get_first_key_uint32(opal_hash_table_t * ht,
 777                                      uint32_t *key, void * *value,
 778                                      void * *node)
 779 {
 780   return opal_hash_table_get_next_key_uint32(ht, key, value, NULL, node);
 781 }
 782 
 783 int                             
 784 opal_hash_table_get_next_key_uint32(opal_hash_table_t * ht,
 785                                     uint32_t *key, void * *value,
 786                                     void * in_node, void * *out_node)
 787 {
 788   opal_hash_element_t * elt;
 789   if (OPAL_SUCCESS == opal_hash_table_get_next_elt(ht, (opal_hash_element_t *) in_node, &elt)) {
 790     *key       = elt->key.u32;
 791     *value     = elt->value;
 792     *out_node  = elt;
 793     return OPAL_SUCCESS;
 794   }
 795   return OPAL_ERROR;
 796 }
 797 
 798 int                             
 799 opal_hash_table_get_first_key_ptr(opal_hash_table_t * ht,
 800                                   void * *key, size_t *key_size, void * *value,
 801                                   void * *node)
 802 {
 803   return opal_hash_table_get_next_key_ptr(ht, key, key_size, value, NULL, node);
 804 }
 805 
 806 int                             
 807 opal_hash_table_get_next_key_ptr(opal_hash_table_t * ht,
 808                                  void * *key, size_t *key_size, void * *value,
 809                                  void * in_node, void * *out_node)
 810 {
 811   opal_hash_element_t * elt;
 812   if (OPAL_SUCCESS == opal_hash_table_get_next_elt(ht, (opal_hash_element_t *) in_node, &elt)) {
 813     *key       = (void *)elt->key.ptr.key;
 814     *key_size  = elt->key.ptr.key_size;
 815     *value     = elt->value;
 816     *out_node  = elt;
 817     return OPAL_SUCCESS;
 818   }
 819   return OPAL_ERROR;
 820 }
 821 
 822 int                             
 823 opal_hash_table_get_first_key_uint64(opal_hash_table_t * ht,
 824                                      uint64_t *key, void * *value,
 825                                      void * *node)
 826 {
 827   return opal_hash_table_get_next_key_uint64(ht, key, value, NULL, node);
 828 }
 829 
 830 int                             
 831 opal_hash_table_get_next_key_uint64(opal_hash_table_t * ht,
 832                                     uint64_t *key, void * *value,
 833                                     void * in_node, void * *out_node)
 834 {
 835   opal_hash_element_t * elt;
 836   if (OPAL_SUCCESS == opal_hash_table_get_next_elt(ht, (opal_hash_element_t *) in_node, &elt)) {
 837     *key       = elt->key.u64;
 838     *value     = elt->value;
 839     *out_node  = elt;
 840     return OPAL_SUCCESS;
 841   }
 842   return OPAL_ERROR;
 843 }
 844 
 845 
 846 
 847 
 848 static void opal_proc_table_construct(opal_proc_table_t* pt);
 849 static void opal_proc_table_destruct(opal_proc_table_t* pt);
 850 
 851 OBJ_CLASS_INSTANCE(
 852     opal_proc_table_t,
 853     opal_hash_table_t,
 854     opal_proc_table_construct,
 855     opal_proc_table_destruct
 856 );
 857 
 858 static void
 859 opal_proc_table_construct(opal_proc_table_t* pt)
 860 {
 861   pt->pt_size = 0;
 862 }
 863 
 864 static void
 865 opal_proc_table_destruct(opal_proc_table_t* pt)
 866 {
 867 }
 868 
 869 
 870 
 871 
 872 
 873 int opal_proc_table_init(opal_proc_table_t* pt, size_t jobids, size_t vpids) {
 874     int rc;
 875     if (OPAL_SUCCESS != (rc=opal_hash_table_init(&pt->super, jobids))) {
 876         return rc;
 877     }
 878     pt->vpids_size = vpids;
 879     return OPAL_SUCCESS;
 880 }
 881 
 882 int opal_proc_table_remove_all(opal_proc_table_t *pt) {
 883     int rc;
 884     opal_hash_table_t * vpids;
 885     uint32_t jobid;
 886     void * node;
 887 
 888     rc = opal_hash_table_get_first_key_uint32(&pt->super, &jobid, (void **)&vpids, &node);
 889 
 890     if (OPAL_SUCCESS == rc) {
 891         do {
 892             if (NULL != vpids) {
 893                 opal_hash_table_remove_all(vpids);
 894                 OBJ_RELEASE(vpids);
 895             }
 896             rc = opal_hash_table_get_next_key_uint32 (&pt->super, &jobid,
 897                                                (void **) &vpids, node, &node);
 898         } while (OPAL_SUCCESS == rc);
 899     }
 900 
 901     return rc;
 902 }
 903 
 904 int opal_proc_table_get_value(opal_proc_table_t* pt, opal_process_name_t key,
 905                               void** ptr) {
 906     int rc;
 907     opal_hash_table_t * vpids;
 908     rc = opal_hash_table_get_value_uint32(&pt->super, key.jobid, (void **)&vpids);
 909     if (rc != OPAL_SUCCESS) {
 910         return rc;
 911     }
 912     rc = opal_hash_table_get_value_uint32(vpids, key.vpid, ptr);
 913     return rc;
 914 }
 915 
 916 int opal_proc_table_set_value(opal_proc_table_t* pt, opal_process_name_t key, void* value) {
 917     int rc;
 918     opal_hash_table_t * vpids;
 919     rc = opal_hash_table_get_value_uint32(&pt->super, key.jobid, (void **)&vpids);
 920     if (rc != OPAL_SUCCESS) {
 921         vpids = OBJ_NEW(opal_hash_table_t);
 922         if (NULL == vpids) {
 923             return OPAL_ERR_OUT_OF_RESOURCE;
 924         }
 925         if (OPAL_SUCCESS != (rc=opal_hash_table_init(vpids, pt->vpids_size))) {
 926             OBJ_RELEASE(vpids);
 927             return rc;
 928         }
 929         if (OPAL_SUCCESS != (rc=opal_hash_table_set_value_uint32(&pt->super, key.jobid, vpids))) {
 930             OBJ_RELEASE(vpids);
 931             return rc;
 932         }
 933     }
 934     rc = opal_hash_table_set_value_uint32(vpids, key.vpid, value);
 935     return rc;
 936 }
 937 
 938 int opal_proc_table_remove_value(opal_proc_table_t* pt, opal_process_name_t key) {
 939     int rc;
 940     opal_hash_table_t * vpids;
 941     if (OPAL_SUCCESS != (rc=opal_hash_table_get_value_uint32(&pt->super, key.jobid, (void **)&vpids))) {
 942         return rc;
 943     }
 944     if (OPAL_SUCCESS == (rc=opal_hash_table_remove_value_uint32(vpids, key.vpid))) {
 945         if (0 == vpids->ht_size) {
 946             opal_hash_table_remove_value_uint32(&pt->super, key.jobid);
 947             OBJ_RELEASE(vpids);
 948         }
 949     }
 950     return rc;
 951 }
 952 
 953 int opal_proc_table_get_first_key(opal_proc_table_t *pt, opal_process_name_t *key,
 954                                   void **value, void **node1, void **node2) {
 955     int rc;
 956     uint32_t jobid, vpid;
 957     opal_hash_table_t * vpids;
 958     if (OPAL_SUCCESS != (rc=opal_hash_table_get_first_key_uint32(&pt->super, &jobid, (void **)&vpids, node1))) {
 959         return rc;
 960     }
 961     rc = opal_hash_table_get_first_key_uint32(vpids, &vpid, value, node2);
 962     if (OPAL_SUCCESS == rc) {
 963         key->jobid = jobid;
 964         key->vpid = vpid;
 965     }
 966     return rc;
 967 }
 968 
 969 int opal_proc_table_get_next_key(opal_proc_table_t *pt, opal_process_name_t *key,
 970                                  void **value, void *in_node1, void **out_node1,
 971                                  void *in_node2, void **out_node2) {
 972     int rc;
 973     uint32_t jobid = ((opal_hash_element_t *)in_node1)->key.u32;
 974     uint32_t vpid;
 975     opal_hash_table_t * vpids = ((opal_hash_element_t *)in_node1)->value;
 976 
 977     rc = opal_hash_table_get_next_key_uint32(vpids, &vpid, value, in_node2, out_node2);
 978     if (OPAL_SUCCESS == rc) {
 979         key->jobid = jobid;
 980         key->vpid = vpid;
 981         *out_node1 = in_node1;
 982         return rc;
 983     }
 984     if (OPAL_SUCCESS != (rc=opal_hash_table_get_next_key_uint32(&pt->super, &jobid, (void **)&vpids, in_node1, out_node1))) {
 985         return rc;
 986     }
 987     rc = opal_hash_table_get_first_key_uint32(vpids, &vpid, value, out_node2);
 988     if (OPAL_SUCCESS == rc) {
 989         key->jobid = jobid;
 990         key->vpid = vpid;
 991     }
 992     return rc;
 993 }