1 #include <ccan/tdb2/private.h> // for tdb_fcntl_unlock
2 #include <ccan/tdb2/tdb2.h>
3 #include <ccan/tap/tap.h>
10 static int mylock(int fd
, int rw
, off_t off
, off_t len
, bool waitflag
,
24 fl
.l_whence
= SEEK_SET
;
29 ret
= fcntl(fd
, F_SETLKW
, &fl
);
31 ret
= fcntl(fd
, F_SETLK
, &fl
);
32 } while (ret
!= 0 && errno
== EINTR
);
38 static int trav(struct tdb_context
*tdb
, TDB_DATA k
, TDB_DATA d
, int *err
)
44 int main(int argc
, char *argv
[])
47 struct tdb_context
*tdb
;
48 int flags
[] = { TDB_DEFAULT
, TDB_NOMMAP
,
49 TDB_CONVERT
, TDB_NOMMAP
|TDB_CONVERT
,
50 TDB_VERSION1
, TDB_NOMMAP
|TDB_VERSION1
,
51 TDB_CONVERT
|TDB_VERSION1
,
52 TDB_NOMMAP
|TDB_CONVERT
|TDB_VERSION1
};
53 union tdb_attribute lock_attr
;
54 struct tdb_data key
= tdb_mkdata("key", 3);
55 struct tdb_data data
= tdb_mkdata("data", 4);
58 lock_attr
.base
.attr
= TDB_ATTRIBUTE_FLOCK
;
59 lock_attr
.base
.next
= &tap_log_attr
;
60 lock_attr
.flock
.lock
= mylock
;
61 lock_attr
.flock
.unlock
= tdb_fcntl_unlock
;
62 lock_attr
.flock
.data
= &lock_err
;
64 plan_tests(sizeof(flags
) / sizeof(flags
[0]) * 80);
66 for (i
= 0; i
< sizeof(flags
) / sizeof(flags
[0]); i
++) {
68 unsigned int num_oom_messages
;
70 /* TDB1 double logs here. */
71 if (flags
[i
] & TDB_VERSION1
) {
77 /* Nonblocking open; expect no error message. */
79 tdb
= tdb_open("run-82-lockattr.tdb", flags
[i
],
80 O_RDWR
|O_CREAT
|O_TRUNC
, 0600, &lock_attr
);
81 ok(errno
== lock_err
, "Errno is %u", errno
);
83 ok1(tap_log_messages
== 0);
86 tdb
= tdb_open("run-82-lockattr.tdb", flags
[i
],
87 O_RDWR
|O_CREAT
|O_TRUNC
, 0600, &lock_attr
);
88 ok(errno
== lock_err
, "Errno is %u", errno
);
90 ok1(tap_log_messages
== 0);
92 /* Forced fail open. */
94 tdb
= tdb_open("run-82-lockattr.tdb", flags
[i
],
95 O_RDWR
|O_CREAT
|O_TRUNC
, 0600, &lock_attr
);
96 ok1(errno
== lock_err
);
98 ok1(tap_log_messages
== 1);
102 tdb
= tdb_open("run-82-lockattr.tdb", flags
[i
],
103 O_RDWR
|O_CREAT
|O_TRUNC
, 0600, &lock_attr
);
106 ok1(tap_log_messages
== 0);
108 /* Nonblocking store. */
110 ok1(tdb_store(tdb
, key
, data
, TDB_REPLACE
) == TDB_ERR_LOCK
);
111 ok1(tap_log_messages
== 0);
113 ok1(tdb_store(tdb
, key
, data
, TDB_REPLACE
) == TDB_ERR_LOCK
);
114 ok1(tap_log_messages
== 0);
116 ok1(tdb_store(tdb
, key
, data
, TDB_REPLACE
) == TDB_ERR_LOCK
);
117 ok1(tap_log_messages
== num_oom_messages
);
118 tap_log_messages
= 0;
120 /* Nonblocking fetch. */
122 ok1(!tdb_exists(tdb
, key
));
123 ok1(tap_log_messages
== 0);
125 ok1(!tdb_exists(tdb
, key
));
126 ok1(tap_log_messages
== 0);
128 ok1(!tdb_exists(tdb
, key
));
129 ok1(tap_log_messages
== num_oom_messages
);
130 tap_log_messages
= 0;
133 ok1(tdb_fetch(tdb
, key
, &d
) == TDB_ERR_LOCK
);
134 ok1(tap_log_messages
== 0);
136 ok1(tdb_fetch(tdb
, key
, &d
) == TDB_ERR_LOCK
);
137 ok1(tap_log_messages
== 0);
139 ok1(tdb_fetch(tdb
, key
, &d
) == TDB_ERR_LOCK
);
140 ok1(tap_log_messages
== num_oom_messages
);
141 tap_log_messages
= 0;
143 /* Nonblocking delete. */
145 ok1(tdb_delete(tdb
, key
) == TDB_ERR_LOCK
);
146 ok1(tap_log_messages
== 0);
148 ok1(tdb_delete(tdb
, key
) == TDB_ERR_LOCK
);
149 ok1(tap_log_messages
== 0);
151 ok1(tdb_delete(tdb
, key
) == TDB_ERR_LOCK
);
152 ok1(tap_log_messages
== num_oom_messages
);
153 tap_log_messages
= 0;
155 /* Nonblocking locks. */
157 ok1(tdb_chainlock(tdb
, key
) == TDB_ERR_LOCK
);
158 ok1(tap_log_messages
== 0);
160 ok1(tdb_chainlock(tdb
, key
) == TDB_ERR_LOCK
);
161 ok1(tap_log_messages
== 0);
163 ok1(tdb_chainlock(tdb
, key
) == TDB_ERR_LOCK
);
164 ok1(tap_log_messages
== num_oom_messages
);
165 tap_log_messages
= 0;
168 ok1(tdb_chainlock_read(tdb
, key
) == TDB_ERR_LOCK
);
169 ok1(tap_log_messages
== 0);
171 ok1(tdb_chainlock_read(tdb
, key
) == TDB_ERR_LOCK
);
172 ok1(tap_log_messages
== 0);
174 ok1(tdb_chainlock_read(tdb
, key
) == TDB_ERR_LOCK
);
175 ok1(tap_log_messages
== num_oom_messages
);
176 tap_log_messages
= 0;
179 ok1(tdb_lockall(tdb
) == TDB_ERR_LOCK
);
180 ok1(tap_log_messages
== 0);
182 ok1(tdb_lockall(tdb
) == TDB_ERR_LOCK
);
183 ok1(tap_log_messages
== 0);
185 ok1(tdb_lockall(tdb
) == TDB_ERR_LOCK
);
186 /* This actually does divide and conquer. */
187 ok1(tap_log_messages
> 0);
188 tap_log_messages
= 0;
191 ok1(tdb_lockall_read(tdb
) == TDB_ERR_LOCK
);
192 ok1(tap_log_messages
== 0);
194 ok1(tdb_lockall_read(tdb
) == TDB_ERR_LOCK
);
195 ok1(tap_log_messages
== 0);
197 ok1(tdb_lockall_read(tdb
) == TDB_ERR_LOCK
);
198 ok1(tap_log_messages
> 0);
199 tap_log_messages
= 0;
201 /* Nonblocking traverse; go nonblock partway through. */
203 ok1(tdb_store(tdb
, key
, data
, TDB_REPLACE
) == 0);
205 ok1(tdb_traverse(tdb
, trav
, &lock_err
) == TDB_ERR_LOCK
);
206 ok1(tap_log_messages
== 0);
209 ok1(tdb_traverse(tdb
, trav
, &lock_err
) == TDB_ERR_LOCK
);
210 ok1(tap_log_messages
== 0);
213 ok1(tdb_traverse(tdb
, trav
, &lock_err
) == TDB_ERR_LOCK
);
214 ok1(tap_log_messages
== num_oom_messages
);
215 tap_log_messages
= 0;
217 /* Nonblocking transactions. */
219 ok1(tdb_transaction_start(tdb
) == TDB_ERR_LOCK
);
220 ok1(tap_log_messages
== 0);
222 ok1(tdb_transaction_start(tdb
) == TDB_ERR_LOCK
);
223 ok1(tap_log_messages
== 0);
225 ok1(tdb_transaction_start(tdb
) == TDB_ERR_LOCK
);
226 ok1(tap_log_messages
== 1);
227 tap_log_messages
= 0;
229 /* Nonblocking transaction prepare. */
231 ok1(tdb_transaction_start(tdb
) == 0);
232 ok1(tdb_delete(tdb
, key
) == 0);
235 ok1(tdb_transaction_prepare_commit(tdb
) == TDB_ERR_LOCK
);
236 ok1(tap_log_messages
== 0);
239 ok1(tdb_transaction_prepare_commit(tdb
) == 0);
240 ok1(tdb_transaction_commit(tdb
) == 0);
242 /* And the transaction was committed, right? */
243 ok1(!tdb_exists(tdb
, key
));
245 ok1(tap_log_messages
== 0);
247 return exit_status();