]> git.ozlabs.org Git - ccan/blob - ccan/ntdb/test/api-82-lockattr.c
f71600c182b4478a7cb5d1a7d1007a10c6ec9292
[ccan] / ccan / ntdb / test / api-82-lockattr.c
1 #include "private.h" // for ntdb_fcntl_unlock
2 #include "ntdb.h"
3 #include "tap-interface.h"
4 #include <errno.h>
5 #include "logging.h"
6
7 static int mylock(int fd, int rw, off_t off, off_t len, bool waitflag,
8                   void *_err)
9 {
10         int *lock_err = _err;
11         struct flock fl;
12         int ret;
13
14         if (*lock_err) {
15                 errno = *lock_err;
16                 return -1;
17         }
18
19         do {
20                 fl.l_type = rw;
21                 fl.l_whence = SEEK_SET;
22                 fl.l_start = off;
23                 fl.l_len = len;
24
25                 if (waitflag)
26                         ret = fcntl(fd, F_SETLKW, &fl);
27                 else
28                         ret = fcntl(fd, F_SETLK, &fl);
29         } while (ret != 0 && errno == EINTR);
30
31         return ret;
32 }
33
34 static int trav_err;
35 static int trav(struct ntdb_context *ntdb, NTDB_DATA k, NTDB_DATA d, int *terr)
36 {
37         *terr = trav_err;
38         return 0;
39 }
40
41 int main(int argc, char *argv[])
42 {
43         unsigned int i;
44         struct ntdb_context *ntdb;
45         int flags[] = { NTDB_DEFAULT, NTDB_NOMMAP,
46                         NTDB_CONVERT, NTDB_NOMMAP|NTDB_CONVERT };
47         union ntdb_attribute lock_attr;
48         NTDB_DATA key = ntdb_mkdata("key", 3);
49         NTDB_DATA data = ntdb_mkdata("data", 4);
50         int lock_err;
51
52         lock_attr.base.attr = NTDB_ATTRIBUTE_FLOCK;
53         lock_attr.base.next = &tap_log_attr;
54         lock_attr.flock.lock = mylock;
55         lock_attr.flock.unlock = ntdb_fcntl_unlock;
56         lock_attr.flock.data = &lock_err;
57
58         plan_tests(sizeof(flags) / sizeof(flags[0]) * 81);
59
60         for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
61                 NTDB_DATA d;
62
63                 /* Nonblocking open; expect no error message. */
64                 lock_err = EAGAIN;
65                 ntdb = ntdb_open("run-82-lockattr.ntdb", flags[i]|MAYBE_NOSYNC,
66                                  O_RDWR|O_CREAT|O_TRUNC, 0600, &lock_attr);
67                 ok(errno == lock_err, "Errno is %u", errno);
68                 ok1(!ntdb);
69                 ok1(tap_log_messages == 0);
70
71                 lock_err = EINTR;
72                 ntdb = ntdb_open("run-82-lockattr.ntdb", flags[i]|MAYBE_NOSYNC,
73                                  O_RDWR|O_CREAT|O_TRUNC, 0600, &lock_attr);
74                 ok(errno == lock_err, "Errno is %u", errno);
75                 ok1(!ntdb);
76                 ok1(tap_log_messages == 0);
77
78                 /* Forced fail open. */
79                 lock_err = ENOMEM;
80                 ntdb = ntdb_open("run-82-lockattr.ntdb", flags[i]|MAYBE_NOSYNC,
81                                  O_RDWR|O_CREAT|O_TRUNC, 0600, &lock_attr);
82                 ok1(errno == lock_err);
83                 ok1(!ntdb);
84                 ok1(tap_log_messages == 1);
85                 tap_log_messages = 0;
86
87                 lock_err = 0;
88                 ntdb = ntdb_open("run-82-lockattr.ntdb", flags[i]|MAYBE_NOSYNC,
89                                  O_RDWR|O_CREAT|O_TRUNC, 0600, &lock_attr);
90                 if (!ok1(ntdb))
91                         continue;
92                 ok1(tap_log_messages == 0);
93
94                 /* Nonblocking store. */
95                 lock_err = EAGAIN;
96                 ok1(ntdb_store(ntdb, key, data, NTDB_REPLACE) == NTDB_ERR_LOCK);
97                 ok1(tap_log_messages == 0);
98                 lock_err = EINTR;
99                 ok1(ntdb_store(ntdb, key, data, NTDB_REPLACE) == NTDB_ERR_LOCK);
100                 ok1(tap_log_messages == 0);
101                 lock_err = ENOMEM;
102                 ok1(ntdb_store(ntdb, key, data, NTDB_REPLACE) == NTDB_ERR_LOCK);
103                 ok1(tap_log_messages == 1);
104                 tap_log_messages = 0;
105
106                 /* Nonblocking fetch. */
107                 lock_err = EAGAIN;
108                 ok1(!ntdb_exists(ntdb, key));
109                 ok1(tap_log_messages == 0);
110                 lock_err = EINTR;
111                 ok1(!ntdb_exists(ntdb, key));
112                 ok1(tap_log_messages == 0);
113                 lock_err = ENOMEM;
114                 ok1(!ntdb_exists(ntdb, key));
115                 ok1(tap_log_messages == 1);
116                 tap_log_messages = 0;
117
118                 lock_err = EAGAIN;
119                 ok1(ntdb_fetch(ntdb, key, &d) == NTDB_ERR_LOCK);
120                 ok1(tap_log_messages == 0);
121                 lock_err = EINTR;
122                 ok1(ntdb_fetch(ntdb, key, &d) == NTDB_ERR_LOCK);
123                 ok1(tap_log_messages == 0);
124                 lock_err = ENOMEM;
125                 ok1(ntdb_fetch(ntdb, key, &d) == NTDB_ERR_LOCK);
126                 ok1(tap_log_messages == 1);
127                 tap_log_messages = 0;
128
129                 /* Nonblocking delete. */
130                 lock_err = EAGAIN;
131                 ok1(ntdb_delete(ntdb, key) == NTDB_ERR_LOCK);
132                 ok1(tap_log_messages == 0);
133                 lock_err = EINTR;
134                 ok1(ntdb_delete(ntdb, key) == NTDB_ERR_LOCK);
135                 ok1(tap_log_messages == 0);
136                 lock_err = ENOMEM;
137                 ok1(ntdb_delete(ntdb, key) == NTDB_ERR_LOCK);
138                 ok1(tap_log_messages == 1);
139                 tap_log_messages = 0;
140
141                 /* Nonblocking locks. */
142                 lock_err = EAGAIN;
143                 ok1(ntdb_chainlock(ntdb, key) == NTDB_ERR_LOCK);
144                 ok1(tap_log_messages == 0);
145                 lock_err = EINTR;
146                 ok1(ntdb_chainlock(ntdb, key) == NTDB_ERR_LOCK);
147                 ok1(tap_log_messages == 0);
148                 lock_err = ENOMEM;
149                 ok1(ntdb_chainlock(ntdb, key) == NTDB_ERR_LOCK);
150                 ok1(tap_log_messages == 1);
151                 tap_log_messages = 0;
152
153                 lock_err = EAGAIN;
154                 ok1(ntdb_chainlock_read(ntdb, key) == NTDB_ERR_LOCK);
155                 ok1(tap_log_messages == 0);
156                 lock_err = EINTR;
157                 ok1(ntdb_chainlock_read(ntdb, key) == NTDB_ERR_LOCK);
158                 ok1(tap_log_messages == 0);
159                 lock_err = ENOMEM;
160                 ok1(ntdb_chainlock_read(ntdb, key) == NTDB_ERR_LOCK);
161                 ok1(tap_log_messages == 1);
162                 tap_log_messages = 0;
163
164                 lock_err = EAGAIN;
165                 ok1(ntdb_lockall(ntdb) == NTDB_ERR_LOCK);
166                 ok1(tap_log_messages == 0);
167                 lock_err = EINTR;
168                 ok1(ntdb_lockall(ntdb) == NTDB_ERR_LOCK);
169                 ok1(tap_log_messages == 0);
170                 lock_err = ENOMEM;
171                 ok1(ntdb_lockall(ntdb) == NTDB_ERR_LOCK);
172                 /* This actually does divide and conquer. */
173                 ok1(tap_log_messages > 0);
174                 tap_log_messages = 0;
175
176                 lock_err = EAGAIN;
177                 ok1(ntdb_lockall_read(ntdb) == NTDB_ERR_LOCK);
178                 ok1(tap_log_messages == 0);
179                 lock_err = EINTR;
180                 ok1(ntdb_lockall_read(ntdb) == NTDB_ERR_LOCK);
181                 ok1(tap_log_messages == 0);
182                 lock_err = ENOMEM;
183                 ok1(ntdb_lockall_read(ntdb) == NTDB_ERR_LOCK);
184                 ok1(tap_log_messages > 0);
185                 tap_log_messages = 0;
186
187                 /* Nonblocking traverse; go nonblock partway through. */
188                 lock_err = 0;
189                 ok1(ntdb_store(ntdb, key, data, NTDB_REPLACE) == 0);
190                 /* Need two entries to ensure two lock attempts! */
191                 ok1(ntdb_store(ntdb, ntdb_mkdata("key2", 4), data,
192                                NTDB_REPLACE) == 0);
193                 trav_err = EAGAIN;
194                 ok1(ntdb_traverse(ntdb, trav, &lock_err) == NTDB_ERR_LOCK);
195                 ok1(tap_log_messages == 0);
196                 trav_err = EINTR;
197                 lock_err = 0;
198                 ok1(ntdb_traverse(ntdb, trav, &lock_err) == NTDB_ERR_LOCK);
199                 ok1(tap_log_messages == 0);
200                 trav_err = ENOMEM;
201                 lock_err = 0;
202                 ok1(ntdb_traverse(ntdb, trav, &lock_err) == NTDB_ERR_LOCK);
203                 ok1(tap_log_messages == 1);
204                 tap_log_messages = 0;
205
206                 /* Nonblocking transactions. */
207                 lock_err = EAGAIN;
208                 ok1(ntdb_transaction_start(ntdb) == NTDB_ERR_LOCK);
209                 ok1(tap_log_messages == 0);
210                 lock_err = EINTR;
211                 ok1(ntdb_transaction_start(ntdb) == NTDB_ERR_LOCK);
212                 ok1(tap_log_messages == 0);
213                 lock_err = ENOMEM;
214                 ok1(ntdb_transaction_start(ntdb) == NTDB_ERR_LOCK);
215                 ok1(tap_log_messages == 1);
216                 tap_log_messages = 0;
217
218                 /* Nonblocking transaction prepare. */
219                 lock_err = 0;
220                 ok1(ntdb_transaction_start(ntdb) == 0);
221                 ok1(ntdb_delete(ntdb, key) == 0);
222
223                 lock_err = EAGAIN;
224                 ok1(ntdb_transaction_prepare_commit(ntdb) == NTDB_ERR_LOCK);
225                 ok1(tap_log_messages == 0);
226
227                 lock_err = 0;
228                 ok1(ntdb_transaction_prepare_commit(ntdb) == 0);
229                 ok1(ntdb_transaction_commit(ntdb) == 0);
230
231                 /* And the transaction was committed, right? */
232                 ok1(!ntdb_exists(ntdb, key));
233                 ntdb_close(ntdb);
234                 ok1(tap_log_messages == 0);
235         }
236         return exit_status();
237 }