ntdb: make sure file is always a multiple of PAGESIZE (now NTDB_PGSIZE)
[kai/samba-autobuild/.git] / lib / ntdb / test / run-30-exhaust-before-expand.c
1 #include "ntdb-source.h"
2 #include "tap-interface.h"
3 #include "logging.h"
4
5 static bool empty_freetable(struct ntdb_context *ntdb)
6 {
7         struct ntdb_freetable ftab;
8         unsigned int i;
9
10         /* Now, free table should be completely exhausted in zone 0 */
11         if (ntdb_read_convert(ntdb, ntdb->ftable_off, &ftab, sizeof(ftab)) != 0)
12                 abort();
13
14         for (i = 0; i < sizeof(ftab.buckets)/sizeof(ftab.buckets[0]); i++) {
15                 if (ftab.buckets[i])
16                         return false;
17         }
18         return true;
19 }
20
21
22 int main(int argc, char *argv[])
23 {
24         unsigned int i, j;
25         struct ntdb_context *ntdb;
26         int flags[] = { NTDB_INTERNAL, NTDB_DEFAULT, NTDB_NOMMAP,
27                         NTDB_INTERNAL|NTDB_CONVERT, NTDB_CONVERT,
28                         NTDB_NOMMAP|NTDB_CONVERT };
29
30         plan_tests(sizeof(flags) / sizeof(flags[0]) * 11 + 1);
31
32         for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
33                 NTDB_DATA k, d;
34                 uint64_t size, old_size;
35                 bool was_empty = false;
36
37                 k.dptr = (void *)&j;
38                 k.dsize = sizeof(j);
39
40                 ntdb = ntdb_open("run-30-exhaust-before-expand.ntdb", flags[i],
41                                O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
42                 ok1(ntdb);
43                 if (!ntdb)
44                         continue;
45
46                 old_size = ntdb->file->map_size;
47
48                 ok1(empty_freetable(ntdb));
49                 /* Need some hash lock for expand. */
50                 ok1(ntdb_lock_hashes(ntdb, 0, 1, F_WRLCK, NTDB_LOCK_WAIT) == 0);
51                 /* Create some free space. */
52                 ok1(ntdb_expand(ntdb, 1) == 0);
53                 ok1(ntdb_unlock_hashes(ntdb, 0, 1, F_WRLCK) == 0);
54                 ok1(ntdb_check(ntdb, NULL, NULL) == 0);
55                 ok1(!empty_freetable(ntdb));
56
57                 size = ntdb->file->map_size;
58
59                 /* Create one record to chew up most space. */
60                 d.dsize = (size - old_size - 32);
61                 d.dptr = malloc(d.dsize);
62                 j = 0;
63                 ok1(ntdb_store(ntdb, k, d, NTDB_INSERT) == 0);
64                 ok1(ntdb->file->map_size == size);
65                 free(d.dptr);
66
67                 /* Now insert minimal-length records until we expand. */
68                 for (j = 1; ntdb->file->map_size == size; j++) {
69                         was_empty = empty_freetable(ntdb);
70                         if (ntdb_store(ntdb, k, k, NTDB_INSERT) != 0)
71                                 err(1, "Failed to store record %i", j);
72                 }
73
74                 /* Would have been empty before expansion, but no longer. */
75                 ok1(was_empty);
76                 ok1(!empty_freetable(ntdb));
77                 ntdb_close(ntdb);
78         }
79
80         ok1(tap_log_messages == 0);
81         return exit_status();
82 }