Home | History | Annotate | Download | only in ext2fs

Lines Matching defs: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
109 #include "tdb.h"
124 #define TDB_MAGIC_FOOD "TDB file\n"
139 #define TDB_HASHTABLE_SIZE(tdb) ((tdb->header.hash_size+1)*sizeof(tdb_off_t))
146 /* NB assumes there is a local variable called "tdb" that is the
149 #define TDB_LOG(x) tdb->log.log_fn x
161 #define BUCKET(hash) ((hash) % tdb->header.hash_size)
163 #define DOCONV() (tdb->flags & TDB_CONVERT)
233 enum TDB_ERROR ecode; /* error code for last tdb error */
238 dev_t device; /* uniquely identifies this tdb */
239 ino_t inode; /* uniquely identifies this tdb */
256 static int tdb_munmap(struct tdb_context *tdb);
257 static void tdb_mmap(struct tdb_context *tdb);
258 static int tdb_lock(struct tdb_context *tdb, int list, int ltype);
259 static int tdb_unlock(struct tdb_context *tdb, int list, int ltype);
260 static int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, int rw_type, int lck_type, int probe, size_t len);
261 static int tdb_transaction_lock(struct tdb_context *tdb, int ltype);
262 static int tdb_transaction_unlock(struct tdb_context *tdb);
263 static int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len);
264 static int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off);
265 static int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off);
266 static int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
267 static int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
269 static int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec);
270 static tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_struct *rec);
271 static int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
272 static int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
273 static int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off);
274 static int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off);
275 static int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec);
276 static int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec);
277 static int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct list_struct *rec);
278 static unsigned char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len);
279 static int tdb_parse_data(struct tdb_context *tdb, TDB_DATA key,
284 static tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, int locktype,
286 static void tdb_io_init(struct tdb_context *tdb);
287 static int tdb_expand(struct tdb_context *tdb, tdb_off_t size);
288 static int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off,
294 enum TDB_ERROR tdb_error(struct tdb_context *tdb)
296 return tdb->ecode;
312 /* Error string for the last tdb error */
313 const char *tdb_errorstr(struct tdb_context *tdb)
317 if (tdb->ecode == emap[i].ecode)
334 int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset,
340 if (tdb->flags & TDB_NOLOCK) {
344 if ((rw_type == F_WRLCK) && (tdb->read_only || tdb->traverse_read)) {
345 tdb->ecode = TDB_ERR_RDONLY;
356 ret = fcntl(tdb->fd,lck_type,&fl);
365 tdb->ecode = TDB_ERR_LOCK;
366 TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d len=%d\n",
367 tdb->fd, offset, rw_type, lck_type, (int)len));
381 int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len)
386 if (tdb_brlock(tdb, offset, F_WRLCK, F_SETLKW, 1, len) == 0) {
397 TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock_upgrade failed at offset %d\n", offset));
403 static int _tdb_lock(struct tdb_context *tdb, int list, int ltype, int op)
412 if (tdb->global_lock.count &&
413 (ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) {
417 if (tdb->global_lock.count) {
421 if (list < -1 || list >= (int)tdb->header.hash_size) {
422 TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_lock: invalid list %d for ltype=%d\n",
426 if (tdb->flags & TDB_NOLOCK)
429 for (i=0; i<tdb->num_lockrecs; i++) {
430 if (tdb->lockrecs[i].list == list) {
431 if (tdb->lockrecs[i].count == 0) {
436 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lock: "
443 tdb->lockrecs[i].count++;
449 tdb->lockrecs,
450 sizeof(*tdb->lockrecs) * (tdb->num_lockrecs+1));
455 tdb->lockrecs = new_lck;
460 tdb->methods->tdb_brlock(tdb,FREELIST_TOP+4*list, ltype, op,
465 tdb->num_locks++;
467 tdb->lockrecs[tdb->num_lockrecs].list = list;
468 tdb->lockrecs[tdb->num_lockrecs].count = 1;
469 tdb->lockrecs[tdb->num_lockrecs].ltype = ltype;
470 tdb->num_lockrecs += 1;
476 int tdb_lock(struct tdb_context *tdb, int list, int ltype)
479 ret = _tdb_lock(tdb, list, ltype, F_SETLKW);
481 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lock failed on list %d "
488 int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype)
490 return _tdb_lock(tdb, list, ltype, F_SETLK);
497 int tdb_unlock(struct tdb_context *tdb, int list, int ltype)
507 if (tdb->global_lock.count &&
508 (ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) {
512 if (tdb->global_lock.count) {
516 if (tdb->flags & TDB_NOLOCK)
520 if (list < -1 || list >= (int)tdb->header.hash_size) {
521 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: list %d invalid (%d)\n", list, tdb->header.hash_size));
525 for (i=0; i<tdb->num_lockrecs; i++) {
526 if (tdb->lockrecs[i].list == list) {
527 lck = &tdb->lockrecs[i];
533 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: count is 0\n"));
552 ret = tdb->methods->tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK,
555 tdb->num_locks--;
562 if (tdb->num_lockrecs > 1) {
563 *lck = tdb->lockrecs[tdb->num_lockrecs-1];
565 tdb->num_lockrecs -= 1;
569 * a completely idle tdb we should get rid of the locked array.
572 if (tdb->num_lockrecs == 0) {
573 SAFE_FREE(tdb->lockrecs);
577 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: An error occurred unlocking!\n"));
584 int tdb_transaction_lock(struct tdb_context *tdb, int ltype)
586 if (tdb->have_transaction_lock || tdb->global_lock.count) {
589 if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, ltype,
591 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_lock: failed to get transaction lock\n"));
592 tdb->ecode = TDB_ERR_LOCK;
595 tdb->have_transaction_lock = 1;
602 int tdb_transaction_unlock(struct tdb_context *tdb)
605 if (!tdb->have_transaction_lock) {
608 ret = tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1);
610 tdb->have_transaction_lock = 0;
619 static int _tdb_lockall(struct tdb_context *tdb, int ltype, int op)
626 if (tdb->read_only || tdb->traverse_read)
629 if (tdb->global_lock.count && tdb->global_lock.ltype == ltype) {
630 tdb->global_lock.count++;
634 if (tdb->global_lock.count) {
639 if (tdb->num_locks != 0) {
645 tdb->methods->tdb_brlock(tdb, FREELIST_TOP, ltype, op,
646 0, 4*tdb->header.hash_size)) {
648 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lockall failed (%s)\n", strerror(errno)));
653 tdb->global_lock.count = 1;
654 tdb->global_lock.ltype = ltype;
662 static int _tdb_unlockall(struct tdb_context *tdb, int ltype)
669 if (tdb->read_only || tdb->traverse_read) {
673 if (tdb->global_lock.ltype != ltype || tdb->global_lock.count == 0) {
677 if (tdb->global_lock.count > 1) {
678 tdb->global_lock.count--;
683 tdb->methods->tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW,
684 0, 4*tdb->header.hash_size)) {
685 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlockall failed (%s)\n", strerror(errno)));
689 tdb->global_lock.count = 0;
690 tdb->global_lock.ltype = 0;
696 int tdb_lockall(struct tdb_context *tdb)
698 return _tdb_lockall(tdb, F_WRLCK, F_SETLKW);
702 int tdb_lockall_mark(struct tdb_context *tdb)
704 return _tdb_lockall(tdb, F_WRLCK | TDB_MARK_LOCK, F_SETLKW);
708 int tdb_lockall_unmark(struct tdb_context *tdb)
710 return _tdb_unlockall(tdb, F_WRLCK | TDB_MARK_LOCK);
714 int tdb_lockall_nonblock(struct tdb_context *tdb)
716 return _tdb_lockall(tdb, F_WRLCK, F_SETLK);
720 int tdb_unlockall(struct tdb_context *tdb)
722 return _tdb_unlockall(tdb, F_WRLCK);
726 int tdb_lockall_read(struct tdb_context *tdb)
728 return _tdb_lockall(tdb, F_RDLCK, F_SETLKW);
732 int tdb_lockall_read_nonblock(struct tdb_context *tdb)
734 return _tdb_lockall(tdb, F_RDLCK, F_SETLK);
738 int tdb_unlockall_read(struct tdb_context *tdb)
740 return _tdb_unlockall(tdb, F_RDLCK);
745 int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key)
747 return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
753 int tdb_chainlock_nonblock(struct tdb_context *tdb, TDB_DATA key)
755 return tdb_lock_nonblock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
759 int tdb_chainlock_mark(struct tdb_context *tdb, TDB_DATA key)
761 return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK | TDB_MARK_LOCK);
765 int tdb_chainlock_unmark(struct tdb_context *tdb, TDB_DATA key)
767 return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK | TDB_MARK_LOCK);
770 int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key)
772 return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
775 int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key)
777 return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK);
780 int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key)
782 return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK);
788 int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off)
790 return off ? tdb->methods->tdb_brlock(tdb, off, F_RDLCK, F_SETLKW, 0, 1) : 0;
798 int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off)
801 for (i = &tdb->travlocks; i; i = i->next)
804 return tdb->methods->tdb_brlock(tdb, off, F_WRLCK, F_SETLK, 1, 1);
811 int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off)
813 return tdb->methods->tdb_brlock(tdb, off, F_UNLCK, F_SETLK, 0, 1);
817 int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off)
824 for (i = &tdb->travlocks; i; i = i->next)
827 return (count == 1 ? tdb->methods->tdb_brlock(tdb, off, F_UNLCK, F_SETLKW, 0, 1) : 0);
837 static int tdb_oob(struct tdb_context *tdb, tdb_off_t len, int probe)
840 if (len <= tdb->map_size)
842 if (tdb->flags & TDB_INTERNAL) {
845 tdb->ecode = TDB_ERR_IO;
846 TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_oob len %d beyond internal malloc size %d\n",
847 (int)len, (int)tdb->map_size));
852 if (fstat(tdb->fd, &st) == -1) {
859 tdb->ecode = TDB_ERR_IO;
860 TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_oob len %d beyond eof at %d\n",
867 if (tdb_munmap(tdb) == -1)
869 tdb->map_size = st.st_size;
870 tdb_mmap(tdb);
875 static int tdb_write(struct tdb_context *tdb, tdb_off_t off,
882 if (tdb->read_only || tdb->traverse_read) {
883 tdb->ecode = TDB_ERR_RDONLY;
887 if (tdb->methods->tdb_oob(tdb, off + len, 0) != 0)
890 if (tdb->map_ptr) {
891 memcpy(off + (char *)tdb->map_ptr, buf, len);
892 } else if (pwrite(tdb->fd, buf, len, off) != (ssize_t)len) {
894 tdb->ecode = TDB_ERR_IO;
895 TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_write failed at %d len=%d (%s)\n",
913 static int tdb_read(struct tdb_context *tdb, tdb_off_t off, void *buf,
916 if (tdb->methods->tdb_oob(tdb, off + len, 0) != 0) {
920 if (tdb->map_ptr) {
921 memcpy(buf, off + (char *)tdb->map_ptr, len);
923 ssize_t ret = pread(tdb->fd, buf, len, off);
926 tdb->ecode = TDB_ERR_IO;
927 TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_read failed at %d "
930 (int)tdb->map_size));
946 static void tdb_next_hash_chain(struct tdb_context *tdb, u32 *chain)
949 if (tdb->map_ptr) {
950 for (;h < tdb->header.hash_size;h++) {
951 if (0 != *(u32 *)(TDB_HASH_TOP(h) + (unsigned char *)tdb->map_ptr)) {
957 for (;h < tdb->header.hash_size;h++) {
958 if (tdb_ofs_read(tdb, TDB_HASH_TOP(h), &off) != 0 || off != 0) {
967 int tdb_munmap(struct tdb_context *tdb)
969 if (tdb->flags & TDB_INTERNAL)
973 if (tdb->map_ptr) {
974 int ret = munmap(tdb->map_ptr, tdb->real_map_size);
977 tdb->real_map_size = 0;
980 tdb->map_ptr = NULL;
984 void tdb_mmap(struct tdb_context *tdb)
986 if (tdb->flags & TDB_INTERNAL)
990 if (!(tdb->flags & TDB_NOMMAP)) {
991 tdb->map_ptr = mmap(NULL, tdb->map_size,
992 PROT_READ|(tdb->read_only? 0:PROT_WRITE),
993 MAP_SHARED|MAP_FILE, tdb->fd, 0);
999 if (tdb->map_ptr == MAP_FAILED) {
1000 tdb->real_map_size = 0;
1001 tdb->map_ptr = NULL;
1002 TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_mmap failed for size %d (%s)\n",
1003 tdb->map_size, strerror(errno)));
1005 tdb->real_map_size = tdb->map_size;
1007 tdb->map_ptr = NULL;
1010 tdb->map_ptr = NULL;
1016 static int tdb_expand_file(struct tdb_context *tdb, tdb_off_t size, tdb_off_t addition)
1020 if (tdb->read_only || tdb->traverse_read) {
1021 tdb->ecode = TDB_ERR_RDONLY;
1025 if (ftruncate(tdb->fd, size+addition) == -1) {
1027 if (pwrite(tdb->fd, &b, 1, (size+addition) - 1) != 1) {
1028 TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file to %d failed (%s)\n",
1040 int ret = pwrite(tdb->fd, buf, n, size);
1042 TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file write of %d failed (%s)\n",
1055 int tdb_expand(struct tdb_context *tdb, tdb_off_t size)
1060 if (tdb_lock(tdb, -1, F_WRLCK) == -1) {
1061 TDB_LOG((tdb, TDB_DEBUG_ERROR, "lock failed in tdb_expand\n"));
1066 tdb->methods->tdb_oob(tdb, tdb->map_size + 1, 1);
1070 size = TDB_ALIGN(tdb->map_size + size*10, tdb->page_size) - tdb->map_size;
1072 if (!(tdb->flags & TDB_INTERNAL))
1073 tdb_munmap(tdb);
1082 if (!(tdb->flags & TDB_INTERNAL)) {
1083 if (tdb->methods->tdb_expand_file(tdb, tdb->map_size, size) != 0)
1087 tdb->map_size += size;
1089 if (tdb->flags & TDB_INTERNAL) {
1090 char *new_map_ptr = (char *)realloc(tdb->map_ptr,
1091 tdb->map_size);
1093 tdb->map_size -= size;
1096 tdb->map_ptr = new_map_ptr;
1105 tdb_mmap(tdb);
1113 offset = tdb->map_size - size;
1114 if (tdb_free(tdb, offset, &rec) == -1)
1117 tdb_unlock(tdb, -1, F_WRLCK);
1120 tdb_unlock(tdb, -1, F_WRLCK);
1125 int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d)
1127 return tdb->methods->tdb_read(tdb, offset, (char*)d, sizeof(*d), DOCONV());
1130 int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d)
1133 return tdb->methods->tdb_write(tdb, offset, CONVERT(off), sizeof(*d));
1138 unsigned char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len)
1149 tdb->ecode = TDB_ERR_OOM;
1150 TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_alloc_read malloc failed len=%d (%s)\n",
1154 if (tdb->methods->tdb_read(tdb, offset, buf, len, 0) == -1) {
1161 /* Give a piece of tdb data to a parser */
1163 int tdb_parse_data(struct tdb_context *tdb, TDB_DATA key,
1174 if ((tdb->transaction == NULL) && (tdb->map_ptr != NULL)) {
1179 if (tdb->methods->tdb_oob(tdb, offset+len, 0) != 0) {
1182 data.dptr = offset + (unsigned char *)tdb->map_ptr;
1186 if (!(data.dptr = tdb_alloc_read(tdb, offset, len))) {
1196 int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec)
1198 if (tdb->methods->tdb_read(tdb
1202 tdb->ecode = TDB_ERR_CORRUPT;
1203 TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_rec_read bad magic 0x%x at offset=%d\n", rec->magic, offset));
1206 return tdb->methods->tdb_oob(tdb, rec->next+sizeof(*rec), 0);
1209 int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec)
1212 return tdb->methods->tdb_write(tdb, offset, CONVERT(r), sizeof(r));
1227 void tdb_io_init(struct tdb_context *tdb)
1229 tdb->methods = &io_methods;
1249 tdb_free() the old record to place it on the normal tdb freelist
1269 - keep a mirrored copy of the tdb hash chain heads to allow for the
1273 - allow callers to mix transaction and non-transaction use of tdb,
1284 - check for a valid recovery record on open of the tdb, while the
1307 /* we keep a mirrored copy of the tdb hash heads here so
1340 static int transaction_read(struct tdb_context *tdb, tdb_off_t off, void *buf,
1346 for (el=tdb->transaction->elements_last;el;el=el->prev) {
1360 if (transaction_read(tdb, off, buf, partial, cv) != 0) {
1380 if (len != 0 && transaction_read(tdb, off, buf, len, cv) != 0) {
1388 return tdb->transaction->io_methods->tdb_read(tdb, off, buf, len, cv);
1391 TDB_LOG((tdb, TDB_DEBUG_FATAL, "transaction_read: failed at off=%d len=%d\n", off, len));
1392 tdb->ecode = TDB_ERR_IO;
1393 tdb->transaction->transaction_error = 1;
1401 static int transaction_write(struct tdb_context *tdb, tdb_off_t off,
1413 off < FREELIST_TOP+TDB_HASHTABLE_SIZE(tdb)) {
1415 memcpy(&tdb->transaction->hash_heads[chain], buf, len);
1419 for (el=tdb->transaction->elements_last;el;el=el->prev) {
1437 if (transaction_write(tdb, off, buf, partial) != 0) {
1454 if (len != 0 && transaction_write(tdb, off, buf, len) != 0) {
1463 (off+len < tdb->transaction->old_map_size ||
1464 off > tdb->transaction->old_map_size)) {
1470 tdb->ecode = TDB_ERR_OOM;
1471 tdb->transaction->transaction_error = 1;
1487 tdb->ecode = TDB_ERR_OOM;
1488 tdb->transaction->transaction_error = 1;
1492 el->prev = tdb->transaction->elements_last;
1498 tdb->ecode = TDB_ERR_OOM;
1499 tdb->transaction->transaction_error = 1;
1510 tdb->transaction->elements = el;
1512 tdb->transaction->elements_last = el;
1516 TDB_LOG((tdb, TDB_DEBUG_FATAL, "transaction_write: failed at off=%d len=%d\n", off, len));
1517 tdb->ecode = TDB_ERR_IO;
1518 tdb->transaction->transaction_error = 1;
1525 static void transaction_next_hash_chain(struct tdb_context *tdb, u32 *chain)
1528 for (;h < tdb->header.hash_size;h++) {
1530 if (0 != tdb->transaction->hash_heads[h+1]) {
1540 static int transaction_oob(struct tdb_context *tdb, tdb_off_t len, int probe)
1542 if (len <= tdb->map_size) {
1551 static int transaction_expand_file(struct tdb_context *tdb, tdb_off_t size,
1556 if (transaction_write(tdb, size, NULL, addition) != 0) {
1566 static int transaction_brlock(struct tdb_context *tdb, tdb_off_t offset,
1583 start a tdb transaction. No token is returned, as only a single
1586 int tdb_transaction_start(struct tdb_context *tdb)
1589 if (tdb->read_only || (tdb->flags & TDB_INTERNAL) || tdb->traverse_read) {
1590 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction on a read-only or internal db\n"));
1591 tdb->ecode = TDB_ERR_EINVAL;
1596 if (tdb->transaction != NULL) {
1597 tdb->transaction->nesting++;
1598 TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_start: nesting %d\n",
1599 tdb->transaction->nesting));
1603 if (tdb->num_locks != 0 || tdb->global_lock.count) {
1607 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction with locks held\n"));
1608 tdb->ecode = TDB_ERR_LOCK;
1612 if (tdb->travlocks.next != NULL) {
1616 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction within a traverse\n"));
1617 tdb->ecode = TDB_ERR_LOCK;
1621 tdb->transaction = (struct tdb_transaction *)
1623 if (tdb->transaction == NULL) {
1624 tdb->ecode = TDB_ERR_OOM;
1631 if (tdb_transaction_lock(tdb, F_WRLCK) == -1) {
1632 SAFE_FREE(tdb->transaction);
1638 if (tdb_brlock(tdb, FREELIST_TOP, F_RDLCK, F_SETLKW, 0, 0) == -1) {
1639 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: failed to get hash locks\n"));
1640 tdb->ecode = TDB_ERR_LOCK;
1646 tdb->transaction->hash_heads = (u32 *)
1647 calloc(tdb->header.hash_size+1, sizeof(u32));
1648 if (tdb->transaction->hash_heads == NULL) {
1649 tdb->ecode = TDB_ERR_OOM;
1652 if (tdb->methods->tdb_read(tdb, FREELIST_TOP, tdb->transaction->hash_heads,
1653 TDB_HASHTABLE_SIZE(tdb), 0) != 0) {
1654 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_start: failed to read hash heads\n"));
1655 tdb->ecode = TDB_ERR_IO;
1661 tdb->methods->tdb_oob(tdb, tdb->map_size + 1, 1);
1662 tdb->transaction->old_map_size = tdb->map_size;
1666 tdb->transaction->io_methods = tdb->methods;
1667 tdb->methods = &transaction_methods;
1671 if (transaction_write(tdb, FREELIST_TOP, tdb->transaction->hash_heads,
1672 TDB_HASHTABLE_SIZE(tdb)) != 0) {
1673 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_start: failed to prime hash table\n"));
1674 tdb->ecode = TDB_ERR_IO;
1675 tdb->methods = tdb->transaction->io_methods;
1682 tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0);
1683 tdb_transaction_unlock(tdb);
1684 SAFE_FREE(tdb->transaction->hash_heads);
1685 SAFE_FREE(tdb->transaction);
1693 int tdb_transaction_cancel(struct tdb_context *tdb)
1695 if (tdb->transaction == NULL) {
1696 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_cancel: no transaction\n"));
1700 if (tdb->transaction->nesting != 0) {
1701 tdb->transaction->transaction_error = 1;
1702 tdb->transaction->nesting--;
1706 tdb->map_size = tdb->transaction->old_map_size;
1709 while (tdb->transaction->elements) {
1710 struct tdb_transaction_el *el = tdb->transaction->elements;
1711 tdb->transaction->elements = el->next;
1717 if (tdb->global_lock.count != 0) {
1718 tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 4*tdb->header.hash_size);
1719 tdb->global_lock.count = 0;
1723 if (tdb->num_locks != 0) {
1725 for (i=0;i<tdb->num_lockrecs;i++) {
1726 tdb_brlock(tdb,FREELIST_TOP+4*tdb->lockrecs[i].list,
1729 tdb->num_locks = 0;
1730 tdb->num_lockrecs = 0;
1731 SAFE_FREE(tdb->lockrecs);
1735 tdb->methods = tdb->transaction->io_methods;
1737 tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0);
1738 tdb_transaction_unlock(tdb);
1739 SAFE_FREE(tdb->transaction->hash_heads);
1740 SAFE_FREE(tdb->transaction);
1748 static int transaction_sync(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t length)
1750 if (fsync(tdb->fd) != 0) {
1751 tdb->ecode = TDB_ERR_IO;
1752 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: fsync failed\n"));
1756 if (tdb->map_ptr) {
1757 tdb_off_t moffset = offset & ~(tdb->page_size-1);
1758 if (msync(moffset + (char *)tdb->map_ptr,
1760 tdb->ecode = TDB_ERR_IO;
1761 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: msync failed - %s\n",
1774 static tdb_len_t tdb_recovery_size(struct tdb_context *tdb)
1780 for (el=tdb->transaction->elements;el;el=el->next) {
1781 if (el->offset >= tdb->transaction->old_map_size) {
1794 static int tdb_recovery_allocate(struct tdb_context *tdb,
1800 const struct tdb_methods *methods = tdb->transaction->io_methods;
1803 if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) {
1804 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery head\n"));
1811 methods->tdb_read(tdb, recovery_head, &rec, sizeof(rec), DOCONV()) == -1) {
1812 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery record\n"));
1816 *recovery_size = tdb_recovery_size(tdb);
1831 if (tdb_free(tdb, recovery_head, &rec) == -1) {
1832 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to free previous recovery area\n"));
1838 *recovery_size = tdb_recovery_size(tdb);
1841 *recovery_max_size = TDB_ALIGN(sizeof(rec) + *recovery_size, tdb->page_size) - sizeof(rec);
1842 *recovery_offset = tdb->map_size;
1845 if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size,
1846 (tdb->map_size - tdb->transaction->old_map_size) +
1848 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to create recovery area\n"));
1853 methods->tdb_oob(tdb, tdb->map_size + 1, 1);
1857 tdb->transaction->old_map_size = tdb->map_size;
1862 if (methods->tdb_write(tdb, TDB_RECOVERY_HEAD,
1864 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to write recovery head\n"));
1875 static int transaction_setup_recovery(struct tdb_context *tdb,
1881 const struct tdb_methods *methods = tdb->transaction->io_methods;
1884 tdb_off_t old_map_size = tdb->transaction->old_map_size;
1890 if (tdb_recovery_allocate(tdb, &recovery_size,
1897 tdb->ecode = TDB_ERR_OOM;
1913 for (el=tdb->transaction->elements;el;el=el->next) {
1917 if (el->offset + el->length > tdb->transaction->old_map_size) {
1918 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: transaction data over new region boundary\n"));
1920 tdb->ecode = TDB_ERR_CORRUPT;
1931 if (methods->tdb_read(tdb, el->offset, p + 8, el->length, 0) != 0) {
1933 tdb->ecode = TDB_ERR_IO;
1945 if (methods->tdb_write(tdb, recovery_offset, data, sizeof(*rec) + recovery_size) == -1) {
1946 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: failed to write recovery data\n"));
1948 tdb->ecode = TDB_ERR_IO;
1955 if (transaction_sync(tdb, recovery_offset, sizeof(*rec) + recovery_size) == -1) {
1967 if (methods->tdb_write(tdb, *magic_offset, &magic, sizeof(magic)) == -1) {
1968 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: failed to write recovery magic\n"));
1969 tdb->ecode = TDB_ERR_IO;
1974 if (transaction_sync(tdb, *magic_offset, sizeof(magic)) == -1) {
1984 int tdb_transaction_commit(struct tdb_context *tdb)
1990 if (tdb->transaction == NULL) {
1991 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: no transaction\n"));
1995 if (tdb->transaction->transaction_error) {
1996 tdb->ecode = TDB_ERR_IO;
1997 tdb_transaction_cancel(tdb);
1998 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: transaction error pending\n"));
2002 if (tdb->transaction->nesting != 0) {
2003 tdb->transaction->nesting--;
2008 if (tdb->transaction->elements == NULL) {
2009 tdb_transaction_cancel(tdb);
2013 methods = tdb->transaction->io_methods;
2017 if (tdb->num_locks || tdb->global_lock.count) {
2018 tdb->ecode = TDB_ERR_LOCK;
2019 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: locks pending on commit\n"));
2020 tdb_transaction_cancel(tdb);
2025 if (tdb_brlock_upgrade(tdb, FREELIST_TOP, 0) == -1) {
2026 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: failed to upgrade hash locks\n"));
2027 tdb->ecode = TDB_ERR_LOCK;
2028 tdb_transaction_cancel(tdb);
2034 if (tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) {
2035 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: failed to get global lock\n"));
2036 tdb->ecode = TDB_ERR_LOCK;
2037 tdb_transaction_cancel(tdb);
2041 if (!(tdb->flags & TDB_NOSYNC)) {
2043 if (transaction_setup_recovery(tdb, &magic_offset) == -1) {
2044 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: failed to setup recovery data\n"));
2045 tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1);
2046 tdb_transaction_cancel(tdb);
2052 if (tdb->map_size != tdb->transaction->old_map_size) {
2053 if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size,
2054 tdb->map_size -
2055 tdb->transaction->old_map_size) == -1) {
2056 tdb->ecode = TDB_ERR_IO;
2057 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: expansion failed\n"));
2058 tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1);
2059 tdb_transaction_cancel(tdb);
2062 tdb->map_size = tdb->transaction->old_map_size;
2063 methods->tdb_oob(tdb, tdb->map_size + 1, 1);
2067 while (tdb->transaction->elements) {
2068 struct tdb_transaction_el *el = tdb->transaction->elements;
2070 if (methods->tdb_write(tdb, el->offset, el->data, el->length) == -1) {
2071 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed during commit\n"));
2076 tdb->methods = methods;
2077 tdb_transaction_recover(tdb);
2079 tdb_transaction_cancel(tdb);
2080 tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1);
2082 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed\n"));
2085 tdb->transaction->elements = el->next;
2090 if (!(tdb->flags & TDB_NOSYNC)) {
2092 if (transaction_sync(tdb, 0, tdb->map_size) == -1) {
2097 if (methods->tdb_write(tdb, magic_offset, &zero, 4) == -1) {
2098 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: failed to remove recovery magic\n"));
2103 if (transaction_sync(tdb, magic_offset, 4) == -1) {
2108 tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1);
2118 not be backed up (as tdb rounding to block sizes means that
2122 utime(tdb->name, NULL);
2127 tdb_transaction_cancel(tdb);
2137 int tdb_transaction_recover(struct tdb_context *tdb)
2145 if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) {
2146 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery head\n"));
2147 tdb->ecode = TDB_ERR_IO;
2157 if (tdb->methods->tdb_read(tdb, recovery_head, &rec,
2159 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery record\n"));
2160 tdb->ecode = TDB_ERR_IO;
2169 if (tdb->read_only) {
2170 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: attempt to recover read only database\n"));
2171 tdb->ecode = TDB_ERR_CORRUPT;
2179 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to allocate recovery data\n"));
2180 tdb->ecode = TDB_ERR_OOM;
2185 if (tdb->methods->tdb_read(tdb, recovery_head + sizeof(rec), data,
2187 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery data\n"));
2188 tdb->ecode = TDB_ERR_IO;
2202 if (tdb->methods->tdb_write(tdb, ofs, p+8, len) == -1) {
2204 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to recover %d bytes at offset %d\n", len, ofs));
2205 tdb->ecode = TDB_ERR_IO;
2213 if (transaction_sync(tdb, 0, tdb->map_size) == -1) {
2214 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to sync recovery\n"));
2215 tdb->ecode = TDB_ERR_IO;
2221 if (tdb_ofs_write(tdb, TDB_RECOVERY_HEAD, &zero) == -1) {
2222 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to remove recovery head\n"));
2223 tdb->ecode = TDB_ERR_IO;
2229 if (tdb_ofs_write(tdb, recovery_head + offsetof(struct list_struct, magic),
2231 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to remove recovery magic\n"));
2232 tdb->ecode = TDB_ERR_IO;
2237 tdb_munmap(tdb);
2238 if (ftruncate(tdb->fd, recovery_eof) != 0) {
2239 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to reduce to recovery size\n"));
2240 tdb->ecode = TDB_ERR_IO;
2243 tdb->map_size = recovery_eof;
2244 tdb_mmap(tdb);
2246 if (transaction_sync(tdb, 0, recovery_eof) == -1) {
2247 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to sync2 recovery\n"));
2248 tdb->ecode = TDB_ERR_IO;
2252 TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_recover: recovered %d byte database\n",
2262 static int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list_struct *rec)
2264 if (tdb->methods->tdb_read(tdb, off, rec, sizeof(*rec),DOCONV()) == -1)
2270 TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_rec_free_read non-free magic 0x%x at offset=%d - fixing\n",
2273 if (tdb->methods->tdb_write(tdb, off, rec, sizeof(*rec)) == -1)
2279 tdb->ecode = TDB_ERR_CORRUPT;
2280 TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_rec_free_read bad magic 0x%x at offset=%d\n",
2284 if (tdb->methods->tdb_oob(tdb, rec->next+sizeof(*rec), 0) != 0)
2292 static int remove_from_freelist(struct tdb_context *tdb, tdb_off_t off, tdb_off_t next)
2298 while (tdb_ofs_read(tdb, last_ptr, &i) != -1 && i != 0) {
2301 return tdb_ofs_write(tdb, last_ptr, &next);
2306 TDB_LOG((tdb, TDB_DEBUG_FATAL,"remove_from_freelist: not on list at off=%d\n", off));
2312 static int update_tailer(struct tdb_context *tdb, tdb_off_t offset,
2319 tdb, offset + totalsize - sizeof(tdb_off_t),
2325 int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec)
2330 if (tdb_lock(tdb, -1, F_WRLCK) != 0)
2334 if (update_tailer(tdb, offset, rec) != 0) {
2335 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: update_tailer failed!\n"));
2341 if (right + sizeof(*rec) <= tdb->map_size) {
2344 if (tdb->methods->tdb_read(tdb, right, &r, sizeof(r), DOCONV()) == -1) {
2345 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: right read failed at %u\n", right));
2351 if (remove_from_freelist(tdb, right, r.next) == -1) {
2352 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: right free failed at %u\n", right));
2362 if (left > TDB_DATA_START(tdb->header.hash_size)) {
2367 if (tdb_ofs_read(tdb, left, &leftsize) == -1) {
2368 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left offset read failed at %u\n", left));
2380 if (tdb->methods->tdb_read(tdb, left, &l, sizeof(l), DOCONV()) == -1) {
2381 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left read failed at %u (%u)\n", left, leftsize));
2387 if (remove_from_freelist(tdb, left, l.next) == -1) {
2388 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left free failed at %u\n", left));
2398 if (update_tailer(tdb, offset, rec) == -1) {
2399 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: update_tailer failed at %u\n", offset));
2406 if (tdb_ofs_read(tdb, FREELIST_TOP, &rec->next) == -1 ||
2407 tdb_rec_write(tdb, offset, rec) == -1 ||
2408 tdb_ofs_write(tdb, FREELIST_TOP, &offset) == -1) {
2409 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free record write failed at offset=%d\n", offset));
2414 tdb_unlock(tdb, -1, F_WRLCK);
2418 tdb_unlock(tdb, -1, F_WRLCK);
2427 static tdb_off_t tdb_allocate_ofs(struct tdb_context *tdb, tdb_len_t length, tdb_off_t rec_ptr,
2451 if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1) {
2460 if (tdb_rec_write(tdb, rec_ptr, rec) == -1) {
2468 if (update_tailer(tdb, rec_ptr, rec) == -1) {
2473 if (tdb_free(tdb, newrec_ptr, &newrec) == -1) {
2488 tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_struct *rec)
2496 if (tdb_lock(tdb, -1, F_WRLCK) == -1)
2506 if (tdb_ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1)
2519 if (tdb_rec_free_read(tdb, rec_ptr, rec) == -1) {
2544 if (tdb_rec_free_read(tdb, bestfit.rec_ptr, rec) == -1) {
2548 newrec_ptr = tdb_allocate_ofs(tdb, length, bestfit.rec_ptr, rec, bestfit.last_ptr);
2549 tdb_unlock(tdb, -1, F_WRLCK);
2555 if (tdb_expand(tdb, length + sizeof(*rec)) == 0)
2558 tdb_unlock(tdb, -1, F_WRLCK);
2566 checker. Heh heh - uses an in memory tdb as the storage
2582 int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries)
2591 mem_tdb = tdb_open("flval", tdb->header.hash_size,
2597 if (tdb_lock(tdb, -1, F_WRLCK) == -1) {
2611 if (tdb_ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1) {
2626 if (tdb_rec_free_read(tdb, rec_ptr, &rec) == -1) {
2641 tdb_unlock(tdb, -1, F_WRLCK);
2648 static int tdb_next_lock(struct tdb_context *tdb, struct tdb_traverse_lock *tlock,
2654 for (; tlock->hash < tdb->header.hash_size; tlock->hash++) {
2658 common for the use of tdb with ldb, where large
2684 tdb->methods->next_hash_chain(tdb, &tlock->hash);
2685 if (tlock->hash == tdb->header.hash_size) {
2690 if (tdb_lock(tdb, tlock->hash, tlock->lock_rw) == -1)
2695 if (tdb_ofs_read(tdb, TDB_HASH_TOP(tlock->hash),
2700 if (tdb_unlock_record(tdb, tlock->off) != 0)
2706 if (tdb_rec_read(tdb, tlock->off, rec) == -1)
2714 if (tdb_rec_read(tdb, tlock->off, rec) == -1)
2719 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_next_lock: loop detected.\n"));
2725 if (tdb_lock_record(tdb, tlock->off) != 0)
2733 if (!(tdb->read_only || tdb->traverse_read) &&
2734 tdb_do_delete(tdb, current, rec) != 0)
2737 tdb_unlock(tdb, tlock->hash, tlock->lock_rw);
2745 if (tdb_unlock(tdb, tlock->hash, tlock->lock_rw) != 0)
2746 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_next_lock: On error unlock failed!\n"));
2750 /* traverse the entire database - calling fn(tdb, key, data) on each element.
2755 static int tdb_traverse_internal(struct tdb_context *tdb,
2766 tl->next = tdb->travlocks.next;
2769 tdb->travlocks.next = tl;
2772 while ((ret = tdb_next_lock(tdb, tl, &rec)) > 0) {
2775 key.dptr = tdb_alloc_read(tdb, tl->off + sizeof(rec),
2779 if (tdb_unlock(tdb, tl->hash, tl->lock_rw) != 0)
2781 if (tdb_unlock_record(tdb, tl->off) != 0)
2782 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_traverse: key.dptr == NULL and unlock_record failed!\n"));
2790 if (tdb_unlock(tdb, tl->hash, tl->lock_rw) != 0) {
2795 if (fn && fn(tdb, key, dbuf, private_data)) {
2798 if (tdb_unlock_record(tdb, tl->off) != 0) {
2799 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_traverse: unlock_record failed!\n"));;
2808 tdb->travlocks.next = tl->next;
2819 int tdb_traverse_read(struct tdb_context *tdb,
2827 if (tdb_transaction_lock(tdb, F_RDLCK)) {
2831 tdb->traverse_read++;
2832 ret = tdb_traverse_internal(tdb, fn, private_data, &tl);
2833 tdb->traverse_read--;
2835 tdb_transaction_unlock(tdb);
2844 int tdb_traverse(struct tdb_context *tdb,
2850 if (tdb->read_only || tdb->traverse_read) {
2851 return tdb_traverse_read(tdb, fn, private_data);
2854 if (tdb_transaction_lock(tdb, F_WRLCK)) {
2858 ret = tdb_traverse_internal(tdb, fn, private_data, &tl);
2860 tdb_transaction_unlock(tdb);
2867 TDB_DATA tdb_firstkey(struct tdb_context *tdb)
2873 if (tdb_unlock_record(tdb, tdb->travlocks.off) != 0)
2875 tdb->travlocks.off = tdb->travlocks.hash = 0;
2876 tdb->travlocks.lock_rw = F_RDLCK;
2879 if (tdb_next_lock(tdb, &tdb->travlocks, &rec) <= 0)
2883 key.dptr =tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),key.dsize);
2886 if (tdb_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0)
2887 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_firstkey: error occurred while tdb_unlocking!\n"));
2892 TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA oldkey)
2900 if (tdb->travlocks.off) {
2901 if (tdb_lock(tdb,tdb->travlocks.hash,tdb->travlocks.lock_rw))
2903 if (tdb_rec_read(tdb, tdb->travlocks.off, &rec) == -1
2904 || !(k = tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),
2908 if (tdb_unlock_record(tdb, tdb->travlocks.off) != 0) {
2912 if (tdb_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0) {
2916 tdb->travlocks.off = 0;
2922 if (!tdb->travlocks.off) {
2924 tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb->hash_fn(&oldkey), tdb->travlocks.lock_rw, &rec);
2925 if (!tdb->travlocks.off)
2927 tdb
2928 if (tdb_lock_record(tdb, tdb->travlocks.off) != 0) {
2929 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: lock_record failed (%s)!\n", strerror(errno)));
2933 oldhash = tdb->travlocks.hash;
2937 if (tdb_next_lock(tdb, &tdb->travlocks, &rec) > 0) {
2939 key.dptr = tdb_alloc_read(tdb, tdb->travlocks.off+sizeof(rec),
2942 if (tdb_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0)
2943 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: WARNING tdb_unlock failed!\n"));
2946 if (tdb_unlock(tdb, BUCKET(oldhash), tdb->travlocks.lock_rw) != 0)
2947 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: WARNING tdb_unlock failed!\n"));
2953 static tdb_off_t tdb_dump_record(struct tdb_context *tdb, int hash,
2959 if (tdb->methods->tdb_read(tdb, offset, (char *)&rec,
2972 if (tdb_ofs_read(tdb, tailer_ofs, &tailer) == -1) {
2984 static int tdb_dump_chain(struct tdb_context *tdb, int i)
2990 if (tdb_lock(tdb, i, F_WRLCK) != 0)
2993 if (tdb_ofs_read(tdb, top, &rec_ptr) == -1)
2994 return tdb_unlock(tdb, i, F_WRLCK);
3000 rec_ptr = tdb_dump_record(tdb, i, rec_ptr);
3003 return tdb_unlock(tdb, i, F_WRLCK);
3006 void tdb_dump_all(struct tdb_context *tdb)
3009 for (i=0;i<tdb->header.hash_size;i++) {
3010 tdb_dump_chain(tdb, i);
3013 tdb_dump_chain(tdb, -1);
3016 int tdb_printfreelist(struct tdb_context *tdb)
3023 if ((ret = tdb_lock(tdb, -1, F_WRLCK)) != 0)
3029 if (tdb_ofs_read(tdb, offset, &rec_ptr) == -1) {
3030 tdb_unlock(tdb, -1, F_WRLCK);
3036 if (tdb->methods->tdb_read(tdb, rec_ptr, (char *)&rec,
3038 tdb_unlock(tdb, -1, F_WRLCK);
3044 tdb_unlock(tdb, -1, F_WRLCK);
3058 return tdb_unlock(tdb, -1, F_WRLCK);
3061 /* file: tdb.c */
3064 non-blocking increment of the tdb sequence number if the tdb has been opened using
3067 void tdb_increment_seqnum_nonblock(struct tdb_context *tdb)
3071 if (!(tdb->flags & TDB_SEQNUM)) {
3078 tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum);
3080 tdb_ofs_write(tdb, TDB_SEQNUM_OFS, &seqnum);
3084 increment the tdb sequence number if the tdb has been opened using
3087 static void tdb_increment_seqnum(struct tdb_context *tdb)
3089 if (!(tdb->flags & TDB_SEQNUM)) {
3093 if (tdb_brlock(tdb, TDB_SEQNUM_OFS, F_WRLCK, F_SETLKW, 1, 1) != 0) {
3097 tdb_increment_seqnum_nonblock(tdb);
3099 tdb_brlock(tdb, TDB_SEQNUM_OFS, F_UNLCK, F_SETLKW, 1, 1);
3109 static tdb_off_t tdb_find(struct tdb_context *tdb, TDB_DATA key, u32 hash,
3115 if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
3120 if (tdb_rec_read(tdb, rec_ptr, r) == -1)
3125 && tdb_parse_data(tdb, key, rec_ptr + sizeof(*r),
3136 tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, int locktype,
3141 if (tdb_lock(tdb, BUCKET(hash), locktype) == -1)
3143 if (!(rec_ptr = tdb_find(tdb, key, hash, rec)))
3144 tdb_unlock(tdb, BUCKET(hash), locktype);
3153 static int tdb_update_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, TDB_DATA dbuf)
3159 if (!(rec_ptr = tdb_find(tdb, key, hash, &rec)))
3164 tdb->ecode = TDB_SUCCESS; /* Not really an error */
3168 if (tdb->methods->tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len,
3175 return tdb_rec_write(tdb, rec_ptr, &rec);
3187 TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key)
3195 hash = tdb->hash_fn(&key);
3196 if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec)))
3199 ret.dptr = tdb_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len,
3202 tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK);
3211 * DONT CALL OTHER TDB CALLS FROM THE PARSER, THIS MIGHT LEAD TO SEGFAULTS.
3213 * For mmapped tdb's that do not have a transaction open it points the parsing
3219 * the tdb records, ldb indexes being one example.
3222 int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key,
3233 hash = tdb->hash_fn(&key);
3235 if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) {
3239 ret = tdb_parse_data(tdb, key, rec_ptr + sizeof(rec) + rec.key_len,
3242 tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK);
3253 static int tdb_exists_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash)
3257 if (tdb_find_lock_hash(tdb, key, hash, F_RDLCK, &rec) == 0)
3259 tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK);
3263 int tdb_exists(struct tdb_context *tdb, TDB_DATA key)
3265 u32 hash = tdb->hash_fn(&key);
3266 return tdb_exists_hash(tdb, key, hash);
3270 int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct list_struct*rec)
3275 if (tdb->read_only || tdb->traverse_read) return -1;
3277 if (tdb_write_lock_record(tdb, rec_ptr) == -1) {
3280 return tdb_rec_write(tdb, rec_ptr, rec);
3282 if (tdb_write_unlock_record(tdb, rec_ptr) != 0)
3286 if (tdb_ofs_read(tdb, TDB_HASH_TOP(rec->full_hash), &i) == -1)
3289 if (tdb_rec_read(tdb, i, &lastrec) == -1)
3295 if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1)
3299 if (tdb_free(tdb, rec_ptr, rec) == -1)
3304 static int tdb_count_dead(struct tdb_context *tdb, u32 hash)
3311 if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
3315 if (tdb_rec_read(tdb, rec_ptr, &rec) == -1)
3329 static int tdb_purge_dead(struct tdb_context *tdb, u32 hash)
3335 if (tdb_lock(tdb, -1, F_WRLCK) == -1) {
3340 if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
3346 if (tdb_rec_read(tdb, rec_ptr, &rec) == -1) {
3353 && tdb_do_delete(tdb, rec_ptr, &rec) == -1) {
3360 tdb_unlock(tdb, -1, F_WRLCK);
3365 static int tdb_delete_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash)
3371 if (tdb->max_dead_records != 0) {
3375 * tdb's with a very high create/delete rate like locking.tdb.
3378 if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
3381 if (tdb_count_dead(tdb, hash) >= tdb->max_dead_records) {
3386 tdb_purge_dead(tdb, hash);
3389 if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) {
3390 tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
3398 ret = tdb_rec_write(tdb, rec_ptr, &rec);
3401 if (!(rec_ptr = tdb_find_lock_hash(tdb, key, hash, F_WRLCK,
3405 ret = tdb_do_delete(tdb, rec_ptr, &rec);
3409 tdb_increment_seqnum(tdb);
3412 if (tdb_unlock(tdb, BUCKET(rec.full_hash), F_WRLCK) != 0)
3413 TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_delete: WARNING tdb_unlock failed!\n"));
3417 int tdb_delete(struct tdb_context *tdb, TDB_DATA key)
3419 u32 hash = tdb->hash_fn(&key);
3420 return tdb_delete_hash(tdb, key, hash);
3426 static tdb_off_t tdb_find_dead(struct tdb_context *tdb, u32 hash,
3432 if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
3437 if (tdb_rec_read(tdb, rec_ptr, r) == -1)
3457 int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
3465 if (tdb->read_only || tdb->traverse_read) {
3466 tdb->ecode = TDB_ERR_RDONLY;
3471 hash = tdb->hash_fn(&key);
3472 if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
3477 if (tdb_exists_hash(tdb, key, hash)) {
3478 tdb->ecode = TDB_ERR_EXISTS;
3483 if (tdb_update_hash(tdb, key, hash, dbuf) == 0) {
3486 if (tdb->ecode == TDB_ERR_NOEXIST &&
3494 tdb->ecode = TDB_SUCCESS;
3500 tdb_delete_hash(tdb, key, hash);
3503 fails and we are left with a dead spot in the tdb. */
3506 tdb->ecode = TDB_ERR_OOM;
3514 if (tdb->max_dead_records != 0) {
3522 tdb, hash, &rec,
3530 if (tdb_rec_write(tdb, rec_ptr, &rec) == -1
3531 || tdb->methods->tdb_write(
3532 tdb, rec_ptr + sizeof(rec),
3546 if (tdb_lock(tdb, -1, F_WRLCK) == -1) {
3550 if ((tdb->max_dead_records != 0)
3551 && (tdb_purge_dead(tdb, hash) == -1)) {
3552 tdb_unlock(tdb, -1, F_WRLCK);
3557 rec_ptr = tdb_allocate(tdb, key.dsize + dbuf.dsize, &rec);
3559 tdb_unlock(tdb, -1, F_WRLCK);
3566 if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1)
3575 if (tdb_rec_write(tdb, rec_ptr, &rec) == -1
3576 || tdb->methods->tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+dbuf.dsize)==-1
3577 || tdb_ofs_write(tdb
3586 tdb_increment_seqnum(tdb);
3590 tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
3596 int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)
3603 hash = tdb->hash_fn(&key);
3604 if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
3607 dbuf = tdb_fetch(tdb, key);
3621 tdb->ecode = TDB_ERR_OOM;
3628 ret = tdb_store(tdb, key, dbuf, 0);
3631 tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
3638 return the name of the current tdb file
3641 const char *tdb_name(struct tdb_context *tdb)
3643 return tdb->name;
3647 return the underlying file descriptor being used by tdb, or -1
3651 int tdb_fd(struct tdb_context *tdb)
3653 return tdb->fd;
3658 useful for external tdb routines that wish to log tdb errors
3660 tdb_log_func tdb_log_fn(struct tdb_context *tdb)
3662 return tdb->log.log_fn;
3667 get the tdb sequence number. Only makes sense if the writers opened
3671 made. If you want a counter then use a tdb record.
3674 test of a possible tdb change.
3676 int tdb_get_seqnum(struct tdb_context *tdb)
3680 tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum);
3684 int tdb_hash_size(struct tdb_context *tdb)
3686 return tdb->header.hash_size;
3689 size_t tdb_map_size(struct tdb_context *tdb)
3691 return tdb->map_size;
3694 int tdb_get_flags(struct tdb_context *tdb)
3696 return tdb->flags;
3701 enable sequence number handling on an open tdb
3703 void tdb_enable_seqnum(struct tdb_context *tdb)
3705 tdb->flags |= TDB_SEQNUM;
3729 static int tdb_new_database(struct tdb_context *tdb, int hash_size)
3742 if (tdb->flags & TDB_INTERNAL) {
3743 tdb->map_size = size;
3744 tdb->map_ptr = (char *)newdb;
3745 memcpy(&tdb->header, newdb, sizeof(tdb->header));
3750 if (lseek(tdb->fd, 0, SEEK_SET) == -1)
3753 if (ftruncate(tdb->fd, 0) == -1)
3758 memcpy(&tdb->header, newdb, sizeof(tdb->header));
3761 if (write(tdb->fd, newdb, size) != size) {
3805 static void null_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4);
3806 static void null_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...)
3816 struct tdb_context *tdb;
3822 if (!(tdb = (struct tdb_context *)calloc(1, sizeof *tdb))) {
3827 tdb_io_init(tdb);
3828 tdb->fd = -1;
3829 tdb->name = NULL;
3830 tdb->map_ptr = NULL;
3831 tdb->flags = tdb_flags;
3832 tdb->open_flags = open_flags;
3834 tdb->log = *log_ctx;
3836 tdb->log.log_fn = null_log_fn;
3837 tdb->log.log_private = NULL;
3839 tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash;
3842 tdb->page_size = sysconf(_SC_PAGESIZE);
3843 if (tdb->page_size <= 0) {
3844 tdb->page_size = 0x2000;
3848 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: can't open tdb %s write-only\n",
3857 tdb->read_only = 1;
3859 tdb->flags |= TDB_NOLOCK;
3860 tdb->flags &= ~TDB_CLEAR_IF_FIRST;
3864 if (tdb->flags & TDB_INTERNAL) {
3865 tdb->flags |= (TDB_NOLOCK | TDB_NOMMAP);
3866 tdb->flags &= ~TDB_CLEAR_IF_FIRST;
3867 if (tdb_new_database(tdb, hash_size) != 0) {
3868 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: tdb_new_database failed!"));
3874 if ((tdb->fd = open(name, open_flags, mode)) == -1) {
3875 TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_open_ex: could not open file %s: %s\n",
3881 if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) {
3882 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to get global lock on %s: %s\n",
3889 (locked = (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0, 1) == 0))) {
3891 if (ftruncate(tdb->fd, 0) == -1) {
3892 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: "
3899 if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header)
3900 || strcmp(tdb->header.magic_food, TDB_MAGIC_FOOD) != 0
3901 || (tdb->header.version != TDB_VERSION
3902 && !(rev = (tdb->header.version==TDB_BYTEREV(TDB_VERSION))))) {
3904 if (!(open_flags & O_CREAT) || tdb_new_database(tdb, hash_size) == -1) {
3908 rev = (tdb->flags & TDB_CONVERT);
3910 vp = (unsigned char *)&tdb->header.version;
3913 tdb->flags |= (vertest==TDB_VERSION) ? TDB_BIGENDIAN : 0;
3915 tdb->flags &= ~TDB_CONVERT;
3917 tdb->flags |= TDB_CONVERT;
3918 tdb_convert(&tdb->header, sizeof(tdb->header));
3920 if (fstat(tdb->fd, &st) == -1)
3923 if (tdb->header.rwlocks != 0) {
3924 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: spinlocks no longer supported\n"));
3930 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: "
3937 if (!(tdb->name = (char *)strdup(name))) {
3942 tdb->map_size = st.st_size;
3943 tdb->device = st.st_dev;
3944 tdb->inode = st.st_ino;
3945 tdb->max_dead_records = 0;
3946 tdb_mmap(tdb);
3948 if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0, 1) == -1) {
3949 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: "
3963 if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1)
3968 if (tdb_transaction_recover(tdb) == -1) {
3976 if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1) == -1)
3978 tdb->next = tdbs;
3979 tdbs = tdb;
3980 return tdb;
3985 if (!tdb)
3988 if (tdb->map_ptr) {
3989 if (tdb->flags & TDB_INTERNAL)
3990 SAFE_FREE(tdb->map_ptr);
3992 tdb_munmap(tdb);
3994 SAFE_FREE(tdb->name);
3995 if (tdb->fd != -1)
3996 if (close(tdb->fd) != 0)
3997 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to close tdb->fd on error!\n"));
3998 SAFE_FREE(tdb);
4008 void tdb_set_max_dead(struct tdb_context *tdb, int max_dead)
4010 tdb->max_dead_records = max_dead;
4018 int tdb_close(struct tdb_context *tdb)
4023 if (tdb->transaction) {
4024 tdb_transaction_cancel(tdb);
4027 if (tdb->map_ptr) {
4028 if (tdb->flags & TDB_INTERNAL)
4029 SAFE_FREE(tdb->map_ptr);
4031 tdb_munmap(tdb);
4033 SAFE_FREE(tdb->name);
4034 if (tdb->fd != -1)
4035 ret = close(tdb->fd);
4036 SAFE_FREE(tdb->lockrecs);
4040 if (*i == tdb) {
4041 *i = tdb->next;
4046 memset(tdb, 0, sizeof(*tdb));
4047 SAFE_FREE(tdb);
4053 void tdb_set_logging_function(struct tdb_context *tdb,
4056 tdb->log = *log_ctx;
4059 void *tdb_get_logging_private(struct tdb_context *tdb)
4061 return tdb->log.log_private;
4064 /* reopen a tdb - this can be used after a fork to ensure that we have an independent
4066 int tdb_reopen(struct tdb_context *tdb)
4070 if (tdb->flags & TDB_INTERNAL) {
4074 if (tdb->num_locks != 0 || tdb->global_lock.count) {
4075 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed with locks held\n"));
4079 if (tdb->transaction != 0) {
4080 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed inside a transaction\n"));
4084 if (tdb_munmap(tdb) != 0) {
4085 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: munmap failed (%s)\n", strerror(errno)));
4088 if (close(tdb->fd) != 0)
4089 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: WARNING closing tdb->fd failed!\n"));
4090 tdb->fd = open(tdb->name, tdb->open_flags & ~(O_CREAT|O_TRUNC), 0);
4091 if (tdb->fd == -1) {
4092 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: open failed (%s)\n", strerror(errno)));
4095 if ((tdb->flags & TDB_CLEAR_IF_FIRST) &&
4096 (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1)) {
4097 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: failed to obtain active lock\n"));
4100 if (fstat(tdb->fd, &st) != 0) {
4101 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: fstat failed (%s)\n", strerror(errno)));
4104 if (st.st_ino != tdb->inode || st.st_dev != tdb->device) {
4105 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: file dev/inode has changed!\n"));
4108 tdb_mmap(tdb);
4113 tdb_close(tdb);
4117 /* reopen all tdb's */
4120 struct tdb_context *tdb;
4122 for (tdb=tdbs; tdb; tdb = tdb->next) {
4127 * tdb opened with CLEAR_IF_FIRST. Thus
4136 tdb->flags &= ~TDB_CLEAR_IF_FIRST;
4139 if (tdb_reopen(tdb) != 0)
4149 int tdb_flush(struct tdb_context *tdb)
4151 if (tdb->fd != -1)
4152 return fsync(tdb->fd);