eb656954f83b64b25862130151f7b17abad6c5f7
[ccan] / ccan / tdb2 / test / run-30-exhaust-before-expand.c
1 #include <ccan/tdb2/tdb.c>
2 #include <ccan/tdb2/free.c>
3 #include <ccan/tdb2/lock.c>
4 #include <ccan/tdb2/io.c>
5 #include <ccan/tdb2/check.c>
6 #include <ccan/tdb2/hash.c>
7 #include <ccan/tap/tap.h>
8 #include <err.h>
9 #include "logging.h"
10
11 int main(int argc, char *argv[])
12 {
13         unsigned int i, j;
14         struct tdb_context *tdb;
15         int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
16                         TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
17                         TDB_NOMMAP|TDB_CONVERT };
18
19         plan_tests(sizeof(flags) / sizeof(flags[0]) * 5 + 1);
20
21         for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
22                 tdb_off_t free[BUCKETS_FOR_ZONE(INITIAL_ZONE_BITS) + 1];
23                 bool all_empty;
24                 TDB_DATA k, d;
25
26                 k.dptr = (void *)&j;
27                 k.dsize = sizeof(j);
28
29                 tdb = tdb_open("run-30-exhaust-before-expand.tdb", flags[i],
30                                O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
31                 ok1(tdb);
32                 if (!tdb)
33                         continue;
34
35                 /* We don't want the hash to expand, so we use one alloc to
36                  * chew up over most of the space first. */
37                 j = -1;
38                 d.dsize = (1 << INITIAL_ZONE_BITS) - 500;
39                 d.dptr = malloc(d.dsize);
40                 ok1(tdb_store(tdb, k, d, TDB_INSERT) == 0);
41                 ok1(tdb->map_size == sizeof(struct tdb_header)
42                     + (1 << INITIAL_ZONE_BITS));
43
44                 /* Insert minimal-length records until we add a zone. */ 
45                 for (j = 0;
46                      tdb->map_size == sizeof(struct tdb_header)
47                              + (1 << INITIAL_ZONE_BITS);
48                      j++) {
49                         if (tdb_store(tdb, k, k, TDB_INSERT) != 0)
50                                 err(1, "Failed to store record %i", j);
51                 }
52
53                 /* Now, free list should be completely exhausted in zone 0 */
54                 ok1(tdb_read_convert(tdb,
55                                      sizeof(struct tdb_header)
56                                      + sizeof(struct free_zone_header),
57                                      &free, sizeof(free)) == 0);
58
59                 all_empty = true;
60                 for (j = 0; j < sizeof(free)/sizeof(free[0]); j++) {
61                         if (free[j]) {
62                                 diag("Free bucket %i not empty", j);
63                                 all_empty = false;
64                         }
65                 }
66                 ok1(all_empty);
67                 tdb_close(tdb);
68         }
69
70         ok1(tap_log_messages == 0);
71         return exit_status();
72 }