~ubuntu-branches/ubuntu/vivid/adios/vivid-proposed

« back to all changes in this revision

Viewing changes to src/core/qhashtbl.c

  • Committer: Package Import Robot
  • Author(s): Alastair McKinstry
  • Date: 2014-06-16 23:06:38 UTC
  • mfrom: (15.1.8 sid)
  • Revision ID: package-import@ubuntu.com-20140616230638-cxryhot6b8ge32l6
Tags: 1.7.0-1
* New upstream release.
* Add adios.pc pkgconfig file. adios_config now uses this.

Show diffs side-by-side

added added

removed removed

Lines of Context:
143
143
    memset((void *)tbl, 0, sizeof(qhashtbl_t));
144
144
 
145
145
    // allocate table space
146
 
    tbl->slots = (qhnobj_t **)malloc(sizeof(qhnobj_t *) * range);
 
146
    tbl->slots = (qhslot_t *)malloc(sizeof(qhslot_t) * range);
147
147
    if (tbl->slots == NULL) {
148
148
        errno = ENOMEM;
149
149
        free_(tbl);
150
150
        return NULL;
151
151
    }
152
 
    memset((void *)tbl->slots, 0, sizeof(qhnobj_t *) * range);
 
152
    memset((void *)tbl->slots, 0, sizeof(qhslot_t) * range);
153
153
 
154
154
    // assign methods
155
155
    tbl->put2       = put2;
166
166
    tbl->range = range;
167
167
    tbl->num = 0;
168
168
 
 
169
    // debug variables
 
170
    tbl->nwalks_get = 0;
 
171
    tbl->ncalls_get = 0;
 
172
    tbl->nwalks_put = 0;
 
173
    tbl->ncalls_put = 0;
 
174
 
169
175
    return tbl;
170
176
}
171
177
 
200
206
    }
201
207
}
202
208
 
 
209
static bool qhput(qhashtbl_t *tbl, char *key, int keylen, const void *data)
 
210
{
 
211
    // get hash integer
 
212
    uint32_t hash = qhashmurmur3_32(key, keylen);
 
213
    int idx = hash % tbl->range;
 
214
    tbl->ncalls_put++; // debug
 
215
 
 
216
    //log_error ("qhastbl:put: key=[%s], keylen=%d hash=%d, idx=%d, d=%x\n", key, keylen, hash, idx, data);
 
217
 
 
218
    // find existing key
 
219
    qhslot_t *slot = &tbl->slots[idx];
 
220
    qhnobj_t *obj;
 
221
    for (obj = slot->head; obj != NULL; obj = obj->next) {
 
222
        if (obj->hash == hash && !strcmp(obj->key, key)) {
 
223
            break;
 
224
        }
 
225
        tbl->nwalks_put++; // debug: we walk one step in a chain of elements 
 
226
    }
 
227
 
 
228
    // put into table
 
229
    if (obj == NULL) {
 
230
        // insert
 
231
        obj = (qhnobj_t *)malloc(sizeof(qhnobj_t));
 
232
        if (obj == NULL) {
 
233
            free(key);
 
234
            errno = ENOMEM;
 
235
            return false;
 
236
        }
 
237
        memset((void *)obj, 0, sizeof(qhnobj_t));
 
238
 
 
239
        if (slot->tail != NULL) {
 
240
            // connect old tail to this new tail 
 
241
            slot->tail->next = obj;
 
242
        }
 
243
        if (slot->head == NULL) {
 
244
            // insert as very first element
 
245
            slot->head = obj;
 
246
        }
 
247
        slot->tail = obj;
 
248
        obj->next = 0;
 
249
 
 
250
        // increase counter
 
251
        tbl->num++;
 
252
 
 
253
        // set data
 
254
        obj->hash  = hash;
 
255
        obj->key   = key;
 
256
        obj->value = (void *)data;
 
257
 
 
258
    } else {
 
259
        /* Do not do anything.
 
260
         * Keep the first definition in place, because consider this example
 
261
         * if we would replace the object here:
 
262
         *  def NX
 
263
         *  def A[NX] --> A's dimension is the first variable NX (a pointer to that)
 
264
         *  def NX    --> hashtable stores this variable reference
 
265
         *  def B[NX]
 
266
         *  write NX  --> value is stored in the NX variable found in the hash table
 
267
         *  write A   --> dimension found (valid first pointer) but value is not found
 
268
         *                (stored in the second reference)
 
269
         *  At this point, A's dimension variable is first NX, but the value of
 
270
         *  write NX goes to the variable found here in the hash table.
 
271
         */
 
272
        free(key);
 
273
    }
 
274
 
 
275
    return true;
 
276
}
 
