QObject *qdict_get(const QDict *qdict, const char *key) { QDictEntry *entry; entry = qdict_find(qdict, key, tdb_hash(key) % QDICT_HASH_SIZE); return (entry == NULL ? NULL : entry->value); }
enum TDB_ERROR tdb1_parse_record(struct tdb_context *tdb, TDB_DATA key, enum TDB_ERROR (*parser)(TDB_DATA key, TDB_DATA data, void *private_data), void *private_data) { tdb1_off_t rec_ptr; struct tdb1_record rec; enum TDB_ERROR ret; uint32_t hash; /* find which hash bucket it is in */ hash = tdb_hash(tdb, key.dptr, key.dsize); if (!(rec_ptr = tdb1_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) { return tdb->last_error; } ret = tdb1_parse_data(tdb, key, rec_ptr + sizeof(rec) + rec.key_len, rec.data_len, parser, private_data); tdb1_unlock(tdb, TDB1_BUCKET(rec.full_hash), F_RDLCK); return ret; }
int tdb1_delete(struct tdb_context *tdb, TDB_DATA key) { uint32_t hash = tdb_hash(tdb, key.dptr, key.dsize); int ret; assert(tdb->flags & TDB_VERSION1); ret = tdb1_delete_hash(tdb, key, hash); return ret; }
void qdict_del(QDict *qdict, const char *key) { QDictEntry *entry; entry = qdict_find(qdict, key, tdb_hash(key) % QDICT_HASH_SIZE); if (entry) { QLIST_REMOVE(entry, next); qentry_destroy(entry); qdict->size--; } }
/** * qdict_next(): Return next qdict entry in an iteration. */ const QDictEntry *qdict_next(const QDict *qdict, const QDictEntry *entry) { QDictEntry *ret; ret = QLIST_NEXT(entry, next); if (!ret) { unsigned int bucket = tdb_hash(entry->key) % QDICT_BUCKET_MAX; ret = qdict_next_entry(qdict, bucket + 1); } return ret; }
/* Append to an entry. Create if not exist. */ int tdb1_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf) { uint32_t hash; TDB_DATA dbuf; int ret = -1; assert(tdb->flags & TDB_VERSION1); /* find which hash bucket it is in */ hash = tdb_hash(tdb, key.dptr, key.dsize); if (tdb1_lock(tdb, TDB1_BUCKET(hash), F_WRLCK) == -1) return -1; dbuf = _tdb1_fetch(tdb, key); if (dbuf.dptr == NULL) { dbuf.dptr = (unsigned char *)malloc(new_dbuf.dsize); } else { unsigned int new_len = dbuf.dsize + new_dbuf.dsize; unsigned char *new_dptr; /* realloc '0' is special: don't do that. */ if (new_len == 0) new_len = 1; new_dptr = (unsigned char *)realloc(dbuf.dptr, new_len); if (new_dptr == NULL) { free(dbuf.dptr); } dbuf.dptr = new_dptr; } if (dbuf.dptr == NULL) { tdb->last_error = TDB_ERR_OOM; goto failed; } memcpy(dbuf.dptr + dbuf.dsize, new_dbuf.dptr, new_dbuf.dsize); dbuf.dsize += new_dbuf.dsize; ret = _tdb1_store(tdb, key, dbuf, 0, hash); failed: tdb1_unlock(tdb, TDB1_BUCKET(hash), F_WRLCK); SAFE_FREE(dbuf.dptr); return ret; }
void qdict_put_obj(QDict *qdict, const char *key, QObject *value) { unsigned int hash; QDictEntry *entry; hash = tdb_hash(key) % QDICT_HASH_SIZE; entry = qdict_find(qdict, key, hash); if (entry) { /* replace key's value */ qobject_decref(entry->value); entry->value = value; } else { /* allocate a new entry */ entry = alloc_entry(key, value); QLIST_INSERT_HEAD(&qdict->table[hash], entry, next); qdict->size++; } }
/* If an entry doesn't exist tdb1_err will be set to * TDB_ERR_NOEXIST. If a key has no data attached * then the TDB_DATA will have zero length but * a non-zero pointer */ static TDB_DATA _tdb1_fetch(struct tdb_context *tdb, TDB_DATA key) { tdb1_off_t rec_ptr; struct tdb1_record rec; TDB_DATA ret; uint32_t hash; /* find which hash bucket it is in */ hash = tdb_hash(tdb, key.dptr, key.dsize); if (!(rec_ptr = tdb1_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) { ret.dptr = NULL; ret.dsize = 0; return ret; } ret.dptr = tdb1_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len, rec.data_len); ret.dsize = rec.data_len; tdb1_unlock(tdb, TDB1_BUCKET(rec.full_hash), F_RDLCK); return ret; }
/* store an element in the database, replacing any existing element with the same key return 0 on success, -1 on failure */ int tdb1_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) { uint32_t hash; int ret; assert(tdb->flags & TDB_VERSION1); if ((tdb->flags & TDB_RDONLY) || tdb->tdb1.traverse_read) { tdb->last_error = tdb_logerr(tdb, TDB_ERR_RDONLY, TDB_LOG_USE_ERROR, "tdb_store: read-only tdb"); return -1; } /* find which hash bucket it is in */ hash = tdb_hash(tdb, key.dptr, key.dsize); if (tdb1_lock(tdb, TDB1_BUCKET(hash), F_WRLCK) == -1) return -1; ret = _tdb1_store(tdb, key, dbuf, flag, hash); tdb1_unlock(tdb, TDB1_BUCKET(hash), F_WRLCK); return ret; }
uint64_t hash_record(struct tdb_context *tdb, tdb_off_t off) { const struct tdb_used_record *r; const void *key; uint64_t klen, hash; r = tdb_access_read(tdb, off, sizeof(*r), true); if (TDB_PTR_IS_ERR(r)) { /* FIXME */ return 0; } klen = rec_key_length(r); tdb_access_release(tdb, r); key = tdb_access_read(tdb, off + sizeof(*r), klen, false); if (TDB_PTR_IS_ERR(key)) { return 0; } hash = tdb_hash(tdb, key, klen); tdb_access_release(tdb, key); return hash; }
/* This is the core routine which searches the hashtable for an entry. * On error, no locks are held and -ve is returned. * Otherwise, hinfo is filled in (and the optional tinfo). * If not found, the return value is 0. * If found, the return value is the offset, and *rec is the record. */ tdb_off_t find_and_lock(struct tdb_context *tdb, struct tdb_data key, int ltype, struct hash_info *h, struct tdb_used_record *rec, struct traverse_info *tinfo) { uint32_t i, group; tdb_off_t hashtable; enum TDB_ERROR ecode; h->h = tdb_hash(tdb, key.dptr, key.dsize); h->hash_used = 0; group = use_bits(h, TDB_TOPLEVEL_HASH_BITS - TDB_HASH_GROUP_BITS); h->home_bucket = use_bits(h, TDB_HASH_GROUP_BITS); h->hlock_start = hlock_range(group, &h->hlock_range); ecode = tdb_lock_hashes(tdb, h->hlock_start, h->hlock_range, ltype, TDB_LOCK_WAIT); if (ecode != TDB_SUCCESS) { return ecode; } hashtable = offsetof(struct tdb_header, hashtable); if (tinfo) { tinfo->toplevel_group = group; tinfo->num_levels = 1; tinfo->levels[0].entry = 0; tinfo->levels[0].hashtable = hashtable + (group << TDB_HASH_GROUP_BITS) * sizeof(tdb_off_t); tinfo->levels[0].total_buckets = 1 << TDB_HASH_GROUP_BITS; } while (h->hash_used <= 64) { /* Read in the hash group. */ h->group_start = hashtable + group * (sizeof(tdb_off_t) << TDB_HASH_GROUP_BITS); ecode = tdb_read_convert(tdb, h->group_start, &h->group, sizeof(h->group)); if (ecode != TDB_SUCCESS) { goto fail; } /* Pointer to another hash table? Go down... */ if (is_subhash(h->group[h->home_bucket])) { hashtable = (h->group[h->home_bucket] & TDB_OFF_MASK) + sizeof(struct tdb_used_record); if (tinfo) { /* When we come back, use *next* bucket */ tinfo->levels[tinfo->num_levels-1].entry += h->home_bucket + 1; } group = use_bits(h, TDB_SUBLEVEL_HASH_BITS - TDB_HASH_GROUP_BITS); h->home_bucket = use_bits(h, TDB_HASH_GROUP_BITS); if (tinfo) { tinfo->levels[tinfo->num_levels].hashtable = hashtable; tinfo->levels[tinfo->num_levels].total_buckets = 1 << TDB_SUBLEVEL_HASH_BITS; tinfo->levels[tinfo->num_levels].entry = group << TDB_HASH_GROUP_BITS; tinfo->num_levels++; } continue; } /* It's in this group: search (until 0 or all searched) */ for (i = 0, h->found_bucket = h->home_bucket; i < (1 << TDB_HASH_GROUP_BITS); i++, h->found_bucket = ((h->found_bucket+1) % (1 << TDB_HASH_GROUP_BITS))) { tdb_bool_err berr; if (is_subhash(h->group[h->found_bucket])) continue; if (!h->group[h->found_bucket]) break; berr = match(tdb, h, &key, h->group[h->found_bucket], rec); if (berr < 0) { ecode = berr; goto fail; } if (berr) { if (tinfo) { tinfo->levels[tinfo->num_levels-1].entry += h->found_bucket; } return h->group[h->found_bucket] & TDB_OFF_MASK; } } /* Didn't find it: h indicates where it would go. */ return 0; } return find_in_chain(tdb, key, hashtable, h, rec, tinfo); fail: tdb_unlock_hashes(tdb, h->hlock_start, h->hlock_range, ltype); return ecode; }
int qdict_haskey(const QDict *qdict, const char *key) { unsigned int hash = tdb_hash(key) % QDICT_HASH_SIZE; return (qdict_find(qdict, key, hash) == NULL ? 0 : 1); }
memset(s, 0, sizeof(*s)); strcpy(s->name, name); s->weak = weak; s->next = next; return s; } /* For the hash of exported symbols */ static struct symbol *new_symbol(const char *name, struct module *module, enum export export) { unsigned int hash; struct symbol *new; hash = tdb_hash(name) % SYMBOL_HASH_SIZE; new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]); new->module = module; new->export = export; return new; } static struct symbol *find_symbol(const char *name) { struct symbol *s; /* For our purposes, .foo matches foo. PPC64 needs this. */ if (name[0] == '.') name++; for (s = symbolhash[tdb_hash(name) % SYMBOL_HASH_SIZE]; s; s=s->next) {
/** * qdict_haskey(): Check if 'key' exists * * Return 1 if 'key' exists in the dict, 0 otherwise */ int qdict_haskey(const QDict *qdict, const char *key) { unsigned int bucket = tdb_hash(key) % QDICT_BUCKET_MAX; return (qdict_find(qdict, key, bucket) == NULL ? 0 : 1); }