home *** CD-ROM | disk | FTP | other *** search
- /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-
- /* use sequental numbers printed to strings
- * to store lots and lots of entries in the
- * database.
- *
- * Start with 100 entries, put them and then
- * read them out. Then delete the first
- * half and verify that all of the first half
- * is gone and then verify that the second
- * half is still there.
- * Then add the first half back and verify
- * again. Then delete the middle third
- * and verify again.
- * Then increase the size by 1000 and do
- * the whole add delete thing again.
- *
- * The data for each object is the number string translated
- * to hex and replicated a random number of times. The
- * number of times that the data is replicated is the first
- * int32 in the data.
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #ifdef STDARG
- #include <stdarg.h>
- #else
- #include <varargs.h>
- #endif
- #include <memory.h>
- #include <string.h>
- #include <assert.h>
- #include "mcom_db.h"
-
- DB *database=0;
- int MsgPriority=5;
-
- #if defined(_WINDOWS) && !defined(WIN32)
- #define int32 long
- #define uint32 unsigned long
- #else
- #define int32 int
- #define uint32 unsigned int
- #endif
-
- typedef enum {
- USE_LARGE_KEY,
- USE_SMALL_KEY
- } key_type_enum;
-
- #define TraceMe(priority, msg) \
- do { \
- if(priority <= MsgPriority) \
- { \
- ReportStatus msg; \
- } \
- } while(0)
-
- int
- ReportStatus(char *string, ...)
- {
- va_list args;
-
- #ifdef STDARG
- va_start(args, string);
- #else
- va_start(args);
- #endif
- vfprintf(stderr, string, args);
- va_end(args);
-
- fprintf (stderr, "\n");
-
- return(0);
- }
-
- int
- ReportError(char *string, ...)
- {
- va_list args;
-
- #ifdef STDARG
- va_start(args, string);
- #else
- va_start(args);
- #endif
- fprintf (stderr, "\n ");
- vfprintf(stderr, string, args);
- fprintf (stderr, "\n");
- va_end(args);
-
- return(0);
- }
-
- DBT * MakeLargeKey(int32 num)
- {
- int32 low_bits;
- static DBT rv;
- static char *string_rv=0;
- int rep_char;
- int32 size;
-
- if(string_rv)
- free(string_rv);
-
- /* generate a really large text key derived from
- * an int32
- */
- low_bits = (num % 10000) + 1;
-
- /* get the repeat char from the low 26 */
- rep_char = (char) ((low_bits % 26) + 'a');
-
- /* malloc a string low_bits wide */
- size = low_bits*sizeof(char);
- string_rv = (char *)malloc(size);
-
- memset(string_rv, rep_char, size);
-
- rv.data = string_rv;
- rv.size = size;
-
- return(&rv);
- }
-
- DBT * MakeSmallKey(int32 num)
- {
- static DBT rv;
- static char data_string[64];
-
- rv.data = data_string;
-
- sprintf(data_string, "%ld", num);
- rv.size = strlen(data_string);
-
- return(&rv);
-
- }
-
- DBT * GenKey(int32 num, key_type_enum key_type)
- {
- DBT *key;
-
- switch(key_type)
- {
- case USE_LARGE_KEY:
- key = MakeLargeKey(num);
- break;
- case USE_SMALL_KEY:
- key = MakeSmallKey(num);
- break;
- default:
- abort();
- break;
- }
-
- return(key);
- }
-
- int
- SeqDatabase()
- {
- int status;
- DBT key, data;
-
- ReportStatus("SEQuencing through database...");
-
- /* seq throught the whole database */
- if(!(status = (*database->seq)(database, &key, &data, R_FIRST)))
- {
- while(!(status = (database->seq) (database, &key, &data, R_NEXT)));
- ; /* null body */
- }
-
- if(status < 0)
- ReportError("Error seq'ing database");
-
- return(status);
- }
-
- int
- VerifyData(DBT *data, int32 num, key_type_enum key_type)
- {
- int32 count, compare_num;
- uint32 size;
- int32 *int32_array;
-
- /* The first int32 is count
- * The other n entries should
- * all equal num
- */
- if(data->size < sizeof(int32))
- {
- ReportError("Data size corrupted");
- return -1;
- }
-
- memcpy(&count, data->data, sizeof(int32));
-
- size = sizeof(int32)*(count+1);
-
- if(size != data->size)
- {
- ReportError("Data size corrupted");
- return -1;
- }
-
- int32_array = (int32*)data->data;
-
- for(;count > 0; count--)
- {
- memcpy(&compare_num, &int32_array[count], sizeof(int32));
-
- if(compare_num != num)
- {
- ReportError("Data corrupted");
- return -1;
- }
- }
-
- return(0);
- }
-
-
- /* verify that a range of number strings exist
- * or don't exist. And that the data is valid
- */
- #define SHOULD_EXIST 1
- #define SHOULD_NOT_EXIST 0
- int
- VerifyRange(int32 low, int32 high, int32 should_exist, key_type_enum key_type)
- {
- char key_buf[128];
- DBT *key, data;
- int32 num;
- int status;
-
- TraceMe(1, ("Verifying: %ld to %ld, using %s keys",
- low, high, key_type == USE_SMALL_KEY ? "SMALL" : "LARGE"));
-
- for(num = low; num <= high; num++)
- {
-
- key = GenKey(num, key_type);
-
- status = (*database->get)(database, key, &data, 0);
-
- if(status == 0)
- {
- /* got the item */
- if(!should_exist)
- {
- ReportError("Item exists but shouldn't: %ld", num);
- }
- else
- {
- /* else verify the data */
- VerifyData(&data, num, key_type);
- }
- }
- else if(status > 0)
- {
- /* item not found */
- if(should_exist)
- {
- ReportError("Item not found but should be: %ld", num);
- }
- }
- else
- {
- /* database error */
- ReportError("Database error");
- return(-1);
- }
-
- }
-
- TraceMe(1, ("Correctly verified: %ld to %ld", low, high));
-
- return(0);
-
- }
-
- DBT *
- GenData(int32 num)
- {
- int32 n;
- static DBT *data=0;
- int32 *int32_array;
- int32 size;
-
- if(!data)
- {
- data = (DBT*)malloc(sizeof(DBT));
- data->size = 0;
- data->data = 0;
- }
- else if(data->data)
- {
- free(data->data);
- }
-
- n = rand();
-
- n = n % 512; /* bound to a 2K size */
-
-
- size = sizeof(int32)*(n+1);
- int32_array = (int32 *) malloc(size);
-
- memcpy(&int32_array[0], &n, sizeof(int32));
-
- for(; n > 0; n--)
- {
- memcpy(&int32_array[n], &num, sizeof(int32));
- }
-
- data->data = (void*)int32_array;
- data->size = size;
-
- return(data);
- }
-
- #define ADD_RANGE 1
- #define DELETE_RANGE 2
-
- int
- AddOrDelRange(int32 low, int32 high, int action, key_type_enum key_type)
- {
- char key_buf[128];
- DBT *key, *data;
- DBT tmp_data;
- int32 num;
- int status;
-
- if(action != ADD_RANGE && action != DELETE_RANGE)
- assert(0);
-
- if(action == ADD_RANGE)
- {
- TraceMe(1, ("Adding: %ld to %ld: %s keys", low, high,
- key_type == USE_SMALL_KEY ? "SMALL" : "LARGE"));
- }
- else
- {
- TraceMe(1, ("Deleting: %ld to %ld: %s keys", low, high,
- key_type == USE_SMALL_KEY ? "SMALL" : "LARGE"));
- }
-
- for(num = low; num <= high; num++)
- {
-
- key = GenKey(num, key_type);
-
- if(action == ADD_RANGE)
- {
- data = GenData(num);
- status = (*database->put)(database, key, data, 0);
- }
- else
- {
- status = (*database->del)(database, key, 0);
- }
-
- if(status < 0)
- {
- ReportError("Database error %s item: %ld",
- action == ADD_RANGE ? "ADDING" : "DELETING",
- num);
- }
- else if(status > 0)
- {
- ReportError("Could not %s item: %ld",
- action == ADD_RANGE ? "ADD" : "DELETE",
- num);
- }
- else if(action == ADD_RANGE)
- {
- #define SYNC_EVERY_TIME
- #ifdef SYNC_EVERY_TIME
- status = (*database->sync)(database, 0);
- if(status != 0)
- ReportError("Database error syncing after add");
- #endif
-
- #if 0 /* only do this if your really analy checking the puts */
-
- /* make sure we can still get it
- */
- status = (*database->get)(database, key, &tmp_data, 0);
-
- if(status != 0)
- {
- ReportError("Database error checking item just added: %d",
- num);
- }
- else
- {
- /* now verify that none of the ones we already
- * put in have disappeared
- */
- VerifyRange(low, num, SHOULD_EXIST, key_type);
- }
- #endif
-
- }
- }
-
-
- if(action == ADD_RANGE)
- {
- TraceMe(1, ("Successfully added: %ld to %ld", low, high));
- }
- else
- {
- TraceMe(1, ("Successfully deleted: %ld to %ld", low, high));
- }
-
- return(0);
- }
-
- int
- TestRange(int32 low, int32 range, key_type_enum key_type)
- {
- int status; int32 low_of_range1, high_of_range1; int32 low_of_range2, high_of_range2;
- int32 low_of_range3, high_of_range3;
-
- status = AddOrDelRange(low, low+range, ADD_RANGE, key_type);
- status = VerifyRange(low, low+range, SHOULD_EXIST, key_type);
-
- TraceMe(1, ("Finished with sub test 1"));
-
- SeqDatabase();
-
- low_of_range1 = low;
- high_of_range1 = low+(range/2);
- low_of_range2 = high_of_range1+1;
- high_of_range2 = low+range;
- status = AddOrDelRange(low_of_range1, high_of_range1, DELETE_RANGE, key_type);
- status = VerifyRange(low_of_range1, high_of_range1, SHOULD_NOT_EXIST, key_type);
- status = VerifyRange(low_of_range2, low_of_range2, SHOULD_EXIST, key_type);
-
- TraceMe(1, ("Finished with sub test 2"));
-
- SeqDatabase();
-
- status = AddOrDelRange(low_of_range1, high_of_range1, ADD_RANGE, key_type);
- /* the whole thing should exist now */
- status = VerifyRange(low, low+range, SHOULD_EXIST, key_type);
-
- TraceMe(1, ("Finished with sub test 3"));
-
- SeqDatabase();
-
- status = AddOrDelRange(low_of_range2, high_of_range2, DELETE_RANGE, key_type);
- status = VerifyRange(low_of_range1, high_of_range1, SHOULD_EXIST, key_type);
- status = VerifyRange(low_of_range2, high_of_range2, SHOULD_NOT_EXIST, key_type);
-
- TraceMe(1, ("Finished with sub test 4"));
-
- SeqDatabase();
-
- status = AddOrDelRange(low_of_range2, high_of_range2, ADD_RANGE, key_type);
- /* the whole thing should exist now */
- status = VerifyRange(low, low+range, SHOULD_EXIST, key_type);
-
- TraceMe(1, ("Finished with sub test 5"));
-
- SeqDatabase();
-
- low_of_range1 = low;
- high_of_range1 = low+(range/3);
- low_of_range2 = high_of_range1+1;
- high_of_range2 = high_of_range1+(range/3);
- low_of_range3 = high_of_range2+1;
- high_of_range3 = low+range;
- /* delete range 2 */
- status = AddOrDelRange(low_of_range2, high_of_range2, DELETE_RANGE, key_type);
- status = VerifyRange(low_of_range1, high_of_range1, SHOULD_EXIST, key_type);
- status = VerifyRange(low_of_range2, low_of_range2, SHOULD_NOT_EXIST, key_type);
- status = VerifyRange(low_of_range3, low_of_range2, SHOULD_EXIST, key_type);
-
- TraceMe(1, ("Finished with sub test 6"));
-
- SeqDatabase();
-
- status = AddOrDelRange(low_of_range2, high_of_range2, ADD_RANGE, key_type);
- /* the whole thing should exist now */
- status = VerifyRange(low, low+range, SHOULD_EXIST, key_type);
-
- TraceMe(1, ("Finished with sub test 7"));
-
- return(0);
- }
-
- #define START_RANGE 109876
- int
- main(int argc, char **argv)
- {
- int32 i, j=0;
- int quick_exit = 0;
- int large_keys = 0;
- HASHINFO hash_info = {
- 16*1024,
- 0,
- 0,
- 0,
- 0,
- 0};
-
-
- if(argc > 1)
- {
- while(argc > 1)
- {
- if(!strcmp(argv[argc-1], "-quick"))
- quick_exit = 1;
- else if(!strcmp(argv[argc-1], "-large"))
- {
- large_keys = 1;
- }
- argc--;
- }
- }
-
- database = dbopen("test.db", O_RDWR | O_CREAT, 0644, DB_HASH, &hash_info);
-
- if(!database)
- {
- ReportError("Could not open database");
- #ifdef unix
- perror("");
- #endif
- exit(1);
- }
-
- if(quick_exit)
- {
- if(large_keys)
- TestRange(START_RANGE, 200, USE_LARGE_KEY);
- else
- TestRange(START_RANGE, 200, USE_SMALL_KEY);
-
- (*database->sync)(database, 0);
- (*database->close)(database);
- exit(0);
- }
-
- for(i=100; i < 10000000; i+=200)
- {
- if(1 || j)
- {
- TestRange(START_RANGE, i, USE_LARGE_KEY);
- j = 0;
- }
- else
- {
- TestRange(START_RANGE, i, USE_SMALL_KEY);
- j = 1;
- }
-
- if(1 == rand() % 3)
- {
- (*database->sync)(database, 0);
- }
-
- if(1 == rand() % 3)
- {
- /* close and reopen */
- (*database->close)(database);
- database = dbopen("test.db", O_RDWR | O_CREAT, 0644, DB_HASH, 0);
- if(!database)
- {
- ReportError("Could not reopen database");
- #ifdef unix
- perror("");
- #endif
- exit(1);
- }
- }
- else
- {
- /* reopen database without closeing the other */
- database = dbopen("test.db", O_RDWR | O_CREAT, 0644, DB_HASH, 0);
- if(!database)
- {
- ReportError("Could not reopen database "
- "after not closing the other");
- #ifdef unix
- perror("");
- #endif
- exit(1);
- }
- }
- }
-
- return(0);
- }
-