277
 
203
278
static bool put(qhashtbl_t *tbl, const char *fullpath, const void *data)
204
279
{
205
280
    if (!fullpath)
208
283
    int keylen = strlen(fullpath);
209
284
    char *key = strdup (fullpath);
210
285
 
211
 
    // get hash integer
212
 
    uint32_t hash = qhashmurmur3_32(key, keylen);
213
 
    int idx = hash % tbl->range;
214
 
 
215
 
    //log_error ("qhastbl:put: key=[%s], keylen=%d hash=%d, idx=%d, d=%x\n", key, keylen, hash, idx, data);
216
 
 
217
 
    // find existence key
218
 
    qhnobj_t *obj;
219
 
    for (obj = tbl->slots[idx]; obj != NULL; obj = obj->next) {
220
 
        if (obj->hash == hash && !strcmp(obj->key, key)) {
221
 
            break;
222
 
        }
223
 
    }
224
 
 
225
 
    // put into table
226
 
    if (obj == NULL) {
227
 
        // insert
228
 
        obj = (qhnobj_t *)malloc(sizeof(qhnobj_t));
229
 
        if (obj == NULL) {
230
 
            free(key);
231
 
            errno = ENOMEM;
232
 
            return false;
233
 
        }
234
 
        memset((void *)obj, 0, sizeof(qhnobj_t));
235
 
 
236
 
        if (tbl->slots[idx] != NULL) {
237
 
            // insert at the beginning
238
 
            obj->next = tbl->slots[idx];
239
 
        }
240
 
        tbl->slots[idx] = obj;
241
 
 
242
 
        // increase counter
243
 
        tbl->num++;
244
 
 
245
 
        // set data
246
 
        obj->hash  = hash;
247
 
        obj->key   = key;
248
 
        obj->value = (void *)data;
249
 
 
250
 
    } else {
251
 
        /* Do not do anything.
252
 
         * Keep the first definition in place, because consider this example
253
 
         * if we would replace the object here:
254
 
         *  def NX
255
 
         *  def A[NX] --> A's dimension is the first variable NX (a pointer to that)
256
 
         *  def NX    --> hashtable stores this variable reference
257
 
         *  def B[NX]
258
 
         *  write NX  --> value is stored in the NX variable found in the hash table
259
 
         *  write A   --> dimension found (valid first pointer) but value is not found
260
 
         *                (stored in the second reference)
261
 
         *  At this point, A's dimension variable is first NX, but the value of
262
 
         *  write NX goes to the variable found here in the hash table.
263
 
         */
264
 
        free(key);
265
 
    }
266
 
 
267
 
    return true;
 
286
    return qhput (tbl, key, keylen, data);
268
287
}
269
288
 
270
289
static bool put2(qhashtbl_t *tbl, const char *path, const char *name, const void *data)
273
292
    char *key;
274
293
    genkey (path, name, &keylen, &key);
275
294
 
276
 
    // get hash integer
277
 
    uint32_t hash = qhashmurmur3_32(key, keylen);
278
 
    int idx = hash % tbl->range;
279
 
 
280
 
    //log_error ("qhastbl:put: key=[%s], keylen=%d hash=%d, idx=%d, d=%x\n", key, keylen, hash, idx, data);
281
 
 
282
 
    // find existence key
283
 
    qhnobj_t *obj;
