blob: 7078263acc3dfc6a83eed6ee4620e975aa958455 [file] [log] [blame]
Chris Masonfec577f2007-02-26 10:40:21 -05001#include <stdio.h>
2#include <stdlib.h>
3#include <signal.h>
4#include "kerncompat.h"
5#include "radix-tree.h"
6#include "ctree.h"
7#include "disk-io.h"
8#include "print-tree.h"
9
10int keep_running = 1;
11
12static int setup_key(struct radix_tree_root *root, struct key *key, int exists)
13{
14 int num = rand();
15 unsigned long res[2];
16 int ret;
17
18 key->flags = 0;
19 key->offset = 0;
20again:
21 ret = radix_tree_gang_lookup(root, (void **)res, num, 2);
22 if (exists) {
23 if (ret == 0)
24 return -1;
25 num = res[0];
26 } else if (ret != 0 && num == res[0]) {
27 num++;
28 if (ret > 1 && num == res[1]) {
29 num++;
30 goto again;
31 }
32 }
33 key->objectid = num;
34 return 0;
35}
36
37static int ins_one(struct ctree_root *root, struct radix_tree_root *radix)
38{
39 struct ctree_path path;
40 struct key key;
41 int ret;
42 char buf[128];
Chris Mason41903fe2007-02-26 10:55:42 -050043 unsigned long oid;
Chris Masonfec577f2007-02-26 10:40:21 -050044 init_path(&path);
45 ret = setup_key(radix, &key, 0);
Chris Mason7cf75962007-02-26 10:55:01 -050046 sprintf(buf, "str-%Lu\n", key.objectid);
Chris Masonfec577f2007-02-26 10:40:21 -050047 ret = insert_item(root, &key, buf, strlen(buf));
48 if (ret)
49 goto error;
Chris Mason41903fe2007-02-26 10:55:42 -050050 oid = (unsigned long)key.objectid;
Chris Masonfec577f2007-02-26 10:40:21 -050051 radix_tree_preload(GFP_KERNEL);
Chris Mason41903fe2007-02-26 10:55:42 -050052 ret = radix_tree_insert(radix, oid, (void *)oid);
Chris Masonfec577f2007-02-26 10:40:21 -050053 radix_tree_preload_end();
54 if (ret)
55 goto error;
56 return ret;
57error:
Chris Mason7cf75962007-02-26 10:55:01 -050058 printf("failed to insert %Lu\n", key.objectid);
Chris Masonfec577f2007-02-26 10:40:21 -050059 return -1;
60}
61
62static int insert_dup(struct ctree_root *root, struct radix_tree_root *radix)
63{
64 struct ctree_path path;
65 struct key key;
66 int ret;
67 char buf[128];
68 init_path(&path);
69 ret = setup_key(radix, &key, 1);
70 if (ret < 0)
71 return 0;
Chris Mason7cf75962007-02-26 10:55:01 -050072 sprintf(buf, "str-%Lu\n", key.objectid);
Chris Masonfec577f2007-02-26 10:40:21 -050073 ret = insert_item(root, &key, buf, strlen(buf));
74 if (ret != -EEXIST) {
Chris Mason7cf75962007-02-26 10:55:01 -050075 printf("insert on %Lu gave us %d\n", key.objectid, ret);
Chris Masonfec577f2007-02-26 10:40:21 -050076 return 1;
77 }
78 return 0;
79}
80
81static int del_one(struct ctree_root *root, struct radix_tree_root *radix)
82{
83 struct ctree_path path;
84 struct key key;
85 int ret;
86 unsigned long *ptr;
87 init_path(&path);
88 ret = setup_key(radix, &key, 1);
89 if (ret < 0)
90 return 0;
91 ret = search_slot(root, &key, &path, -1);
92 if (ret)
93 goto error;
94 ret = del_item(root, &path);
95 release_path(root, &path);
96 if (ret != 0)
97 goto error;
98 ptr = radix_tree_delete(radix, key.objectid);
99 if (!ptr)
100 goto error;
101 return 0;
102error:
Chris Mason7cf75962007-02-26 10:55:01 -0500103 printf("failed to delete %Lu\n", key.objectid);
Chris Masonfec577f2007-02-26 10:40:21 -0500104 return -1;
105}
106
107static int lookup_item(struct ctree_root *root, struct radix_tree_root *radix)
108{
109 struct ctree_path path;
110 struct key key;
111 int ret;
112 init_path(&path);
113 ret = setup_key(radix, &key, 1);
114 if (ret < 0)
115 return 0;
116 ret = search_slot(root, &key, &path, 0);
117 release_path(root, &path);
118 if (ret)
119 goto error;
120 return 0;
121error:
Chris Mason7cf75962007-02-26 10:55:01 -0500122 printf("unable to find key %Lu\n", key.objectid);
Chris Masonfec577f2007-02-26 10:40:21 -0500123 return -1;
124}
125
126static int lookup_enoent(struct ctree_root *root, struct radix_tree_root *radix)
127{
128 struct ctree_path path;
129 struct key key;
130 int ret;
131 init_path(&path);
132 ret = setup_key(radix, &key, 0);
133 if (ret < 0)
134 return ret;
135 ret = search_slot(root, &key, &path, 0);
136 release_path(root, &path);
137 if (ret == 0)
138 goto error;
139 return 0;
140error:
Chris Mason7cf75962007-02-26 10:55:01 -0500141 printf("able to find key that should not exist %Lu\n", key.objectid);
Chris Masonfec577f2007-02-26 10:40:21 -0500142 return -1;
143}
144
145int (*ops[])(struct ctree_root *root, struct radix_tree_root *radix) =
146{ ins_one, insert_dup, del_one, lookup_item, lookup_enoent };
147
148static int fill_radix(struct ctree_root *root, struct radix_tree_root *radix)
149{
150 struct ctree_path path;
151 struct key key;
Chris Mason7cf75962007-02-26 10:55:01 -0500152 unsigned long found;
Chris Masonfec577f2007-02-26 10:40:21 -0500153 int ret;
154 int slot;
155 int i;
156 key.offset = 0;
157 key.flags = 0;
158 key.objectid = (unsigned long)-1;
159 while(1) {
160 init_path(&path);
161 ret = search_slot(root, &key, &path, 0);
162 slot = path.slots[0];
163 if (ret != 0) {
164 if (slot == 0) {
165 release_path(root, &path);
166 break;
167 }
168 slot -= 1;
169 }
170 for (i = slot; i >= 0; i--) {
171 found = path.nodes[0]->leaf.items[i].key.objectid;
172 radix_tree_preload(GFP_KERNEL);
173 ret = radix_tree_insert(radix, found, (void *)found);
174 if (ret) {
175 fprintf(stderr,
176 "failed to insert %lu into radix\n",
177 found);
178 exit(1);
179 }
180
181 radix_tree_preload_end();
182 }
183 release_path(root, &path);
184 key.objectid = found - 1;
185 if (key.objectid > found)
186 break;
187 }
188 return 0;
189}
190
191void sigstopper(int ignored)
192{
193 keep_running = 0;
194 fprintf(stderr, "caught exit signal, stopping\n");
195}
196
197int print_usage(void)
198{
199 printf("usage: tester [-ih] [-c count] [-f count]\n");
200 printf("\t -c count -- iteration count after filling\n");
201 printf("\t -f count -- run this many random inserts before starting\n");
202 printf("\t -i -- only do initial fill\n");
203 printf("\t -h -- this help text\n");
204 exit(1);
205}
206int main(int ac, char **av)
207{
208 RADIX_TREE(radix, GFP_KERNEL);
209 struct ctree_super_block super;
210 struct ctree_root *root;
211 int i;
212 int ret;
213 int count;
214 int op;
215 int iterations = 20000;
216 int init_fill_count = 800000;
217 int err = 0;
218 int initial_only = 0;
219 radix_tree_init();
220 root = open_ctree("dbfile", &super);
221 fill_radix(root, &radix);
222
223 signal(SIGTERM, sigstopper);
224 signal(SIGINT, sigstopper);
225
226 for (i = 1 ; i < ac ; i++) {
227 if (strcmp(av[i], "-i") == 0) {
228 initial_only = 1;
229 } else if (strcmp(av[i], "-c") == 0) {
230 iterations = atoi(av[i+1]);
231 i++;
232 } else if (strcmp(av[i], "-f") == 0) {
233 init_fill_count = atoi(av[i+1]);
234 i++;
235 } else {
236 print_usage();
237 }
238 }
239 for (i = 0; i < init_fill_count; i++) {
240 ret = ins_one(root, &radix);
241 if (ret) {
242 printf("initial fill failed\n");
243 err = ret;
244 goto out;
245 }
246 if (i % 10000 == 0) {
247 printf("initial fill %d level %d count %d\n", i,
248 node_level(root->node->node.header.flags),
249 root->node->node.header.nritems);
250 }
251 if (keep_running == 0) {
252 err = 0;
253 goto out;
254 }
255 }
256 if (initial_only == 1) {
257 goto out;
258 }
259 for (i = 0; i < iterations; i++) {
260 op = rand() % ARRAY_SIZE(ops);
261 count = rand() % 128;
262 if (i % 2000 == 0) {
263 printf("%d\n", i);
264 fflush(stdout);
265 }
266 if (i && i % 5000 == 0) {
267 printf("open & close, root level %d nritems %d\n",
268 node_level(root->node->node.header.flags),
269 root->node->node.header.nritems);
270 write_ctree_super(root, &super);
271 close_ctree(root);
272 root = open_ctree("dbfile", &super);
273 }
274 while(count--) {
275 ret = ops[op](root, &radix);
276 if (ret) {
277 fprintf(stderr, "op %d failed %d:%d\n",
278 op, i, iterations);
279 print_tree(root, root->node);
280 fprintf(stderr, "op %d failed %d:%d\n",
281 op, i, iterations);
282 err = ret;
283 goto out;
284 }
285 if (keep_running == 0) {
286 err = 0;
287 goto out;
288 }
289 }
290 }
291out:
292 write_ctree_super(root, &super);
293 close_ctree(root);
294 return err;
295}
296