tdb/tools/tdbtorture.c

説明を見る。
00001 /* this tests tdb by doing lots of ops from several simultaneous
00002    writers - that stresses the locking code. 
00003 */
00004 
00005 #include "replace.h"
00006 #include "tdb.h"
00007 #include "system/time.h"
00008 #include "system/wait.h"
00009 #include "system/filesys.h"
00010 
00011 #ifdef HAVE_GETOPT_H
00012 #include <getopt.h>
00013 #endif
00014 
00015 
00016 #define REOPEN_PROB 30
00017 #define DELETE_PROB 8
00018 #define STORE_PROB 4
00019 #define APPEND_PROB 6
00020 #define TRANSACTION_PROB 10
00021 #define LOCKSTORE_PROB 5
00022 #define TRAVERSE_PROB 20
00023 #define TRAVERSE_READ_PROB 20
00024 #define CULL_PROB 100
00025 #define KEYLEN 3
00026 #define DATALEN 100
00027 
00028 static struct tdb_context *db;
00029 static int in_transaction;
00030 static int error_count;
00031 
00032 #ifdef PRINTF_ATTRIBUTE
00033 static void tdb_log(struct tdb_context *tdb, enum tdb_debug_level level, const char *format, ...) PRINTF_ATTRIBUTE(3,4);
00034 #endif
00035 static void tdb_log(struct tdb_context *tdb, enum tdb_debug_level level, const char *format, ...)
00036 {
00037         va_list ap;
00038     
00039         error_count++;
00040 
00041         va_start(ap, format);
00042         vfprintf(stdout, format, ap);
00043         va_end(ap);
00044         fflush(stdout);
00045 #if 0
00046         {
00047                 char *ptr;
00048                 asprintf(&ptr,"xterm -e gdb /proc/%d/exe %d", getpid(), getpid());
00049                 system(ptr);
00050                 free(ptr);
00051         }
00052 #endif  
00053 }
00054 
00055 static void fatal(const char *why)
00056 {
00057         perror(why);
00058         error_count++;
00059 }
00060 
00061 static char *randbuf(int len)
00062 {
00063         char *buf;
00064         int i;
00065         buf = (char *)malloc(len+1);
00066 
00067         for (i=0;i<len;i++) {
00068                 buf[i] = 'a' + (rand() % 26);
00069         }
00070         buf[i] = 0;
00071         return buf;
00072 }
00073 
00074 static int cull_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf,
00075                          void *state)
00076 {
00077 #if CULL_PROB
00078         if (random() % CULL_PROB == 0) {
00079                 tdb_delete(tdb, key);
00080         }
00081 #endif
00082         return 0;
00083 }
00084 
00085 static void addrec_db(void)
00086 {
00087         int klen, dlen;
00088         char *k, *d;
00089         TDB_DATA key, data;
00090 
00091         klen = 1 + (rand() % KEYLEN);
00092         dlen = 1 + (rand() % DATALEN);
00093 
00094         k = randbuf(klen);
00095         d = randbuf(dlen);
00096 
00097         key.dptr = (unsigned char *)k;
00098         key.dsize = klen+1;
00099 
00100         data.dptr = (unsigned char *)d;
00101         data.dsize = dlen+1;
00102 
00103 #if TRANSACTION_PROB
00104         if (in_transaction == 0 && random() % TRANSACTION_PROB == 0) {
00105                 if (tdb_transaction_start(db) != 0) {
00106                         fatal("tdb_transaction_start failed");
00107                 }
00108                 in_transaction++;
00109                 goto next;
00110         }
00111         if (in_transaction && random() % TRANSACTION_PROB == 0) {
00112                 if (tdb_transaction_commit(db) != 0) {
00113                         fatal("tdb_transaction_commit failed");
00114                 }
00115                 in_transaction--;
00116                 goto next;
00117         }
00118         if (in_transaction && random() % TRANSACTION_PROB == 0) {
00119                 if (tdb_transaction_cancel(db) != 0) {
00120                         fatal("tdb_transaction_cancel failed");
00121                 }
00122                 in_transaction--;
00123                 goto next;
00124         }
00125 #endif
00126 
00127 #if REOPEN_PROB
00128         if (in_transaction == 0 && random() % REOPEN_PROB == 0) {
00129                 tdb_reopen_all(0);
00130                 goto next;
00131         } 
00132 #endif
00133 
00134 #if DELETE_PROB
00135         if (random() % DELETE_PROB == 0) {
00136                 tdb_delete(db, key);
00137                 goto next;
00138         }
00139 #endif
00140 
00141 #if STORE_PROB
00142         if (random() % STORE_PROB == 0) {
00143                 if (tdb_store(db, key, data, TDB_REPLACE) != 0) {
00144                         fatal("tdb_store failed");
00145                 }
00146                 goto next;
00147         }
00148 #endif
00149 
00150 #if APPEND_PROB
00151         if (random() % APPEND_PROB == 0) {
00152                 if (tdb_append(db, key, data) != 0) {
00153                         fatal("tdb_append failed");
00154                 }
00155                 goto next;
00156         }
00157 #endif
00158 
00159 #if LOCKSTORE_PROB
00160         if (random() % LOCKSTORE_PROB == 0) {
00161                 tdb_chainlock(db, key);
00162                 data = tdb_fetch(db, key);
00163                 if (tdb_store(db, key, data, TDB_REPLACE) != 0) {
00164                         fatal("tdb_store failed");
00165                 }
00166                 if (data.dptr) free(data.dptr);
00167                 tdb_chainunlock(db, key);
00168                 goto next;
00169         } 
00170 #endif
00171 
00172 #if TRAVERSE_PROB
00173         if (random() % TRAVERSE_PROB == 0) {
00174                 tdb_traverse(db, cull_traverse, NULL);
00175                 goto next;
00176         }
00177 #endif
00178 
00179 #if TRAVERSE_READ_PROB
00180         if (random() % TRAVERSE_READ_PROB == 0) {
00181                 tdb_traverse_read(db, NULL, NULL);
00182                 goto next;
00183         }
00184 #endif
00185 
00186         data = tdb_fetch(db, key);
00187         if (data.dptr) free(data.dptr);
00188 
00189 next:
00190         free(k);
00191         free(d);
00192 }
00193 
00194 static int traverse_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf,
00195                        void *state)
00196 {
00197         tdb_delete(tdb, key);
00198         return 0;
00199 }
00200 
00201 static void usage(void)
00202 {
00203         printf("Usage: tdbtorture [-n NUM_PROCS] [-l NUM_LOOPS] [-s SEED] [-H HASH_SIZE]\n");
00204         exit(0);
00205 }
00206 
00207  int main(int argc, char * const *argv)
00208 {
00209         int i, seed = -1;
00210         int num_procs = 3;
00211         int num_loops = 5000;
00212         int hash_size = 2;
00213         int c;
00214         extern char *optarg;
00215         pid_t *pids;
00216 
00217         struct tdb_logging_context log_ctx;
00218         log_ctx.log_fn = tdb_log;
00219 
00220         while ((c = getopt(argc, argv, "n:l:s:H:h")) != -1) {
00221                 switch (c) {
00222                 case 'n':
00223                         num_procs = strtol(optarg, NULL, 0);
00224                         break;
00225                 case 'l':
00226                         num_loops = strtol(optarg, NULL, 0);
00227                         break;
00228                 case 'H':
00229                         hash_size = strtol(optarg, NULL, 0);
00230                         break;
00231                 case 's':
00232                         seed = strtol(optarg, NULL, 0);
00233                         break;
00234                 default:
00235                         usage();
00236                 }
00237         }
00238 
00239         unlink("torture.tdb");
00240 
00241         pids = calloc(sizeof(pid_t), num_procs);
00242         pids[0] = getpid();
00243 
00244         for (i=0;i<num_procs-1;i++) {
00245                 if ((pids[i+1]=fork()) == 0) break;
00246         }
00247 
00248         db = tdb_open_ex("torture.tdb", hash_size, TDB_CLEAR_IF_FIRST, 
00249                          O_RDWR | O_CREAT, 0600, &log_ctx, NULL);
00250         if (!db) {
00251                 fatal("db open failed");
00252         }
00253 
00254         if (seed == -1) {
00255                 seed = (getpid() + time(NULL)) & 0x7FFFFFFF;
00256         }
00257 
00258         if (i == 0) {
00259                 printf("testing with %d processes, %d loops, %d hash_size, seed=%d\n", 
00260                        num_procs, num_loops, hash_size, seed);
00261         }
00262 
00263         srand(seed + i);
00264         srandom(seed + i);
00265 
00266         for (i=0;i<num_loops && error_count == 0;i++) {
00267                 addrec_db();
00268         }
00269 
00270         if (error_count == 0) {
00271                 tdb_traverse_read(db, NULL, NULL);
00272                 tdb_traverse(db, traverse_fn, NULL);
00273                 tdb_traverse(db, traverse_fn, NULL);
00274         }
00275 
00276         tdb_close(db);
00277 
00278         if (getpid() != pids[0]) {
00279                 return error_count;
00280         }
00281 
00282         for (i=1;i<num_procs;i++) {
00283                 int status, j;
00284                 pid_t pid;
00285                 if (error_count != 0) {
00286                         /* try and stop the test on any failure */
00287                         for (j=1;j<num_procs;j++) {
00288                                 if (pids[j] != 0) {
00289                                         kill(pids[j], SIGTERM);
00290                                 }
00291                         }
00292                 }
00293                 pid = waitpid(-1, &status, 0);
00294                 if (pid == -1) {
00295                         perror("failed to wait for child\n");
00296                         exit(1);
00297                 }
00298                 for (j=1;j<num_procs;j++) {
00299                         if (pids[j] == pid) break;
00300                 }
00301                 if (j == num_procs) {
00302                         printf("unknown child %d exited!?\n", (int)pid);
00303                         exit(1);
00304                 }
00305                 if (WEXITSTATUS(status) != 0) {
00306                         printf("child %d exited with status %d\n",
00307                                (int)pid, WEXITSTATUS(status));
00308                         error_count++;
00309                 }
00310                 pids[j] = 0;
00311         }
00312 
00313         if (error_count == 0) {
00314                 printf("OK\n");
00315         }
00316 
00317         return error_count;
00318 }

Sambaに対してSat Aug 29 21:23:27 2009に生成されました。  doxygen 1.4.7