284
 
    for (obj = tbl->slots[idx]; obj != NULL; obj = obj->next) {
285
 
        if (obj->hash == hash && !strcmp(obj->key, key)) {
286
 
            break;
287
 
        }
288
 
    }
289
 
 
290
 
    // put into table
291
 
    if (obj == NULL) {
292
 
        // insert
293
 
        obj = (qhnobj_t *)malloc(sizeof(qhnobj_t));
294
 
        if (obj == NULL) {
295
 
            free(key);
296
 
            errno = ENOMEM;
297
 
            return false;
298
 
        }
299
 
        memset((void *)obj, 0, sizeof(qhnobj_t));
300
 
 
301
 
        if (tbl->slots[idx] != NULL) {
302
 
            // insert at the beginning
303
 
            obj->next = tbl->slots[idx];
304
 
        }
305
 
        tbl->slots[idx] = obj;
306
 
 
307
 
        // increase counter
308
 
        tbl->num++;
309
 
 
310
 
        // set data
311
 
        obj->hash  = hash;
312
 
        obj->key   = key;
313
 
        obj->value = (void *)data;
314
 
 
315
 
    } else {
316
 
        /* Do not do anything.
317
 
         * Keep the first definition in place, because consider this example
318
 
         * if we would replace the object here:
319
 
         *  def NX
320
 
         *  def A[NX] --> A's dimension is the first variable NX (a pointer to that)
321
 
         *  def NX    --> hashtable stores this variable reference
322
 
         *  def B[NX]
323
 
         *  write NX  --> value is stored in the NX variable found in the hash table
324
 
         *  write A   --> dimension found (valid first pointer) but value is not found
325
 
         *                (stored in the second reference)
326
 
         *  At this point, A's dimension variable is first NX, but the value of
327
 
         *  write NX goes to the variable found here in the hash table.
328
 
         */
329
 
        free(key);
330
 
    }
331
 
 
332
 
    return true;
 
295
    return qhput (tbl, key, keylen, data);
333
296
}
334
297
 
335
298
 
362
325
 * @endcode
363
326
 *
364
327
 */
 
328
static void *qhget(qhashtbl_t *tbl, char *key, int keylen)
 
329
{
 
330
    // get hash integer
 
331
    uint32_t hash = qhashmurmur3_32(key, keylen);
 
332
    int idx = hash % tbl->range;
 
333
    tbl->ncalls_get++; // debug
 
334
 
 
335
    //log_error ("qhastbl:get: key=[%s], keylen=%d, hash=%d, idx=%d\n", fullpath, strlen(fullpath), hash, idx);
 
336
 
 
337
    // find key
 
338
    qhslot_t *slot = &tbl->slots[idx];
 
339
    qhnobj_t *obj;
 
340
    for (obj = slot->head; obj != NULL; obj = obj->next) {
 
341
        if (obj->hash == hash && !strcmp(obj->key, key)) {
 
342
            break;
 
343
        }
 
344
        tbl->nwalks_get++; // debug: we walk one step in a chain of elements 
 
345
    }
 
346
 
 
347
    void *data = NULL;
 
348
    if (obj != NULL) {
 
349
        data = obj->value;
 
350
    }
 
351
 
 
352
    if (data == NULL) errno = ENOENT;
 
353
    //log_error ("qhastbl:get: data=%x\n", data);
 
354
    return data;
 
355
}
 
356
 
