Lines Matching refs:tdb

2 URL: svn://svnanon.samba.org/samba/branches/SAMBA_4_0/source/lib/tdb/common
13 ** NOTE! The following LGPL license applies to the tdb
108 #include "tdb.h"
138 #define TDB_HASHTABLE_SIZE(tdb) ((tdb->header.hash_size+1)*sizeof(tdb_off_t))
145 /* NB assumes there is a local variable called "tdb" that is the
148 #define TDB_LOG(x) tdb->log.log_fn x
160 #define BUCKET(hash) ((hash) % tdb->header.hash_size)
162 #define DOCONV() (tdb->flags & TDB_CONVERT)
232 enum TDB_ERROR ecode; /* error code for last tdb error */
237 dev_t device; /* uniquely identifies this tdb */
238 ino_t inode; /* uniquely identifies this tdb */
254 static int tdb_munmap(struct tdb_context *tdb);
255 static void tdb_mmap(struct tdb_context *tdb);
256 static int tdb_lock(struct tdb_context *tdb, int list, int ltype);
257 static int tdb_unlock(struct tdb_context *tdb, int list, int ltype);
258 static int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, int rw_type, int lck_type, int probe, size_t len);
259 static int tdb_transaction_lock(struct tdb_context *tdb, int ltype);
260 static int tdb_transaction_unlock(struct tdb_context *tdb);
261 static int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len);
262 static int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off);
263 static int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off);
264 static int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
265 static int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
267 static int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec);
268 static tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_struct *rec);
269 static int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
270 static int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
271 static int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off);
272 static int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off);
273 static int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec);
274 static int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec);
275 static int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct list_struct *rec);
276 static unsigned char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len);
277 static int tdb_parse_data(struct tdb_context *tdb, TDB_DATA key,
282 static tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, int locktype,
284 static void tdb_io_init(struct tdb_context *tdb);
285 static int tdb_expand(struct tdb_context *tdb, tdb_off_t size);
286 static int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off,
292 enum TDB_ERROR tdb_error(struct tdb_context *tdb)
294 return tdb->ecode;
310 /* Error string for the last tdb error */
311 const char *tdb_errorstr(struct tdb_context *tdb)
315 if (tdb->ecode == emap[i].ecode)
332 int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset,
338 if (tdb->flags & TDB_NOLOCK) {
342 if ((rw_type == F_WRLCK) && (tdb->read_only || tdb->traverse_read)) {
343 tdb->ecode = TDB_ERR_RDONLY;
354 ret = fcntl(tdb->fd,lck_type,&fl);
363 tdb->ecode = TDB_ERR_LOCK;
364 TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d len=%d\n",
365 tdb->fd, offset, rw_type, lck_type, (int)len));
379 int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len)
384 if (tdb_brlock(tdb, offset, F_WRLCK, F_SETLKW, 1, len) == 0) {
395 TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock_upgrade failed at offset %d\n", offset));
401 static int _tdb_lock(struct tdb_context *tdb, int list, int ltype, int op)
410 if (tdb->global_lock.count &&
411 (ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) {
415 if (tdb->global_lock.count) {
419 if (list < -1 || list >= (int)tdb->header.hash_size) {
420 TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_lock: invalid list %d for ltype=%d\n",
424 if (tdb->flags & TDB_NOLOCK)
427 for (i=0; i<tdb->num_lockrecs; i++) {
428 if (tdb->lockrecs[i].list == list) {
429 if (tdb->lockrecs[i].count == 0) {
434 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lock: "
441 tdb->lockrecs[i].count++;
447 tdb->lockrecs,
448 sizeof(*tdb->lockrecs) * (tdb->num_lockrecs+1));
453 tdb->lockrecs = new_lck;
458 tdb->methods->tdb_brlock(tdb,FREELIST_TOP+4*list, ltype, op,
463 tdb->num_locks++;
465 tdb->lockrecs[tdb->num_lockrecs].list = list;
466 tdb->lockrecs[tdb->num_lockrecs].count = 1;
467 tdb->lockrecs[tdb->num_lockrecs].ltype = ltype;
468 tdb->num_lockrecs += 1;
474 int tdb_lock(struct tdb_context *tdb, int list, int ltype)
477 ret = _tdb_lock(tdb, list, ltype, F_SETLKW);
479 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lock failed on list %d "
486 int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype)
488 return _tdb_lock(tdb, list, ltype, F_SETLK);
495 int tdb_unlock(struct tdb_context *tdb, int list, int ltype)
505 if (tdb->global_lock.count &&
506 (ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) {
510 if (tdb->global_lock.count) {
514 if (tdb->flags & TDB_NOLOCK)
518 if (list < -1 || list >= (int)tdb->header.hash_size) {
519 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: list %d invalid (%d)\n", list, tdb->header.hash_size));
523 for (i=0; i<tdb->num_lockrecs; i++) {
524 if (tdb->lockrecs[i].list == list) {
525 lck = &tdb->lockrecs[i];
531 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: count is 0\n"));
550 ret = tdb->methods->tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK,
553 tdb->num_locks--;
560 if (tdb->num_lockrecs > 1) {
561 *lck = tdb->lockrecs[tdb->num_lockrecs-1];
563 tdb->num_lockrecs -= 1;
567 * a completely idle tdb we should get rid of the locked array.
570 if (tdb->num_lockrecs == 0) {
571 SAFE_FREE(tdb->lockrecs);
575 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: An error occurred unlocking!\n"));
582 int tdb_transaction_lock(struct tdb_context *tdb, int ltype)
584 if (tdb->have_transaction_lock || tdb->global_lock.count) {
587 if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, ltype,
589 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_lock: failed to get transaction lock\n"));
590 tdb->ecode = TDB_ERR_LOCK;
593 tdb->have_transaction_lock = 1;
600 int tdb_transaction_unlock(struct tdb_context *tdb)
603 if (!tdb->have_transaction_lock) {
606 ret = tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1);
608 tdb->have_transaction_lock = 0;
617 static int _tdb_lockall(struct tdb_context *tdb, int ltype, int op)
624 if (tdb->read_only || tdb->traverse_read)
627 if (tdb->global_lock.count && tdb->global_lock.ltype == ltype) {
628 tdb->global_lock.count++;
632 if (tdb->global_lock.count) {
637 if (tdb->num_locks != 0) {
643 tdb->methods->tdb_brlock(tdb, FREELIST_TOP, ltype, op,
644 0, 4*tdb->header.hash_size)) {
646 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lockall failed (%s)\n", strerror(errno)));
651 tdb->global_lock.count = 1;
652 tdb->global_lock.ltype = ltype;
660 static int _tdb_unlockall(struct tdb_context *tdb, int ltype)
667 if (tdb->read_only || tdb->traverse_read) {
671 if (tdb->global_lock.ltype != ltype || tdb->global_lock.count == 0) {
675 if (tdb->global_lock.count > 1) {
676 tdb->global_lock.count--;
681 tdb->methods->tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW,
682 0, 4*tdb->header.hash_size)) {
683 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlockall failed (%s)\n", strerror(errno)));
687 tdb->global_lock.count = 0;
688 tdb->global_lock.ltype = 0;
694 int tdb_lockall(struct tdb_context *tdb)
696 return _tdb_lockall(tdb, F_WRLCK, F_SETLKW);
700 int tdb_lockall_mark(struct tdb_context *tdb)
702 return _tdb_lockall(tdb, F_WRLCK | TDB_MARK_LOCK, F_SETLKW);
706 int tdb_lockall_unmark(struct tdb_context *tdb)
708 return _tdb_unlockall(tdb, F_WRLCK | TDB_MARK_LOCK);
712 int tdb_lockall_nonblock(struct tdb_context *tdb)
714 return _tdb_lockall(tdb, F_WRLCK, F_SETLK);
718 int tdb_unlockall(struct tdb_context *tdb)
720 return _tdb_unlockall(tdb, F_WRLCK);
724 int tdb_lockall_read(struct tdb_context *tdb)
726 return _tdb_lockall(tdb, F_RDLCK, F_SETLKW);
730 int tdb_lockall_read_nonblock(struct tdb_context *tdb)
732 return _tdb_lockall(tdb, F_RDLCK, F_SETLK);
736 int tdb_unlockall_read(struct tdb_context *tdb)
738 return _tdb_unlockall(tdb, F_RDLCK);
743 int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key)
745 return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
751 int tdb_chainlock_nonblock(struct tdb_context *tdb, TDB_DATA key)
753 return tdb_lock_nonblock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
757 int tdb_chainlock_mark(struct tdb_context *tdb, TDB_DATA key)
759 return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK | TDB_MARK_LOCK);
763 int tdb_chainlock_unmark(struct tdb_context *tdb, TDB_DATA key)
765 return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK | TDB_MARK_LOCK);
768 int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key)
770 return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
773 int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key)
775 return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK);
778 int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key)
780 return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK);
786 int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off)
788 return off ? tdb->methods->tdb_brlock(tdb, off, F_RDLCK, F_SETLKW, 0, 1) : 0;
796 int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off)
799 for (i = &tdb->travlocks; i; i = i->next)
802 return tdb->methods->tdb_brlock(tdb, off, F_WRLCK, F_SETLK, 1, 1);
809 int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off)
811 return tdb->methods->tdb_brlock(tdb, off, F_UNLCK, F_SETLK, 0, 1);
815 int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off)
822 for (i = &tdb->travlocks; i; i = i->next)
825 return (count == 1 ? tdb->methods->tdb_brlock(tdb, off, F_UNLCK, F_SETLKW, 0, 1) : 0);
835 static int tdb_oob(struct tdb_context *tdb, tdb_off_t len, int probe)
838 if (len <= tdb->map_size)
840 if (tdb->flags & TDB_INTERNAL) {
843 tdb->ecode = TDB_ERR_IO;
844 TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_oob len %d beyond internal malloc size %d\n",
845 (int)len, (int)tdb->map_size));
850 if (fstat(tdb->fd, &st) == -1) {
857 tdb->ecode = TDB_ERR_IO;
858 TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_oob len %d beyond eof at %d\n",
865 if (tdb_munmap(tdb) == -1)
867 tdb->map_size = st.st_size;
868 tdb_mmap(tdb);
873 static int tdb_write(struct tdb_context *tdb, tdb_off_t off,
880 if (tdb->read_only || tdb->traverse_read) {
881 tdb->ecode = TDB_ERR_RDONLY;
885 if (tdb->methods->tdb_oob(tdb, off + len, 0) != 0)
888 if (tdb->map_ptr) {
889 memcpy(off + (char *)tdb->map_ptr, buf, len);
890 } else if (pwrite(tdb->fd, buf, len, off) != (ssize_t)len) {
892 tdb->ecode = TDB_ERR_IO;
893 TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_write failed at %d len=%d (%s)\n",
911 static int tdb_read(struct tdb_context *tdb, tdb_off_t off, void *buf,
914 if (tdb->methods->tdb_oob(tdb, off + len, 0) != 0) {
918 if (tdb->map_ptr) {
919 memcpy(buf, off + (char *)tdb->map_ptr, len);
921 ssize_t ret = pread(tdb->fd, buf, len, off);
924 tdb->ecode = TDB_ERR_IO;
925 TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_read failed at %d "
928 (int)tdb->map_size));
944 static void tdb_next_hash_chain(struct tdb_context *tdb, u32 *chain)
947 if (tdb->map_ptr) {
948 for (;h < tdb->header.hash_size;h++) {
949 if (0 != *(u32 *)(TDB_HASH_TOP(h) + (unsigned char *)tdb->map_ptr)) {
955 for (;h < tdb->header.hash_size;h++) {
956 if (tdb_ofs_read(tdb, TDB_HASH_TOP(h), &off) != 0 || off != 0) {
965 int tdb_munmap(struct tdb_context *tdb)
967 if (tdb->flags & TDB_INTERNAL)
971 if (tdb->map_ptr) {
972 int ret = munmap(tdb->map_ptr, tdb->map_size);
977 tdb->map_ptr = NULL;
981 void tdb_mmap(struct tdb_context *tdb)
983 if (tdb->flags & TDB_INTERNAL)
987 if (!(tdb->flags & TDB_NOMMAP)) {
988 tdb->map_ptr = mmap(NULL, tdb->map_size,
989 PROT_READ|(tdb->read_only? 0:PROT_WRITE),
990 MAP_SHARED|MAP_FILE, tdb->fd, 0);
996 if (tdb->map_ptr == MAP_FAILED) {
997 tdb->map_ptr = NULL;
998 TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_mmap failed for size %d (%s)\n",
999 tdb->map_size, strerror(errno)));
1002 tdb->map_ptr = NULL;
1005 tdb->map_ptr = NULL;
1011 static int tdb_expand_file(struct tdb_context *tdb, tdb_off_t size, tdb_off_t addition)
1015 if (tdb->read_only || tdb->traverse_read) {
1016 tdb->ecode = TDB_ERR_RDONLY;
1020 if (ftruncate(tdb->fd, size+addition) == -1) {
1022 if (pwrite(tdb->fd, &b, 1, (size+addition) - 1) != 1) {
1023 TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file to %d failed (%s)\n",
1035 int ret = pwrite(tdb->fd, buf, n, size);
1037 TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file write of %d failed (%s)\n",
1050 int tdb_expand(struct tdb_context *tdb, tdb_off_t size)
1055 if (tdb_lock(tdb, -1, F_WRLCK) == -1) {
1056 TDB_LOG((tdb, TDB_DEBUG_ERROR, "lock failed in tdb_expand\n"));
1061 tdb->methods->tdb_oob(tdb, tdb->map_size + 1, 1);
1065 size = TDB_ALIGN(tdb->map_size + size*10, tdb->page_size) - tdb->map_size;
1067 if (!(tdb->flags & TDB_INTERNAL))
1068 tdb_munmap(tdb);
1077 if (!(tdb->flags & TDB_INTERNAL)) {
1078 if (tdb->methods->tdb_expand_file(tdb, tdb->map_size, size) != 0)
1082 tdb->map_size += size;
1084 if (tdb->flags & TDB_INTERNAL) {
1085 char *new_map_ptr = (char *)realloc(tdb->map_ptr,
1086 tdb->map_size);
1088 tdb->map_size -= size;
1091 tdb->map_ptr = new_map_ptr;
1100 tdb_mmap(tdb);
1108 offset = tdb->map_size - size;
1109 if (tdb_free(tdb, offset, &rec) == -1)
1112 tdb_unlock(tdb, -1, F_WRLCK);
1115 tdb_unlock(tdb, -1, F_WRLCK);
1120 int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d)
1122 return tdb->methods->tdb_read(tdb, offset, (char*)d, sizeof(*d), DOCONV());
1125 int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d)
1128 return tdb->methods->tdb_write(tdb, offset, CONVERT(off), sizeof(*d));
1133 unsigned char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len)
1144 tdb->ecode = TDB_ERR_OOM;
1145 TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_alloc_read malloc failed len=%d (%s)\n",
1149 if (tdb->methods->tdb_read(tdb, offset, buf, len, 0) == -1) {
1156 /* Give a piece of tdb data to a parser */
1158 int tdb_parse_data(struct tdb_context *tdb, TDB_DATA key,
1169 if ((tdb->transaction == NULL) && (tdb->map_ptr != NULL)) {
1174 if (tdb->methods->tdb_oob(tdb, offset+len, 0) != 0) {
1177 data.dptr = offset + (unsigned char *)tdb->map_ptr;
1181 if (!(data.dptr = tdb_alloc_read(tdb, offset, len))) {
1191 int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec)
1193 if (tdb->methods->tdb_read(tdb, offset, rec, sizeof(*rec),DOCONV()) == -1)
1197 tdb->ecode = TDB_ERR_CORRUPT;
1198 TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_rec_read bad magic 0x%x at offset=%d\n", rec->magic, offset));
1201 return tdb->methods->tdb_oob(tdb, rec->next+sizeof(*rec), 0);
1204 int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec)
1207 return tdb->methods->tdb_write(tdb, offset, CONVERT(r), sizeof(r));
1222 void tdb_io_init(struct tdb_context *tdb)
1224 tdb->methods = &io_methods;
1244 tdb_free() the old record to place it on the normal tdb freelist
1264 - keep a mirrored copy of the tdb hash chain heads to allow for the
1268 - allow callers to mix transaction and non-transaction use of tdb,
1279 - check for a valid recovery record on open of the tdb, while the
1302 /* we keep a mirrored copy of the tdb hash heads here so
1335 static int transaction_read(struct tdb_context *tdb, tdb_off_t off, void *buf,
1341 for (el=tdb->transaction->elements_last;el;el=el->prev) {
1355 if (transaction_read(tdb, off, buf, partial, cv) != 0) {
1375 if (len != 0 && transaction_read(tdb, off, buf, len, cv) != 0) {
1383 return tdb->transaction->io_methods->tdb_read(tdb, off, buf, len, cv);
1386 TDB_LOG((tdb, TDB_DEBUG_FATAL, "transaction_read: failed at off=%d len=%d\n", off, len));
1387 tdb->ecode = TDB_ERR_IO;
1388 tdb->transaction->transaction_error = 1;
1396 static int transaction_write(struct tdb_context *tdb, tdb_off_t off,
1408 off < FREELIST_TOP+TDB_HASHTABLE_SIZE(tdb)) {
1410 memcpy(&tdb->transaction->hash_heads[chain], buf, len);
1414 for (el=tdb->transaction->elements_last;el;el=el->prev) {
1432 if (transaction_write(tdb, off, buf, partial) != 0) {
1449 if (len != 0 && transaction_write(tdb, off, buf, len) != 0) {
1458 (off+len < tdb->transaction->old_map_size ||
1459 off > tdb->transaction->old_map_size)) {
1465 tdb->ecode = TDB_ERR_OOM;
1466 tdb->transaction->transaction_error = 1;
1482 tdb->ecode = TDB_ERR_OOM;
1483 tdb->transaction->transaction_error = 1;
1487 el->prev = tdb->transaction->elements_last;
1493 tdb->ecode = TDB_ERR_OOM;
1494 tdb->transaction->transaction_error = 1;
1505 tdb->transaction->elements = el;
1507 tdb->transaction->elements_last = el;
1511 TDB_LOG((tdb, TDB_DEBUG_FATAL, "transaction_write: failed at off=%d len=%d\n", off, len));
1512 tdb->ecode = TDB_ERR_IO;
1513 tdb->transaction->transaction_error = 1;
1520 static void transaction_next_hash_chain(struct tdb_context *tdb, u32 *chain)
1523 for (;h < tdb->header.hash_size;h++) {
1525 if (0 != tdb->transaction->hash_heads[h+1]) {
1535 static int transaction_oob(struct tdb_context *tdb, tdb_off_t len, int probe)
1537 if (len <= tdb->map_size) {
1546 static int transaction_expand_file(struct tdb_context *tdb, tdb_off_t size,
1551 if (transaction_write(tdb, size, NULL, addition) != 0) {
1561 static int transaction_brlock(struct tdb_context *tdb, tdb_off_t offset,
1578 start a tdb transaction. No token is returned, as only a single
1581 int tdb_transaction_start(struct tdb_context *tdb)
1584 if (tdb->read_only || (tdb->flags & TDB_INTERNAL) || tdb->traverse_read) {
1585 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction on a read-only or internal db\n"));
1586 tdb->ecode = TDB_ERR_EINVAL;
1591 if (tdb->transaction != NULL) {
1592 tdb->transaction->nesting++;
1593 TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_start: nesting %d\n",
1594 tdb->transaction->nesting));
1598 if (tdb->num_locks != 0 || tdb->global_lock.count) {
1602 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction with locks held\n"));
1603 tdb->ecode = TDB_ERR_LOCK;
1607 if (tdb->travlocks.next != NULL) {
1611 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction within a traverse\n"));
1612 tdb->ecode = TDB_ERR_LOCK;
1616 tdb->transaction = (struct tdb_transaction *)
1618 if (tdb->transaction == NULL) {
1619 tdb->ecode = TDB_ERR_OOM;
1626 if (tdb_transaction_lock(tdb, F_WRLCK) == -1) {
1627 SAFE_FREE(tdb->transaction);
1633 if (tdb_brlock(tdb, FREELIST_TOP, F_RDLCK, F_SETLKW, 0, 0) == -1) {
1634 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: failed to get hash locks\n"));
1635 tdb->ecode = TDB_ERR_LOCK;
1641 tdb->transaction->hash_heads = (u32 *)
1642 calloc(tdb->header.hash_size+1, sizeof(u32));
1643 if (tdb->transaction->hash_heads == NULL) {
1644 tdb->ecode = TDB_ERR_OOM;
1647 if (tdb->methods->tdb_read(tdb, FREELIST_TOP, tdb->transaction->hash_heads,
1648 TDB_HASHTABLE_SIZE(tdb), 0) != 0) {
1649 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_start: failed to read hash heads\n"));
1650 tdb->ecode = TDB_ERR_IO;
1656 tdb->methods->tdb_oob(tdb, tdb->map_size + 1, 1);
1657 tdb->transaction->old_map_size = tdb->map_size;
1661 tdb->transaction->io_methods = tdb->methods;
1662 tdb->methods = &transaction_methods;
1666 if (transaction_write(tdb, FREELIST_TOP, tdb->transaction->hash_heads,
1667 TDB_HASHTABLE_SIZE(tdb)) != 0) {
1668 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_start: failed to prime hash table\n"));
1669 tdb->ecode = TDB_ERR_IO;
1670 tdb->methods = tdb->transaction->io_methods;
1677 tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0);
1678 tdb_transaction_unlock(tdb);
1679 SAFE_FREE(tdb->transaction->hash_heads);
1680 SAFE_FREE(tdb->transaction);
1688 int tdb_transaction_cancel(struct tdb_context *tdb)
1690 if (tdb->transaction == NULL) {
1691 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_cancel: no transaction\n"));
1695 if (tdb->transaction->nesting != 0) {
1696 tdb->transaction->transaction_error = 1;
1697 tdb->transaction->nesting--;
1701 tdb->map_size = tdb->transaction->old_map_size;
1704 while (tdb->transaction->elements) {
1705 struct tdb_transaction_el *el = tdb->transaction->elements;
1706 tdb->transaction->elements = el->next;
1712 if (tdb->global_lock.count != 0) {
1713 tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 4*tdb->header.hash_size);
1714 tdb->global_lock.count = 0;
1718 if (tdb->num_locks != 0) {
1720 for (i=0;i<tdb->num_lockrecs;i++) {
1721 tdb_brlock(tdb,FREELIST_TOP+4*tdb->lockrecs[i].list,
1724 tdb->num_locks = 0;
1725 tdb->num_lockrecs = 0;
1726 SAFE_FREE(tdb->lockrecs);
1730 tdb->methods = tdb->transaction->io_methods;
1732 tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0);
1733 tdb_transaction_unlock(tdb);
1734 SAFE_FREE(tdb->transaction->hash_heads);
1735 SAFE_FREE(tdb->transaction);
1743 static int transaction_sync(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t length)
1745 if (fsync(tdb->fd) != 0) {
1746 tdb->ecode = TDB_ERR_IO;
1747 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: fsync failed\n"));
1751 if (tdb->map_ptr) {
1752 tdb_off_t moffset = offset & ~(tdb->page_size-1);
1753 if (msync(moffset + (char *)tdb->map_ptr,
1755 tdb->ecode = TDB_ERR_IO;
1756 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: msync failed - %s\n",
1769 static tdb_len_t tdb_recovery_size(struct tdb_context *tdb)
1775 for (el=tdb->transaction->elements;el;el=el->next) {
1776 if (el->offset >= tdb->transaction->old_map_size) {
1789 static int tdb_recovery_allocate(struct tdb_context *tdb,
1795 const struct tdb_methods *methods = tdb->transaction->io_methods;
1798 if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) {
1799 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery head\n"));
1806 methods->tdb_read(tdb, recovery_head, &rec, sizeof(rec), DOCONV()) == -1) {
1807 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery record\n"));
1811 *recovery_size = tdb_recovery_size(tdb);
1826 if (tdb_free(tdb, recovery_head, &rec) == -1) {
1827 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to free previous recovery area\n"));
1833 *recovery_size = tdb_recovery_size(tdb);
1836 *recovery_max_size = TDB_ALIGN(sizeof(rec) + *recovery_size, tdb->page_size) - sizeof(rec);
1837 *recovery_offset = tdb->map_size;
1840 if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size,
1841 (tdb->map_size - tdb->transaction->old_map_size) +
1843 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to create recovery area\n"));
1848 methods->tdb_oob(tdb, tdb->map_size + 1, 1);
1852 tdb->transaction->old_map_size = tdb->map_size;
1857 if (methods->tdb_write(tdb, TDB_RECOVERY_HEAD,
1859 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to write recovery head\n"));
1870 static int transaction_setup_recovery(struct tdb_context *tdb,
1876 const struct tdb_methods *methods = tdb->transaction->io_methods;
1879 tdb_off_t old_map_size = tdb->transaction->old_map_size;
1885 if (tdb_recovery_allocate(tdb, &recovery_size,
1892 tdb->ecode = TDB_ERR_OOM;
1908 for (el=tdb->transaction->elements;el;el=el->next) {
1912 if (el->offset + el->length > tdb->transaction->old_map_size) {
1913 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: transaction data over new region boundary\n"));
1915 tdb->ecode = TDB_ERR_CORRUPT;
1926 if (methods->tdb_read(tdb, el->offset, p + 8, el->length, 0) != 0) {
1928 tdb->ecode = TDB_ERR_IO;
1940 if (methods->tdb_write(tdb, recovery_offset, data, sizeof(*rec) + recovery_size) == -1) {
1941 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: failed to write recovery data\n"));
1943 tdb->ecode = TDB_ERR_IO;
1950 if (transaction_sync(tdb, recovery_offset, sizeof(*rec) + recovery_size) == -1) {
1962 if (methods->tdb_write(tdb, *magic_offset, &magic, sizeof(magic)) == -1) {
1963 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: failed to write recovery magic\n"));
1964 tdb->ecode = TDB_ERR_IO;
1969 if (transaction_sync(tdb, *magic_offset, sizeof(magic)) == -1) {
1979 int tdb_transaction_commit(struct tdb_context *tdb)
1985 if (tdb->transaction == NULL) {
1986 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: no transaction\n"));
1990 if (tdb->transaction->transaction_error) {
1991 tdb->ecode = TDB_ERR_IO;
1992 tdb_transaction_cancel(tdb);
1993 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: transaction error pending\n"));
1997 if (tdb->transaction->nesting != 0) {
1998 tdb->transaction->nesting--;
2003 if (tdb->transaction->elements == NULL) {
2004 tdb_transaction_cancel(tdb);
2008 methods = tdb->transaction->io_methods;
2012 if (tdb->num_locks || tdb->global_lock.count) {
2013 tdb->ecode = TDB_ERR_LOCK;
2014 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: locks pending on commit\n"));
2015 tdb_transaction_cancel(tdb);
2020 if (tdb_brlock_upgrade(tdb, FREELIST_TOP, 0) == -1) {
2021 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: failed to upgrade hash locks\n"));
2022 tdb->ecode = TDB_ERR_LOCK;
2023 tdb_transaction_cancel(tdb);
2029 if (tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) {
2030 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: failed to get global lock\n"));
2031 tdb->ecode = TDB_ERR_LOCK;
2032 tdb_transaction_cancel(tdb);
2036 if (!(tdb->flags & TDB_NOSYNC)) {
2038 if (transaction_setup_recovery(tdb, &magic_offset) == -1) {
2039 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: failed to setup recovery data\n"));
2040 tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1);
2041 tdb_transaction_cancel(tdb);
2047 if (tdb->map_size != tdb->transaction->old_map_size) {
2048 if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size,
2049 tdb->map_size -
2050 tdb->transaction->old_map_size) == -1) {
2051 tdb->ecode = TDB_ERR_IO;
2052 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: expansion failed\n"));
2053 tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1);
2054 tdb_transaction_cancel(tdb);
2057 tdb->map_size = tdb->transaction->old_map_size;
2058 methods->tdb_oob(tdb, tdb->map_size + 1, 1);
2062 while (tdb->transaction->elements) {
2063 struct tdb_transaction_el *el = tdb->transaction->elements;
2065 if (methods->tdb_write(tdb, el->offset, el->data, el->length) == -1) {
2066 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed during commit\n"));
2071 tdb->methods = methods;
2072 tdb_transaction_recover(tdb);
2074 tdb_transaction_cancel(tdb);
2075 tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1);
2077 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed\n"));
2080 tdb->transaction->elements = el->next;
2085 if (!(tdb->flags & TDB_NOSYNC)) {
2087 if (transaction_sync(tdb, 0, tdb->map_size) == -1) {
2092 if (methods->tdb_write(tdb, magic_offset, &zero, 4) == -1) {
2093 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: failed to remove recovery magic\n"));
2098 if (transaction_sync(tdb, magic_offset, 4) == -1) {
2103 tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1);
2113 not be backed up (as tdb rounding to block sizes means that
2117 utime(tdb->name, NULL);
2122 tdb_transaction_cancel(tdb);
2132 int tdb_transaction_recover(struct tdb_context *tdb)
2140 if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) {
2141 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery head\n"));
2142 tdb->ecode = TDB_ERR_IO;
2152 if (tdb->methods->tdb_read(tdb, recovery_head, &rec,
2154 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery record\n"));
2155 tdb->ecode = TDB_ERR_IO;
2164 if (tdb->read_only) {
2165 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: attempt to recover read only database\n"));
2166 tdb->ecode = TDB_ERR_CORRUPT;
2174 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to allocate recovery data\n"));
2175 tdb->ecode = TDB_ERR_OOM;
2180 if (tdb->methods->tdb_read(tdb, recovery_head + sizeof(rec), data,
2182 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery data\n"));
2183 tdb->ecode = TDB_ERR_IO;
2197 if (tdb->methods->tdb_write(tdb, ofs, p+8, len) == -1) {
2199 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to recover %d bytes at offset %d\n", len, ofs));
2200 tdb->ecode = TDB_ERR_IO;
2208 if (transaction_sync(tdb, 0, tdb->map_size) == -1) {
2209 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to sync recovery\n"));
2210 tdb->ecode = TDB_ERR_IO;
2216 if (tdb_ofs_write(tdb, TDB_RECOVERY_HEAD, &zero) == -1) {
2217 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to remove recovery head\n"));
2218 tdb->ecode = TDB_ERR_IO;
2224 if (tdb_ofs_write(tdb, recovery_head + offsetof(struct list_struct, magic),
2226 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to remove recovery magic\n"));
2227 tdb->ecode = TDB_ERR_IO;
2232 tdb_munmap(tdb);
2233 if (ftruncate(tdb->fd, recovery_eof) != 0) {
2234 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to reduce to recovery size\n"));
2235 tdb->ecode = TDB_ERR_IO;
2238 tdb->map_size = recovery_eof;
2239 tdb_mmap(tdb);
2241 if (transaction_sync(tdb, 0, recovery_eof) == -1) {
2242 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to sync2 recovery\n"));
2243 tdb->ecode = TDB_ERR_IO;
2247 TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_recover: recovered %d byte database\n",
2257 static int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list_struct *rec)
2259 if (tdb->methods->tdb_read(tdb, off, rec, sizeof(*rec),DOCONV()) == -1)
2265 TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_rec_free_read non-free magic 0x%x at offset=%d - fixing\n",
2268 if (tdb->methods->tdb_write(tdb, off, rec, sizeof(*rec)) == -1)
2274 tdb->ecode = TDB_ERR_CORRUPT;
2275 TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_rec_free_read bad magic 0x%x at offset=%d\n",
2279 if (tdb->methods->tdb_oob(tdb, rec->next+sizeof(*rec), 0) != 0)
2287 static int remove_from_freelist(struct tdb_context *tdb, tdb_off_t off, tdb_off_t next)
2293 while (tdb_ofs_read(tdb, last_ptr, &i) != -1 && i != 0) {
2296 return tdb_ofs_write(tdb, last_ptr, &next);
2301 TDB_LOG((tdb, TDB_DEBUG_FATAL,"remove_from_freelist: not on list at off=%d\n", off));
2307 static int update_tailer(struct tdb_context *tdb, tdb_off_t offset,
2314 return tdb_ofs_write(tdb, offset + totalsize - sizeof(tdb_off_t),
2320 int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec)
2325 if (tdb_lock(tdb, -1, F_WRLCK) != 0)
2329 if (update_tailer(tdb, offset, rec) != 0) {
2330 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: update_tailer failed!\n"));
2336 if (right + sizeof(*rec) <= tdb->map_size) {
2339 if (tdb->methods->tdb_read(tdb, right, &r, sizeof(r), DOCONV()) == -1) {
2340 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: right read failed at %u\n", right));
2346 if (remove_from_freelist(tdb, right, r.next) == -1) {
2347 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: right free failed at %u\n", right));
2357 if (left > TDB_DATA_START(tdb->header.hash_size)) {
2362 if (tdb_ofs_read(tdb, left, &leftsize) == -1) {
2363 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left offset read failed at %u\n", left));
2375 if (tdb->methods->tdb_read(tdb, left, &l, sizeof(l), DOCONV()) == -1) {
2376 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left read failed at %u (%u)\n", left, leftsize));
2382 if (remove_from_freelist(tdb, left, l.next) == -1) {
2383 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left free failed at %u\n", left));
2393 if (update_tailer(tdb, offset, rec) == -1) {
2394 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: update_tailer failed at %u\n", offset));
2401 if (tdb_ofs_read(tdb, FREELIST_TOP, &rec->next) == -1 ||
2402 tdb_rec_write(tdb, offset, rec) == -1 ||
2403 tdb_ofs_write(tdb, FREELIST_TOP, &offset) == -1) {
2404 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free record write failed at offset=%d\n", offset));
2409 tdb_unlock(tdb, -1, F_WRLCK);
2413 tdb_unlock(tdb, -1, F_WRLCK);
2422 static tdb_off_t tdb_allocate_ofs(struct tdb_context *tdb, tdb_len_t length, tdb_off_t rec_ptr,
2446 if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1) {
2455 if (tdb_rec_write(tdb, rec_ptr, rec) == -1) {
2463 if (update_tailer(tdb, rec_ptr, rec) == -1) {
2468 if (tdb_free(tdb, newrec_ptr, &newrec) == -1) {
2483 tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_struct *rec)
2491 if (tdb_lock(tdb, -1, F_WRLCK) == -1)
2501 if (tdb_ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1)
2514 if (tdb_rec_free_read(tdb, rec_ptr, rec) == -1) {
2539 if (tdb_rec_free_read(tdb, bestfit.rec_ptr, rec) == -1) {
2543 newrec_ptr = tdb_allocate_ofs(tdb, length, bestfit.rec_ptr, rec, bestfit.last_ptr);
2544 tdb_unlock(tdb, -1, F_WRLCK);
2550 if (tdb_expand(tdb, length + sizeof(*rec)) == 0)
2553 tdb_unlock(tdb, -1, F_WRLCK);
2561 checker. Heh heh - uses an in memory tdb as the storage
2577 int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries)
2586 mem_tdb = tdb_open("flval", tdb->header.hash_size,
2592 if (tdb_lock(tdb, -1, F_WRLCK) == -1) {
2606 if (tdb_ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1) {
2621 if (tdb_rec_free_read(tdb, rec_ptr, &rec) == -1) {
2636 tdb_unlock(tdb, -1, F_WRLCK);
2643 static int tdb_next_lock(struct tdb_context *tdb, struct tdb_traverse_lock *tlock,
2649 for (; tlock->hash < tdb->header.hash_size; tlock->hash++) {
2653 common for the use of tdb with ldb, where large
2679 tdb->methods->next_hash_chain(tdb, &tlock->hash);
2680 if (tlock->hash == tdb->header.hash_size) {
2685 if (tdb_lock(tdb, tlock->hash, tlock->lock_rw) == -1)
2690 if (tdb_ofs_read(tdb, TDB_HASH_TOP(tlock->hash),
2695 if (tdb_unlock_record(tdb, tlock->off) != 0)
2701 if (tdb_rec_read(tdb, tlock->off, rec) == -1)
2709 if (tdb_rec_read(tdb, tlock->off, rec) == -1)
2714 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_next_lock: loop detected.\n"));
2720 if (tdb_lock_record(tdb, tlock->off) != 0)
2728 if (!(tdb->read_only || tdb->traverse_read) &&
2729 tdb_do_delete(tdb, current, rec) != 0)
2732 tdb_unlock(tdb, tlock->hash, tlock->lock_rw);
2740 if (tdb_unlock(tdb, tlock->hash, tlock->lock_rw) != 0)
2741 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_next_lock: On error unlock failed!\n"));
2745 /* traverse the entire database - calling fn(tdb, key, data) on each element.
2750 static int tdb_traverse_internal(struct tdb_context *tdb,
2761 tl->next = tdb->travlocks.next;
2764 tdb->travlocks.next = tl;
2767 while ((ret = tdb_next_lock(tdb, tl, &rec)) > 0) {
2770 key.dptr = tdb_alloc_read(tdb, tl->off + sizeof(rec),
2774 if (tdb_unlock(tdb, tl->hash, tl->lock_rw) != 0)
2776 if (tdb_unlock_record(tdb, tl->off) != 0)
2777 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_traverse: key.dptr == NULL and unlock_record failed!\n"));
2785 if (tdb_unlock(tdb, tl->hash, tl->lock_rw) != 0) {
2790 if (fn && fn(tdb, key, dbuf, private_data)) {
2793 if (tdb_unlock_record(tdb, tl->off) != 0) {
2794 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_traverse: unlock_record failed!\n"));;
2803 tdb->travlocks.next = tl->next;
2814 int tdb_traverse_read(struct tdb_context *tdb,
2822 if (tdb_transaction_lock(tdb, F_RDLCK)) {
2826 tdb->traverse_read++;
2827 ret = tdb_traverse_internal(tdb, fn, private_data, &tl);
2828 tdb->traverse_read--;
2830 tdb_transaction_unlock(tdb);
2839 int tdb_traverse(struct tdb_context *tdb,
2845 if (tdb->read_only || tdb->traverse_read) {
2846 return tdb_traverse_read(tdb, fn, private_data);
2849 if (tdb_transaction_lock(tdb, F_WRLCK)) {
2853 ret = tdb_traverse_internal(tdb, fn, private_data, &tl);
2855 tdb_transaction_unlock(tdb);
2862 TDB_DATA tdb_firstkey(struct tdb_context *tdb)
2868 if (tdb_unlock_record(tdb, tdb->travlocks.off) != 0)
2870 tdb->travlocks.off = tdb->travlocks.hash = 0;
2871 tdb->travlocks.lock_rw = F_RDLCK;
2874 if (tdb_next_lock(tdb, &tdb->travlocks, &rec) <= 0)
2878 key.dptr =tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),key.dsize);
2881 if (tdb_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0)
2882 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_firstkey: error occurred while tdb_unlocking!\n"));
2887 TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA oldkey)
2895 if (tdb->travlocks.off) {
2896 if (tdb_lock(tdb,tdb->travlocks.hash,tdb->travlocks.lock_rw))
2898 if (tdb_rec_read(tdb, tdb->travlocks.off, &rec) == -1
2899 || !(k = tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),
2903 if (tdb_unlock_record(tdb, tdb->travlocks.off) != 0) {
2907 if (tdb_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0) {
2911 tdb->travlocks.off = 0;
2917 if (!tdb->travlocks.off) {
2919 tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb->hash_fn(&oldkey), tdb->travlocks.lock_rw, &rec);
2920 if (!tdb->travlocks.off)
2922 tdb->travlocks.hash = BUCKET(rec.full_hash);
2923 if (tdb_lock_record(tdb, tdb->travlocks.off) != 0) {
2924 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: lock_record failed (%s)!\n", strerror(errno)));
2928 oldhash = tdb->travlocks.hash;
2932 if (tdb_next_lock(tdb, &tdb->travlocks, &rec) > 0) {
2934 key.dptr = tdb_alloc_read(tdb, tdb->travlocks.off+sizeof(rec),
2937 if (tdb_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0)
2938 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: WARNING tdb_unlock failed!\n"));
2941 if (tdb_unlock(tdb, BUCKET(oldhash), tdb->travlocks.lock_rw) != 0)
2942 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: WARNING tdb_unlock failed!\n"));
2948 static tdb_off_t tdb_dump_record(struct tdb_context *tdb, int hash,
2954 if (tdb->methods->tdb_read(tdb, offset, (char *)&rec,
2967 if (tdb_ofs_read(tdb, tailer_ofs, &tailer) == -1) {
2979 static int tdb_dump_chain(struct tdb_context *tdb, int i)
2985 if (tdb_lock(tdb, i, F_WRLCK) != 0)
2988 if (tdb_ofs_read(tdb, top, &rec_ptr) == -1)
2989 return tdb_unlock(tdb, i, F_WRLCK);
2995 rec_ptr = tdb_dump_record(tdb, i, rec_ptr);
2998 return tdb_unlock(tdb, i, F_WRLCK);
3001 void tdb_dump_all(struct tdb_context *tdb)
3004 for (i=0;i<tdb->header.hash_size;i++) {
3005 tdb_dump_chain(tdb, i);
3008 tdb_dump_chain(tdb, -1);
3011 int tdb_printfreelist(struct tdb_context *tdb)
3018 if ((ret = tdb_lock(tdb, -1, F_WRLCK)) != 0)
3024 if (tdb_ofs_read(tdb, offset, &rec_ptr) == -1) {
3025 tdb_unlock(tdb, -1, F_WRLCK);
3031 if (tdb->methods->tdb_read(tdb, rec_ptr, (char *)&rec,
3033 tdb_unlock(tdb, -1, F_WRLCK);
3039 tdb_unlock(tdb, -1, F_WRLCK);
3053 return tdb_unlock(tdb, -1, F_WRLCK);
3056 /* file: tdb.c */
3059 non-blocking increment of the tdb sequence number if the tdb has been opened using
3062 void tdb_increment_seqnum_nonblock(struct tdb_context *tdb)
3066 if (!(tdb->flags & TDB_SEQNUM)) {
3073 tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum);
3075 tdb_ofs_write(tdb, TDB_SEQNUM_OFS, &seqnum);
3079 increment the tdb sequence number if the tdb has been opened using
3082 static void tdb_increment_seqnum(struct tdb_context *tdb)
3084 if (!(tdb->flags & TDB_SEQNUM)) {
3088 if (tdb_brlock(tdb, TDB_SEQNUM_OFS, F_WRLCK, F_SETLKW, 1, 1) != 0) {
3092 tdb_increment_seqnum_nonblock(tdb);
3094 tdb_brlock(tdb, TDB_SEQNUM_OFS, F_UNLCK, F_SETLKW, 1, 1);
3104 static tdb_off_t tdb_find(struct tdb_context *tdb, TDB_DATA key, u32 hash,
3110 if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
3115 if (tdb_rec_read(tdb, rec_ptr, r) == -1)
3120 && tdb_parse_data(tdb, key, rec_ptr + sizeof(*r),
3131 tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, int locktype,
3136 if (tdb_lock(tdb, BUCKET(hash), locktype) == -1)
3138 if (!(rec_ptr = tdb_find(tdb, key, hash, rec)))
3139 tdb_unlock(tdb, BUCKET(hash), locktype);
3148 static int tdb_update_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, TDB_DATA dbuf)
3154 if (!(rec_ptr = tdb_find(tdb, key, hash, &rec)))
3159 tdb->ecode = TDB_SUCCESS; /* Not really an error */
3163 if (tdb->methods->tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len,
3170 return tdb_rec_write(tdb, rec_ptr, &rec);
3182 TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key)
3190 hash = tdb->hash_fn(&key);
3191 if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec)))
3194 ret.dptr = tdb_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len,
3197 tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK);
3208 * For mmapped tdb's that do not have a transaction open it points the parsing
3214 * the tdb records, ldb indexes being one example.
3217 int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key,
3228 hash = tdb->hash_fn(&key);
3230 if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) {
3234 ret = tdb_parse_data(tdb, key, rec_ptr + sizeof(rec) + rec.key_len,
3237 tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK);
3248 static int tdb_exists_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash)
3252 if (tdb_find_lock_hash(tdb, key, hash, F_RDLCK, &rec) == 0)
3254 tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK);
3258 int tdb_exists(struct tdb_context *tdb, TDB_DATA key)
3260 u32 hash = tdb->hash_fn(&key);
3261 return tdb_exists_hash(tdb, key, hash);
3265 int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct list_struct*rec)
3270 if (tdb->read_only || tdb->traverse_read) return -1;
3272 if (tdb_write_lock_record(tdb, rec_ptr) == -1) {
3275 return tdb_rec_write(tdb, rec_ptr, rec);
3277 if (tdb_write_unlock_record(tdb, rec_ptr) != 0)
3281 if (tdb_ofs_read(tdb, TDB_HASH_TOP(rec->full_hash), &i) == -1)
3284 if (tdb_rec_read(tdb, i, &lastrec) == -1)
3290 if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1)
3294 if (tdb_free(tdb, rec_ptr, rec) == -1)
3299 static int tdb_count_dead(struct tdb_context *tdb, u32 hash)
3306 if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
3310 if (tdb_rec_read(tdb, rec_ptr, &rec) == -1)
3324 static int tdb_purge_dead(struct tdb_context *tdb, u32 hash)
3330 if (tdb_lock(tdb, -1, F_WRLCK) == -1) {
3335 if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
3341 if (tdb_rec_read(tdb, rec_ptr, &rec) == -1) {
3348 && tdb_do_delete(tdb, rec_ptr, &rec) == -1) {
3355 tdb_unlock(tdb, -1, F_WRLCK);
3360 static int tdb_delete_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash)
3366 if (tdb->max_dead_records != 0) {
3370 * tdb's with a very high create/delete rate like locking.tdb.
3373 if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
3376 if (tdb_count_dead(tdb, hash) >= tdb->max_dead_records) {
3381 tdb_purge_dead(tdb, hash);
3384 if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) {
3385 tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
3393 ret = tdb_rec_write(tdb, rec_ptr, &rec);
3396 if (!(rec_ptr = tdb_find_lock_hash(tdb, key, hash, F_WRLCK,
3400 ret = tdb_do_delete(tdb, rec_ptr, &rec);
3404 tdb_increment_seqnum(tdb);
3407 if (tdb_unlock(tdb, BUCKET(rec.full_hash), F_WRLCK) != 0)
3408 TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_delete: WARNING tdb_unlock failed!\n"));
3412 int tdb_delete(struct tdb_context *tdb, TDB_DATA key)
3414 u32 hash = tdb->hash_fn(&key);
3415 return tdb_delete_hash(tdb, key, hash);
3421 static tdb_off_t tdb_find_dead(struct tdb_context *tdb, u32 hash,
3427 if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
3432 if (tdb_rec_read(tdb, rec_ptr, r) == -1)
3452 int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
3460 if (tdb->read_only || tdb->traverse_read) {
3461 tdb->ecode = TDB_ERR_RDONLY;
3466 hash = tdb->hash_fn(&key);
3467 if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
3472 if (tdb_exists_hash(tdb, key, hash)) {
3473 tdb->ecode = TDB_ERR_EXISTS;
3478 if (tdb_update_hash(tdb, key, hash, dbuf) == 0) {
3481 if (tdb->ecode == TDB_ERR_NOEXIST &&
3489 tdb->ecode = TDB_SUCCESS;
3495 tdb_delete_hash(tdb, key, hash);
3498 fails and we are left with a dead spot in the tdb. */
3501 tdb->ecode = TDB_ERR_OOM;
3509 if (tdb->max_dead_records != 0) {
3517 tdb, hash, &rec,
3525 if (tdb_rec_write(tdb, rec_ptr, &rec) == -1
3526 || tdb->methods->tdb_write(
3527 tdb, rec_ptr + sizeof(rec),
3541 if (tdb_lock(tdb, -1, F_WRLCK) == -1) {
3545 if ((tdb->max_dead_records != 0)
3546 && (tdb_purge_dead(tdb, hash) == -1)) {
3547 tdb_unlock(tdb, -1, F_WRLCK);
3552 rec_ptr = tdb_allocate(tdb, key.dsize + dbuf.dsize, &rec);
3554 tdb_unlock(tdb, -1, F_WRLCK);
3561 if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1)
3570 if (tdb_rec_write(tdb, rec_ptr, &rec) == -1
3571 || tdb->methods->tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+dbuf.dsize)==-1
3572 || tdb_ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) {
3581 tdb_increment_seqnum(tdb);
3585 tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
3591 int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)
3598 hash = tdb->hash_fn(&key);
3599 if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
3602 dbuf = tdb_fetch(tdb, key);
3616 tdb->ecode = TDB_ERR_OOM;
3623 ret = tdb_store(tdb, key, dbuf, 0);
3626 tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
3633 return the name of the current tdb file
3636 const char *tdb_name(struct tdb_context *tdb)
3638 return tdb->name;
3642 return the underlying file descriptor being used by tdb, or -1
3646 int tdb_fd(struct tdb_context *tdb)
3648 return tdb->fd;
3653 useful for external tdb routines that wish to log tdb errors
3655 tdb_log_func tdb_log_fn(struct tdb_context *tdb)
3657 return tdb->log.log_fn;
3662 get the tdb sequence number. Only makes sense if the writers opened
3666 made. If you want a counter then use a tdb record.
3669 test of a possible tdb change.
3671 int tdb_get_seqnum(struct tdb_context *tdb)
3675 tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum);
3679 int tdb_hash_size(struct tdb_context *tdb)
3681 return tdb->header.hash_size;
3684 size_t tdb_map_size(struct tdb_context *tdb)
3686 return tdb->map_size;
3689 int tdb_get_flags(struct tdb_context *tdb)
3691 return tdb->flags;
3696 enable sequence number handling on an open tdb
3698 void tdb_enable_seqnum(struct tdb_context *tdb)
3700 tdb->flags |= TDB_SEQNUM;
3724 static int tdb_new_database(struct tdb_context *tdb, int hash_size)
3737 if (tdb->flags & TDB_INTERNAL) {
3738 tdb->map_size = size;
3739 tdb->map_ptr = (char *)newdb;
3740 memcpy(&tdb->header, newdb, sizeof(tdb->header));
3745 if (lseek(tdb->fd, 0, SEEK_SET) == -1)
3748 if (ftruncate(tdb->fd, 0) == -1)
3753 memcpy(&tdb->header, newdb, sizeof(tdb->header));
3756 if (write(tdb->fd, newdb, size) != size) {
3800 static void null_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4);
3801 static void null_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...)
3811 struct tdb_context *tdb;
3817 if (!(tdb = (struct tdb_context *)calloc(1, sizeof *tdb))) {
3822 tdb_io_init(tdb);
3823 tdb->fd = -1;
3824 tdb->name = NULL;
3825 tdb->map_ptr = NULL;
3826 tdb->flags = tdb_flags;
3827 tdb->open_flags = open_flags;
3829 tdb->log = *log_ctx;
3831 tdb->log.log_fn = null_log_fn;
3832 tdb->log.log_private = NULL;
3834 tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash;
3837 tdb->page_size = sysconf(_SC_PAGESIZE);
3838 if (tdb->page_size <= 0) {
3839 tdb->page_size = 0x2000;
3843 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: can't open tdb %s write-only\n",
3852 tdb->read_only = 1;
3854 tdb->flags |= TDB_NOLOCK;
3855 tdb->flags &= ~TDB_CLEAR_IF_FIRST;
3859 if (tdb->flags & TDB_INTERNAL) {
3860 tdb->flags |= (TDB_NOLOCK | TDB_NOMMAP);
3861 tdb->flags &= ~TDB_CLEAR_IF_FIRST;
3862 if (tdb_new_database(tdb, hash_size) != 0) {
3863 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: tdb_new_database failed!"));
3869 if ((tdb->fd = open(name, open_flags, mode)) == -1) {
3870 TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_open_ex: could not open file %s: %s\n",
3876 if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) {
3877 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to get global lock on %s: %s\n",
3884 (locked = (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0, 1) == 0))) {
3886 if (ftruncate(tdb->fd, 0) == -1) {
3887 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: "
3894 if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header)
3895 || strcmp(tdb->header.magic_food, TDB_MAGIC_FOOD) != 0
3896 || (tdb->header.version != TDB_VERSION
3897 && !(rev = (tdb->header.version==TDB_BYTEREV(TDB_VERSION))))) {
3899 if (!(open_flags & O_CREAT) || tdb_new_database(tdb, hash_size) == -1) {
3903 rev = (tdb->flags & TDB_CONVERT);
3905 vp = (unsigned char *)&tdb->header.version;
3908 tdb->flags |= (vertest==TDB_VERSION) ? TDB_BIGENDIAN : 0;
3910 tdb->flags &= ~TDB_CONVERT;
3912 tdb->flags |= TDB_CONVERT;
3913 tdb_convert(&tdb->header, sizeof(tdb->header));
3915 if (fstat(tdb->fd, &st) == -1)
3918 if (tdb->header.rwlocks != 0) {
3919 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: spinlocks no longer supported\n"));
3925 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: "
3932 if (!(tdb->name = (char *)strdup(name))) {
3937 tdb->map_size = st.st_size;
3938 tdb->device = st.st_dev;
3939 tdb->inode = st.st_ino;
3940 tdb->max_dead_records = 0;
3941 tdb_mmap(tdb);
3943 if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0, 1) == -1) {
3944 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: "
3958 if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1)
3963 if (tdb_transaction_recover(tdb) == -1) {
3971 if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1) == -1)
3973 tdb->next = tdbs;
3974 tdbs = tdb;
3975 return tdb;
3980 if (!tdb)
3983 if (tdb->map_ptr) {
3984 if (tdb->flags & TDB_INTERNAL)
3985 SAFE_FREE(tdb->map_ptr);
3987 tdb_munmap(tdb);
3989 SAFE_FREE(tdb->name);
3990 if (tdb->fd != -1)
3991 if (close(tdb->fd) != 0)
3992 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to close tdb->fd on error!\n"));
3993 SAFE_FREE(tdb);
4003 void tdb_set_max_dead(struct tdb_context *tdb, int max_dead)
4005 tdb->max_dead_records = max_dead;
4013 int tdb_close(struct tdb_context *tdb)
4018 if (tdb->transaction) {
4019 tdb_transaction_cancel(tdb);
4022 if (tdb->map_ptr) {
4023 if (tdb->flags & TDB_INTERNAL)
4024 SAFE_FREE(tdb->map_ptr);
4026 tdb_munmap(tdb);
4028 SAFE_FREE(tdb->name);
4029 if (tdb->fd != -1)
4030 ret = close(tdb->fd);
4031 SAFE_FREE(tdb->lockrecs);
4035 if (*i == tdb) {
4036 *i = tdb->next;
4041 memset(tdb, 0, sizeof(*tdb));
4042 SAFE_FREE(tdb);
4048 void tdb_set_logging_function(struct tdb_context *tdb,
4051 tdb->log = *log_ctx;
4054 void *tdb_get_logging_private(struct tdb_context *tdb)
4056 return tdb->log.log_private;
4059 /* reopen a tdb - this can be used after a fork to ensure that we have an independent
4061 int tdb_reopen(struct tdb_context *tdb)
4065 if (tdb->flags & TDB_INTERNAL) {
4069 if (tdb->num_locks != 0 || tdb->global_lock.count) {
4070 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed with locks held\n"));
4074 if (tdb->transaction != 0) {
4075 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed inside a transaction\n"));
4079 if (tdb_munmap(tdb) != 0) {
4080 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: munmap failed (%s)\n", strerror(errno)));
4083 if (close(tdb->fd) != 0)
4084 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: WARNING closing tdb->fd failed!\n"));
4085 tdb->fd = open(tdb->name, tdb->open_flags & ~(O_CREAT|O_TRUNC), 0);
4086 if (tdb->fd == -1) {
4087 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: open failed (%s)\n", strerror(errno)));
4090 if ((tdb->flags & TDB_CLEAR_IF_FIRST) &&
4091 (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1)) {
4092 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: failed to obtain active lock\n"));
4095 if (fstat(tdb->fd, &st) != 0) {
4096 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: fstat failed (%s)\n", strerror(errno)));
4099 if (st.st_ino != tdb->inode || st.st_dev != tdb->device) {
4100 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: file dev/inode has changed!\n"));
4103 tdb_mmap(tdb);
4108 tdb_close(tdb);
4112 /* reopen all tdb's */
4115 struct tdb_context *tdb;
4117 for (tdb=tdbs; tdb; tdb = tdb->next) {
4122 * tdb opened with CLEAR_IF_FIRST. Thus
4131 tdb->flags &= ~TDB_CLEAR_IF_FIRST;
4134 if (tdb_reopen(tdb) != 0)