tdb: use same expansion factor logic when expanding for new recovery area.
[ccan] / ccan / tdb / test / run-transaction-expand.c
1 /* We need this otherwise fcntl locking fails. */
2 #define _FILE_OFFSET_BITS 64
3 #define _XOPEN_SOURCE 500
4 #include <ccan/tdb/tdb_private.h>
5
6 /* Speed up the tests: setting TDB_NOSYNC removed recovery altogether. */
7 static inline int fake_fsync(int fd)
8 {
9         return 0;
10 }
11 #define fsync fake_fsync
12
13 #ifdef MS_SYNC
14 static inline int fake_msync(void *addr, size_t length, int flags)
15 {
16         return 0;
17 }
18 #define msync fake_msync
19 #endif
20
21 #include <ccan/tdb/tdb.h>
22 #include <ccan/tdb/io.c>
23 #include <ccan/tdb/tdb.c>
24 #include <ccan/tdb/lock.c>
25 #include <ccan/tdb/freelist.c>
26 #include <ccan/tdb/traverse.c>
27 #include <ccan/tdb/transaction.c>
28 #include <ccan/tdb/error.c>
29 #include <ccan/tdb/open.c>
30 #include <ccan/tdb/check.c>
31 #include <ccan/tdb/hash.c>
32 #include <ccan/tap/tap.h>
33 #include <stdlib.h>
34 #include <err.h>
35 #include "logging.h"
36
37 static void write_record(struct tdb_context *tdb, size_t extra_len,
38                          TDB_DATA *data)
39 {
40         TDB_DATA key;
41         key.dsize = strlen("hi");
42         key.dptr = (void *)"hi";
43
44         data->dsize += extra_len;
45         tdb_transaction_start(tdb);
46         tdb_store(tdb, key, *data, TDB_REPLACE);
47         tdb_transaction_commit(tdb);
48 }
49
50 int main(int argc, char *argv[])
51 {
52         struct tdb_context *tdb;
53         size_t i;
54         TDB_DATA data;
55         struct tdb_record rec;
56         tdb_off_t off;
57
58         plan_tests(2);
59         tdb = tdb_open_ex("run-transaction-expand.tdb",
60                           1024, TDB_CLEAR_IF_FIRST,
61                           O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL);
62         ok1(tdb);
63
64         data.dsize = 0;
65         data.dptr = calloc(1000, getpagesize());
66
67         /* Simulate a slowly growing record. */
68         for (i = 0; i < 1000; i++)
69                 write_record(tdb, getpagesize(), &data);
70
71         tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &off);
72         tdb_read(tdb, off, &rec, sizeof(rec), DOCONV());
73         diag("TDB size = %zu, recovery = %u-%u",
74              (size_t)tdb->map_size, off, off + sizeof(rec) + rec.rec_len);
75
76         /* We should only be about 5 times larger than largest record. */
77         ok1(tdb->map_size < 6 * i * getpagesize());
78         tdb_close(tdb);
79         free(data.dptr);
80
81         return exit_status();
82 }