365
357
static void *get(qhashtbl_t *tbl, const char *fullpath)
366
358
{
367
 
    // get hash integer
368
 
    uint32_t hash = qhashmurmur3_32(fullpath, strlen(fullpath));
369
 
    int idx = hash % tbl->range;
370
 
 
371
 
    //log_error ("qhastbl:get: key=[%s], keylen=%d, hash=%d, idx=%d\n", fullpath, strlen(fullpath), hash, idx);
372
 
 
373
 
    // find key
374
 
    qhnobj_t *obj;
375
 
    for (obj = tbl->slots[idx]; obj != NULL; obj = obj->next) {
376
 
        if (obj->hash == hash && !strcmp(obj->key, fullpath)) {
377
 
            break;
378
 
        }
379
 
    }
380
 
 
381
 
    void *data = NULL;
382
 
    if (obj != NULL) {
383
 
        data = obj->value;
384
 
    }
385
 
 
386
 
    if (data == NULL) errno = ENOENT;
387
 
    //log_error ("qhastbl:get: data=%x\n", data);
 
359
    if (!fullpath)
 
360
        return NULL;
 
361
 
 
362
    int keylen = strlen(fullpath);
 
363
    char *key = strdup (fullpath);
 
364
 
 
365
    void * data = qhget (tbl, key, keylen);
 
366
    free (key);
388
367
    return data;
389
368
}
390
369
 
391
 
/**
392
 
 * qhashtbl->get2(): Get a object from this table.
393
 
 *
394
 
 * @param tbl       qhashtbl_t container pointer.
395
 
 * @param name      key name.
396
 
 * @param size      if not NULL, oject size will be stored.
397
 
 * @param newmem    whether or not to allocate memory for the data.
398
 
 *
399
 
 * @return a pointer of data if the key is found, otherwise returns NULL.
400
 
 * @retval errno will be set in error condition.
401
 
 *  - ENOENT : No such key found.
402
 
 *  - EINVAL : Invalid argument.
403
 
 *  - ENOMEM : Memory allocation failure.
404
 
 *
405
 
 * @code
406
 
 *  qhashtbl_t *tbl = qHashtbl(1000);
407
 
 *  (...codes...)
408
 
 *
409
 
 *  // with newmem flag unset
410
 
 *  int size;
411
 
 *  struct myobj *obj = (struct myobj*)tbl->get(tbl, "key_name", &size, false);
412
 
 *
413
 
 *  // with newmem flag set
414
 
 *  int size;
415
 
 *  struct myobj *obj = (struct myobj*)tbl->get(tbl, "key_name", &size, true);
416
 
 *  if(obj != NULL) free(obj);
417
 
 * @endcode
418
 
 *
419
 
 */
420
370
static void *get2(qhashtbl_t *tbl, const char *path, const char *name)
421
371
{
422
372
    int keylen;
423
373
    char *key;
424
374
    genkey (path, name, &keylen, &key);
425
375
 
426
 
    // get hash integer
427
 
    uint32_t hash = qhashmurmur3_32(key, keylen);
428
 
    int idx = hash % tbl->range;
429
 
 
430
 
    //log_error ("qhastbl:get: key=[%s], keylen=%d, hash=%d, idx=%d\n", key, keylen, hash, idx);
431
 
 
432
 
    // find key
433
 
    qhnobj_t *obj;
434
 
    for (obj = tbl->slots[idx]; obj != NULL; obj = obj->next) {
435
 
        if (obj->hash == hash && !strcmp(obj->key, key)) {
436
 
            break;
437
 
        }
438
 
    }
439
 
 
440
 
    void *data = NULL;
441
 
    if (obj != NULL) {
442
 
        data = obj->value;
443
 
    }
444
 
 
445
 
    if (data == NULL) errno = ENOENT;
446
 
    //log_error ("qhastbl:get: data=%x\n", data);
 
376
    void * data = qhget (tbl, key, keylen);
 
377
    free (key);
447
378
    return data;
448
379
}
449
380
 
