/* traverse the entire database - calling fn(tdb, key, data) on each element. return -1 on error or the record count traversed if fn is NULL then it is not called a non-zero return value from fn() indicates that the traversal should stop */ static int tdb_traverse_internal(struct tdb_context *tdb, tdb_traverse_func fn, void *private_data, struct tdb_traverse_lock *tl) { TDB_DATA key, dbuf; struct tdb_record rec; int ret = 0, count = 0; tdb_off_t off; size_t recbuf_len; recbuf_len = 4096; key.dptr = malloc(recbuf_len); if (key.dptr == NULL) { return -1; } /* This was in the initialization, above, but the IRIX compiler * did not like it. crh */ tl->next = tdb->travlocks.next; /* fcntl locks don't stack: beware traverse inside traverse */ tdb->travlocks.next = tl; /* tdb_next_lock places locks on the record returned, and its chain */ while ((off = tdb_next_lock(tdb, tl, &rec)) != 0) { tdb_len_t full_len; int nread; if (off == TDB_NEXT_LOCK_ERR) { ret = -1; goto out; } full_len = rec.key_len + rec.data_len; if (full_len > recbuf_len) { recbuf_len = full_len; /* * No realloc, we don't need the old data and thus can * do without the memcpy */ free(key.dptr); key.dptr = malloc(recbuf_len); if (key.dptr == NULL) { ret = -1; if (tdb_unlock(tdb, tl->list, tl->lock_rw) != 0) { goto out; } if (tdb_unlock_record(tdb, tl->off) != 0) { TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_traverse: malloc " "failed and unlock_record " "failed!\n")); } goto out; } } count++; /* now read the full record */ nread = tdb->methods->tdb_read(tdb, tl->off + sizeof(rec), key.dptr, full_len, 0); if (nread == -1) { ret = -1; if (tdb_unlock(tdb, tl->list, tl->lock_rw) != 0) goto out; if (tdb_unlock_record(tdb, tl->off) != 0) TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_traverse: key.dptr == NULL and unlock_record failed!\n")); goto out; } key.dsize = rec.key_len; dbuf.dptr = key.dptr + rec.key_len; dbuf.dsize = rec.data_len; tdb_trace_1rec_retrec(tdb, "traverse", key, dbuf); /* Drop chain lock, call out */ if (tdb_unlock(tdb, tl->list, tl->lock_rw) != 0) { ret = -1; goto out; } if (fn && fn(tdb, key, dbuf, private_data)) { /* They want us to terminate traversal */ tdb_trace_ret(tdb, "tdb_traverse_end", count); if (tdb_unlock_record(tdb, tl->off) != 0) { TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_traverse: unlock_record failed!\n"));; ret = -1; } goto out; } } tdb_trace(tdb, "tdb_traverse_end"); out: SAFE_FREE(key.dptr); tdb->travlocks.next = tl->next; if (ret < 0) return -1; else return count; }
/* lock entire database with read lock - nonblock varient */ int tdb_lockall_read_nonblock(struct tdb_context *tdb) { int ret = _tdb_lockall(tdb, F_RDLCK, F_SETLK); tdb_trace_ret(tdb, "tdb_lockall_read_nonblock", ret); return ret; }
/* lock entire database with read lock - nonblock varient */ _PUBLIC_ int tdb_lockall_read_nonblock(struct tdb_context *tdb) { int ret = tdb_allrecord_lock(tdb, F_RDLCK, TDB_LOCK_NOWAIT, false); tdb_trace_ret(tdb, "tdb_lockall_read_nonblock", ret); return ret; }
/* traverse the entire database - calling fn(tdb, key, data) on each element. return -1 on error or the record count traversed if fn is NULL then it is not called a non-zero return value from fn() indicates that the traversal should stop */ static int tdb_traverse_internal(struct tdb_context *tdb, tdb_traverse_func fn, void *private_data, struct tdb_traverse_lock *tl) { TDB_DATA key, dbuf; struct tdb_record rec; int ret = 0, count = 0; tdb_off_t off; /* This was in the initialization, above, but the IRIX compiler * did not like it. crh */ tl->next = tdb->travlocks.next; /* fcntl locks don't stack: beware traverse inside traverse */ tdb->travlocks.next = tl; /* tdb_next_lock places locks on the record returned, and its chain */ while ((off = tdb_next_lock(tdb, tl, &rec)) != 0) { if (off == TDB_NEXT_LOCK_ERR) { ret = -1; goto out; } count++; /* now read the full record */ key.dptr = tdb_alloc_read(tdb, tl->off + sizeof(rec), rec.key_len + rec.data_len); if (!key.dptr) { ret = -1; if (tdb_unlock(tdb, tl->hash, tl->lock_rw) != 0) goto out; if (tdb_unlock_record(tdb, tl->off) != 0) TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_traverse: key.dptr == NULL and unlock_record failed!\n")); goto out; } key.dsize = rec.key_len; dbuf.dptr = key.dptr + rec.key_len; dbuf.dsize = rec.data_len; tdb_trace_1rec_retrec(tdb, "traverse", key, dbuf); /* Drop chain lock, call out */ if (tdb_unlock(tdb, tl->hash, tl->lock_rw) != 0) { ret = -1; SAFE_FREE(key.dptr); goto out; } if (fn && fn(tdb, key, dbuf, private_data)) { /* They want us to terminate traversal */ tdb_trace_ret(tdb, "tdb_traverse_end", count); if (tdb_unlock_record(tdb, tl->off) != 0) { TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_traverse: unlock_record failed!\n"));; ret = -1; } SAFE_FREE(key.dptr); goto out; } SAFE_FREE(key.dptr); } tdb_trace(tdb, "tdb_traverse_end"); out: tdb->travlocks.next = tl->next; if (ret < 0) return -1; else return count; }