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
);
33 static int trav(struct tdb_context
*tdb
, TDB_DATA k
, TDB_DATA d
, int *err
)
39 int main(int argc
, char *argv
[])
42 struct tdb_context
*tdb
;
43 int flags
[] = { TDB_DEFAULT
, TDB_NOMMAP
,
44 TDB_CONVERT
, TDB_NOMMAP
|TDB_CONVERT
,
45 TDB_VERSION1
, TDB_NOMMAP
|TDB_VERSION1
,
46 TDB_CONVERT
|TDB_VERSION1
,
47 TDB_NOMMAP
|TDB_CONVERT
|TDB_VERSION1
};
48 union tdb_attribute lock_attr
;
49 struct tdb_data key
= tdb_mkdata("key", 3);
50 struct tdb_data data
= tdb_mkdata("data", 4);
53 lock_attr
.base
.attr
= TDB_ATTRIBUTE_FLOCK
;
54 lock_attr
.base
.next
= &tap_log_attr
;
55 lock_attr
.flock
.lock
= mylock
;
56 lock_attr
.flock
.unlock
= tdb_fcntl_unlock
;
57 lock_attr
.flock
.data
= &lock_err
;
59 plan_tests(sizeof(flags
) / sizeof(flags
[0]) * 80);
61 for (i
= 0; i
< sizeof(flags
) / sizeof(flags
[0]); i
++) {
63 unsigned int num_oom_messages
;
65 /* TDB1 double logs here. */
66 if (flags
[i
] & TDB_VERSION1
) {
72 /* Nonblocking open; expect no error message. */
74 tdb
= tdb_open("run-82-lockattr.tdb", flags
[i
],
75 O_RDWR
|O_CREAT
|O_TRUNC
, 0600, &lock_attr
);
76 ok(errno
== lock_err
, "Errno is %u", errno
);
78 ok1(tap_log_messages
== 0);
81 tdb
= tdb_open("run-82-lockattr.tdb", flags
[i
],
82 O_RDWR
|O_CREAT
|O_TRUNC
, 0600, &lock_attr
);
83 ok(errno
== lock_err
, "Errno is %u", errno
);
85 ok1(tap_log_messages
== 0);
87 /* Forced fail open. */
89 tdb
= tdb_open("run-82-lockattr.tdb", flags
[i
],
90 O_RDWR
|O_CREAT
|O_TRUNC
, 0600, &lock_attr
);
91 ok1(errno
== lock_err
);
93 ok1(tap_log_messages
== 1);
97 tdb
= tdb_open("run-82-lockattr.tdb", flags
[i
],
98 O_RDWR
|O_CREAT
|O_TRUNC
, 0600, &lock_attr
);
101 ok1(tap_log_messages
== 0);
103 /* Nonblocking store. */
105 ok1(tdb_store(tdb
, key
, data
, TDB_REPLACE
) == TDB_ERR_LOCK
);
106 ok1(tap_log_messages
== 0);
108 ok1(tdb_store(tdb
, key
, data
, TDB_REPLACE
) == TDB_ERR_LOCK
);
109 ok1(tap_log_messages
== 0);
111 ok1(tdb_store(tdb
, key
, data
, TDB_REPLACE
) == TDB_ERR_LOCK
);
112 ok1(tap_log_messages
== num_oom_messages
);
113 tap_log_messages
= 0;
115 /* Nonblocking fetch. */
117 ok1(!tdb_exists(tdb
, key
));
118 ok1(tap_log_messages
== 0);
120 ok1(!tdb_exists(tdb
, key
));
121 ok1(tap_log_messages
== 0);
123 ok1(!tdb_exists(tdb
, key
));
124 ok1(tap_log_messages
== num_oom_messages
);
125 tap_log_messages
= 0;
128 ok1(tdb_fetch(tdb
, key
, &d
) == TDB_ERR_LOCK
);
129 ok1(tap_log_messages
== 0);
131 ok1(tdb_fetch(tdb
, key
, &d
) == TDB_ERR_LOCK
);
132 ok1(tap_log_messages
== 0);
134 ok1(tdb_fetch(tdb
, key
, &d
) == TDB_ERR_LOCK
);
135 ok1(tap_log_messages
== num_oom_messages
);
136 tap_log_messages
= 0;
138 /* Nonblocking delete. */
140 ok1(tdb_delete(tdb
, key
) == TDB_ERR_LOCK
);
141 ok1(tap_log_messages
== 0);
143 ok1(tdb_delete(tdb
, key
) == TDB_ERR_LOCK
);
144 ok1(tap_log_messages
== 0);
146 ok1(tdb_delete(tdb
, key
) == TDB_ERR_LOCK
);
147 ok1(tap_log_messages
== num_oom_messages
);
148 tap_log_messages
= 0;
150 /* Nonblocking locks. */
152 ok1(tdb_chainlock(tdb
, key
) == TDB_ERR_LOCK
);
153 ok1(tap_log_messages
== 0);
155 ok1(tdb_chainlock(tdb
, key
) == TDB_ERR_LOCK
);
156 ok1(tap_log_messages
== 0);
158 ok1(tdb_chainlock(tdb
, key
) == TDB_ERR_LOCK
);
159 ok1(tap_log_messages
== num_oom_messages
);
160 tap_log_messages
= 0;
163 ok1(tdb_chainlock_read(tdb
, key
) == TDB_ERR_LOCK
);
164 ok1(tap_log_messages
== 0);
166 ok1(tdb_chainlock_read(tdb
, key
) == TDB_ERR_LOCK
);
167 ok1(tap_log_messages
== 0);
169 ok1(tdb_chainlock_read(tdb
, key
) == TDB_ERR_LOCK
);
170 ok1(tap_log_messages
== num_oom_messages
);
171 tap_log_messages
= 0;
174 ok1(tdb_lockall(tdb
) == TDB_ERR_LOCK
);
175 ok1(tap_log_messages
== 0);
177 ok1(tdb_lockall(tdb
) == TDB_ERR_LOCK
);
178 ok1(tap_log_messages
== 0);
180 ok1(tdb_lockall(tdb
) == TDB_ERR_LOCK
);
181 /* This actually does divide and conquer. */
182 ok1(tap_log_messages
> 0);
183 tap_log_messages
= 0;
186 ok1(tdb_lockall_read(tdb
) == TDB_ERR_LOCK
);
187 ok1(tap_log_messages
== 0);
189 ok1(tdb_lockall_read(tdb
) == TDB_ERR_LOCK
);
190 ok1(tap_log_messages
== 0);
192 ok1(tdb_lockall_read(tdb
) == TDB_ERR_LOCK
);
193 ok1(tap_log_messages
> 0);
194 tap_log_messages
= 0;
196 /* Nonblocking traverse; go nonblock partway through. */
198 ok1(tdb_store(tdb
, key
, data
, TDB_REPLACE
) == 0);
200 ok1(tdb_traverse(tdb
, trav
, &lock_err
) == TDB_ERR_LOCK
);
201 ok1(tap_log_messages
== 0);
204 ok1(tdb_traverse(tdb
, trav
, &lock_err
) == TDB_ERR_LOCK
);
205 ok1(tap_log_messages
== 0);
208 ok1(tdb_traverse(tdb
, trav
, &lock_err
) == TDB_ERR_LOCK
);
209 ok1(tap_log_messages
== num_oom_messages
);
210 tap_log_messages
= 0;
212 /* Nonblocking transactions. */
214 ok1(tdb_transaction_start(tdb
) == TDB_ERR_LOCK
);
215 ok1(tap_log_messages
== 0);
217 ok1(tdb_transaction_start(tdb
) == TDB_ERR_LOCK
);
218 ok1(tap_log_messages
== 0);
220 ok1(tdb_transaction_start(tdb
) == TDB_ERR_LOCK
);
221 ok1(tap_log_messages
== 1);
222 tap_log_messages
= 0;
224 /* Nonblocking transaction prepare. */
226 ok1(tdb_transaction_start(tdb
) == 0);
227 ok1(tdb_delete(tdb
, key
) == 0);
230 ok1(tdb_transaction_prepare_commit(tdb
) == TDB_ERR_LOCK
);
231 ok1(tap_log_messages
== 0);
234 ok1(tdb_transaction_prepare_commit(tdb
) == 0);
235 ok1(tdb_transaction_commit(tdb
) == 0);
237 /* And the transaction was committed, right? */
238 ok1(!tdb_exists(tdb
, key
));
240 ok1(tap_log_messages
== 0);
242 return exit_status();