diff options
author | Volker Lendecke <vlendec@samba.org> | 2007-02-19 11:19:53 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 12:18:04 -0500 |
commit | 39c1ebff22aaacbe2745e7b6ad832e9ed302fe81 (patch) | |
tree | 010f391cb7fd5deb6d981d7bff9fb6e9028c4197 /source3/tdb/common/tdb.c | |
parent | c909c6722b065e898da43b0e1448fc4314649553 (diff) | |
download | samba-39c1ebff22aaacbe2745e7b6ad832e9ed302fe81.tar.gz samba-39c1ebff22aaacbe2745e7b6ad832e9ed302fe81.tar.bz2 samba-39c1ebff22aaacbe2745e7b6ad832e9ed302fe81.zip |
r21444: Check in tdb_parse_record. Not merging to the other branches yet, we need to
agree on the behaviour of non-existing records.
Tridge, can you comment? Should we change tdb_fetch, or should we have
different concepts in tdb_fetch() and tdb_parse_record() ?
Volker
(This used to be commit fba79e75c0138c3ae4e73014a1d1a2c2045c35bb)
Diffstat (limited to 'source3/tdb/common/tdb.c')
-rw-r--r-- | source3/tdb/common/tdb.c | 71 |
1 files changed, 58 insertions, 13 deletions
diff --git a/source3/tdb/common/tdb.c b/source3/tdb/common/tdb.c index 248acb7374..008b168734 100644 --- a/source3/tdb/common/tdb.c +++ b/source3/tdb/common/tdb.c @@ -56,6 +56,10 @@ static void tdb_increment_seqnum(struct tdb_context *tdb) tdb_brlock(tdb, TDB_SEQNUM_OFS, F_UNLCK, F_SETLKW, 1, 1); } +static int tdb_key_compare(TDB_DATA key, TDB_DATA data, void *private_data) +{ + return memcmp(data.dptr, key.dptr, data.dsize); +} /* Returns 0 on fail. On success, return offset of record, and fills in rec */ @@ -73,19 +77,12 @@ static tdb_off_t tdb_find(struct tdb_context *tdb, TDB_DATA key, u32 hash, if (tdb_rec_read(tdb, rec_ptr, r) == -1) return 0; - if (!TDB_DEAD(r) && hash==r->full_hash && key.dsize==r->key_len) { - char *k; - /* a very likely hit - read the key */ - k = tdb_alloc_read(tdb, rec_ptr + sizeof(*r), - r->key_len); - if (!k) - return 0; - - if (memcmp(key.dptr, k, key.dsize) == 0) { - SAFE_FREE(k); - return rec_ptr; - } - SAFE_FREE(k); + if (!TDB_DEAD(r) && hash==r->full_hash + && key.dsize==r->key_len + && tdb_parse_data(tdb, key, rec_ptr + sizeof(*r), + r->key_len, tdb_key_compare, + NULL) == 0) { + return rec_ptr; } rec_ptr = r->next; } @@ -163,6 +160,54 @@ TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key) return ret; } +/* + * Find an entry in the database and hand the record's data to a parsing + * function. The parsing function is executed under the chain read lock, so it + * should be fast and should not block on other syscalls. + * + * DONT CALL OTHER TDB CALLS FROM THE PARSER, THIS MIGHT LEAD TO SEGFAULTS. + * + * For mmapped tdb's that do not have a transaction open it points the parsing + * function directly at the mmap area, it avoids the malloc/memcpy in this + * case. If a transaction is open or no mmap is available, it has to do + * malloc/read/parse/free. + * + * This is interesting for all readers of potentially large data structures in + * the tdb records, ldb indexes being one example. + */ + +int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key, + int (*parser)(TDB_DATA key, TDB_DATA data, + void *private_data), + void *private_data) +{ + tdb_off_t rec_ptr; + struct list_struct rec; + TDB_DATA data; + int ret; + u32 hash; + + /* find which hash bucket it is in */ + hash = tdb->hash_fn(&key); + + rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec); + + if (rec_ptr == 0) { + data.dptr = NULL; + data.dsize = 0; + return parser(key, data, private_data); + } + + ret = tdb_parse_data(tdb, key, rec_ptr + sizeof(rec) + rec.key_len, + rec.data_len, parser, private_data); + + tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); + + return ret; + +} + + /* check if an entry in the database exists note that 1 is returned if the key is found and 0 is returned if not found |