9e82a9230568d4fe6a5e23d3546022df5aff38e2
[ccan] / ccan / tdb2 / test / run-15-append.c
1 #include "tdb2-source.h"
2 #include <ccan/tap/tap.h>
3 #include <ccan/ilog/ilog.h>
4 #include "logging.h"
5
6 #define MAX_SIZE 13100
7 #define SIZE_STEP 131
8
9 static tdb_off_t tdb_offset(struct tdb_context *tdb, struct tdb_data key)
10 {
11         tdb_off_t off;
12         struct tdb_used_record rec;
13         struct hash_info h;
14
15         off = find_and_lock(tdb, key, F_RDLCK, &h, &rec, NULL);
16         if (TDB_OFF_IS_ERR(off))
17                 return 0;
18         tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_RDLCK);
19         return off;
20 }
21
22 int main(int argc, char *argv[])
23 {
24         unsigned int i, j, moves;
25         struct tdb_context *tdb;
26         unsigned char *buffer;
27         tdb_off_t oldoff = 0, newoff;
28         int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
29                         TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT, 
30                         TDB_NOMMAP|TDB_CONVERT };
31         struct tdb_data key = tdb_mkdata("key", 3);
32         struct tdb_data data;
33
34         buffer = malloc(MAX_SIZE);
35         for (i = 0; i < MAX_SIZE; i++)
36                 buffer[i] = i;
37
38         plan_tests(sizeof(flags) / sizeof(flags[0])
39                    * ((3 + MAX_SIZE/SIZE_STEP * 5) * 2 + 7)
40                    + 1);
41
42         /* Using tdb_store. */
43         for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
44                 tdb = tdb_open("run-append.tdb", flags[i],
45                                O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
46                 ok1(tdb);
47                 if (!tdb)
48                         continue;
49
50                 moves = 0;
51                 for (j = 0; j < MAX_SIZE; j += SIZE_STEP) {
52                         data.dptr = buffer;
53                         data.dsize = j;
54                         ok1(tdb_store(tdb, key, data, TDB_REPLACE) == 0);
55                         ok1(tdb_check(tdb, NULL, NULL) == 0);
56                         ok1(tdb_fetch(tdb, key, &data) == TDB_SUCCESS);
57                         ok1(data.dsize == j);
58                         ok1(memcmp(data.dptr, buffer, data.dsize) == 0);
59                         free(data.dptr);
60                         newoff = tdb_offset(tdb, key);
61                         if (newoff != oldoff)
62                                 moves++;
63                         oldoff = newoff;
64                 }
65                 ok1(!tdb->file || (tdb->file->allrecord_lock.count == 0
66                                    && tdb->file->num_lockrecs == 0));
67                 /* We should increase by 50% each time... */
68                 ok(moves <= ilog64(j / SIZE_STEP)*2, "Moved %u times", moves);
69                 tdb_close(tdb);
70         }
71
72         /* Using tdb_append. */
73         for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
74                 size_t prev_len = 0;
75                 tdb = tdb_open("run-append.tdb", flags[i],
76                                O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
77                 ok1(tdb);
78                 if (!tdb)
79                         continue;
80
81                 moves = 0;
82                 for (j = 0; j < MAX_SIZE; j += SIZE_STEP) {
83                         data.dptr = buffer + prev_len;
84                         data.dsize = j - prev_len;
85                         ok1(tdb_append(tdb, key, data) == 0);
86                         ok1(tdb_check(tdb, NULL, NULL) == 0);
87                         ok1(tdb_fetch(tdb, key, &data) == TDB_SUCCESS);
88                         ok1(data.dsize == j);
89                         ok1(memcmp(data.dptr, buffer, data.dsize) == 0);
90                         free(data.dptr);
91                         prev_len = data.dsize;
92                         newoff = tdb_offset(tdb, key);
93                         if (newoff != oldoff)
94                                 moves++;
95                         oldoff = newoff;
96                 }
97                 ok1(!tdb->file || (tdb->file->allrecord_lock.count == 0
98                                    && tdb->file->num_lockrecs == 0));
99                 /* We should increase by 50% each time... */
100                 ok(moves <= ilog64(j / SIZE_STEP)*2, "Moved %u times", moves);
101                 tdb_close(tdb);
102         }
103
104         for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
105                 tdb = tdb_open("run-append.tdb", flags[i],
106                                O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
107                 ok1(tdb);
108                 if (!tdb)
109                         continue;
110
111                 /* Huge initial store. */
112                 data.dptr = buffer;
113                 data.dsize = MAX_SIZE;
114                 ok1(tdb_append(tdb, key, data) == 0);
115                 ok1(tdb_check(tdb, NULL, NULL) == 0);
116                 ok1(tdb_fetch(tdb, key, &data) == TDB_SUCCESS);
117                 ok1(data.dsize == MAX_SIZE);
118                 ok1(memcmp(data.dptr, buffer, data.dsize) == 0);
119                 free(data.dptr);
120                 ok1(!tdb->file || (tdb->file->allrecord_lock.count == 0
121                                    && tdb->file->num_lockrecs == 0));
122                 tdb_close(tdb);
123         }
124
125         ok1(tap_log_messages == 0);
126         free(buffer);
127         return exit_status();
128 }