home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / dbm / tests / lots.c next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  12.8 KB  |  616 lines

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