Lines Matching refs:tdb

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