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 }
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)