tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

lots.c (13415B)


      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            ReportStatus msg;          \
     63        }                              \
     64    } while (0)
     65 
     66 int
     67 ReportStatus(char *string, ...)
     68 {
     69    va_list args;
     70 
     71 #ifdef STDC_HEADERS
     72    va_start(args, string);
     73 #else
     74    va_start(args);
     75 #endif
     76    vfprintf(stderr, string, args);
     77    va_end(args);
     78 
     79    fprintf(stderr, "\n");
     80 
     81    return (0);
     82 }
     83 
     84 int
     85 ReportError(char *string, ...)
     86 {
     87    va_list args;
     88 
     89 #ifdef STDC_HEADERS
     90    va_start(args, string);
     91 #else
     92    va_start(args);
     93 #endif
     94    fprintf(stderr, "\n	");
     95    vfprintf(stderr, string, args);
     96    fprintf(stderr, "\n");
     97    va_end(args);
     98 
     99    return (0);
    100 }
    101 
    102 DBT *
    103 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 *
    135 MakeSmallKey(int32 num)
    136 {
    137    static DBT rv;
    138    static char data_string[64];
    139 
    140    rv.data = data_string;
    141 
    142    snprintf(data_string, sizeof(data_string), "%ld", (long)num);
    143    rv.size = strlen(data_string);
    144 
    145    return (&rv);
    146 }
    147 
    148 DBT *
    149 GenKey(int32 num, key_type_enum key_type)
    150 {
    151    DBT *key;
    152 
    153    switch (key_type) {
    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        while (!(status = (database->seq)(database, &key, &data, R_NEXT)))
    179            ; /* null body */
    180    }
    181 
    182    if (status < 0)
    183        ReportError("Error seq'ing database");
    184 
    185    return (status);
    186 }
    187 
    188 int
    189 VerifyData(DBT *data, int32 num, key_type_enum key_type)
    190 {
    191    int32 count, compare_num;
    192    size_t size;
    193    int32 *int32_array;
    194 
    195    /* The first int32 is count
    196     * The other n entries should
    197     * all equal num
    198     */
    199    if (data->size < sizeof(int32)) {
    200        ReportError("Data size corrupted");
    201        return -1;
    202    }
    203 
    204    memcpy(&count, data->data, sizeof(int32));
    205 
    206    size = sizeof(int32) * (count + 1);
    207 
    208    if (size != data->size) {
    209        ReportError("Data size corrupted");
    210        return -1;
    211    }
    212 
    213    int32_array = (int32 *)data->data;
    214 
    215    for (; count > 0; count--) {
    216        memcpy(&compare_num, &int32_array[count], sizeof(int32));
    217 
    218        if (compare_num != num) {
    219            ReportError("Data corrupted");
    220            return -1;
    221        }
    222    }
    223 
    224    return (0);
    225 }
    226 
    227 /* verify that a range of number strings exist
    228 * or don't exist. And that the data is valid
    229 */
    230 #define SHOULD_EXIST 1
    231 #define SHOULD_NOT_EXIST 0
    232 int
    233 VerifyRange(int32 low, int32 high, int32 should_exist, key_type_enum key_type)
    234 {
    235    DBT *key, data;
    236    int32 num;
    237    int status;
    238 
    239    TraceMe(1, ("Verifying: %ld to %ld, using %s keys",
    240                low, high, key_type == USE_SMALL_KEY ? "SMALL" : "LARGE"));
    241 
    242    for (num = low; num <= high; num++) {
    243 
    244        key = GenKey(num, key_type);
    245 
    246        status = (*database->get)(database, key, &data, 0);
    247 
    248        if (status == 0) {
    249            /* got the item */
    250            if (!should_exist) {
    251                ReportError("Item exists but shouldn't: %ld", num);
    252            } else {
    253                /* else verify the data */
    254                VerifyData(&data, num, key_type);
    255            }
    256        } else if (status > 0) {
    257            /* item not found */
    258            if (should_exist) {
    259                ReportError("Item not found but should be: %ld", num);
    260            }
    261        } else {
    262            /* database error */
    263            ReportError("Database error");
    264            return (-1);
    265        }
    266    }
    267 
    268    TraceMe(1, ("Correctly verified: %ld to %ld", low, high));
    269 
    270    return (0);
    271 }
    272 
    273 DBT *
    274 GenData(int32 num)
    275 {
    276    int32 n;
    277    static DBT *data = 0;
    278    int32 *int32_array;
    279    size_t size;
    280 
    281    if (!data) {
    282        data = (DBT *)malloc(sizeof(DBT));
    283        data->size = 0;
    284        data->data = 0;
    285    } else if (data->data) {
    286        free(data->data);
    287    }
    288 
    289    n = rand();
    290 
    291    n = n % 512; /* bound to a 2K size */
    292 
    293    size = sizeof(int32) * (n + 1);
    294    int32_array = (int32 *)malloc(size);
    295 
    296    memcpy(&int32_array[0], &n, sizeof(int32));
    297 
    298    for (; n > 0; n--) {
    299        memcpy(&int32_array[n], &num, sizeof(int32));
    300    }
    301 
    302    data->data = (void *)int32_array;
    303    data->size = size;
    304 
    305    return (data);
    306 }
    307 
    308 #define ADD_RANGE 1
    309 #define DELETE_RANGE 2
    310 
    311 int
    312 AddOrDelRange(int32 low, int32 high, int action, key_type_enum key_type)
    313 {
    314    DBT *key, *data;
    315 #if 0 /* only do this if your really analy checking the puts */
    316 DBT tmp_data;
    317 #endif
    318    int32 num;
    319    int status;
    320 
    321    if (action != ADD_RANGE && action != DELETE_RANGE)
    322        assert(0);
    323 
    324    if (action == ADD_RANGE) {
    325        TraceMe(1, ("Adding: %ld to %ld: %s keys", low, high,
    326                    key_type == USE_SMALL_KEY ? "SMALL" : "LARGE"));
    327    } else {
    328        TraceMe(1, ("Deleting: %ld to %ld: %s keys", low, high,
    329                    key_type == USE_SMALL_KEY ? "SMALL" : "LARGE"));
    330    }
    331 
    332    for (num = low; num <= high; num++) {
    333 
    334        key = GenKey(num, key_type);
    335 
    336        if (action == ADD_RANGE) {
    337            data = GenData(num);
    338            status = (*database->put)(database, key, data, 0);
    339        } else {
    340            status = (*database->del)(database, key, 0);
    341        }
    342 
    343        if (status < 0) {
    344            ReportError("Database error %s item: %ld",
    345                        action == ADD_RANGE ? "ADDING" : "DELETING",
    346                        num);
    347        } else if (status > 0) {
    348            ReportError("Could not %s item: %ld",
    349                        action == ADD_RANGE ? "ADD" : "DELETE",
    350                        num);
    351        } else if (action == ADD_RANGE) {
    352 #define SYNC_EVERY_TIME
    353 #ifdef SYNC_EVERY_TIME
    354            status = (*database->sync)(database, 0);
    355            if (status != 0)
    356                ReportError("Database error syncing after add");
    357 #endif
    358 
    359 #if 0 /* only do this if your really analy checking the puts */
    360 
    361 		/* make sure we can still get it
    362 		 */
    363 		status = (*database->get)(database, key, &tmp_data, 0);
    364 
    365 		if(status != 0)
    366 		  {
    367 			ReportError("Database error checking item just added: %d",
    368 						num);
    369 		  }
    370 		else
    371 		  {
    372 			/* now verify that none of the ones we already
    373 			 * put in have disappeared
    374 			 */
    375 			VerifyRange(low, num, SHOULD_EXIST, key_type);
    376 		  }
    377 #endif
    378        }
    379    }
    380 
    381    if (action == ADD_RANGE) {
    382        TraceMe(1, ("Successfully added: %ld to %ld", low, high));
    383    } else {
    384        TraceMe(1, ("Successfully deleted: %ld to %ld", low, high));
    385    }
    386 
    387    return (0);
    388 }
    389 
    390 int
    391 TestRange(int32 low, int32 range, key_type_enum key_type)
    392 {
    393    int status;
    394    int32 low_of_range1, high_of_range1;
    395    int32 low_of_range2, high_of_range2;
    396    int32 low_of_range3, high_of_range3;
    397 
    398    status = AddOrDelRange(low, low + range, ADD_RANGE, key_type);
    399    status = VerifyRange(low, low + range, SHOULD_EXIST, key_type);
    400 
    401    TraceMe(1, ("Finished with sub test 1"));
    402 
    403    SeqDatabase();
    404 
    405    low_of_range1 = low;
    406    high_of_range1 = low + (range / 2);
    407    low_of_range2 = high_of_range1 + 1;
    408    high_of_range2 = low + range;
    409    status = AddOrDelRange(low_of_range1, high_of_range1, DELETE_RANGE, key_type);
    410    status = VerifyRange(low_of_range1, high_of_range1, SHOULD_NOT_EXIST, key_type);
    411    status = VerifyRange(low_of_range2, low_of_range2, SHOULD_EXIST, key_type);
    412 
    413    TraceMe(1, ("Finished with sub test 2"));
    414 
    415    SeqDatabase();
    416 
    417    status = AddOrDelRange(low_of_range1, high_of_range1, ADD_RANGE, key_type);
    418    /* the whole thing should exist now */
    419    status = VerifyRange(low, low + range, SHOULD_EXIST, key_type);
    420 
    421    TraceMe(1, ("Finished with sub test 3"));
    422 
    423    SeqDatabase();
    424 
    425    status = AddOrDelRange(low_of_range2, high_of_range2, DELETE_RANGE, key_type);
    426    status = VerifyRange(low_of_range1, high_of_range1, SHOULD_EXIST, key_type);
    427    status = VerifyRange(low_of_range2, high_of_range2, SHOULD_NOT_EXIST, key_type);
    428 
    429    TraceMe(1, ("Finished with sub test 4"));
    430 
    431    SeqDatabase();
    432 
    433    status = AddOrDelRange(low_of_range2, high_of_range2, ADD_RANGE, key_type);
    434    /* the whole thing should exist now */
    435    status = VerifyRange(low, low + range, SHOULD_EXIST, key_type);
    436 
    437    TraceMe(1, ("Finished with sub test 5"));
    438 
    439    SeqDatabase();
    440 
    441    low_of_range1 = low;
    442    high_of_range1 = low + (range / 3);
    443    low_of_range2 = high_of_range1 + 1;
    444    high_of_range2 = high_of_range1 + (range / 3);
    445    low_of_range3 = high_of_range2 + 1;
    446    high_of_range3 = low + range;
    447    /* delete range 2 */
    448    status = AddOrDelRange(low_of_range2, high_of_range2, DELETE_RANGE, key_type);
    449    status = VerifyRange(low_of_range1, high_of_range1, SHOULD_EXIST, key_type);
    450    status = VerifyRange(low_of_range2, low_of_range2, SHOULD_NOT_EXIST, key_type);
    451    status = VerifyRange(low_of_range3, low_of_range2, SHOULD_EXIST, key_type);
    452 
    453    TraceMe(1, ("Finished with sub test 6"));
    454 
    455    SeqDatabase();
    456 
    457    status = AddOrDelRange(low_of_range2, high_of_range2, ADD_RANGE, key_type);
    458    /* the whole thing should exist now */
    459    status = VerifyRange(low, low + range, SHOULD_EXIST, key_type);
    460 
    461    TraceMe(1, ("Finished with sub test 7"));
    462 
    463    return (0);
    464 }
    465 
    466 #define START_RANGE 109876
    467 int
    468 main(int argc, char **argv)
    469 {
    470    int32 i, j = 0;
    471    int quick_exit = 0;
    472    int large_keys = 0;
    473    HASHINFO hash_info = {
    474        16 * 1024,
    475        0,
    476        0,
    477        0,
    478        0,
    479        0
    480    };
    481 
    482    if (argc > 1) {
    483        while (argc > 1) {
    484            if (!strcmp(argv[argc - 1], "-quick"))
    485                quick_exit = 1;
    486            else if (!strcmp(argv[argc - 1], "-large")) {
    487                large_keys = 1;
    488            }
    489            argc--;
    490        }
    491    }
    492 
    493    database = dbopen("test.db", O_RDWR | O_CREAT, 0644, DB_HASH, &hash_info);
    494 
    495    if (!database) {
    496        ReportError("Could not open database");
    497 #ifdef unix
    498        perror("");
    499 #endif
    500        exit(1);
    501    }
    502 
    503    if (quick_exit) {
    504        if (large_keys)
    505            TestRange(START_RANGE, 200, USE_LARGE_KEY);
    506        else
    507            TestRange(START_RANGE, 200, USE_SMALL_KEY);
    508 
    509        (*database->sync)(database, 0);
    510        (*database->close)(database);
    511        exit(0);
    512    }
    513 
    514    for (i = 100; i < 10000000; i += 200) {
    515        if (1 || j) {
    516            TestRange(START_RANGE, i, USE_LARGE_KEY);
    517            j = 0;
    518        } else {
    519            TestRange(START_RANGE, i, USE_SMALL_KEY);
    520            j = 1;
    521        }
    522 
    523        if (1 == rand() % 3) {
    524            (*database->sync)(database, 0);
    525        }
    526 
    527        if (1 == rand() % 3) {
    528            /* close and reopen */
    529            (*database->close)(database);
    530            database = dbopen("test.db", O_RDWR | O_CREAT, 0644, DB_HASH, 0);
    531            if (!database) {
    532                ReportError("Could not reopen database");
    533 #ifdef unix
    534                perror("");
    535 #endif
    536                exit(1);
    537            }
    538        } else {
    539            /* reopen database without closeing the other */
    540            database = dbopen("test.db", O_RDWR | O_CREAT, 0644, DB_HASH, 0);
    541            if (!database) {
    542                ReportError("Could not reopen database "
    543                            "after not closing the other");
    544 #ifdef unix
    545                perror("");
    546 #endif
    547                exit(1);
    548            }
    549        }
    550    }
    551 
    552    return (0);
    553 }