462
393
static bool remove_(qhashtbl_t *tbl, const char *fullpath)
463
394
{
464
395
    int keylen = strlen (fullpath);
465
 
    char *key = fullpath;
 
396
    const char *key = fullpath;
466
397
 
467
398
    // get hash integer
468
399
    uint32_t hash = qhashmurmur3_32(key, keylen);
472
403
 
473
404
    // find key
474
405
    bool found = false;
 
406
    qhslot_t *slot = &tbl->slots[idx];
475
407
    qhnobj_t *prev = NULL;
476
408
    qhnobj_t *obj;
477
 
    for (obj = tbl->slots[idx]; obj != NULL; obj = obj->next) {
 
409
    for (obj = slot->head; obj != NULL; obj = obj->next) {
478
410
        if (obj->hash == hash && !strcmp(obj->key, key)) {
479
 
            // adjust link
480
 
            if (prev == NULL) tbl->slots[idx] = obj->next;
481
 
            else prev->next = obj->next;
 
411
            // adjust links
 
412
            if (prev == NULL) {
 
413
                // remove as very first
 
414
                slot->head = obj->next;
 
415
            } else {
 
416
                // remove otherwise
 
417
                prev->next = obj->next;
 
418
            }
 
419
 
 
420
            if (obj == slot->tail) {
 
421
                // this was last element: update tail
 
422
                slot->tail = prev;
 
423
            }
482
424
 
483
425
            // remove
484
426
            free(obj->key);
516
458
 */
517
459
void clear(qhashtbl_t *tbl)
518
460
{
 
461
    if (!tbl) return;
 
462
    //debug(tbl, stdout, 0);
519
463
    int idx;
 
464
    qhnobj_t *obj;
520
465
    for (idx = 0; idx < tbl->range && tbl->num > 0; idx++) {
521
 
        if (tbl->slots[idx] == NULL) continue;
522
 
        qhnobj_t *obj = tbl->slots[idx];
523
 
        tbl->slots[idx] = NULL;
 
466
        obj = tbl->slots[idx].head;
524
467
        while (obj != NULL) {
525
468
            qhnobj_t *next = obj->next;
526
469
            free(obj->key);
528
471
            obj = next;
529
472
            tbl->num--;
530
473
        }
 
474
        tbl->slots[idx].head = NULL;
 
475
        tbl->slots[idx].tail = NULL;
531
476
    }
532
477
}
533
478
 
545
490
    }
546
491
    int len, lenmin=1000000, lenmax=0;
547
492
 
548
 
    qhnobj_t obj;
 
493
    qhnobj_t *obj;
549
494
    int idx;
550
495
    for (idx = 0; idx < tbl->range && tbl->num > 0; idx++) {
551
496
        len = 0;
552
497
        if (detailed) fprintf(out, "[%d]:", idx);
553
 
        qhnobj_t *obj = tbl->slots[idx];
 
498
        obj = tbl->slots[idx].head;
554
499
        while (obj != NULL) {
555
500
            qhnobj_t *next = obj->next;
556
501
            if (detailed) fprintf(out, "(%s,%p)" , obj->key, obj->value);
561
506
        if (len < lenmin) lenmin = len;
562
507
        if (len > lenmax) lenmax = len;
563
508
    }
 
509
    fprintf(out, "Hash table %p\n", tbl);
564
510
    fprintf(out, "Hash table size = %d\n", tbl->range);
565
511
    fprintf(out, "Number of elements = %d\n", tbl->num);
566
512
    fprintf(out, "Shortest collision list size = %d\n", lenmin);
567
513
    fprintf(out, "Longest  collision list size = %d\n", lenmax);
 
514
    fprintf(out, "get() calls = %d, walks = %d\n", tbl->ncalls_get, tbl->nwalks_get);
 
515
    fprintf(out, "put() calls = %d, walks = %d\n", tbl->ncalls_put, tbl->nwalks_put);
568
516
    fflush(out);
569
517
}
570
518
 
576
524
 */
577
525
void free_(qhashtbl_t *tbl)
578
526
{
 
527
    if (!tbl) return;
579
528
    clear(tbl);
580
529
    if (tbl->slots != NULL) free(tbl->slots);
581
530
    free(tbl);
613
562
 
614
563
    const int nblocks = nbytes / 4;
615
564
    const uint32_t *blocks = (const uint32_t *)(data);
616
 
    const uint8_t *tail = (const uint8_t *)(data + (nblocks * 4));
 
565
    const uint8_t *tail = (const uint8_t *)data + (nblocks * 4);
617
566
 
618
567
    uint32_t h = 0;
619
568