| 1 | /*
|
|---|
| 2 | Unix SMB/CIFS implementation.
|
|---|
| 3 | Samba database functions
|
|---|
| 4 | Copyright (C) Andrew Tridgell 1999-2000
|
|---|
| 5 | Copyright (C) Paul `Rusty' Russell 2000
|
|---|
| 6 | Copyright (C) Jeremy Allison 2000
|
|---|
| 7 | Copyright (C) Andrew Esh 2001
|
|---|
| 8 |
|
|---|
| 9 | This program is free software; you can redistribute it and/or modify
|
|---|
| 10 | it under the terms of the GNU General Public License as published by
|
|---|
| 11 | the Free Software Foundation; either version 3 of the License, or
|
|---|
| 12 | (at your option) any later version.
|
|---|
| 13 |
|
|---|
| 14 | This program is distributed in the hope that it will be useful,
|
|---|
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|---|
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|---|
| 17 | GNU General Public License for more details.
|
|---|
| 18 |
|
|---|
| 19 | You should have received a copy of the GNU General Public License
|
|---|
| 20 | along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|---|
| 21 | */
|
|---|
| 22 |
|
|---|
| 23 | #include "replace.h"
|
|---|
| 24 | #include "system/locale.h"
|
|---|
| 25 | #include "system/time.h"
|
|---|
| 26 | #include "system/filesys.h"
|
|---|
| 27 | #include "system/wait.h"
|
|---|
| 28 | #include "tdb.h"
|
|---|
| 29 |
|
|---|
| 30 | static int do_command(void);
|
|---|
| 31 | const char *cmdname;
|
|---|
| 32 | char *arg1, *arg2;
|
|---|
| 33 | size_t arg1len, arg2len;
|
|---|
| 34 | int bIterate = 0;
|
|---|
| 35 | char *line;
|
|---|
| 36 | TDB_DATA iterate_kbuf;
|
|---|
| 37 | char cmdline[1024];
|
|---|
| 38 | static int disable_mmap;
|
|---|
| 39 |
|
|---|
| 40 | enum commands {
|
|---|
| 41 | CMD_CREATE_TDB,
|
|---|
| 42 | CMD_OPEN_TDB,
|
|---|
| 43 | CMD_TRANSACTION_START,
|
|---|
| 44 | CMD_TRANSACTION_COMMIT,
|
|---|
| 45 | CMD_TRANSACTION_CANCEL,
|
|---|
| 46 | CMD_ERASE,
|
|---|
| 47 | CMD_DUMP,
|
|---|
| 48 | CMD_INSERT,
|
|---|
| 49 | CMD_MOVE,
|
|---|
| 50 | CMD_STORE,
|
|---|
| 51 | CMD_SHOW,
|
|---|
| 52 | CMD_KEYS,
|
|---|
| 53 | CMD_HEXKEYS,
|
|---|
| 54 | CMD_DELETE,
|
|---|
| 55 | CMD_LIST_HASH_FREE,
|
|---|
| 56 | CMD_LIST_FREE,
|
|---|
| 57 | CMD_INFO,
|
|---|
| 58 | CMD_MMAP,
|
|---|
| 59 | CMD_SPEED,
|
|---|
| 60 | CMD_FIRST,
|
|---|
| 61 | CMD_NEXT,
|
|---|
| 62 | CMD_SYSTEM,
|
|---|
| 63 | CMD_CHECK,
|
|---|
| 64 | CMD_QUIT,
|
|---|
| 65 | CMD_HELP
|
|---|
| 66 | };
|
|---|
| 67 |
|
|---|
| 68 | typedef struct {
|
|---|
| 69 | const char *name;
|
|---|
| 70 | enum commands cmd;
|
|---|
| 71 | } COMMAND_TABLE;
|
|---|
| 72 |
|
|---|
| 73 | COMMAND_TABLE cmd_table[] = {
|
|---|
| 74 | {"create", CMD_CREATE_TDB},
|
|---|
| 75 | {"open", CMD_OPEN_TDB},
|
|---|
| 76 | {"transaction_start", CMD_TRANSACTION_START},
|
|---|
| 77 | {"transaction_commit", CMD_TRANSACTION_COMMIT},
|
|---|
| 78 | {"transaction_cancel", CMD_TRANSACTION_CANCEL},
|
|---|
| 79 | {"erase", CMD_ERASE},
|
|---|
| 80 | {"dump", CMD_DUMP},
|
|---|
| 81 | {"insert", CMD_INSERT},
|
|---|
| 82 | {"move", CMD_MOVE},
|
|---|
| 83 | {"store", CMD_STORE},
|
|---|
| 84 | {"show", CMD_SHOW},
|
|---|
| 85 | {"keys", CMD_KEYS},
|
|---|
| 86 | {"hexkeys", CMD_HEXKEYS},
|
|---|
| 87 | {"delete", CMD_DELETE},
|
|---|
| 88 | {"list", CMD_LIST_HASH_FREE},
|
|---|
| 89 | {"free", CMD_LIST_FREE},
|
|---|
| 90 | {"info", CMD_INFO},
|
|---|
| 91 | {"speed", CMD_SPEED},
|
|---|
| 92 | {"mmap", CMD_MMAP},
|
|---|
| 93 | {"first", CMD_FIRST},
|
|---|
| 94 | {"1", CMD_FIRST},
|
|---|
| 95 | {"next", CMD_NEXT},
|
|---|
| 96 | {"n", CMD_NEXT},
|
|---|
| 97 | {"check", CMD_CHECK},
|
|---|
| 98 | {"quit", CMD_QUIT},
|
|---|
| 99 | {"q", CMD_QUIT},
|
|---|
| 100 | {"!", CMD_SYSTEM},
|
|---|
| 101 | {NULL, CMD_HELP}
|
|---|
| 102 | };
|
|---|
| 103 |
|
|---|
| 104 | struct timeval tp1,tp2;
|
|---|
| 105 |
|
|---|
| 106 | static void _start_timer(void)
|
|---|
| 107 | {
|
|---|
| 108 | gettimeofday(&tp1,NULL);
|
|---|
| 109 | }
|
|---|
| 110 |
|
|---|
| 111 | static double _end_timer(void)
|
|---|
| 112 | {
|
|---|
| 113 | gettimeofday(&tp2,NULL);
|
|---|
| 114 | return((tp2.tv_sec - tp1.tv_sec) +
|
|---|
| 115 | (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
|
|---|
| 116 | }
|
|---|
| 117 |
|
|---|
| 118 | #ifdef PRINTF_ATTRIBUTE
|
|---|
| 119 | static void tdb_log(struct tdb_context *tdb, enum tdb_debug_level level, const char *format, ...) PRINTF_ATTRIBUTE(3,4);
|
|---|
| 120 | #endif
|
|---|
| 121 | static void tdb_log(struct tdb_context *tdb, enum tdb_debug_level level, const char *format, ...)
|
|---|
| 122 | {
|
|---|
| 123 | va_list ap;
|
|---|
| 124 |
|
|---|
| 125 | va_start(ap, format);
|
|---|
| 126 | vfprintf(stderr, format, ap);
|
|---|
| 127 | va_end(ap);
|
|---|
| 128 | }
|
|---|
| 129 |
|
|---|
| 130 | /* a tdb tool for manipulating a tdb database */
|
|---|
| 131 |
|
|---|
| 132 | static TDB_CONTEXT *tdb;
|
|---|
| 133 |
|
|---|
| 134 | static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
|
|---|
| 135 | static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
|
|---|
| 136 | static int print_hexkey(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
|
|---|
| 137 |
|
|---|
| 138 | static void print_asc(const char *buf,int len)
|
|---|
| 139 | {
|
|---|
| 140 | int i;
|
|---|
| 141 |
|
|---|
| 142 | /* We're probably printing ASCII strings so don't try to display
|
|---|
| 143 | the trailing NULL character. */
|
|---|
| 144 |
|
|---|
| 145 | if (buf[len - 1] == 0)
|
|---|
| 146 | len--;
|
|---|
| 147 |
|
|---|
| 148 | for (i=0;i<len;i++)
|
|---|
| 149 | printf("%c",isprint(buf[i])?buf[i]:'.');
|
|---|
| 150 | }
|
|---|
| 151 |
|
|---|
| 152 | static void print_data(const char *buf,int len)
|
|---|
| 153 | {
|
|---|
| 154 | int i=0;
|
|---|
| 155 | if (len<=0) return;
|
|---|
| 156 | printf("[%03X] ",i);
|
|---|
| 157 | for (i=0;i<len;) {
|
|---|
| 158 | printf("%02X ",(int)((unsigned char)buf[i]));
|
|---|
| 159 | i++;
|
|---|
| 160 | if (i%8 == 0) printf(" ");
|
|---|
| 161 | if (i%16 == 0) {
|
|---|
| 162 | print_asc(&buf[i-16],8); printf(" ");
|
|---|
| 163 | print_asc(&buf[i-8],8); printf("\n");
|
|---|
| 164 | if (i<len) printf("[%03X] ",i);
|
|---|
| 165 | }
|
|---|
| 166 | }
|
|---|
| 167 | if (i%16) {
|
|---|
| 168 | int n;
|
|---|
| 169 |
|
|---|
| 170 | n = 16 - (i%16);
|
|---|
| 171 | printf(" ");
|
|---|
| 172 | if (n>8) printf(" ");
|
|---|
| 173 | while (n--) printf(" ");
|
|---|
| 174 |
|
|---|
| 175 | n = i%16;
|
|---|
| 176 | if (n > 8) n = 8;
|
|---|
| 177 | print_asc(&buf[i-(i%16)],n); printf(" ");
|
|---|
| 178 | n = (i%16) - n;
|
|---|
| 179 | if (n>0) print_asc(&buf[i-n],n);
|
|---|
| 180 | printf("\n");
|
|---|
| 181 | }
|
|---|
| 182 | }
|
|---|
| 183 |
|
|---|
| 184 | static void help(void)
|
|---|
| 185 | {
|
|---|
| 186 | printf("\n"
|
|---|
| 187 | "tdbtool: \n"
|
|---|
| 188 | " create dbname : create a database\n"
|
|---|
| 189 | " open dbname : open an existing database\n"
|
|---|
| 190 | " transaction_start : start a transaction\n"
|
|---|
| 191 | " transaction_commit : commit a transaction\n"
|
|---|
| 192 | " transaction_cancel : cancel a transaction\n"
|
|---|
| 193 | " erase : erase the database\n"
|
|---|
| 194 | " dump : dump the database as strings\n"
|
|---|
| 195 | " keys : dump the database keys as strings\n"
|
|---|
| 196 | " hexkeys : dump the database keys as hex values\n"
|
|---|
| 197 | " info : print summary info about the database\n"
|
|---|
| 198 | " insert key data : insert a record\n"
|
|---|
| 199 | " move key file : move a record to a destination tdb\n"
|
|---|
| 200 | " store key data : store a record (replace)\n"
|
|---|
| 201 | " show key : show a record by key\n"
|
|---|
| 202 | " delete key : delete a record by key\n"
|
|---|
| 203 | " list : print the database hash table and freelist\n"
|
|---|
| 204 | " free : print the database freelist\n"
|
|---|
| 205 | " check : check the integrity of an opened database\n"
|
|---|
| 206 | " speed : perform speed tests on the database\n"
|
|---|
| 207 | " ! command : execute system command\n"
|
|---|
| 208 | " 1 | first : print the first record\n"
|
|---|
| 209 | " n | next : print the next record\n"
|
|---|
| 210 | " q | quit : terminate\n"
|
|---|
| 211 | " \\n : repeat 'next' command\n"
|
|---|
| 212 | "\n");
|
|---|
| 213 | }
|
|---|
| 214 |
|
|---|
| 215 | static void terror(const char *why)
|
|---|
| 216 | {
|
|---|
| 217 | printf("%s\n", why);
|
|---|
| 218 | }
|
|---|
| 219 |
|
|---|
| 220 | static void create_tdb(const char *tdbname)
|
|---|
| 221 | {
|
|---|
| 222 | struct tdb_logging_context log_ctx;
|
|---|
| 223 | log_ctx.log_fn = tdb_log;
|
|---|
| 224 |
|
|---|
| 225 | if (tdb) tdb_close(tdb);
|
|---|
| 226 | tdb = tdb_open_ex(tdbname, 0, TDB_CLEAR_IF_FIRST | (disable_mmap?TDB_NOMMAP:0),
|
|---|
| 227 | O_RDWR | O_CREAT | O_TRUNC, 0600, &log_ctx, NULL);
|
|---|
| 228 | if (!tdb) {
|
|---|
| 229 | printf("Could not create %s: %s\n", tdbname, strerror(errno));
|
|---|
| 230 | }
|
|---|
| 231 | }
|
|---|
| 232 |
|
|---|
| 233 | static void open_tdb(const char *tdbname)
|
|---|
| 234 | {
|
|---|
| 235 | struct tdb_logging_context log_ctx;
|
|---|
| 236 | log_ctx.log_fn = tdb_log;
|
|---|
| 237 |
|
|---|
| 238 | if (tdb) tdb_close(tdb);
|
|---|
| 239 | tdb = tdb_open_ex(tdbname, 0, disable_mmap?TDB_NOMMAP:0, O_RDWR, 0600,
|
|---|
| 240 | &log_ctx, NULL);
|
|---|
| 241 | if (!tdb) {
|
|---|
| 242 | printf("Could not open %s: %s\n", tdbname, strerror(errno));
|
|---|
| 243 | }
|
|---|
| 244 | }
|
|---|
| 245 |
|
|---|
| 246 | static void insert_tdb(char *keyname, size_t keylen, char* data, size_t datalen)
|
|---|
| 247 | {
|
|---|
| 248 | TDB_DATA key, dbuf;
|
|---|
| 249 |
|
|---|
| 250 | if ((keyname == NULL) || (keylen == 0)) {
|
|---|
| 251 | terror("need key");
|
|---|
| 252 | return;
|
|---|
| 253 | }
|
|---|
| 254 |
|
|---|
| 255 | key.dptr = (unsigned char *)keyname;
|
|---|
| 256 | key.dsize = keylen;
|
|---|
| 257 | dbuf.dptr = (unsigned char *)data;
|
|---|
| 258 | dbuf.dsize = datalen;
|
|---|
| 259 |
|
|---|
| 260 | if (tdb_store(tdb, key, dbuf, TDB_INSERT) == -1) {
|
|---|
| 261 | terror("insert failed");
|
|---|
| 262 | }
|
|---|
| 263 | }
|
|---|
| 264 |
|
|---|
| 265 | static void store_tdb(char *keyname, size_t keylen, char* data, size_t datalen)
|
|---|
| 266 | {
|
|---|
| 267 | TDB_DATA key, dbuf;
|
|---|
| 268 |
|
|---|
| 269 | if ((keyname == NULL) || (keylen == 0)) {
|
|---|
| 270 | terror("need key");
|
|---|
| 271 | return;
|
|---|
| 272 | }
|
|---|
| 273 |
|
|---|
| 274 | if ((data == NULL) || (datalen == 0)) {
|
|---|
| 275 | terror("need data");
|
|---|
| 276 | return;
|
|---|
| 277 | }
|
|---|
| 278 |
|
|---|
| 279 | key.dptr = (unsigned char *)keyname;
|
|---|
| 280 | key.dsize = keylen;
|
|---|
| 281 | dbuf.dptr = (unsigned char *)data;
|
|---|
| 282 | dbuf.dsize = datalen;
|
|---|
| 283 |
|
|---|
| 284 | printf("Storing key:\n");
|
|---|
| 285 | print_rec(tdb, key, dbuf, NULL);
|
|---|
| 286 |
|
|---|
| 287 | if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) {
|
|---|
| 288 | terror("store failed");
|
|---|
| 289 | }
|
|---|
| 290 | }
|
|---|
| 291 |
|
|---|
| 292 | static void show_tdb(char *keyname, size_t keylen)
|
|---|
| 293 | {
|
|---|
| 294 | TDB_DATA key, dbuf;
|
|---|
| 295 |
|
|---|
| 296 | if ((keyname == NULL) || (keylen == 0)) {
|
|---|
| 297 | terror("need key");
|
|---|
| 298 | return;
|
|---|
| 299 | }
|
|---|
| 300 |
|
|---|
| 301 | key.dptr = (unsigned char *)keyname;
|
|---|
| 302 | key.dsize = keylen;
|
|---|
| 303 |
|
|---|
| 304 | dbuf = tdb_fetch(tdb, key);
|
|---|
| 305 | if (!dbuf.dptr) {
|
|---|
| 306 | terror("fetch failed");
|
|---|
| 307 | return;
|
|---|
| 308 | }
|
|---|
| 309 |
|
|---|
| 310 | print_rec(tdb, key, dbuf, NULL);
|
|---|
| 311 |
|
|---|
| 312 | free( dbuf.dptr );
|
|---|
| 313 |
|
|---|
| 314 | return;
|
|---|
| 315 | }
|
|---|
| 316 |
|
|---|
| 317 | static void delete_tdb(char *keyname, size_t keylen)
|
|---|
| 318 | {
|
|---|
| 319 | TDB_DATA key;
|
|---|
| 320 |
|
|---|
| 321 | if ((keyname == NULL) || (keylen == 0)) {
|
|---|
| 322 | terror("need key");
|
|---|
| 323 | return;
|
|---|
| 324 | }
|
|---|
| 325 |
|
|---|
| 326 | key.dptr = (unsigned char *)keyname;
|
|---|
| 327 | key.dsize = keylen;
|
|---|
| 328 |
|
|---|
| 329 | if (tdb_delete(tdb, key) != 0) {
|
|---|
| 330 | terror("delete failed");
|
|---|
| 331 | }
|
|---|
| 332 | }
|
|---|
| 333 |
|
|---|
| 334 | static void move_rec(char *keyname, size_t keylen, char* tdbname)
|
|---|
| 335 | {
|
|---|
| 336 | TDB_DATA key, dbuf;
|
|---|
| 337 | TDB_CONTEXT *dst_tdb;
|
|---|
| 338 |
|
|---|
| 339 | if ((keyname == NULL) || (keylen == 0)) {
|
|---|
| 340 | terror("need key");
|
|---|
| 341 | return;
|
|---|
| 342 | }
|
|---|
| 343 |
|
|---|
| 344 | if ( !tdbname ) {
|
|---|
| 345 | terror("need destination tdb name");
|
|---|
| 346 | return;
|
|---|
| 347 | }
|
|---|
| 348 |
|
|---|
| 349 | key.dptr = (unsigned char *)keyname;
|
|---|
| 350 | key.dsize = keylen;
|
|---|
| 351 |
|
|---|
| 352 | dbuf = tdb_fetch(tdb, key);
|
|---|
| 353 | if (!dbuf.dptr) {
|
|---|
| 354 | terror("fetch failed");
|
|---|
| 355 | return;
|
|---|
| 356 | }
|
|---|
| 357 |
|
|---|
| 358 | print_rec(tdb, key, dbuf, NULL);
|
|---|
| 359 |
|
|---|
| 360 | dst_tdb = tdb_open(tdbname, 0, 0, O_RDWR, 0600);
|
|---|
| 361 | if ( !dst_tdb ) {
|
|---|
| 362 | terror("unable to open destination tdb");
|
|---|
| 363 | return;
|
|---|
| 364 | }
|
|---|
| 365 |
|
|---|
| 366 | if ( tdb_store( dst_tdb, key, dbuf, TDB_REPLACE ) == -1 ) {
|
|---|
| 367 | terror("failed to move record");
|
|---|
| 368 | }
|
|---|
| 369 | else
|
|---|
| 370 | printf("record moved\n");
|
|---|
| 371 |
|
|---|
| 372 | tdb_close( dst_tdb );
|
|---|
| 373 |
|
|---|
| 374 | return;
|
|---|
| 375 | }
|
|---|
| 376 |
|
|---|
| 377 | static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
|
|---|
| 378 | {
|
|---|
| 379 | printf("\nkey %d bytes\n", (int)key.dsize);
|
|---|
| 380 | print_asc((const char *)key.dptr, key.dsize);
|
|---|
| 381 | printf("\ndata %d bytes\n", (int)dbuf.dsize);
|
|---|
| 382 | print_data((const char *)dbuf.dptr, dbuf.dsize);
|
|---|
| 383 | return 0;
|
|---|
| 384 | }
|
|---|
| 385 |
|
|---|
| 386 | static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
|
|---|
| 387 | {
|
|---|
| 388 | printf("key %d bytes: ", (int)key.dsize);
|
|---|
| 389 | print_asc((const char *)key.dptr, key.dsize);
|
|---|
| 390 | printf("\n");
|
|---|
| 391 | return 0;
|
|---|
| 392 | }
|
|---|
| 393 |
|
|---|
| 394 | static int print_hexkey(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
|
|---|
| 395 | {
|
|---|
| 396 | printf("key %d bytes\n", (int)key.dsize);
|
|---|
| 397 | print_data((const char *)key.dptr, key.dsize);
|
|---|
| 398 | printf("\n");
|
|---|
| 399 | return 0;
|
|---|
| 400 | }
|
|---|
| 401 |
|
|---|
| 402 | static int total_bytes;
|
|---|
| 403 |
|
|---|
| 404 | static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
|
|---|
| 405 | {
|
|---|
| 406 | total_bytes += dbuf.dsize;
|
|---|
| 407 | return 0;
|
|---|
| 408 | }
|
|---|
| 409 |
|
|---|
| 410 | static void info_tdb(void)
|
|---|
| 411 | {
|
|---|
| 412 | int count;
|
|---|
| 413 | total_bytes = 0;
|
|---|
| 414 | if ((count = tdb_traverse(tdb, traverse_fn, NULL)) == -1)
|
|---|
| 415 | printf("Error = %s\n", tdb_errorstr(tdb));
|
|---|
| 416 | else
|
|---|
| 417 | printf("%d records totalling %d bytes\n", count, total_bytes);
|
|---|
| 418 | }
|
|---|
| 419 |
|
|---|
| 420 | static void speed_tdb(const char *tlimit)
|
|---|
| 421 | {
|
|---|
| 422 | const char *str = "store test", *str2 = "transaction test";
|
|---|
| 423 | unsigned timelimit = tlimit?atoi(tlimit):0;
|
|---|
| 424 | double t;
|
|---|
| 425 | int ops;
|
|---|
| 426 | if (timelimit == 0) timelimit = 5;
|
|---|
| 427 |
|
|---|
| 428 | ops = 0;
|
|---|
| 429 | printf("Testing store speed for %u seconds\n", timelimit);
|
|---|
| 430 | _start_timer();
|
|---|
| 431 | do {
|
|---|
| 432 | long int r = random();
|
|---|
| 433 | TDB_DATA key, dbuf;
|
|---|
| 434 | key.dptr = discard_const_p(uint8_t, str);
|
|---|
| 435 | key.dsize = strlen((char *)key.dptr);
|
|---|
| 436 | dbuf.dptr = (uint8_t *) &r;
|
|---|
| 437 | dbuf.dsize = sizeof(r);
|
|---|
| 438 | tdb_store(tdb, key, dbuf, TDB_REPLACE);
|
|---|
| 439 | t = _end_timer();
|
|---|
| 440 | ops++;
|
|---|
| 441 | } while (t < timelimit);
|
|---|
| 442 | printf("%10.3f ops/sec\n", ops/t);
|
|---|
| 443 |
|
|---|
| 444 | ops = 0;
|
|---|
| 445 | printf("Testing fetch speed for %u seconds\n", timelimit);
|
|---|
| 446 | _start_timer();
|
|---|
| 447 | do {
|
|---|
| 448 | long int r = random();
|
|---|
| 449 | TDB_DATA key, dbuf;
|
|---|
| 450 | key.dptr = discard_const_p(uint8_t, str);
|
|---|
| 451 | key.dsize = strlen((char *)key.dptr);
|
|---|
| 452 | dbuf.dptr = (uint8_t *) &r;
|
|---|
| 453 | dbuf.dsize = sizeof(r);
|
|---|
| 454 | tdb_fetch(tdb, key);
|
|---|
| 455 | t = _end_timer();
|
|---|
| 456 | ops++;
|
|---|
| 457 | } while (t < timelimit);
|
|---|
| 458 | printf("%10.3f ops/sec\n", ops/t);
|
|---|
| 459 |
|
|---|
| 460 | ops = 0;
|
|---|
| 461 | printf("Testing transaction speed for %u seconds\n", timelimit);
|
|---|
| 462 | _start_timer();
|
|---|
| 463 | do {
|
|---|
| 464 | long int r = random();
|
|---|
| 465 | TDB_DATA key, dbuf;
|
|---|
| 466 | key.dptr = discard_const_p(uint8_t, str2);
|
|---|
| 467 | key.dsize = strlen((char *)key.dptr);
|
|---|
| 468 | dbuf.dptr = (uint8_t *) &r;
|
|---|
| 469 | dbuf.dsize = sizeof(r);
|
|---|
| 470 | tdb_transaction_start(tdb);
|
|---|
| 471 | tdb_store(tdb, key, dbuf, TDB_REPLACE);
|
|---|
| 472 | tdb_transaction_commit(tdb);
|
|---|
| 473 | t = _end_timer();
|
|---|
| 474 | ops++;
|
|---|
| 475 | } while (t < timelimit);
|
|---|
| 476 | printf("%10.3f ops/sec\n", ops/t);
|
|---|
| 477 |
|
|---|
| 478 | ops = 0;
|
|---|
| 479 | printf("Testing traverse speed for %u seconds\n", timelimit);
|
|---|
| 480 | _start_timer();
|
|---|
| 481 | do {
|
|---|
| 482 | tdb_traverse(tdb, traverse_fn, NULL);
|
|---|
| 483 | t = _end_timer();
|
|---|
| 484 | ops++;
|
|---|
| 485 | } while (t < timelimit);
|
|---|
| 486 | printf("%10.3f ops/sec\n", ops/t);
|
|---|
| 487 | }
|
|---|
| 488 |
|
|---|
| 489 | static void toggle_mmap(void)
|
|---|
| 490 | {
|
|---|
| 491 | disable_mmap = !disable_mmap;
|
|---|
| 492 | if (disable_mmap) {
|
|---|
| 493 | printf("mmap is disabled\n");
|
|---|
| 494 | } else {
|
|---|
| 495 | printf("mmap is enabled\n");
|
|---|
| 496 | }
|
|---|
| 497 | }
|
|---|
| 498 |
|
|---|
| 499 | static char *tdb_getline(const char *prompt)
|
|---|
| 500 | {
|
|---|
| 501 | static char thisline[1024];
|
|---|
| 502 | char *p;
|
|---|
| 503 | fputs(prompt, stdout);
|
|---|
| 504 | thisline[0] = 0;
|
|---|
| 505 | p = fgets(thisline, sizeof(thisline)-1, stdin);
|
|---|
| 506 | if (p) p = strchr(p, '\n');
|
|---|
| 507 | if (p) *p = 0;
|
|---|
| 508 | return p?thisline:NULL;
|
|---|
| 509 | }
|
|---|
| 510 |
|
|---|
| 511 | static int do_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf,
|
|---|
| 512 | void *state)
|
|---|
| 513 | {
|
|---|
| 514 | return tdb_delete(the_tdb, key);
|
|---|
| 515 | }
|
|---|
| 516 |
|
|---|
| 517 | static void first_record(TDB_CONTEXT *the_tdb, TDB_DATA *pkey)
|
|---|
| 518 | {
|
|---|
| 519 | TDB_DATA dbuf;
|
|---|
| 520 | *pkey = tdb_firstkey(the_tdb);
|
|---|
| 521 |
|
|---|
| 522 | dbuf = tdb_fetch(the_tdb, *pkey);
|
|---|
| 523 | if (!dbuf.dptr) terror("fetch failed");
|
|---|
| 524 | else {
|
|---|
| 525 | print_rec(the_tdb, *pkey, dbuf, NULL);
|
|---|
| 526 | }
|
|---|
| 527 | }
|
|---|
| 528 |
|
|---|
| 529 | static void next_record(TDB_CONTEXT *the_tdb, TDB_DATA *pkey)
|
|---|
| 530 | {
|
|---|
| 531 | TDB_DATA dbuf;
|
|---|
| 532 | *pkey = tdb_nextkey(the_tdb, *pkey);
|
|---|
| 533 |
|
|---|
| 534 | dbuf = tdb_fetch(the_tdb, *pkey);
|
|---|
| 535 | if (!dbuf.dptr)
|
|---|
| 536 | terror("fetch failed");
|
|---|
| 537 | else
|
|---|
| 538 | print_rec(the_tdb, *pkey, dbuf, NULL);
|
|---|
| 539 | }
|
|---|
| 540 |
|
|---|
| 541 | static int count(TDB_DATA key, TDB_DATA data, void *private_data)
|
|---|
| 542 | {
|
|---|
| 543 | (*(unsigned int *)private_data)++;
|
|---|
| 544 | return 0;
|
|---|
| 545 | }
|
|---|
| 546 |
|
|---|
| 547 | static void check_db(TDB_CONTEXT *the_tdb)
|
|---|
| 548 | {
|
|---|
| 549 | int tdbcount = 0;
|
|---|
| 550 | if (!the_tdb)
|
|---|
| 551 | printf("Error: No database opened!\n");
|
|---|
| 552 | else if (tdb_check(the_tdb, count, &tdbcount) == -1)
|
|---|
| 553 | printf("Integrity check for the opened database failed.\n");
|
|---|
| 554 | else
|
|---|
| 555 | printf("Database integrity is OK and has %d records.\n",
|
|---|
| 556 | tdbcount);
|
|---|
| 557 | }
|
|---|
| 558 |
|
|---|
| 559 | static int do_command(void)
|
|---|
| 560 | {
|
|---|
| 561 | COMMAND_TABLE *ctp = cmd_table;
|
|---|
| 562 | enum commands mycmd = CMD_HELP;
|
|---|
| 563 | int cmd_len;
|
|---|
| 564 |
|
|---|
| 565 | if (cmdname && strlen(cmdname) == 0) {
|
|---|
| 566 | mycmd = CMD_NEXT;
|
|---|
| 567 | } else {
|
|---|
| 568 | while (ctp->name) {
|
|---|
| 569 | cmd_len = strlen(ctp->name);
|
|---|
| 570 | if (strncmp(ctp->name,cmdname,cmd_len) == 0) {
|
|---|
| 571 | mycmd = ctp->cmd;
|
|---|
| 572 | break;
|
|---|
| 573 | }
|
|---|
| 574 | ctp++;
|
|---|
| 575 | }
|
|---|
| 576 | }
|
|---|
| 577 |
|
|---|
| 578 | switch (mycmd) {
|
|---|
| 579 | case CMD_CREATE_TDB:
|
|---|
| 580 | bIterate = 0;
|
|---|
| 581 | create_tdb(arg1);
|
|---|
| 582 | return 0;
|
|---|
| 583 | case CMD_OPEN_TDB:
|
|---|
| 584 | bIterate = 0;
|
|---|
| 585 | open_tdb(arg1);
|
|---|
| 586 | return 0;
|
|---|
| 587 | case CMD_SYSTEM:
|
|---|
| 588 | /* Shell command */
|
|---|
| 589 | if (system(arg1) == -1) {
|
|---|
| 590 | terror("system() call failed\n");
|
|---|
| 591 | }
|
|---|
| 592 | return 0;
|
|---|
| 593 | case CMD_QUIT:
|
|---|
| 594 | return 1;
|
|---|
| 595 | default:
|
|---|
| 596 | /* all the rest require a open database */
|
|---|
| 597 | if (!tdb) {
|
|---|
| 598 | bIterate = 0;
|
|---|
| 599 | terror("database not open");
|
|---|
| 600 | help();
|
|---|
| 601 | return 0;
|
|---|
| 602 | }
|
|---|
| 603 | switch (mycmd) {
|
|---|
| 604 | case CMD_TRANSACTION_START:
|
|---|
| 605 | bIterate = 0;
|
|---|
| 606 | tdb_transaction_start(tdb);
|
|---|
| 607 | return 0;
|
|---|
| 608 | case CMD_TRANSACTION_COMMIT:
|
|---|
| 609 | bIterate = 0;
|
|---|
| 610 | tdb_transaction_commit(tdb);
|
|---|
| 611 | return 0;
|
|---|
| 612 | case CMD_TRANSACTION_CANCEL:
|
|---|
| 613 | bIterate = 0;
|
|---|
| 614 | tdb_transaction_cancel(tdb);
|
|---|
| 615 | return 0;
|
|---|
| 616 | case CMD_ERASE:
|
|---|
| 617 | bIterate = 0;
|
|---|
| 618 | tdb_traverse(tdb, do_delete_fn, NULL);
|
|---|
| 619 | return 0;
|
|---|
| 620 | case CMD_DUMP:
|
|---|
| 621 | bIterate = 0;
|
|---|
| 622 | tdb_traverse(tdb, print_rec, NULL);
|
|---|
| 623 | return 0;
|
|---|
| 624 | case CMD_INSERT:
|
|---|
| 625 | bIterate = 0;
|
|---|
| 626 | insert_tdb(arg1, arg1len,arg2,arg2len);
|
|---|
| 627 | return 0;
|
|---|
| 628 | case CMD_MOVE:
|
|---|
| 629 | bIterate = 0;
|
|---|
| 630 | move_rec(arg1,arg1len,arg2);
|
|---|
| 631 | return 0;
|
|---|
| 632 | case CMD_STORE:
|
|---|
| 633 | bIterate = 0;
|
|---|
| 634 | store_tdb(arg1,arg1len,arg2,arg2len);
|
|---|
| 635 | return 0;
|
|---|
| 636 | case CMD_SHOW:
|
|---|
| 637 | bIterate = 0;
|
|---|
| 638 | show_tdb(arg1, arg1len);
|
|---|
| 639 | return 0;
|
|---|
| 640 | case CMD_KEYS:
|
|---|
| 641 | tdb_traverse(tdb, print_key, NULL);
|
|---|
| 642 | return 0;
|
|---|
| 643 | case CMD_HEXKEYS:
|
|---|
| 644 | tdb_traverse(tdb, print_hexkey, NULL);
|
|---|
| 645 | return 0;
|
|---|
| 646 | case CMD_DELETE:
|
|---|
| 647 | bIterate = 0;
|
|---|
| 648 | delete_tdb(arg1,arg1len);
|
|---|
| 649 | return 0;
|
|---|
| 650 | case CMD_LIST_HASH_FREE:
|
|---|
| 651 | tdb_dump_all(tdb);
|
|---|
| 652 | return 0;
|
|---|
| 653 | case CMD_LIST_FREE:
|
|---|
| 654 | tdb_printfreelist(tdb);
|
|---|
| 655 | return 0;
|
|---|
| 656 | case CMD_INFO:
|
|---|
| 657 | info_tdb();
|
|---|
| 658 | return 0;
|
|---|
| 659 | case CMD_SPEED:
|
|---|
| 660 | speed_tdb(arg1);
|
|---|
| 661 | return 0;
|
|---|
| 662 | case CMD_MMAP:
|
|---|
| 663 | toggle_mmap();
|
|---|
| 664 | return 0;
|
|---|
| 665 | case CMD_FIRST:
|
|---|
| 666 | bIterate = 1;
|
|---|
| 667 | first_record(tdb, &iterate_kbuf);
|
|---|
| 668 | return 0;
|
|---|
| 669 | case CMD_NEXT:
|
|---|
| 670 | if (bIterate)
|
|---|
| 671 | next_record(tdb, &iterate_kbuf);
|
|---|
| 672 | return 0;
|
|---|
| 673 | case CMD_CHECK:
|
|---|
| 674 | check_db(tdb);
|
|---|
| 675 | return 0;
|
|---|
| 676 | case CMD_HELP:
|
|---|
| 677 | help();
|
|---|
| 678 | return 0;
|
|---|
| 679 | case CMD_CREATE_TDB:
|
|---|
| 680 | case CMD_OPEN_TDB:
|
|---|
| 681 | case CMD_SYSTEM:
|
|---|
| 682 | case CMD_QUIT:
|
|---|
| 683 | /*
|
|---|
| 684 | * unhandled commands. cases included here to avoid compiler
|
|---|
| 685 | * warnings.
|
|---|
| 686 | */
|
|---|
| 687 | return 0;
|
|---|
| 688 | }
|
|---|
| 689 | }
|
|---|
| 690 |
|
|---|
| 691 | return 0;
|
|---|
| 692 | }
|
|---|
| 693 |
|
|---|
| 694 | static char *convert_string(char *instring, size_t *sizep)
|
|---|
| 695 | {
|
|---|
| 696 | size_t length = 0;
|
|---|
| 697 | char *outp, *inp;
|
|---|
| 698 | char temp[3];
|
|---|
| 699 |
|
|---|
| 700 | outp = inp = instring;
|
|---|
| 701 |
|
|---|
| 702 | while (*inp) {
|
|---|
| 703 | if (*inp == '\\') {
|
|---|
| 704 | inp++;
|
|---|
| 705 | if (*inp && strchr("0123456789abcdefABCDEF",(int)*inp)) {
|
|---|
| 706 | temp[0] = *inp++;
|
|---|
| 707 | temp[1] = '\0';
|
|---|
| 708 | if (*inp && strchr("0123456789abcdefABCDEF",(int)*inp)) {
|
|---|
| 709 | temp[1] = *inp++;
|
|---|
| 710 | temp[2] = '\0';
|
|---|
| 711 | }
|
|---|
| 712 | *outp++ = (char)strtol((const char *)temp,NULL,16);
|
|---|
| 713 | } else {
|
|---|
| 714 | *outp++ = *inp++;
|
|---|
| 715 | }
|
|---|
| 716 | } else {
|
|---|
| 717 | *outp++ = *inp++;
|
|---|
| 718 | }
|
|---|
| 719 | length++;
|
|---|
| 720 | }
|
|---|
| 721 | *sizep = length;
|
|---|
| 722 | return instring;
|
|---|
| 723 | }
|
|---|
| 724 |
|
|---|
| 725 | int main(int argc, char *argv[])
|
|---|
| 726 | {
|
|---|
| 727 | cmdname = "";
|
|---|
| 728 | arg1 = NULL;
|
|---|
| 729 | arg1len = 0;
|
|---|
| 730 | arg2 = NULL;
|
|---|
| 731 | arg2len = 0;
|
|---|
| 732 |
|
|---|
| 733 | if (argv[1]) {
|
|---|
| 734 | cmdname = "open";
|
|---|
| 735 | arg1 = argv[1];
|
|---|
| 736 | do_command();
|
|---|
| 737 | cmdname = "";
|
|---|
| 738 | arg1 = NULL;
|
|---|
| 739 | }
|
|---|
| 740 |
|
|---|
| 741 | switch (argc) {
|
|---|
| 742 | case 1:
|
|---|
| 743 | case 2:
|
|---|
| 744 | /* Interactive mode */
|
|---|
| 745 | while ((cmdname = tdb_getline("tdb> "))) {
|
|---|
| 746 | arg2 = arg1 = NULL;
|
|---|
| 747 | if ((arg1 = strchr((const char *)cmdname,' ')) != NULL) {
|
|---|
| 748 | arg1++;
|
|---|
| 749 | arg2 = arg1;
|
|---|
| 750 | while (*arg2) {
|
|---|
| 751 | if (*arg2 == ' ') {
|
|---|
| 752 | *arg2++ = '\0';
|
|---|
| 753 | break;
|
|---|
| 754 | }
|
|---|
| 755 | if ((*arg2++ == '\\') && (*arg2 == ' ')) {
|
|---|
| 756 | arg2++;
|
|---|
| 757 | }
|
|---|
| 758 | }
|
|---|
| 759 | }
|
|---|
| 760 | if (arg1) arg1 = convert_string(arg1,&arg1len);
|
|---|
| 761 | if (arg2) arg2 = convert_string(arg2,&arg2len);
|
|---|
| 762 | if (do_command()) break;
|
|---|
| 763 | }
|
|---|
| 764 | break;
|
|---|
| 765 | case 5:
|
|---|
| 766 | arg2 = convert_string(argv[4],&arg2len);
|
|---|
| 767 | case 4:
|
|---|
| 768 | arg1 = convert_string(argv[3],&arg1len);
|
|---|
| 769 | case 3:
|
|---|
| 770 | cmdname = argv[2];
|
|---|
| 771 | default:
|
|---|
| 772 | do_command();
|
|---|
| 773 | break;
|
|---|
| 774 | }
|
|---|
| 775 |
|
|---|
| 776 | if (tdb) tdb_close(tdb);
|
|---|
| 777 |
|
|---|
| 778 | return 0;
|
|---|
| 779 | }
|
|---|