Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/dbm/tests/lots.c @ 3:150b72113545
Add DBM and legacydb support
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Tue, 05 Aug 2014 18:32:02 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
2:a945361df361 | 3:150b72113545 |
---|---|
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ | |
2 /* This Source Code Form is subject to the terms of the Mozilla Public | |
3 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
5 | |
6 /* use sequental numbers printed to strings | |
7 * to store lots and lots of entries in the | |
8 * database. | |
9 * | |
10 * Start with 100 entries, put them and then | |
11 * read them out. Then delete the first | |
12 * half and verify that all of the first half | |
13 * is gone and then verify that the second | |
14 * half is still there. | |
15 * Then add the first half back and verify | |
16 * again. Then delete the middle third | |
17 * and verify again. | |
18 * Then increase the size by 1000 and do | |
19 * the whole add delete thing again. | |
20 * | |
21 * The data for each object is the number string translated | |
22 * to hex and replicated a random number of times. The | |
23 * number of times that the data is replicated is the first | |
24 * int32 in the data. | |
25 */ | |
26 | |
27 #include <stdio.h> | |
28 | |
29 #include <stdlib.h> | |
30 #ifdef STDC_HEADERS | |
31 #include <stdarg.h> | |
32 #else | |
33 #include <varargs.h> | |
34 #endif | |
35 | |
36 #ifdef HAVE_MEMORY_H | |
37 #include <memory.h> | |
38 #endif | |
39 #include <string.h> | |
40 #include <assert.h> | |
41 #include "mcom_db.h" | |
42 | |
43 DB *database=0; | |
44 int MsgPriority=5; | |
45 | |
46 #if defined(_WINDOWS) && !defined(WIN32) | |
47 #define int32 long | |
48 #define uint32 unsigned long | |
49 #else | |
50 #define int32 int | |
51 #define uint32 unsigned int | |
52 #endif | |
53 | |
54 typedef enum { | |
55 USE_LARGE_KEY, | |
56 USE_SMALL_KEY | |
57 } key_type_enum; | |
58 | |
59 #define TraceMe(priority, msg) \ | |
60 do { \ | |
61 if(priority <= MsgPriority) \ | |
62 { \ | |
63 ReportStatus msg; \ | |
64 } \ | |
65 } while(0) | |
66 | |
67 int | |
68 ReportStatus(char *string, ...) | |
69 { | |
70 va_list args; | |
71 | |
72 #ifdef STDC_HEADERS | |
73 va_start(args, string); | |
74 #else | |
75 va_start(args); | |
76 #endif | |
77 vfprintf(stderr, string, args); | |
78 va_end(args); | |
79 | |
80 fprintf (stderr, "\n"); | |
81 | |
82 return(0); | |
83 } | |
84 | |
85 int | |
86 ReportError(char *string, ...) | |
87 { | |
88 va_list args; | |
89 | |
90 #ifdef STDC_HEADERS | |
91 va_start(args, string); | |
92 #else | |
93 va_start(args); | |
94 #endif | |
95 fprintf (stderr, "\n "); | |
96 vfprintf(stderr, string, args); | |
97 fprintf (stderr, "\n"); | |
98 va_end(args); | |
99 | |
100 return(0); | |
101 } | |
102 | |
103 DBT * MakeLargeKey(int32 num) | |
104 { | |
105 int32 low_bits; | |
106 static DBT rv; | |
107 static char *string_rv=0; | |
108 int rep_char; | |
109 size_t size; | |
110 | |
111 if(string_rv) | |
112 free(string_rv); | |
113 | |
114 /* generate a really large text key derived from | |
115 * an int32 | |
116 */ | |
117 low_bits = (num % 10000) + 1; | |
118 | |
119 /* get the repeat char from the low 26 */ | |
120 rep_char = (char) ((low_bits % 26) + 'a'); | |
121 | |
122 /* malloc a string low_bits wide */ | |
123 size = low_bits*sizeof(char); | |
124 string_rv = (char *)malloc(size); | |
125 | |
126 memset(string_rv, rep_char, size); | |
127 | |
128 rv.data = string_rv; | |
129 rv.size = size; | |
130 | |
131 return(&rv); | |
132 } | |
133 | |
134 DBT * MakeSmallKey(int32 num) | |
135 { | |
136 static DBT rv; | |
137 static char data_string[64]; | |
138 | |
139 rv.data = data_string; | |
140 | |
141 sprintf(data_string, "%ld", (long)num); | |
142 rv.size = strlen(data_string); | |
143 | |
144 return(&rv); | |
145 | |
146 } | |
147 | |
148 DBT * GenKey(int32 num, key_type_enum key_type) | |
149 { | |
150 DBT *key; | |
151 | |
152 switch(key_type) | |
153 { | |
154 case USE_LARGE_KEY: | |
155 key = MakeLargeKey(num); | |
156 break; | |
157 case USE_SMALL_KEY: | |
158 key = MakeSmallKey(num); | |
159 break; | |
160 default: | |
161 abort(); | |
162 break; | |
163 } | |
164 | |
165 return(key); | |
166 } | |
167 | |
168 int | |
169 SeqDatabase() | |
170 { | |
171 int status; | |
172 DBT key, data; | |
173 | |
174 ReportStatus("SEQuencing through database..."); | |
175 | |
176 /* seq through the whole database */ | |
177 if(!(status = (*database->seq)(database, &key, &data, R_FIRST))) | |
178 { | |
179 while(!(status = (database->seq) (database, &key, &data, R_NEXT))) | |
180 ; /* null body */ | |
181 } | |
182 | |
183 if(status < 0) | |
184 ReportError("Error seq'ing database"); | |
185 | |
186 return(status); | |
187 } | |
188 | |
189 int | |
190 VerifyData(DBT *data, int32 num, key_type_enum key_type) | |
191 { | |
192 int32 count, compare_num; | |
193 size_t size; | |
194 int32 *int32_array; | |
195 | |
196 /* The first int32 is count | |
197 * The other n entries should | |
198 * all equal num | |
199 */ | |
200 if(data->size < sizeof(int32)) | |
201 { | |
202 ReportError("Data size corrupted"); | |
203 return -1; | |
204 } | |
205 | |
206 memcpy(&count, data->data, sizeof(int32)); | |
207 | |
208 size = sizeof(int32)*(count+1); | |
209 | |
210 if(size != data->size) | |
211 { | |
212 ReportError("Data size corrupted"); | |
213 return -1; | |
214 } | |
215 | |
216 int32_array = (int32*)data->data; | |
217 | |
218 for(;count > 0; count--) | |
219 { | |
220 memcpy(&compare_num, &int32_array[count], sizeof(int32)); | |
221 | |
222 if(compare_num != num) | |
223 { | |
224 ReportError("Data corrupted"); | |
225 return -1; | |
226 } | |
227 } | |
228 | |
229 return(0); | |
230 } | |
231 | |
232 | |
233 /* verify that a range of number strings exist | |
234 * or don't exist. And that the data is valid | |
235 */ | |
236 #define SHOULD_EXIST 1 | |
237 #define SHOULD_NOT_EXIST 0 | |
238 int | |
239 VerifyRange(int32 low, int32 high, int32 should_exist, key_type_enum key_type) | |
240 { | |
241 DBT *key, data; | |
242 int32 num; | |
243 int status; | |
244 | |
245 TraceMe(1, ("Verifying: %ld to %ld, using %s keys", | |
246 low, high, key_type == USE_SMALL_KEY ? "SMALL" : "LARGE")); | |
247 | |
248 for(num = low; num <= high; num++) | |
249 { | |
250 | |
251 key = GenKey(num, key_type); | |
252 | |
253 status = (*database->get)(database, key, &data, 0); | |
254 | |
255 if(status == 0) | |
256 { | |
257 /* got the item */ | |
258 if(!should_exist) | |
259 { | |
260 ReportError("Item exists but shouldn't: %ld", num); | |
261 } | |
262 else | |
263 { | |
264 /* else verify the data */ | |
265 VerifyData(&data, num, key_type); | |
266 } | |
267 } | |
268 else if(status > 0) | |
269 { | |
270 /* item not found */ | |
271 if(should_exist) | |
272 { | |
273 ReportError("Item not found but should be: %ld", num); | |
274 } | |
275 } | |
276 else | |
277 { | |
278 /* database error */ | |
279 ReportError("Database error"); | |
280 return(-1); | |
281 } | |
282 | |
283 } | |
284 | |
285 TraceMe(1, ("Correctly verified: %ld to %ld", low, high)); | |
286 | |
287 return(0); | |
288 | |
289 } | |
290 | |
291 DBT * | |
292 GenData(int32 num) | |
293 { | |
294 int32 n; | |
295 static DBT *data=0; | |
296 int32 *int32_array; | |
297 size_t size; | |
298 | |
299 if(!data) | |
300 { | |
301 data = (DBT*)malloc(sizeof(DBT)); | |
302 data->size = 0; | |
303 data->data = 0; | |
304 } | |
305 else if(data->data) | |
306 { | |
307 free(data->data); | |
308 } | |
309 | |
310 n = rand(); | |
311 | |
312 n = n % 512; /* bound to a 2K size */ | |
313 | |
314 | |
315 size = sizeof(int32)*(n+1); | |
316 int32_array = (int32 *) malloc(size); | |
317 | |
318 memcpy(&int32_array[0], &n, sizeof(int32)); | |
319 | |
320 for(; n > 0; n--) | |
321 { | |
322 memcpy(&int32_array[n], &num, sizeof(int32)); | |
323 } | |
324 | |
325 data->data = (void*)int32_array; | |
326 data->size = size; | |
327 | |
328 return(data); | |
329 } | |
330 | |
331 #define ADD_RANGE 1 | |
332 #define DELETE_RANGE 2 | |
333 | |
334 int | |
335 AddOrDelRange(int32 low, int32 high, int action, key_type_enum key_type) | |
336 { | |
337 DBT *key, *data; | |
338 #if 0 /* only do this if your really analy checking the puts */ | |
339 DBT tmp_data; | |
340 #endif | |
341 int32 num; | |
342 int status; | |
343 | |
344 if(action != ADD_RANGE && action != DELETE_RANGE) | |
345 assert(0); | |
346 | |
347 if(action == ADD_RANGE) | |
348 { | |
349 TraceMe(1, ("Adding: %ld to %ld: %s keys", low, high, | |
350 key_type == USE_SMALL_KEY ? "SMALL" : "LARGE")); | |
351 } | |
352 else | |
353 { | |
354 TraceMe(1, ("Deleting: %ld to %ld: %s keys", low, high, | |
355 key_type == USE_SMALL_KEY ? "SMALL" : "LARGE")); | |
356 } | |
357 | |
358 for(num = low; num <= high; num++) | |
359 { | |
360 | |
361 key = GenKey(num, key_type); | |
362 | |
363 if(action == ADD_RANGE) | |
364 { | |
365 data = GenData(num); | |
366 status = (*database->put)(database, key, data, 0); | |
367 } | |
368 else | |
369 { | |
370 status = (*database->del)(database, key, 0); | |
371 } | |
372 | |
373 if(status < 0) | |
374 { | |
375 ReportError("Database error %s item: %ld", | |
376 action == ADD_RANGE ? "ADDING" : "DELETING", | |
377 num); | |
378 } | |
379 else if(status > 0) | |
380 { | |
381 ReportError("Could not %s item: %ld", | |
382 action == ADD_RANGE ? "ADD" : "DELETE", | |
383 num); | |
384 } | |
385 else if(action == ADD_RANGE) | |
386 { | |
387 #define SYNC_EVERY_TIME | |
388 #ifdef SYNC_EVERY_TIME | |
389 status = (*database->sync)(database, 0); | |
390 if(status != 0) | |
391 ReportError("Database error syncing after add"); | |
392 #endif | |
393 | |
394 #if 0 /* only do this if your really analy checking the puts */ | |
395 | |
396 /* make sure we can still get it | |
397 */ | |
398 status = (*database->get)(database, key, &tmp_data, 0); | |
399 | |
400 if(status != 0) | |
401 { | |
402 ReportError("Database error checking item just added: %d", | |
403 num); | |
404 } | |
405 else | |
406 { | |
407 /* now verify that none of the ones we already | |
408 * put in have disappeared | |
409 */ | |
410 VerifyRange(low, num, SHOULD_EXIST, key_type); | |
411 } | |
412 #endif | |
413 | |
414 } | |
415 } | |
416 | |
417 | |
418 if(action == ADD_RANGE) | |
419 { | |
420 TraceMe(1, ("Successfully added: %ld to %ld", low, high)); | |
421 } | |
422 else | |
423 { | |
424 TraceMe(1, ("Successfully deleted: %ld to %ld", low, high)); | |
425 } | |
426 | |
427 return(0); | |
428 } | |
429 | |
430 int | |
431 TestRange(int32 low, int32 range, key_type_enum key_type) | |
432 { | |
433 int status; int32 low_of_range1, high_of_range1; int32 low_of_range2, high_of_range2; | |
434 int32 low_of_range3, high_of_range3; | |
435 | |
436 status = AddOrDelRange(low, low+range, ADD_RANGE, key_type); | |
437 status = VerifyRange(low, low+range, SHOULD_EXIST, key_type); | |
438 | |
439 TraceMe(1, ("Finished with sub test 1")); | |
440 | |
441 SeqDatabase(); | |
442 | |
443 low_of_range1 = low; | |
444 high_of_range1 = low+(range/2); | |
445 low_of_range2 = high_of_range1+1; | |
446 high_of_range2 = low+range; | |
447 status = AddOrDelRange(low_of_range1, high_of_range1, DELETE_RANGE, key_type); | |
448 status = VerifyRange(low_of_range1, high_of_range1, SHOULD_NOT_EXIST, key_type); | |
449 status = VerifyRange(low_of_range2, low_of_range2, SHOULD_EXIST, key_type); | |
450 | |
451 TraceMe(1, ("Finished with sub test 2")); | |
452 | |
453 SeqDatabase(); | |
454 | |
455 status = AddOrDelRange(low_of_range1, high_of_range1, ADD_RANGE, key_type); | |
456 /* the whole thing should exist now */ | |
457 status = VerifyRange(low, low+range, SHOULD_EXIST, key_type); | |
458 | |
459 TraceMe(1, ("Finished with sub test 3")); | |
460 | |
461 SeqDatabase(); | |
462 | |
463 status = AddOrDelRange(low_of_range2, high_of_range2, DELETE_RANGE, key_type); | |
464 status = VerifyRange(low_of_range1, high_of_range1, SHOULD_EXIST, key_type); | |
465 status = VerifyRange(low_of_range2, high_of_range2, SHOULD_NOT_EXIST, key_type); | |
466 | |
467 TraceMe(1, ("Finished with sub test 4")); | |
468 | |
469 SeqDatabase(); | |
470 | |
471 status = AddOrDelRange(low_of_range2, high_of_range2, ADD_RANGE, key_type); | |
472 /* the whole thing should exist now */ | |
473 status = VerifyRange(low, low+range, SHOULD_EXIST, key_type); | |
474 | |
475 TraceMe(1, ("Finished with sub test 5")); | |
476 | |
477 SeqDatabase(); | |
478 | |
479 low_of_range1 = low; | |
480 high_of_range1 = low+(range/3); | |
481 low_of_range2 = high_of_range1+1; | |
482 high_of_range2 = high_of_range1+(range/3); | |
483 low_of_range3 = high_of_range2+1; | |
484 high_of_range3 = low+range; | |
485 /* delete range 2 */ | |
486 status = AddOrDelRange(low_of_range2, high_of_range2, DELETE_RANGE, key_type); | |
487 status = VerifyRange(low_of_range1, high_of_range1, SHOULD_EXIST, key_type); | |
488 status = VerifyRange(low_of_range2, low_of_range2, SHOULD_NOT_EXIST, key_type); | |
489 status = VerifyRange(low_of_range3, low_of_range2, SHOULD_EXIST, key_type); | |
490 | |
491 TraceMe(1, ("Finished with sub test 6")); | |
492 | |
493 SeqDatabase(); | |
494 | |
495 status = AddOrDelRange(low_of_range2, high_of_range2, ADD_RANGE, key_type); | |
496 /* the whole thing should exist now */ | |
497 status = VerifyRange(low, low+range, SHOULD_EXIST, key_type); | |
498 | |
499 TraceMe(1, ("Finished with sub test 7")); | |
500 | |
501 return(0); | |
502 } | |
503 | |
504 #define START_RANGE 109876 | |
505 int | |
506 main(int argc, char **argv) | |
507 { | |
508 int32 i, j=0; | |
509 int quick_exit = 0; | |
510 int large_keys = 0; | |
511 HASHINFO hash_info = { | |
512 16*1024, | |
513 0, | |
514 0, | |
515 0, | |
516 0, | |
517 0}; | |
518 | |
519 | |
520 if(argc > 1) | |
521 { | |
522 while(argc > 1) | |
523 { | |
524 if(!strcmp(argv[argc-1], "-quick")) | |
525 quick_exit = 1; | |
526 else if(!strcmp(argv[argc-1], "-large")) | |
527 { | |
528 large_keys = 1; | |
529 } | |
530 argc--; | |
531 } | |
532 } | |
533 | |
534 database = dbopen("test.db", O_RDWR | O_CREAT, 0644, DB_HASH, &hash_info); | |
535 | |
536 if(!database) | |
537 { | |
538 ReportError("Could not open database"); | |
539 #ifdef unix | |
540 perror(""); | |
541 #endif | |
542 exit(1); | |
543 } | |
544 | |
545 if(quick_exit) | |
546 { | |
547 if(large_keys) | |
548 TestRange(START_RANGE, 200, USE_LARGE_KEY); | |
549 else | |
550 TestRange(START_RANGE, 200, USE_SMALL_KEY); | |
551 | |
552 (*database->sync)(database, 0); | |
553 (*database->close)(database); | |
554 exit(0); | |
555 } | |
556 | |
557 for(i=100; i < 10000000; i+=200) | |
558 { | |
559 if(1 || j) | |
560 { | |
561 TestRange(START_RANGE, i, USE_LARGE_KEY); | |
562 j = 0; | |
563 } | |
564 else | |
565 { | |
566 TestRange(START_RANGE, i, USE_SMALL_KEY); | |
567 j = 1; | |
568 } | |
569 | |
570 if(1 == rand() % 3) | |
571 { | |
572 (*database->sync)(database, 0); | |
573 } | |
574 | |
575 if(1 == rand() % 3) | |
576 { | |
577 /* close and reopen */ | |
578 (*database->close)(database); | |
579 database = dbopen("test.db", O_RDWR | O_CREAT, 0644, DB_HASH, 0); | |
580 if(!database) | |
581 { | |
582 ReportError("Could not reopen database"); | |
583 #ifdef unix | |
584 perror(""); | |
585 #endif | |
586 exit(1); | |
587 } | |
588 } | |
589 else | |
590 { | |
591 /* reopen database without closeing the other */ | |
592 database = dbopen("test.db", O_RDWR | O_CREAT, 0644, DB_HASH, 0); | |
593 if(!database) | |
594 { | |
595 ReportError("Could not reopen database " | |
596 "after not closing the other"); | |
597 #ifdef unix | |
598 perror(""); | |
599 #endif | |
600 exit(1); | |
601 } | |
602 } | |
603 } | |
604 | |
605 return(0); | |
606 } |