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
,