1 | #include "../common/tdb_private.h"
|
---|
2 |
|
---|
3 | /* Speed up the tests, but do the actual sync tests. */
|
---|
4 | static unsigned int sync_counts = 0;
|
---|
5 | static inline int fake_fsync(int fd)
|
---|
6 | {
|
---|
7 | sync_counts++;
|
---|
8 | return 0;
|
---|
9 | }
|
---|
10 | #define fsync fake_fsync
|
---|
11 |
|
---|
12 | #ifdef MS_SYNC
|
---|
13 | static inline int fake_msync(void *addr, size_t length, int flags)
|
---|
14 | {
|
---|
15 | sync_counts++;
|
---|
16 | return 0;
|
---|
17 | }
|
---|
18 | #define msync fake_msync
|
---|
19 | #endif
|
---|
20 |
|
---|
21 | #ifdef HAVE_FDATASYNC
|
---|
22 | static inline int fake_fdatasync(int fd)
|
---|
23 | {
|
---|
24 | sync_counts++;
|
---|
25 | return 0;
|
---|
26 | }
|
---|
27 | #define fdatasync fake_fdatasync
|
---|
28 | #endif
|
---|
29 |
|
---|
30 | #include "../common/io.c"
|
---|
31 | #include "../common/tdb.c"
|
---|
32 | #include "../common/lock.c"
|
---|
33 | #include "../common/freelist.c"
|
---|
34 | #include "../common/traverse.c"
|
---|
35 | #include "../common/transaction.c"
|
---|
36 | #include "../common/error.c"
|
---|
37 | #include "../common/open.c"
|
---|
38 | #include "../common/check.c"
|
---|
39 | #include "../common/hash.c"
|
---|
40 | #include "../common/mutex.c"
|
---|
41 | #include "tap-interface.h"
|
---|
42 | #include <stdlib.h>
|
---|
43 | #include "logging.h"
|
---|
44 |
|
---|
45 | static void write_record(struct tdb_context *tdb, size_t extra_len,
|
---|
46 | TDB_DATA *data)
|
---|
47 | {
|
---|
48 | TDB_DATA key;
|
---|
49 | key.dsize = strlen("hi");
|
---|
50 | key.dptr = discard_const_p(uint8_t, "hi");
|
---|
51 |
|
---|
52 | data->dsize += extra_len;
|
---|
53 | tdb_transaction_start(tdb);
|
---|
54 | tdb_store(tdb, key, *data, TDB_REPLACE);
|
---|
55 | tdb_transaction_commit(tdb);
|
---|
56 | }
|
---|
57 |
|
---|
58 | int main(int argc, char *argv[])
|
---|
59 | {
|
---|
60 | struct tdb_context *tdb;
|
---|
61 | size_t i;
|
---|
62 | TDB_DATA data;
|
---|
63 | struct tdb_record rec;
|
---|
64 | tdb_off_t off;
|
---|
65 |
|
---|
66 | /* Do *not* suppress sync for this test; we do it ourselves. */
|
---|
67 | unsetenv("TDB_NO_FSYNC");
|
---|
68 |
|
---|
69 | plan_tests(5);
|
---|
70 | tdb = tdb_open_ex("run-transaction-expand.tdb",
|
---|
71 | 1024, TDB_CLEAR_IF_FIRST,
|
---|
72 | O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL);
|
---|
73 | ok1(tdb);
|
---|
74 |
|
---|
75 | data.dsize = 0;
|
---|
76 | data.dptr = calloc(1000, getpagesize());
|
---|
77 | if (data.dptr == NULL) {
|
---|
78 | diag("Unable to allocate memory for data.dptr");
|
---|
79 | tdb_close(tdb);
|
---|
80 | exit(1);
|
---|
81 | }
|
---|
82 |
|
---|
83 | /* Simulate a slowly growing record. */
|
---|
84 | for (i = 0; i < 1000; i++)
|
---|
85 | write_record(tdb, getpagesize(), &data);
|
---|
86 |
|
---|
87 | tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &off);
|
---|
88 | tdb_read(tdb, off, &rec, sizeof(rec), DOCONV());
|
---|
89 | diag("TDB size = %zu, recovery = %llu-%llu",
|
---|
90 | (size_t)tdb->map_size, (unsigned long long)off, (unsigned long long)(off + sizeof(rec) + rec.rec_len));
|
---|
91 |
|
---|
92 | /* We should only be about 5 times larger than largest record. */
|
---|
93 | ok1(tdb->map_size < 6 * i * getpagesize());
|
---|
94 | tdb_close(tdb);
|
---|
95 |
|
---|
96 | tdb = tdb_open_ex("run-transaction-expand.tdb",
|
---|
97 | 1024, TDB_CLEAR_IF_FIRST,
|
---|
98 | O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL);
|
---|
99 | ok1(tdb);
|
---|
100 |
|
---|
101 | data.dsize = 0;
|
---|
102 |
|
---|
103 | /* Simulate a slowly growing record, repacking to keep
|
---|
104 | * recovery area at end. */
|
---|
105 | for (i = 0; i < 1000; i++) {
|
---|
106 | write_record(tdb, getpagesize(), &data);
|
---|
107 | if (i % 10 == 0)
|
---|
108 | tdb_repack(tdb);
|
---|
109 | }
|
---|
110 |
|
---|
111 | tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &off);
|
---|
112 | tdb_read(tdb, off, &rec, sizeof(rec), DOCONV());
|
---|
113 | diag("TDB size = %zu, recovery = %llu-%llu",
|
---|
114 | (size_t)tdb->map_size, (unsigned long long)off, (unsigned long long)(off + sizeof(rec) + rec.rec_len));
|
---|
115 |
|
---|
116 | /* We should only be about 4 times larger than largest record. */
|
---|
117 | ok1(tdb->map_size < 5 * i * getpagesize());
|
---|
118 |
|
---|
119 | /* We should have synchronized multiple times. */
|
---|
120 | ok1(sync_counts);
|
---|
121 | tdb_close(tdb);
|
---|
122 | free(data.dptr);
|
---|
123 |
|
---|
124 | return exit_status();
|
---|
125 | }
|
---|