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/hash.c>
6 #include <ccan/tdb2/check.c>
7 #include <ccan/tap/tap.h>
11 static tdb_len_t free_record_length(struct tdb_context *tdb, tdb_off_t off)
13 struct tdb_free_record f;
15 if (tdb_read_convert(tdb, off, &f, sizeof(f)) != 0)
17 if (frec_magic(&f) != TDB_FREE_MAGIC)
22 int main(int argc, char *argv[])
25 struct tdb_context *tdb;
26 struct tdb_layout *layout;
27 struct tdb_data data, key;
30 /* FIXME: Test TDB_CONVERT */
33 data.dptr = (void *)"world";
35 key.dptr = (void *)"hello";
38 /* No coalescing can be done due to EOF */
39 layout = new_tdb_layout(NULL);
40 tdb_layout_add_freelist(layout);
42 tdb_layout_add_free(layout, len);
43 tdb = tdb_layout_get(layout);
44 ok1(tdb_check(tdb, NULL, NULL) == 0);
45 ok1(free_record_length(tdb, layout->elem[1].base.off) == len);
47 /* Figure out which bucket free entry is. */
48 b_off = bucket_off(tdb->flist_off, size_to_bucket(len));
49 /* Lock and fail to coalesce. */
50 ok1(tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT) == 0);
51 ok1(coalesce(tdb, layout->elem[1].base.off, b_off, len) == 0);
52 tdb_unlock_free_bucket(tdb, b_off);
53 ok1(free_record_length(tdb, layout->elem[1].base.off) == len);
54 ok1(tdb_check(tdb, NULL, NULL) == 0);
57 /* No coalescing can be done due to used record */
58 layout = new_tdb_layout(NULL);
59 tdb_layout_add_freelist(layout);
60 tdb_layout_add_free(layout, 1024);
61 tdb_layout_add_used(layout, key, data, 6);
62 tdb = tdb_layout_get(layout);
63 ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024);
64 ok1(tdb_check(tdb, NULL, NULL) == 0);
66 /* Figure out which bucket free entry is. */
67 b_off = bucket_off(tdb->flist_off, size_to_bucket(1024));
68 /* Lock and fail to coalesce. */
69 ok1(tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT) == 0);
70 ok1(coalesce(tdb, layout->elem[1].base.off, b_off, 1024) == 0);
71 tdb_unlock_free_bucket(tdb, b_off);
72 ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024);
73 ok1(tdb_check(tdb, NULL, NULL) == 0);
76 /* Coalescing can be done due to two free records, then EOF */
77 layout = new_tdb_layout(NULL);
78 tdb_layout_add_freelist(layout);
79 tdb_layout_add_free(layout, 1024);
80 tdb_layout_add_free(layout, 2048);
81 tdb = tdb_layout_get(layout);
82 ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024);
83 ok1(free_record_length(tdb, layout->elem[2].base.off) == 2048);
84 ok1(tdb_check(tdb, NULL, NULL) == 0);
86 /* Figure out which bucket (first) free entry is. */
87 b_off = bucket_off(tdb->flist_off, size_to_bucket(1024));
88 /* Lock and coalesce. */
89 ok1(tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT) == 0);
90 ok1(coalesce(tdb, layout->elem[1].base.off, b_off, 1024) == 1);
91 ok1(!tdb_has_locks(tdb));
92 ok1(free_record_length(tdb, layout->elem[1].base.off)
93 == 1024 + sizeof(struct tdb_used_record) + 2048);
94 ok1(tdb_check(tdb, NULL, NULL) == 0);
97 /* Coalescing can be done due to two free records, then data */
98 layout = new_tdb_layout(NULL);
99 tdb_layout_add_freelist(layout);
100 tdb_layout_add_free(layout, 1024);
101 tdb_layout_add_free(layout, 512);
102 tdb_layout_add_used(layout, key, data, 6);
103 tdb = tdb_layout_get(layout);
104 ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024);
105 ok1(free_record_length(tdb, layout->elem[2].base.off) == 512);
106 ok1(tdb_check(tdb, NULL, NULL) == 0);
108 /* Figure out which bucket free entry is. */
109 b_off = bucket_off(tdb->flist_off, size_to_bucket(1024));
110 /* Lock and coalesce. */
111 ok1(tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT) == 0);
112 ok1(coalesce(tdb, layout->elem[1].base.off, b_off, 1024) == 1);
113 ok1(!tdb_has_locks(tdb));
114 ok1(free_record_length(tdb, layout->elem[1].base.off)
115 == 1024 + sizeof(struct tdb_used_record) + 512);
116 ok1(tdb_check(tdb, NULL, NULL) == 0);
119 /* Coalescing can be done due to three free records, then EOF */
120 layout = new_tdb_layout(NULL);
121 tdb_layout_add_freelist(layout);
122 tdb_layout_add_free(layout, 1024);
123 tdb_layout_add_free(layout, 512);
124 tdb_layout_add_free(layout, 256);
125 tdb = tdb_layout_get(layout);
126 ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024);
127 ok1(free_record_length(tdb, layout->elem[2].base.off) == 512);
128 ok1(free_record_length(tdb, layout->elem[3].base.off) == 256);
129 ok1(tdb_check(tdb, NULL, NULL) == 0);
131 /* Figure out which bucket free entry is. */
132 b_off = bucket_off(tdb->flist_off, size_to_bucket(1024));
133 /* Lock and coalesce. */
134 ok1(tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT) == 0);
135 ok1(coalesce(tdb, layout->elem[1].base.off, b_off, 1024) == 1);
136 ok1(!tdb_has_locks(tdb));
137 ok1(free_record_length(tdb, layout->elem[1].base.off)
138 == 1024 + sizeof(struct tdb_used_record) + 512
139 + sizeof(struct tdb_used_record) + 256);
140 ok1(tdb_check(tdb, NULL, NULL) == 0);
143 ok1(tap_log_messages == 0);
144 return exit_status();