bool hashtable_remove(hashtable_t *table, void *key) { bool res = false; hash_entry_t *e, *prev_e; uint hindex = hash_key(table, key); if (table->synch) dr_mutex_lock(table->lock); for (e = table->table[hindex], prev_e = NULL; e != NULL; prev_e = e, e = e->next) { if (keys_equal(table, e->key, key)) { if (prev_e == NULL) table->table[hindex] = e->next; else prev_e->next = e->next; if (table->str_dup) hash_free(e->key, strlen((const char *)e->key) + 1); if (table->free_payload_func != NULL) (table->free_payload_func)(e->payload); hash_free(e, sizeof(*e)); res = true; table->entries--; break; } } if (table->synch) dr_mutex_unlock(table->lock); return res; }
bool hashtable_add(hashtable_t *table, void *key, void *payload) { uint hindex = hash_key(table, key); hash_entry_t *e; /* if payload is null can't tell from lookup miss */ ASSERT(payload != NULL, "hashtable_add internal error"); if (table->synch) dr_mutex_lock(table->lock); for (e = table->table[hindex]; e != NULL; e = e->next) { if (keys_equal(table, e->key, key)) { /* we have a use where payload != existing entry so we don't assert on that */ if (table->synch) dr_mutex_unlock(table->lock); return false; } } e = (hash_entry_t *) hash_alloc(sizeof(*e)); if (table->str_dup) { const char *s = (const char *) key; e->key = hash_alloc(strlen(s)+1); strncpy((char *)e->key, s, strlen(s)+1); } else e->key = key; e->payload = payload; e->next = table->table[hindex]; table->table[hindex] = e; table->entries++; hashtable_check_for_resize(table); if (table->synch) dr_mutex_unlock(table->lock); return true; }
static rc_t loop_until_key_found( struct lookup_reader * reader, uint64_t key_to_find, uint64_t *key_found , uint64_t *offset ) { rc_t rc = 0; bool done = false; uint64_t curr = *offset; while ( !done && rc == 0 ) { size_t found_len; rc = read_key_and_len( reader, curr, key_found, &found_len ); if ( keys_equal( key_to_find, *key_found ) ) { done = true; *offset = curr; } else if ( key_to_find > *key_found ) curr += found_len; else { done = true; rc = SILENT_RC( rcVDB, rcNoTarg, rcReading, rcId, rcNotFound ); } } return rc; }
static rc_t indexed_seek( struct lookup_reader * reader, uint64_t key_to_find, uint64_t * key_found, bool exactly ) { /* we have a index! find set pos to the found offset */ uint64_t offset = 0; uint64_t max_key; rc_t rc = get_max_key( reader->index, &max_key ); if ( rc == 0 ) { if ( key_to_find > max_key ) rc = RC( rcVDB, rcNoTarg, rcReading, rcId, rcTooBig ); else { rc = get_nearest_offset( reader->index, key_to_find, key_found, &offset ); /* in index.c */ if ( rc == 0 ) { if ( keys_equal( key_to_find, *key_found ) ) reader->pos = offset; else { if ( exactly ) { rc = loop_until_key_found( reader, key_to_find, key_found, &offset ); if ( rc == 0 ) { if ( keys_equal( key_to_find, *key_found ) ) reader->pos = offset; else rc = RC( rcVDB, rcNoTarg, rcReading, rcId, rcNotFound ); } else rc = RC( rcVDB, rcNoTarg, rcReading, rcId, rcNotFound ); } else { reader->pos = offset; rc = RC( rcVDB, rcNoTarg, rcReading, rcId, rcNotFound ); } } } } } return rc; }
static struct dm_bio_prison_cell *__search_bucket(struct hlist_head *bucket, struct dm_cell_key *key) { struct dm_bio_prison_cell *cell; hlist_for_each_entry(cell, bucket, list) if (keys_equal(&cell->key, key)) return cell; return NULL; }
static rc_t full_table_seek( struct lookup_reader * reader, uint64_t key_to_find, uint64_t * key_found ) { /* we have no index! search the whole thing... */ uint64_t offset = 0; rc_t rc = loop_until_key_found( reader, key_to_find, key_found, &offset ); if ( rc == 0 ) { if ( keys_equal( key_to_find, *key_found ) ) reader->pos = offset; else { rc = RC( rcVDB, rcNoTarg, rcReading, rcId, rcNotFound ); ErrMsg( "seek_lookup_reader( key: %ld ) -> %R", key_to_find, rc ); } } return rc; }
/* Lookup an entry by key and return a pointer to the corresponding entry * Returns NULL if no such entry exists */ void * hashtable_lookup(hashtable_t *table, void *key) { void *res = NULL; hash_entry_t *e; uint hindex = hash_key(table, key); if (table->synch) dr_mutex_lock(table->lock); for (e = table->table[hindex]; e != NULL; e = e->next) { if (keys_equal(table, e->key, key)) { res = e->payload; break; } } if (table->synch) dr_mutex_unlock(table->lock); return res; }
void * hashtable_add_replace(hashtable_t *table, void *key, void *payload) { void *old_payload = NULL; uint hindex = hash_key(table, key); hash_entry_t *e, *new_e, *prev_e; /* if payload is null can't tell from lookup miss */ ASSERT(payload != NULL, "hashtable_add_replace internal error"); new_e = (hash_entry_t *) hash_alloc(sizeof(*new_e)); if (table->str_dup) { const char *s = (const char *) key; new_e->key = hash_alloc(strlen(s)+1); strncpy((char *)new_e->key, s, strlen(s)+1); } else new_e->key = key; new_e->payload = payload; if (table->synch) dr_mutex_lock(table->lock); for (e = table->table[hindex], prev_e = NULL; e != NULL; prev_e = e, e = e->next) { if (keys_equal(table, e->key, key)) { if (prev_e == NULL) table->table[hindex] = new_e; else prev_e->next = new_e; new_e->next = e->next; if (table->str_dup) hash_free(e->key, strlen((const char *)e->key) + 1); /* up to caller to free payload */ old_payload = e->payload; hash_free(e, sizeof(*e)); break; } } if (old_payload == NULL) { new_e->next = table->table[hindex]; table->table[hindex] = new_e; table->entries++; hashtable_check_for_resize(table); } if (table->synch) dr_mutex_unlock(table->lock); return old_payload; }