1 #include <tdb_compat.h>
3 /* Note: for the moment, we only need this file for TDB2, so we can
6 TDB_DATA tdb_null = { NULL, 0 };
8 /* Proxy which sets waitflag to false so we never block. */
9 static int lock_nonblock(int fd, int rw, off_t off, off_t len, bool waitflag,
12 struct tdb_attribute_flock *orig = _orig;
14 return orig->lock(fd, rw, off, len, false, orig->data);
17 enum TDB_ERROR tdb_transaction_start_nonblock(struct tdb_context *tdb)
19 union tdb_attribute locking, orig;
22 orig.base.attr = TDB_ATTRIBUTE_FLOCK;
23 ecode = tdb_get_attribute(tdb, &orig);
24 if (ecode != TDB_SUCCESS)
27 /* Replace locking function with our own. */
29 locking.flock.data = &orig;
30 locking.flock.lock = lock_nonblock;
32 ecode = tdb_set_attribute(tdb, &locking);
33 if (ecode != TDB_SUCCESS)
36 ecode = tdb_transaction_start(tdb);
37 tdb_unset_attribute(tdb, TDB_ATTRIBUTE_FLOCK);
42 * This handles TDB_CLEAR_IF_FIRST.
44 static enum TDB_ERROR clear_if_first(int fd, void *unused)
46 /* We hold a lock offset 63 always, so we can tell if anyone else is. */
50 fl.l_whence = SEEK_SET;
54 if (fcntl(fd, F_SETLK, &fl) == 0) {
55 /* We must be first ones to open it w/ TDB_CLEAR_IF_FIRST! */
56 if (ftruncate(fd, 0) != 0) {
61 if (fcntl(fd, F_SETLKW, &fl) != 0) {
68 tdb_open_compat_(const char *name, int hash_size_unused,
69 int tdb_flags, int open_flags, mode_t mode,
70 void (*log_fn)(struct tdb_context *,
76 union tdb_attribute cif, log, *attr = NULL;
79 log.log.base.attr = TDB_ATTRIBUTE_LOG;
80 log.log.base.next = NULL;
82 log.log.data = log_data;
86 if (tdb_flags & TDB_CLEAR_IF_FIRST) {
87 cif.openhook.base.attr = TDB_ATTRIBUTE_OPENHOOK;
88 cif.openhook.base.next = attr;
89 cif.openhook.fn = clear_if_first;
91 tdb_flags &= ~TDB_CLEAR_IF_FIRST;
94 /* Testsuite uses this to speed things up. */
95 if (getenv("TDB_NO_FSYNC")) {
96 tdb_flags |= TDB_NOSYNC;
99 return tdb_open(name, tdb_flags|TDB_ALLOW_NESTING, open_flags, mode,