From 84366daa2a6e31fbb891005501e27b4a4a8d0cdb Mon Sep 17 00:00:00 2001 From: Bron Gondwana Date: Wed, 24 Dec 2008 23:26:30 +1100 Subject: [PATCH] hammer skiplist Hammer skiplist This adds a debugging tool handy for hammering away at a skiplist file. --- imap/Makefile.in | 6 +- imap/hammer_skiplist.c | 218 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 223 insertions(+), 1 deletions(-) create mode 100644 imap/hammer_skiplist.c diff --git a/imap/Makefile.in b/imap/Makefile.in index 2652e1c..11fc4b5 100644 --- a/imap/Makefile.in +++ b/imap/Makefile.in @@ -116,7 +116,7 @@ SERVICETHREAD=../master/service-thread.o PROGS = imapd lmtpd pop3d \ fud smmapd reconstruct quota mbpath ipurge cyr_dbtool cyr_synclog \ - cyrdump chk_cyrus cvt_cyrusdb deliver ctl_mboxlist \ + cyrdump chk_cyrus cvt_cyrusdb deliver ctl_mboxlist hammer_skiplist \ ctl_deliver ctl_cyrusdb squatter mbexamine cyr_expire arbitron \ unexpunge cyr_df @IMAP_PROGS@ @@ -262,6 +262,10 @@ cyr_dbtool: cyr_dbtool.o mutex_fake.o libimap.a $(DEPLIBS) $(CC) $(LDFLAGS) -o cyr_dbtool cyr_dbtool.o $(CLIOBJS) \ libimap.a $(DEPLIBS) $(LIBS) +hammer_skiplist: hammer_skiplist.o mutex_fake.o libimap.a $(DEPLIBS) + $(CC) $(LDFLAGS) -o hammer_skiplist hammer_skiplist.o $(CLIOBJS) \ + libimap.a $(DEPLIBS) $(LIBS) + cyr_synclog: cyr_synclog.o mutex_fake.o libimap.a $(DEPLIBS) $(CC) $(LDFLAGS) -o cyr_synclog cyr_synclog.o $(CLIOBJS) \ libimap.a $(DEPLIBS) $(LIBS) diff --git a/imap/hammer_skiplist.c b/imap/hammer_skiplist.c new file mode 100644 index 0000000..f222ec5 --- /dev/null +++ b/imap/hammer_skiplist.c @@ -0,0 +1,218 @@ +/* hammer_skiplist.c - tool to harass a skiplist file + * + * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any other legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * $Id: hammer_skiplist.c,v 1.4 2007/09/28 02:27:46 murch Exp $ + */ + +#include + +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "acl.h" +#include "assert.h" +#include "auth.h" +#include "cyrusdb.h" +#include "exitcodes.h" +#include "glob.h" +#include "imap_err.h" +#include "global.h" +#include "mailbox.h" +#include "util.h" +#include "xmalloc.h" + +const int config_need_data = 0; +struct cyrusdb_backend *DB_OLD = NULL; + +void hammer(struct db *db) +{ + int c; + for (c = 0;c < 10000; c++) { /* should be enough! */ + struct txn *tid = NULL; + struct txn **tp; + char key[100]; + char value[100]; + const char *valp; + int klen, vlen, i, r = 0; + int rop; + + /* protect against silly things */ + + tp = (rand() % 2) ? &tid : NULL; + klen = 1 + (rand() % 6); + for (i = 0; i < klen; i++) { + key[i] = 'A' + (rand() % 26); + } + key[klen] = '\0'; + vlen = rand() % 20; + for (i = 0; i < vlen; i++) { + value[i] = 'a' + (rand() % 26); + } + value[vlen] = '\0'; + rop = rand() % 1000; + if (rop >= 999) { + if (!r) r = DB_OLD->store(db, key, klen, value, vlen, tp); + /* forget to commit */ + } + else if (rop >= 800) { + if (!r) r = DB_OLD->store(db, key, klen, value, vlen, tp); + if (!r) r = DB_OLD->delete(db, key, klen, tp, 0); + if (!r) r = DB_OLD->store(db, key, klen, value, vlen, tp); + if (!r && tp) DB_OLD->commit(db, *tp); + } + else if (rop >= 700) { + if (!r) r = DB_OLD->delete(db, key, klen, tp, 0); + if (!r && tp) DB_OLD->commit(db, *tp); + } + else if (rop >= 600) { /* will fail */ + if (!r) r = DB_OLD->store(db, key, klen, value, vlen, tp); + if (!r) r = DB_OLD->create(db, key, klen, value, vlen, tp); + if (!r && tp) DB_OLD->commit(db, *tp); + } + else if (rop > 500) { + r = DB_OLD->fetch(db, key, klen, &valp, &vlen, tp); + if (!r && tp) DB_OLD->abort(db, *tp); + } + else if (rop > 300) { + r = DB_OLD->fetch(db, key, klen, &valp, &vlen, tp); + if (!r && tp) DB_OLD->commit(db, *tp); + } + else if (rop > 100) { + if (!r) r = DB_OLD->store(db, key, klen, value, vlen, tp); + key[klen-1] = 'a'; + if (!r) r = DB_OLD->create(db, key, klen, value, vlen, tp); + key[klen-1] = 'b'; + if (!r) r = DB_OLD->create(db, key, klen, value, vlen, tp); + key[klen-1] = 'd'; + if (!r) r = DB_OLD->create(db, key, klen, value, vlen, tp); + key[klen-1] = 'c'; + if (!r) r = DB_OLD->create(db, key, klen, value, vlen, tp); + if (!r && tp) DB_OLD->commit(db, *tp); + } + else { + if (!r) r = DB_OLD->store(db, key, klen, value, vlen, tp); + key[klen-1] = 'a'; + if (!r) r = DB_OLD->create(db, key, klen, value, vlen, tp); + key[klen-1] = 'b'; + if (!r) r = DB_OLD->create(db, key, klen, value, vlen, tp); + key[klen-1] = 'd'; + if (!r) r = DB_OLD->create(db, key, klen, value, vlen, tp); + key[klen-1] = 'c'; + if (!r) r = DB_OLD->create(db, key, klen, value, vlen, tp); + if (!r && tp) DB_OLD->abort(db, *tp); + } + + } +} + +int main(int argc, char *argv[]) +{ + struct db *odb; + const char *old_db; + int opt, i, r; + char *alt_config = NULL; + int db_flags = 0; + + while ((opt = getopt(argc, argv, "C:n")) != EOF) { + switch (opt) { + case 'C': /* alt config file */ + alt_config = optarg; + break; + case 'n': /* create new */ + db_flags |= CYRUSDB_CREATE; + break; + } + } + + if((argc - optind) < 1) { + fprintf(stderr, "Usage: %s [-C altconfig] \n", argv[0]); + + exit(-1); + } + + old_db = argv[optind]; + + if(old_db[0] != '/') { + printf("\nSorry, you cannot use this tool with relative path names.\n" + "This is because some database backends (mainly berkeley) do not\n" + "always do what you would expect with them.\n" + "\nPlease use absolute pathnames instead.\n\n"); + exit(EC_OSERR); + } + + for(i=0; cyrusdb_backends[i]; i++) { + if(!strcmp(cyrusdb_backends[i]->name, "skiplist")) { + DB_OLD = cyrusdb_backends[i]; break; + } + } + if(!cyrusdb_backends[i]) { + fatal("unknown backend", EC_TEMPFAIL); + } + + cyrus_init(alt_config, "hammer_skiplist", 0); + + + r = (DB_OLD->open)(old_db, db_flags, &odb); + if(r != CYRUSDB_OK) + fatal("can't open database", EC_TEMPFAIL); + + hammer(odb); + + cyrus_done(); + + return 0; +} + -- 1.5.6.5