1 #include "tdb2-source.h"
2 #include <ccan/tap/tap.h>
5 static int mylock(int fd, int rw, off_t off, off_t len, bool waitflag,
19 fl.l_whence = SEEK_SET;
24 ret = fcntl(fd, F_SETLKW, &fl);
26 ret = fcntl(fd, F_SETLK, &fl);
27 } while (ret != 0 && errno == EINTR);
32 static int myunlock(int fd, int rw, off_t off, off_t len, void *_err)
45 fl.l_whence = SEEK_SET;
49 ret = fcntl(fd, F_SETLKW, &fl);
50 } while (ret != 0 && errno == EINTR);
56 static int trav(struct tdb_context *tdb, TDB_DATA k, TDB_DATA d, int *err)
62 int main(int argc, char *argv[])
65 struct tdb_context *tdb;
66 int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
67 TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT };
68 union tdb_attribute lock_attr;
69 struct tdb_data key = tdb_mkdata("key", 3);
70 struct tdb_data data = tdb_mkdata("data", 4);
73 lock_attr.base.attr = TDB_ATTRIBUTE_FLOCK;
74 lock_attr.base.next = &tap_log_attr;
75 lock_attr.flock.lock = mylock;
76 lock_attr.flock.unlock = myunlock;
77 lock_attr.flock.data = &lock_err;
79 plan_tests(sizeof(flags) / sizeof(flags[0]) * 80);
81 for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
84 /* Nonblocking open; expect no error message. */
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);
93 tdb = tdb_open("run-82-lockattr.tdb", flags[i],
94 O_RDWR|O_CREAT|O_TRUNC, 0600, &lock_attr);
95 ok(errno == lock_err, "Errno is %u", errno);
97 ok1(tap_log_messages == 0);
99 /* Forced fail open. */
101 tdb = tdb_open("run-82-lockattr.tdb", flags[i],
102 O_RDWR|O_CREAT|O_TRUNC, 0600, &lock_attr);
103 ok1(errno == lock_err);
105 ok1(tap_log_messages == 1);
106 tap_log_messages = 0;
109 tdb = tdb_open("run-82-lockattr.tdb", flags[i],
110 O_RDWR|O_CREAT|O_TRUNC, 0600, &lock_attr);
113 ok1(tap_log_messages == 0);
115 /* Nonblocking store. */
117 ok1(tdb_store(tdb, key, data, TDB_REPLACE) == TDB_ERR_LOCK);
118 ok1(tap_log_messages == 0);
120 ok1(tdb_store(tdb, key, data, TDB_REPLACE) == TDB_ERR_LOCK);
121 ok1(tap_log_messages == 0);
123 ok1(tdb_store(tdb, key, data, TDB_REPLACE) == TDB_ERR_LOCK);
124 ok1(tap_log_messages == 1);
125 tap_log_messages = 0;
127 /* Nonblocking fetch. */
129 ok1(!tdb_exists(tdb, key));
130 ok1(tap_log_messages == 0);
132 ok1(!tdb_exists(tdb, key));
133 ok1(tap_log_messages == 0);
135 ok1(!tdb_exists(tdb, key));
136 ok1(tap_log_messages == 1);
137 tap_log_messages = 0;
140 ok1(tdb_fetch(tdb, key, &d) == TDB_ERR_LOCK);
141 ok1(tap_log_messages == 0);
143 ok1(tdb_fetch(tdb, key, &d) == TDB_ERR_LOCK);
144 ok1(tap_log_messages == 0);
146 ok1(tdb_fetch(tdb, key, &d) == TDB_ERR_LOCK);
147 ok1(tap_log_messages == 1);
148 tap_log_messages = 0;
150 /* Nonblocking delete. */
152 ok1(tdb_delete(tdb, key) == TDB_ERR_LOCK);
153 ok1(tap_log_messages == 0);
155 ok1(tdb_delete(tdb, key) == TDB_ERR_LOCK);
156 ok1(tap_log_messages == 0);
158 ok1(tdb_delete(tdb, key) == TDB_ERR_LOCK);
159 ok1(tap_log_messages == 1);
160 tap_log_messages = 0;
162 /* Nonblocking locks. */
164 ok1(tdb_chainlock(tdb, key) == TDB_ERR_LOCK);
165 ok1(tap_log_messages == 0);
167 ok1(tdb_chainlock(tdb, key) == TDB_ERR_LOCK);
168 ok1(tap_log_messages == 0);
170 ok1(tdb_chainlock(tdb, key) == TDB_ERR_LOCK);
171 ok1(tap_log_messages == 1);
172 tap_log_messages = 0;
175 ok1(tdb_chainlock_read(tdb, key) == TDB_ERR_LOCK);
176 ok1(tap_log_messages == 0);
178 ok1(tdb_chainlock_read(tdb, key) == TDB_ERR_LOCK);
179 ok1(tap_log_messages == 0);
181 ok1(tdb_chainlock_read(tdb, key) == TDB_ERR_LOCK);
182 ok1(tap_log_messages == 1);
183 tap_log_messages = 0;
186 ok1(tdb_lockall(tdb) == TDB_ERR_LOCK);
187 ok1(tap_log_messages == 0);
189 ok1(tdb_lockall(tdb) == TDB_ERR_LOCK);
190 ok1(tap_log_messages == 0);
192 ok1(tdb_lockall(tdb) == TDB_ERR_LOCK);
193 /* This actually does divide and conquer. */
194 ok1(tap_log_messages > 0);
195 tap_log_messages = 0;
198 ok1(tdb_lockall_read(tdb) == TDB_ERR_LOCK);
199 ok1(tap_log_messages == 0);
201 ok1(tdb_lockall_read(tdb) == TDB_ERR_LOCK);
202 ok1(tap_log_messages == 0);
204 ok1(tdb_lockall_read(tdb) == TDB_ERR_LOCK);
205 ok1(tap_log_messages > 0);
206 tap_log_messages = 0;
208 /* Nonblocking traverse; go nonblock partway through. */
210 ok1(tdb_store(tdb, key, data, TDB_REPLACE) == 0);
212 ok1(tdb_traverse(tdb, trav, &lock_err) == TDB_ERR_LOCK);
213 ok1(tap_log_messages == 0);
216 ok1(tdb_traverse(tdb, trav, &lock_err) == TDB_ERR_LOCK);
217 ok1(tap_log_messages == 0);
220 ok1(tdb_traverse(tdb, trav, &lock_err) == TDB_ERR_LOCK);
221 ok1(tap_log_messages == 1);
222 tap_log_messages = 0;
224 /* Nonblocking transactions. */
226 ok1(tdb_transaction_start(tdb) == TDB_ERR_LOCK);
227 ok1(tap_log_messages == 0);
229 ok1(tdb_transaction_start(tdb) == TDB_ERR_LOCK);
230 ok1(tap_log_messages == 0);
232 ok1(tdb_transaction_start(tdb) == TDB_ERR_LOCK);
233 ok1(tap_log_messages == 1);
234 tap_log_messages = 0;
236 /* Nonblocking transaction prepare. */
238 ok1(tdb_transaction_start(tdb) == 0);
239 ok1(tdb_delete(tdb, key) == 0);
242 ok1(tdb_transaction_prepare_commit(tdb) == TDB_ERR_LOCK);
243 ok1(tap_log_messages == 0);
246 ok1(tdb_transaction_prepare_commit(tdb) == 0);
247 ok1(tdb_transaction_commit(tdb) == 0);
249 /* And the transaction was committed, right? */
250 ok1(!tdb_exists(tdb, key));
252 ok1(tap_log_messages == 0);
254 return exit_status();