int main(int argc, char *argv[]) { struct tdb_context *tdb; TDB_DATA key, data; plan_tests(4); tdb = tdb_open_ex(NULL, 1024, TDB_INTERNAL, O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL); ok1(tdb); /* Tickle bug on appending zero length buffer to zero length buffer. */ key.dsize = strlen("hi"); key.dptr = (void *)"hi"; data.dptr = (void *)"world"; data.dsize = 0; ok1(tdb_append(tdb, key, data) == 0); ok1(tdb_append(tdb, key, data) == 0); data = tdb_fetch(tdb, key); ok1(data.dsize == 0); tdb_close(tdb); free(data.dptr); return exit_status(); }
int main(int argc, char *argv[]) { struct tdb_context *tdb; TDB_DATA key, data; union tdb_attribute hsize; hsize.base.attr = TDB_ATTRIBUTE_TDB1_HASHSIZE; hsize.base.next = &tap_log_attr; hsize.tdb1_hashsize.hsize = 1024; plan_tests(5); tdb = tdb_open(NULL, TDB_INTERNAL|TDB_VERSION1, O_CREAT|O_TRUNC|O_RDWR, 0600, &hsize); ok1(tdb); /* Tickle bug on appending zero length buffer to zero length buffer. */ key = tdb_mkdata("hi", strlen("hi")); data = tdb_mkdata("world", 0); ok1(tdb_append(tdb, key, data) == TDB_SUCCESS); ok1(tdb_append(tdb, key, data) == TDB_SUCCESS); ok1(tdb_fetch(tdb, key, &data) == TDB_SUCCESS); ok1(data.dsize == 0); free(data.dptr); tdb_close(tdb); return exit_status(); }
static PyObject *obj_append(PyTdbObject *self, PyObject *args) { TDB_DATA key, data; PyObject *py_key, *py_data; int ret; PyErr_TDB_RAISE_IF_CLOSED(self); if (!PyArg_ParseTuple(args, "OO", &py_key, &py_data)) return NULL; key = PyString_AsTDB_DATA(py_key); if (!key.dptr) return NULL; data = PyString_AsTDB_DATA(py_data); if (!data.dptr) return NULL; ret = tdb_append(self->ctx, key, data); PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); Py_RETURN_NONE; }
int main(int argc, char *argv[]) { unsigned int i, j, num = 1000, stage = 0, stopat = -1; int flags = TDB_DEFAULT; bool transaction = false, summary = false; TDB_DATA key, data; struct tdb_context *tdb; struct timeval start, stop; union tdb_attribute seed, log; bool do_stats = false; enum TDB_ERROR ecode; /* Try to keep benchmarks even. */ seed.base.attr = TDB_ATTRIBUTE_SEED; seed.base.next = NULL; seed.seed.seed = 0; log.base.attr = TDB_ATTRIBUTE_LOG; log.base.next = &seed; log.log.fn = tdb_log; if (argv[1] && strcmp(argv[1], "--internal") == 0) { flags = TDB_INTERNAL; argc--; argv++; } if (argv[1] && strcmp(argv[1], "--transaction") == 0) { transaction = true; argc--; argv++; } if (argv[1] && strcmp(argv[1], "--no-sync") == 0) { flags |= TDB_NOSYNC; argc--; argv++; } if (argv[1] && strcmp(argv[1], "--summary") == 0) { summary = true; argc--; argv++; } if (argv[1] && strcmp(argv[1], "--stats") == 0) { do_stats = true; argc--; argv++; } tdb = tdb_open("/tmp/speed.tdb", flags, O_RDWR|O_CREAT|O_TRUNC, 0600, &log); if (!tdb) err(1, "Opening /tmp/speed.tdb"); key.dptr = (void *)&i; key.dsize = sizeof(i); data = key; if (argv[1]) { num = atoi(argv[1]); argv++; argc--; } if (argv[1]) { stopat = atoi(argv[1]); argv++; argc--; } /* Add 1000 records. */ printf("Adding %u records: ", num); fflush(stdout); if (transaction && (ecode = tdb_transaction_start(tdb))) errx(1, "starting transaction: %s", tdb_errorstr(ecode)); gettimeofday(&start, NULL); for (i = 0; i < num; i++) if ((ecode = tdb_store(tdb, key, data, TDB_INSERT)) != 0) errx(1, "Inserting key %u in tdb: %s", i, tdb_errorstr(ecode)); gettimeofday(&stop, NULL); if (transaction && (ecode = tdb_transaction_commit(tdb))) errx(1, "committing transaction: %s", tdb_errorstr(ecode)); printf(" %zu ns (%zu bytes)\n", normalize(&start, &stop, num), file_size()); if (tdb_check(tdb, NULL, NULL)) errx(1, "tdb_check failed!"); if (summary) { char *sumstr = NULL; tdb_summary(tdb, TDB_SUMMARY_HISTOGRAMS, &sumstr); printf("%s\n", sumstr); free(sumstr); } if (do_stats) dump_and_clear_stats(&tdb, flags, &log); if (++stage == stopat) exit(0); /* Finding 1000 records. */ printf("Finding %u records: ", num); fflush(stdout); if (transaction && (ecode = tdb_transaction_start(tdb))) errx(1, "starting transaction: %s", tdb_errorstr(ecode)); gettimeofday(&start, NULL); for (i = 0; i < num; i++) { struct tdb_data dbuf; if ((ecode = tdb_fetch(tdb, key, &dbuf)) != TDB_SUCCESS || *(int *)dbuf.dptr != i) { errx(1, "Fetching key %u in tdb gave %u", i, ecode ? ecode : *(int *)dbuf.dptr); } } gettimeofday(&stop, NULL); if (transaction && (ecode = tdb_transaction_commit(tdb))) errx(1, "committing transaction: %s", tdb_errorstr(ecode)); printf(" %zu ns (%zu bytes)\n", normalize(&start, &stop, num), file_size()); if (tdb_check(tdb, NULL, NULL)) errx(1, "tdb_check failed!"); if (summary) { char *sumstr = NULL; tdb_summary(tdb, TDB_SUMMARY_HISTOGRAMS, &sumstr); printf("%s\n", sumstr); free(sumstr); } if (do_stats) dump_and_clear_stats(&tdb, flags, &log); if (++stage == stopat) exit(0); /* Missing 1000 records. */ printf("Missing %u records: ", num); fflush(stdout); if (transaction && (ecode = tdb_transaction_start(tdb))) errx(1, "starting transaction: %s", tdb_errorstr(ecode)); gettimeofday(&start, NULL); for (i = num; i < num*2; i++) { struct tdb_data dbuf; ecode = tdb_fetch(tdb, key, &dbuf); if (ecode != TDB_ERR_NOEXIST) errx(1, "Fetching key %u in tdb gave %s", i, tdb_errorstr(ecode)); } gettimeofday(&stop, NULL); if (transaction && (ecode = tdb_transaction_commit(tdb))) errx(1, "committing transaction: %s", tdb_errorstr(ecode)); printf(" %zu ns (%zu bytes)\n", normalize(&start, &stop, num), file_size()); if (tdb_check(tdb, NULL, NULL)) errx(1, "tdb_check failed!"); if (summary) { char *sumstr = NULL; tdb_summary(tdb, TDB_SUMMARY_HISTOGRAMS, &sumstr); printf("%s\n", sumstr); free(sumstr); } if (do_stats) dump_and_clear_stats(&tdb, flags, &log); if (++stage == stopat) exit(0); /* Traverse 1000 records. */ printf("Traversing %u records: ", num); fflush(stdout); if (transaction && (ecode = tdb_transaction_start(tdb))) errx(1, "starting transaction: %s", tdb_errorstr(ecode)); i = 0; gettimeofday(&start, NULL); if (tdb_traverse(tdb, count_record, &i) != num) errx(1, "Traverse returned wrong number of records"); if (i != (num - 1) * (num / 2)) errx(1, "Traverse tallied to %u", i); gettimeofday(&stop, NULL); if (transaction && (ecode = tdb_transaction_commit(tdb))) errx(1, "committing transaction: %s", tdb_errorstr(ecode)); printf(" %zu ns (%zu bytes)\n", normalize(&start, &stop, num), file_size()); if (tdb_check(tdb, NULL, NULL)) errx(1, "tdb_check failed!"); if (summary) { char *sumstr = NULL; tdb_summary(tdb, TDB_SUMMARY_HISTOGRAMS, &sumstr); printf("%s\n", sumstr); free(sumstr); } if (do_stats) dump_and_clear_stats(&tdb, flags, &log); if (++stage == stopat) exit(0); /* Delete 1000 records (not in order). */ printf("Deleting %u records: ", num); fflush(stdout); if (transaction && (ecode = tdb_transaction_start(tdb))) errx(1, "starting transaction: %s", tdb_errorstr(ecode)); gettimeofday(&start, NULL); for (j = 0; j < num; j++) { i = (j + 100003) % num; if ((ecode = tdb_delete(tdb, key)) != TDB_SUCCESS) errx(1, "Deleting key %u in tdb: %s", i, tdb_errorstr(ecode)); } gettimeofday(&stop, NULL); if (transaction && (ecode = tdb_transaction_commit(tdb))) errx(1, "committing transaction: %s", tdb_errorstr(ecode)); printf(" %zu ns (%zu bytes)\n", normalize(&start, &stop, num), file_size()); if (tdb_check(tdb, NULL, NULL)) errx(1, "tdb_check failed!"); if (summary) { char *sumstr = NULL; tdb_summary(tdb, TDB_SUMMARY_HISTOGRAMS, &sumstr); printf("%s\n", sumstr); free(sumstr); } if (do_stats) dump_and_clear_stats(&tdb, flags, &log); if (++stage == stopat) exit(0); /* Re-add 1000 records (not in order). */ printf("Re-adding %u records: ", num); fflush(stdout); if (transaction && (ecode = tdb_transaction_start(tdb))) errx(1, "starting transaction: %s", tdb_errorstr(ecode)); gettimeofday(&start, NULL); for (j = 0; j < num; j++) { i = (j + 100003) % num; if ((ecode = tdb_store(tdb, key, data, TDB_INSERT)) != 0) errx(1, "Inserting key %u in tdb: %s", i, tdb_errorstr(ecode)); } gettimeofday(&stop, NULL); if (transaction && (ecode = tdb_transaction_commit(tdb))) errx(1, "committing transaction: %s", tdb_errorstr(ecode)); printf(" %zu ns (%zu bytes)\n", normalize(&start, &stop, num), file_size()); if (tdb_check(tdb, NULL, NULL)) errx(1, "tdb_check failed!"); if (summary) { char *sumstr = NULL; tdb_summary(tdb, TDB_SUMMARY_HISTOGRAMS, &sumstr); printf("%s\n", sumstr); free(sumstr); } if (do_stats) dump_and_clear_stats(&tdb, flags, &log); if (++stage == stopat) exit(0); /* Append 1000 records. */ if (transaction && (ecode = tdb_transaction_start(tdb))) errx(1, "starting transaction: %s", tdb_errorstr(ecode)); printf("Appending %u records: ", num); fflush(stdout); gettimeofday(&start, NULL); for (i = 0; i < num; i++) if ((ecode = tdb_append(tdb, key, data)) != TDB_SUCCESS) errx(1, "Appending key %u in tdb: %s", i, tdb_errorstr(ecode)); gettimeofday(&stop, NULL); if (transaction && (ecode = tdb_transaction_commit(tdb))) errx(1, "committing transaction: %s", tdb_errorstr(ecode)); printf(" %zu ns (%zu bytes)\n", normalize(&start, &stop, num), file_size()); if (tdb_check(tdb, NULL, NULL)) errx(1, "tdb_check failed!"); if (summary) { char *sumstr = NULL; tdb_summary(tdb, TDB_SUMMARY_HISTOGRAMS, &sumstr); printf("%s\n", sumstr); free(sumstr); } if (++stage == stopat) exit(0); /* Churn 1000 records: not in order! */ if (transaction && (ecode = tdb_transaction_start(tdb))) errx(1, "starting transaction: %s", tdb_errorstr(ecode)); printf("Churning %u records: ", num); fflush(stdout); gettimeofday(&start, NULL); for (j = 0; j < num; j++) { i = (j + 1000019) % num; if ((ecode = tdb_delete(tdb, key)) != TDB_SUCCESS) errx(1, "Deleting key %u in tdb: %s", i, tdb_errorstr(ecode)); i += num; if ((ecode = tdb_store(tdb, key, data, TDB_INSERT)) != 0) errx(1, "Inserting key %u in tdb: %s", i, tdb_errorstr(ecode)); } gettimeofday(&stop, NULL); if (transaction && (ecode = tdb_transaction_commit(tdb))) errx(1, "committing transaction: %s", tdb_errorstr(ecode)); printf(" %zu ns (%zu bytes)\n", normalize(&start, &stop, num), file_size()); if (tdb_check(tdb, NULL, NULL)) errx(1, "tdb_check failed!"); if (summary) { char *sumstr = NULL; tdb_summary(tdb, TDB_SUMMARY_HISTOGRAMS, &sumstr); printf("%s\n", sumstr); free(sumstr); } if (do_stats) dump_and_clear_stats(&tdb, flags, &log); if (++stage == stopat) exit(0); return 0; }
static void addrec_db(void) { int klen, dlen; char *k, *d; TDB_DATA key, data; klen = 1 + (rand() % KEYLEN); dlen = 1 + (rand() % DATALEN); k = randbuf(klen); d = randbuf(dlen); key.dptr = (unsigned char *)k; key.dsize = klen+1; data.dptr = (unsigned char *)d; data.dsize = dlen+1; #if REOPEN_PROB if (in_transaction == 0 && random() % REOPEN_PROB == 0) { tdb_reopen_all(0); goto next; } #endif #if TRANSACTION_PROB if (in_transaction == 0 && (always_transaction || random() % TRANSACTION_PROB == 0)) { if (tdb_transaction_start(db) != 0) { fatal("tdb_transaction_start failed"); } in_transaction++; goto next; } if (in_transaction && random() % TRANSACTION_PROB == 0) { if (random() % TRANSACTION_PREPARE_PROB == 0) { if (tdb_transaction_prepare_commit(db) != 0) { fatal("tdb_transaction_prepare_commit failed"); } } if (tdb_transaction_commit(db) != 0) { fatal("tdb_transaction_commit failed"); } in_transaction--; goto next; } if (in_transaction && random() % TRANSACTION_PROB == 0) { if (tdb_transaction_cancel(db) != 0) { fatal("tdb_transaction_cancel failed"); } in_transaction--; goto next; } #endif #if DELETE_PROB if (random() % DELETE_PROB == 0) { tdb_delete(db, key); goto next; } #endif #if STORE_PROB if (random() % STORE_PROB == 0) { if (tdb_store(db, key, data, TDB_REPLACE) != 0) { fatal("tdb_store failed"); } goto next; } #endif #if APPEND_PROB if (random() % APPEND_PROB == 0) { if (tdb_append(db, key, data) != 0) { fatal("tdb_append failed"); } goto next; } #endif #if LOCKSTORE_PROB if (random() % LOCKSTORE_PROB == 0) { tdb_chainlock(db, key); data = tdb_fetch(db, key); if (tdb_store(db, key, data, TDB_REPLACE) != 0) { fatal("tdb_store failed"); } if (data.dptr) free(data.dptr); tdb_chainunlock(db, key); goto next; } #endif #if TRAVERSE_PROB if (random() % TRAVERSE_PROB == 0) { tdb_traverse(db, cull_traverse, NULL); goto next; } #endif #if TRAVERSE_READ_PROB if (random() % TRAVERSE_READ_PROB == 0) { tdb_traverse_read(db, NULL, NULL); goto next; } #endif data = tdb_fetch(db, key); if (data.dptr) free(data.dptr); next: free(k); free(d); }
int main(int argc, char *argv[]) { unsigned int i, extra_msgs; struct tdb_context *tdb; struct tdb_data key = tdb_mkdata("key", 3); struct tdb_data data = tdb_mkdata("data", 4); int flags[] = { TDB_DEFAULT, TDB_NOMMAP, TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT, TDB_VERSION1, TDB_NOMMAP|TDB_VERSION1, TDB_CONVERT|TDB_VERSION1, TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 }; plan_tests(sizeof(flags) / sizeof(flags[0]) * 48); for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) { /* RW -> R0 */ tdb = tdb_open("run-92-get-set-readonly.tdb", flags[i], O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr); ok1(tdb); ok1(!(tdb_get_flags(tdb) & TDB_RDONLY)); /* TDB1 complains multiple times. */ if (flags[i] & TDB_VERSION1) { extra_msgs = 1; } else { extra_msgs = 0; } ok1(tdb_store(tdb, key, data, TDB_INSERT) == TDB_SUCCESS); tdb_add_flag(tdb, TDB_RDONLY); ok1(tdb_get_flags(tdb) & TDB_RDONLY); /* Can't store, append, delete. */ ok1(tdb_store(tdb, key, data, TDB_MODIFY) == TDB_ERR_RDONLY); ok1(tap_log_messages == 1); ok1(tdb_append(tdb, key, data) == TDB_ERR_RDONLY); tap_log_messages -= extra_msgs; ok1(tap_log_messages == 2); ok1(tdb_delete(tdb, key) == TDB_ERR_RDONLY); tap_log_messages -= extra_msgs; ok1(tap_log_messages == 3); /* Can't start a transaction, or any write lock. */ ok1(tdb_transaction_start(tdb) == TDB_ERR_RDONLY); ok1(tap_log_messages == 4); ok1(tdb_chainlock(tdb, key) == TDB_ERR_RDONLY); tap_log_messages -= extra_msgs; ok1(tap_log_messages == 5); ok1(tdb_lockall(tdb) == TDB_ERR_RDONLY); ok1(tap_log_messages == 6); ok1(tdb_wipe_all(tdb) == TDB_ERR_RDONLY); ok1(tap_log_messages == 7); /* Back to RW. */ tdb_remove_flag(tdb, TDB_RDONLY); ok1(!(tdb_get_flags(tdb) & TDB_RDONLY)); ok1(tdb_store(tdb, key, data, TDB_MODIFY) == TDB_SUCCESS); ok1(tdb_append(tdb, key, data) == TDB_SUCCESS); ok1(tdb_delete(tdb, key) == TDB_SUCCESS); ok1(tdb_transaction_start(tdb) == TDB_SUCCESS); ok1(tdb_store(tdb, key, data, TDB_INSERT) == TDB_SUCCESS); ok1(tdb_transaction_commit(tdb) == TDB_SUCCESS); ok1(tdb_chainlock(tdb, key) == TDB_SUCCESS); tdb_chainunlock(tdb, key); ok1(tdb_lockall(tdb) == TDB_SUCCESS); tdb_unlockall(tdb); ok1(tdb_wipe_all(tdb) == TDB_SUCCESS); ok1(tap_log_messages == 7); tdb_close(tdb); /* R0 -> RW */ tdb = tdb_open("run-92-get-set-readonly.tdb", flags[i], O_RDONLY, 0600, &tap_log_attr); ok1(tdb); ok1(tdb_get_flags(tdb) & TDB_RDONLY); /* Can't store, append, delete. */ ok1(tdb_store(tdb, key, data, TDB_INSERT) == TDB_ERR_RDONLY); ok1(tap_log_messages == 8); ok1(tdb_append(tdb, key, data) == TDB_ERR_RDONLY); tap_log_messages -= extra_msgs; ok1(tap_log_messages == 9); ok1(tdb_delete(tdb, key) == TDB_ERR_RDONLY); tap_log_messages -= extra_msgs; ok1(tap_log_messages == 10); /* Can't start a transaction, or any write lock. */ ok1(tdb_transaction_start(tdb) == TDB_ERR_RDONLY); ok1(tap_log_messages == 11); ok1(tdb_chainlock(tdb, key) == TDB_ERR_RDONLY); tap_log_messages -= extra_msgs; ok1(tap_log_messages == 12); ok1(tdb_lockall(tdb) == TDB_ERR_RDONLY); ok1(tap_log_messages == 13); ok1(tdb_wipe_all(tdb) == TDB_ERR_RDONLY); ok1(tap_log_messages == 14); /* Can't remove TDB_RDONLY since we opened with O_RDONLY */ tdb_remove_flag(tdb, TDB_RDONLY); ok1(tap_log_messages == 15); ok1(tdb_get_flags(tdb) & TDB_RDONLY); tdb_close(tdb); ok1(tap_log_messages == 15); tap_log_messages = 0; } return exit_status(); }
static BOOL message_send_pid_internal(struct process_id pid, int msg_type, const void *buf, size_t len, BOOL duplicates_allowed, unsigned int timeout) { TDB_DATA kbuf; TDB_DATA dbuf; TDB_DATA old_dbuf; struct message_rec rec; char *ptr; struct message_rec prec; /* NULL pointer means implicit length zero. */ if (!buf) { SMB_ASSERT(len == 0); } /* * Doing kill with a non-positive pid causes messages to be * sent to places we don't want. */ SMB_ASSERT(procid_to_pid(&pid) > 0); rec.msg_version = MESSAGE_VERSION; rec.msg_type = msg_type; rec.dest = pid; rec.src = procid_self(); rec.len = buf ? len : 0; kbuf = message_key_pid(pid); dbuf.dptr = (void *)SMB_MALLOC(len + sizeof(rec)); if (!dbuf.dptr) return False; memcpy(dbuf.dptr, &rec, sizeof(rec)); if (len > 0 && buf) memcpy((void *)((char*)dbuf.dptr+sizeof(rec)), buf, len); dbuf.dsize = len + sizeof(rec); if (duplicates_allowed) { /* If duplicates are allowed we can just append the message and return. */ /* lock the record for the destination */ if (timeout) { if (tdb_chainlock_with_timeout(tdb, kbuf, timeout) == -1) { DEBUG(0,("message_send_pid_internal: failed to get chainlock with timeout %ul.\n", timeout)); return False; } } else { if (tdb_chainlock(tdb, kbuf) == -1) { DEBUG(0,("message_send_pid_internal: failed to get chainlock.\n")); return False; } } tdb_append(tdb, kbuf, dbuf); tdb_chainunlock(tdb, kbuf); SAFE_FREE(dbuf.dptr); errno = 0; /* paranoia */ return message_notify(pid); } /* lock the record for the destination */ if (timeout) { if (tdb_chainlock_with_timeout(tdb, kbuf, timeout) == -1) { DEBUG(0,("message_send_pid_internal: failed to get chainlock with timeout %ul.\n", timeout)); return False; } } else { if (tdb_chainlock(tdb, kbuf) == -1) { DEBUG(0,("message_send_pid_internal: failed to get chainlock.\n")); return False; } } old_dbuf = tdb_fetch(tdb, kbuf); if (!old_dbuf.dptr) { /* its a new record */ tdb_store(tdb, kbuf, dbuf, TDB_REPLACE); tdb_chainunlock(tdb, kbuf); SAFE_FREE(dbuf.dptr); errno = 0; /* paranoia */ return message_notify(pid); } /* Not a new record. Check for duplicates. */ for(ptr = (char *)old_dbuf.dptr; ptr < old_dbuf.dptr + old_dbuf.dsize; ) { /* * First check if the message header matches, then, if it's a non-zero * sized message, check if the data matches. If so it's a duplicate and * we can discard it. JRA. */ if (!memcmp(ptr, &rec, sizeof(rec))) { if (!len || (len && !memcmp( ptr + sizeof(rec), buf, len))) { tdb_chainunlock(tdb, kbuf); DEBUG(10,("message_send_pid_internal: discarding duplicate message.\n")); SAFE_FREE(dbuf.dptr); SAFE_FREE(old_dbuf.dptr); return True; } } memcpy(&prec, ptr, sizeof(prec)); ptr += sizeof(rec) + prec.len; } /* we're adding to an existing entry */ tdb_append(tdb, kbuf, dbuf); tdb_chainunlock(tdb, kbuf); SAFE_FREE(old_dbuf.dptr); SAFE_FREE(dbuf.dptr); errno = 0; /* paranoia */ return message_notify(pid); }
int main(int argc, char *argv[]) { unsigned int i, j, num = 1000, stage = 0, stopat = -1; int flags = TDB_DEFAULT; bool transaction = false; TDB_DATA key, data; struct tdb_context *tdb; struct timeval start, stop; union tdb_attribute seed, stats; /* Try to keep benchmarks even. */ seed.base.attr = TDB_ATTRIBUTE_SEED; seed.base.next = NULL; seed.seed.seed = 0; memset(&stats, 0, sizeof(stats)); stats.base.attr = TDB_ATTRIBUTE_STATS; stats.base.next = NULL; stats.stats.size = sizeof(stats); if (argv[1] && strcmp(argv[1], "--internal") == 0) { flags = TDB_INTERNAL; argc--; argv++; } if (argv[1] && strcmp(argv[1], "--transaction") == 0) { transaction = true; argc--; argv++; } if (argv[1] && strcmp(argv[1], "--stats") == 0) { seed.base.next = &stats; argc--; argv++; } tdb = tdb_open("/tmp/speed.tdb", flags, O_RDWR|O_CREAT|O_TRUNC, 0600, &seed); if (!tdb) err(1, "Opening /tmp/speed.tdb"); key.dptr = (void *)&i; key.dsize = sizeof(i); data = key; if (argv[1]) { num = atoi(argv[1]); argv++; argc--; } if (argv[1]) { stopat = atoi(argv[1]); argv++; argc--; } if (transaction && tdb_transaction_start(tdb)) errx(1, "starting transaction: %s", tdb_errorstr(tdb)); /* Add 1000 records. */ printf("Adding %u records: ", num); fflush(stdout); gettimeofday(&start, NULL); for (i = 0; i < num; i++) if (tdb_store(tdb, key, data, TDB_INSERT) != 0) errx(1, "Inserting key %u in tdb: %s", i, tdb_errorstr(tdb)); gettimeofday(&stop, NULL); if (transaction && tdb_transaction_commit(tdb)) errx(1, "committing transaction: %s", tdb_errorstr(tdb)); printf(" %zu ns (%zu bytes)\n", normalize(&start, &stop, num), file_size()); if (seed.base.next) dump_and_clear_stats(&stats.stats); if (++stage == stopat) exit(0); if (transaction && tdb_transaction_start(tdb)) errx(1, "starting transaction: %s", tdb_errorstr(tdb)); /* Finding 1000 records. */ printf("Finding %u records: ", num); fflush(stdout); gettimeofday(&start, NULL); for (i = 0; i < num; i++) { int *dptr; dptr = (int *)tdb_fetch(tdb, key).dptr; if (!dptr || *dptr != i) errx(1, "Fetching key %u in tdb gave %u", i, dptr ? *dptr : -1); } gettimeofday(&stop, NULL); if (transaction && tdb_transaction_commit(tdb)) errx(1, "committing transaction: %s", tdb_errorstr(tdb)); printf(" %zu ns (%zu bytes)\n", normalize(&start, &stop, num), file_size()); if (seed.base.next) dump_and_clear_stats(&stats.stats); if (++stage == stopat) exit(0); if (transaction && tdb_transaction_start(tdb)) errx(1, "starting transaction: %s", tdb_errorstr(tdb)); /* Missing 1000 records. */ printf("Missing %u records: ", num); fflush(stdout); gettimeofday(&start, NULL); for (i = num; i < num*2; i++) { int *dptr; dptr = (int *)tdb_fetch(tdb, key).dptr; if (dptr) errx(1, "Fetching key %u in tdb gave %u", i, *dptr); } gettimeofday(&stop, NULL); if (transaction && tdb_transaction_commit(tdb)) errx(1, "committing transaction: %s", tdb_errorstr(tdb)); printf(" %zu ns (%zu bytes)\n", normalize(&start, &stop, num), file_size()); if (seed.base.next) dump_and_clear_stats(&stats.stats); if (++stage == stopat) exit(0); if (transaction && tdb_transaction_start(tdb)) errx(1, "starting transaction: %s", tdb_errorstr(tdb)); /* Traverse 1000 records. */ printf("Traversing %u records: ", num); fflush(stdout); i = 0; gettimeofday(&start, NULL); if (tdb_traverse(tdb, count_record, &i) != num) errx(1, "Traverse returned wrong number of records"); if (i != (num - 1) * (num / 2)) errx(1, "Traverse tallied to %u", i); gettimeofday(&stop, NULL); if (transaction && tdb_transaction_commit(tdb)) errx(1, "committing transaction: %s", tdb_errorstr(tdb)); printf(" %zu ns (%zu bytes)\n", normalize(&start, &stop, num), file_size()); if (seed.base.next) dump_and_clear_stats(&stats.stats); if (++stage == stopat) exit(0); if (transaction && tdb_transaction_start(tdb)) errx(1, "starting transaction: %s", tdb_errorstr(tdb)); /* Delete 1000 records (not in order). */ printf("Deleting %u records: ", num); fflush(stdout); gettimeofday(&start, NULL); for (j = 0; j < num; j++) { i = (j + 100003) % num; if (tdb_delete(tdb, key) != 0) errx(1, "Deleting key %u in tdb: %s", i, tdb_errorstr(tdb)); } gettimeofday(&stop, NULL); if (transaction && tdb_transaction_commit(tdb)) errx(1, "committing transaction: %s", tdb_errorstr(tdb)); printf(" %zu ns (%zu bytes)\n", normalize(&start, &stop, num), file_size()); if (seed.base.next) dump_and_clear_stats(&stats.stats); if (++stage == stopat) exit(0); if (transaction && tdb_transaction_start(tdb)) errx(1, "starting transaction: %s", tdb_errorstr(tdb)); /* Re-add 1000 records (not in order). */ printf("Re-adding %u records: ", num); fflush(stdout); gettimeofday(&start, NULL); for (j = 0; j < num; j++) { i = (j + 100003) % num; if (tdb_store(tdb, key, data, TDB_INSERT) != 0) errx(1, "Inserting key %u in tdb: %s", i, tdb_errorstr(tdb)); } gettimeofday(&stop, NULL); if (transaction && tdb_transaction_commit(tdb)) errx(1, "committing transaction: %s", tdb_errorstr(tdb)); printf(" %zu ns (%zu bytes)\n", normalize(&start, &stop, num), file_size()); if (seed.base.next) dump_and_clear_stats(&stats.stats); if (++stage == stopat) exit(0); if (transaction && tdb_transaction_start(tdb)) errx(1, "starting transaction: %s", tdb_errorstr(tdb)); /* Append 1000 records. */ printf("Appending %u records: ", num); fflush(stdout); gettimeofday(&start, NULL); for (i = 0; i < num; i++) if (tdb_append(tdb, key, data) != 0) errx(1, "Appending key %u in tdb: %s", i, tdb_errorstr(tdb)); gettimeofday(&stop, NULL); if (transaction && tdb_transaction_commit(tdb)) errx(1, "committing transaction: %s", tdb_errorstr(tdb)); printf(" %zu ns (%zu bytes)\n", normalize(&start, &stop, num), file_size()); if (++stage == stopat) exit(0); if (transaction && tdb_transaction_start(tdb)) errx(1, "starting transaction: %s", tdb_errorstr(tdb)); /* Churn 1000 records: not in order! */ printf("Churning %u records: ", num); fflush(stdout); gettimeofday(&start, NULL); for (j = 0; j < num; j++) { i = (j + 1000019) % num; if (tdb_delete(tdb, key) != 0) errx(1, "Deleting key %u in tdb: %s", i, tdb_errorstr(tdb)); i += num; if (tdb_store(tdb, key, data, TDB_INSERT) != 0) errx(1, "Inserting key %u in tdb: %s", i, tdb_errorstr(tdb)); } gettimeofday(&stop, NULL); if (transaction && tdb_transaction_commit(tdb)) errx(1, "committing transaction: %s", tdb_errorstr(tdb)); printf(" %zu ns (%zu bytes)\n", normalize(&start, &stop, num), file_size()); if (seed.base.next) dump_and_clear_stats(&stats.stats); if (++stage == stopat) exit(0); return 0; }
int main(int argc, char *argv[]) { unsigned int i, j, moves; struct tdb_context *tdb; unsigned char *buffer; tdb_off_t oldoff = 0, newoff; int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP, TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT }; struct tdb_data key = { (unsigned char *)"key", 3 }; struct tdb_data data; buffer = malloc(MAX_SIZE); for (i = 0; i < MAX_SIZE; i++) buffer[i] = i; plan_tests(sizeof(flags) / sizeof(flags[0]) * ((3 + MAX_SIZE/SIZE_STEP * 4) * 2 + 6) + 1); /* Using tdb_store. */ for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) { tdb = tdb_open("run-append.tdb", flags[i], O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr); ok1(tdb); if (!tdb) continue; moves = 0; for (j = 0; j < MAX_SIZE; j += SIZE_STEP) { data.dptr = buffer; data.dsize = j; ok1(tdb_store(tdb, key, data, TDB_REPLACE) == 0); ok1(tdb_check(tdb, NULL, NULL) == 0); data = tdb_fetch(tdb, key); ok1(data.dsize == j); ok1(memcmp(data.dptr, buffer, data.dsize) == 0); free(data.dptr); newoff = tdb_offset(tdb, key); if (newoff != oldoff) moves++; oldoff = newoff; } ok1(tdb->allrecord_lock.count == 0 && tdb->num_lockrecs == 0); /* We should increase by 50% each time... */ ok(moves <= ilog64(j / SIZE_STEP)*2, "Moved %u times", moves); tdb_close(tdb); } /* Using tdb_append. */ for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) { size_t prev_len = 0; tdb = tdb_open("run-append.tdb", flags[i], O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr); ok1(tdb); if (!tdb) continue; moves = 0; for (j = 0; j < MAX_SIZE; j += SIZE_STEP) { data.dptr = buffer + prev_len; data.dsize = j - prev_len; ok1(tdb_append(tdb, key, data) == 0); ok1(tdb_check(tdb, NULL, NULL) == 0); data = tdb_fetch(tdb, key); ok1(data.dsize == j); ok1(memcmp(data.dptr, buffer, data.dsize) == 0); free(data.dptr); prev_len = data.dsize; newoff = tdb_offset(tdb, key); if (newoff != oldoff) moves++; oldoff = newoff; } ok1(tdb->allrecord_lock.count == 0 && tdb->num_lockrecs == 0); /* We should increase by 50% each time... */ ok(moves <= ilog64(j / SIZE_STEP)*2, "Moved %u times", moves); tdb_close(tdb); } for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) { tdb = tdb_open("run-append.tdb", flags[i], O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr); ok1(tdb); if (!tdb) continue; /* Huge initial store. */ data.dptr = buffer; data.dsize = MAX_SIZE; ok1(tdb_append(tdb, key, data) == 0); ok1(tdb_check(tdb, NULL, NULL) == 0); data = tdb_fetch(tdb, key); ok1(data.dsize == MAX_SIZE); ok1(memcmp(data.dptr, buffer, data.dsize) == 0); free(data.dptr); ok1(tdb->allrecord_lock.count == 0 && tdb->num_lockrecs == 0); tdb_close(tdb); } ok1(tap_log_messages == 0); return exit_status(); }