1
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* ***** BEGIN LICENSE BLOCK *****
3
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
5
* The contents of this file are subject to the Netscape Public License
6
* Version 1.1 (the "License"); you may not use this file except in
7
* compliance with the License. You may obtain a copy of the License at
8
* http://www.mozilla.org/NPL/
10
* Software distributed under the License is distributed on an "AS IS" basis,
11
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12
* for the specific language governing rights and limitations under the
15
* The Original Code is mozilla.org code.
17
* The Initial Developer of the Original Code is
18
* Netscape Communications Corporation.
19
* Portions created by the Initial Developer are Copyright (C) 1998
20
* the Initial Developer. All Rights Reserved.
25
* Alternatively, the contents of this file may be used under the terms of
26
* either the GNU General Public License Version 2 or later (the "GPL"), or
27
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28
* in which case the provisions of the GPL or the LGPL are applicable instead
29
* of those above. If you wish to allow use of your version of this file only
30
* under the terms of either the GPL or the LGPL, and not to allow others to
31
* use your version of this file under the terms of the NPL, indicate your
32
* decision by deleting the provisions above and replace them with the notice
33
* and other provisions required by the GPL or the LGPL. If you do not delete
34
* the provisions above, a recipient may use your version of this file under
35
* the terms of any one of the NPL, the GPL or the LGPL.
37
* ***** END LICENSE BLOCK ***** */
39
/* use sequental numbers printed to strings
40
* to store lots and lots of entries in the
43
* Start with 100 entries, put them and then
44
* read them out. Then delete the first
45
* half and verify that all of the first half
46
* is gone and then verify that the second
47
* half is still there.
48
* Then add the first half back and verify
49
* again. Then delete the middle third
51
* Then increase the size by 1000 and do
52
* the whole add delete thing again.
54
* The data for each object is the number string translated
55
* to hex and replicated a random number of times. The
56
* number of times that the data is replicated is the first
79
#if defined(_WINDOWS) && !defined(WIN32)
81
#define uint32 unsigned long
84
#define uint32 unsigned int
92
#define TraceMe(priority, msg) \
94
if(priority <= MsgPriority) \
101
ReportStatus(char *string, ...)
106
va_start(args, string);
110
vfprintf(stderr, string, args);
113
fprintf (stderr, "\n");
119
ReportError(char *string, ...)
124
va_start(args, string);
128
fprintf (stderr, "\n ");
129
vfprintf(stderr, string, args);
130
fprintf (stderr, "\n");
136
DBT * MakeLargeKey(int32 num)
140
static char *string_rv=0;
147
/* generate a really large text key derived from
150
low_bits = (num % 10000) + 1;
152
/* get the repeat char from the low 26 */
153
rep_char = (char) ((low_bits % 26) + 'a');
155
/* malloc a string low_bits wide */
156
size = low_bits*sizeof(char);
157
string_rv = (char *)malloc(size);
159
memset(string_rv, rep_char, size);
167
DBT * MakeSmallKey(int32 num)
170
static char data_string[64];
172
rv.data = data_string;
174
sprintf(data_string, "%ld", (long)num);
175
rv.size = strlen(data_string);
181
DBT * GenKey(int32 num, key_type_enum key_type)
188
key = MakeLargeKey(num);
191
key = MakeSmallKey(num);
207
ReportStatus("SEQuencing through database...");
209
/* seq throught the whole database */
210
if(!(status = (*database->seq)(database, &key, &data, R_FIRST)))
212
while(!(status = (database->seq) (database, &key, &data, R_NEXT)));
217
ReportError("Error seq'ing database");
223
VerifyData(DBT *data, int32 num, key_type_enum key_type)
225
int32 count, compare_num;
229
/* The first int32 is count
230
* The other n entries should
233
if(data->size < sizeof(int32))
235
ReportError("Data size corrupted");
239
memcpy(&count, data->data, sizeof(int32));
241
size = sizeof(int32)*(count+1);
243
if(size != data->size)
245
ReportError("Data size corrupted");
249
int32_array = (int32*)data->data;
251
for(;count > 0; count--)
253
memcpy(&compare_num, &int32_array[count], sizeof(int32));
255
if(compare_num != num)
257
ReportError("Data corrupted");
266
/* verify that a range of number strings exist
267
* or don't exist. And that the data is valid
269
#define SHOULD_EXIST 1
270
#define SHOULD_NOT_EXIST 0
272
VerifyRange(int32 low, int32 high, int32 should_exist, key_type_enum key_type)
278
TraceMe(1, ("Verifying: %ld to %ld, using %s keys",
279
low, high, key_type == USE_SMALL_KEY ? "SMALL" : "LARGE"));
281
for(num = low; num <= high; num++)
284
key = GenKey(num, key_type);
286
status = (*database->get)(database, key, &data, 0);
293
ReportError("Item exists but shouldn't: %ld", num);
297
/* else verify the data */
298
VerifyData(&data, num, key_type);
306
ReportError("Item not found but should be: %ld", num);
312
ReportError("Database error");
318
TraceMe(1, ("Correctly verified: %ld to %ld", low, high));
334
data = (DBT*)malloc(sizeof(DBT));
345
n = n % 512; /* bound to a 2K size */
348
size = sizeof(int32)*(n+1);
349
int32_array = (int32 *) malloc(size);
351
memcpy(&int32_array[0], &n, sizeof(int32));
355
memcpy(&int32_array[n], &num, sizeof(int32));
358
data->data = (void*)int32_array;
365
#define DELETE_RANGE 2
368
AddOrDelRange(int32 low, int32 high, int action, key_type_enum key_type)
371
#if 0 /* only do this if your really analy checking the puts */
377
if(action != ADD_RANGE && action != DELETE_RANGE)
380
if(action == ADD_RANGE)
382
TraceMe(1, ("Adding: %ld to %ld: %s keys", low, high,
383
key_type == USE_SMALL_KEY ? "SMALL" : "LARGE"));
387
TraceMe(1, ("Deleting: %ld to %ld: %s keys", low, high,
388
key_type == USE_SMALL_KEY ? "SMALL" : "LARGE"));
391
for(num = low; num <= high; num++)
394
key = GenKey(num, key_type);
396
if(action == ADD_RANGE)
399
status = (*database->put)(database, key, data, 0);
403
status = (*database->del)(database, key, 0);
408
ReportError("Database error %s item: %ld",
409
action == ADD_RANGE ? "ADDING" : "DELETING",
414
ReportError("Could not %s item: %ld",
415
action == ADD_RANGE ? "ADD" : "DELETE",
418
else if(action == ADD_RANGE)
420
#define SYNC_EVERY_TIME
421
#ifdef SYNC_EVERY_TIME
422
status = (*database->sync)(database, 0);
424
ReportError("Database error syncing after add");
427
#if 0 /* only do this if your really analy checking the puts */
429
/* make sure we can still get it
431
status = (*database->get)(database, key, &tmp_data, 0);
435
ReportError("Database error checking item just added: %d",
440
/* now verify that none of the ones we already
441
* put in have disappeared
443
VerifyRange(low, num, SHOULD_EXIST, key_type);
451
if(action == ADD_RANGE)
453
TraceMe(1, ("Successfully added: %ld to %ld", low, high));
457
TraceMe(1, ("Successfully deleted: %ld to %ld", low, high));
464
TestRange(int32 low, int32 range, key_type_enum key_type)
466
int status; int32 low_of_range1, high_of_range1; int32 low_of_range2, high_of_range2;
467
int32 low_of_range3, high_of_range3;
469
status = AddOrDelRange(low, low+range, ADD_RANGE, key_type);
470
status = VerifyRange(low, low+range, SHOULD_EXIST, key_type);
472
TraceMe(1, ("Finished with sub test 1"));
477
high_of_range1 = low+(range/2);
478
low_of_range2 = high_of_range1+1;
479
high_of_range2 = low+range;
480
status = AddOrDelRange(low_of_range1, high_of_range1, DELETE_RANGE, key_type);
481
status = VerifyRange(low_of_range1, high_of_range1, SHOULD_NOT_EXIST, key_type);
482
status = VerifyRange(low_of_range2, low_of_range2, SHOULD_EXIST, key_type);
484
TraceMe(1, ("Finished with sub test 2"));
488
status = AddOrDelRange(low_of_range1, high_of_range1, ADD_RANGE, key_type);
489
/* the whole thing should exist now */
490
status = VerifyRange(low, low+range, SHOULD_EXIST, key_type);
492
TraceMe(1, ("Finished with sub test 3"));
496
status = AddOrDelRange(low_of_range2, high_of_range2, DELETE_RANGE, key_type);
497
status = VerifyRange(low_of_range1, high_of_range1, SHOULD_EXIST, key_type);
498
status = VerifyRange(low_of_range2, high_of_range2, SHOULD_NOT_EXIST, key_type);
500
TraceMe(1, ("Finished with sub test 4"));
504
status = AddOrDelRange(low_of_range2, high_of_range2, ADD_RANGE, key_type);
505
/* the whole thing should exist now */
506
status = VerifyRange(low, low+range, SHOULD_EXIST, key_type);
508
TraceMe(1, ("Finished with sub test 5"));
513
high_of_range1 = low+(range/3);
514
low_of_range2 = high_of_range1+1;
515
high_of_range2 = high_of_range1+(range/3);
516
low_of_range3 = high_of_range2+1;
517
high_of_range3 = low+range;
519
status = AddOrDelRange(low_of_range2, high_of_range2, DELETE_RANGE, key_type);
520
status = VerifyRange(low_of_range1, high_of_range1, SHOULD_EXIST, key_type);
521
status = VerifyRange(low_of_range2, low_of_range2, SHOULD_NOT_EXIST, key_type);
522
status = VerifyRange(low_of_range3, low_of_range2, SHOULD_EXIST, key_type);
524
TraceMe(1, ("Finished with sub test 6"));
528
status = AddOrDelRange(low_of_range2, high_of_range2, ADD_RANGE, key_type);
529
/* the whole thing should exist now */
530
status = VerifyRange(low, low+range, SHOULD_EXIST, key_type);
532
TraceMe(1, ("Finished with sub test 7"));
537
#define START_RANGE 109876
539
main(int argc, char **argv)
544
HASHINFO hash_info = {
557
if(!strcmp(argv[argc-1], "-quick"))
559
else if(!strcmp(argv[argc-1], "-large"))
567
database = dbopen("test.db", O_RDWR | O_CREAT, 0644, DB_HASH, &hash_info);
571
ReportError("Could not open database");
581
TestRange(START_RANGE, 200, USE_LARGE_KEY);
583
TestRange(START_RANGE, 200, USE_SMALL_KEY);
585
(*database->sync)(database, 0);
586
(*database->close)(database);
590
for(i=100; i < 10000000; i+=200)
594
TestRange(START_RANGE, i, USE_LARGE_KEY);
599
TestRange(START_RANGE, i, USE_SMALL_KEY);
605
(*database->sync)(database, 0);
610
/* close and reopen */
611
(*database->close)(database);
612
database = dbopen("test.db", O_RDWR | O_CREAT, 0644, DB_HASH, 0);
615
ReportError("Could not reopen database");
624
/* reopen database without closeing the other */
625
database = dbopen("test.db", O_RDWR | O_CREAT, 0644, DB_HASH, 0);
628
ReportError("Could not reopen database "
629
"after not closing the other");