1 #include <ccan/tdb2/tdb.c>
2 #include <ccan/tdb2/open.c>
3 #include <ccan/tdb2/free.c>
4 #include <ccan/tdb2/lock.c>
5 #include <ccan/tdb2/io.c>
6 #include <ccan/tdb2/hash.c>
7 #include <ccan/tdb2/check.c>
8 #include <ccan/tdb2/transaction.c>
9 #include <ccan/tdb2/traverse.c>
10 #include <ccan/tap/tap.h>
13 static int mylock(int fd
, int rw
, off_t off
, off_t len
, bool waitflag
,
27 fl
.l_whence
= SEEK_SET
;
32 ret
= fcntl(fd
, F_SETLKW
, &fl
);
34 ret
= fcntl(fd
, F_SETLK
, &fl
);
35 } while (ret
!= 0 && errno
== EINTR
);
40 static int myunlock(int fd
, int rw
, off_t off
, off_t len
, void *_err
)
53 fl
.l_whence
= SEEK_SET
;
57 ret
= fcntl(fd
, F_SETLKW
, &fl
);
58 } while (ret
!= 0 && errno
== EINTR
);
64 static int trav(struct tdb_context
*tdb
, TDB_DATA k
, TDB_DATA d
, int *err
)
70 int main(int argc
, char *argv
[])
73 struct tdb_context
*tdb
;
74 int flags
[] = { TDB_DEFAULT
, TDB_NOMMAP
,
75 TDB_CONVERT
, TDB_NOMMAP
|TDB_CONVERT
};
76 union tdb_attribute lock_attr
;
77 struct tdb_data key
= tdb_mkdata("key", 3);
78 struct tdb_data data
= tdb_mkdata("data", 4);
81 lock_attr
.base
.attr
= TDB_ATTRIBUTE_FLOCK
;
82 lock_attr
.base
.next
= &tap_log_attr
;
83 lock_attr
.flock
.lock
= mylock
;
84 lock_attr
.flock
.unlock
= myunlock
;
85 lock_attr
.flock
.data
= &lock_err
;
87 plan_tests(sizeof(flags
) / sizeof(flags
[0]) * 80);
89 for (i
= 0; i
< sizeof(flags
) / sizeof(flags
[0]); i
++) {
92 /* Nonblocking open; expect no error message. */
94 tdb
= tdb_open("run-82-lockattr.tdb", flags
[i
],
95 O_RDWR
|O_CREAT
|O_TRUNC
, 0600, &lock_attr
);
96 ok(errno
== lock_err
, "Errno is %u", errno
);
98 ok1(tap_log_messages
== 0);
101 tdb
= tdb_open("run-82-lockattr.tdb", flags
[i
],
102 O_RDWR
|O_CREAT
|O_TRUNC
, 0600, &lock_attr
);
103 ok(errno
== lock_err
, "Errno is %u", errno
);
105 ok1(tap_log_messages
== 0);
107 /* Forced fail open. */
109 tdb
= tdb_open("run-82-lockattr.tdb", flags
[i
],
110 O_RDWR
|O_CREAT
|O_TRUNC
, 0600, &lock_attr
);
111 ok1(errno
== lock_err
);
113 ok1(tap_log_messages
== 1);
114 tap_log_messages
= 0;
117 tdb
= tdb_open("run-82-lockattr.tdb", flags
[i
],
118 O_RDWR
|O_CREAT
|O_TRUNC
, 0600, &lock_attr
);
121 ok1(tap_log_messages
== 0);
123 /* Nonblocking store. */
125 ok1(tdb_store(tdb
, key
, data
, TDB_REPLACE
) == TDB_ERR_LOCK
);
126 ok1(tap_log_messages
== 0);
128 ok1(tdb_store(tdb
, key
, data
, TDB_REPLACE
) == TDB_ERR_LOCK
);
129 ok1(tap_log_messages
== 0);
131 ok1(tdb_store(tdb
, key
, data
, TDB_REPLACE
) == TDB_ERR_LOCK
);
132 ok1(tap_log_messages
== 1);
133 tap_log_messages
= 0;
135 /* Nonblocking fetch. */
137 ok1(!tdb_exists(tdb
, key
));
138 ok1(tap_log_messages
== 0);
140 ok1(!tdb_exists(tdb
, key
));
141 ok1(tap_log_messages
== 0);
143 ok1(!tdb_exists(tdb
, key
));
144 ok1(tap_log_messages
== 1);
145 tap_log_messages
= 0;
148 ok1(tdb_fetch(tdb
, key
, &d
) == TDB_ERR_LOCK
);
149 ok1(tap_log_messages
== 0);
151 ok1(tdb_fetch(tdb
, key
, &d
) == TDB_ERR_LOCK
);
152 ok1(tap_log_messages
== 0);
154 ok1(tdb_fetch(tdb
, key
, &d
) == TDB_ERR_LOCK
);
155 ok1(tap_log_messages
== 1);
156 tap_log_messages
= 0;
158 /* Nonblocking delete. */
160 ok1(tdb_delete(tdb
, key
) == TDB_ERR_LOCK
);
161 ok1(tap_log_messages
== 0);
163 ok1(tdb_delete(tdb
, key
) == TDB_ERR_LOCK
);
164 ok1(tap_log_messages
== 0);
166 ok1(tdb_delete(tdb
, key
) == TDB_ERR_LOCK
);
167 ok1(tap_log_messages
== 1);
168 tap_log_messages
= 0;
170 /* Nonblocking locks. */
172 ok1(tdb_chainlock(tdb
, key
) == TDB_ERR_LOCK
);
173 ok1(tap_log_messages
== 0);
175 ok1(tdb_chainlock(tdb
, key
) == TDB_ERR_LOCK
);
176 ok1(tap_log_messages
== 0);
178 ok1(tdb_chainlock(tdb
, key
) == TDB_ERR_LOCK
);
179 ok1(tap_log_messages
== 1);
180 tap_log_messages
= 0;
183 ok1(tdb_chainlock_read(tdb
, key
) == TDB_ERR_LOCK
);
184 ok1(tap_log_messages
== 0);
186 ok1(tdb_chainlock_read(tdb
, key
) == TDB_ERR_LOCK
);
187 ok1(tap_log_messages
== 0);
189 ok1(tdb_chainlock_read(tdb
, key
) == TDB_ERR_LOCK
);
190 ok1(tap_log_messages
== 1);
191 tap_log_messages
= 0;
194 ok1(tdb_lockall(tdb
) == TDB_ERR_LOCK
);
195 ok1(tap_log_messages
== 0);
197 ok1(tdb_lockall(tdb
) == TDB_ERR_LOCK
);
198 ok1(tap_log_messages
== 0);
200 ok1(tdb_lockall(tdb
) == TDB_ERR_LOCK
);
201 /* This actually does divide and conquer. */
202 ok1(tap_log_messages
> 0);
203 tap_log_messages
= 0;
206 ok1(tdb_lockall_read(tdb
) == TDB_ERR_LOCK
);
207 ok1(tap_log_messages
== 0);
209 ok1(tdb_lockall_read(tdb
) == TDB_ERR_LOCK
);
210 ok1(tap_log_messages
== 0);
212 ok1(tdb_lockall_read(tdb
) == TDB_ERR_LOCK
);
213 ok1(tap_log_messages
> 0);
214 tap_log_messages
= 0;
216 /* Nonblocking traverse; go nonblock partway through. */
218 ok1(tdb_store(tdb
, key
, data
, TDB_REPLACE
) == 0);
220 ok1(tdb_traverse(tdb
, trav
, &lock_err
) == TDB_ERR_LOCK
);
221 ok1(tap_log_messages
== 0);
224 ok1(tdb_traverse(tdb
, trav
, &lock_err
) == TDB_ERR_LOCK
);
225 ok1(tap_log_messages
== 0);
228 ok1(tdb_traverse(tdb
, trav
, &lock_err
) == TDB_ERR_LOCK
);
229 ok1(tap_log_messages
== 1);
230 tap_log_messages
= 0;
232 /* Nonblocking transactions. */
234 ok1(tdb_transaction_start(tdb
) == TDB_ERR_LOCK
);
235 ok1(tap_log_messages
== 0);
237 ok1(tdb_transaction_start(tdb
) == TDB_ERR_LOCK
);
238 ok1(tap_log_messages
== 0);
240 ok1(tdb_transaction_start(tdb
) == TDB_ERR_LOCK
);
241 ok1(tap_log_messages
== 1);
242 tap_log_messages
= 0;
244 /* Nonblocking transaction prepare. */
246 ok1(tdb_transaction_start(tdb
) == 0);
247 ok1(tdb_delete(tdb
, key
) == 0);
250 ok1(tdb_transaction_prepare_commit(tdb
) == TDB_ERR_LOCK
);
251 ok1(tap_log_messages
== 0);
254 ok1(tdb_transaction_prepare_commit(tdb
) == 0);
255 ok1(tdb_transaction_commit(tdb
) == 0);
257 /* And the transaction was committed, right? */
258 ok1(!tdb_exists(tdb
, key
));
260 ok1(tap_log_messages
== 0);
262 return exit_status();