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