00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <errno.h>
00023 #include <fcntl.h>
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <string.h>
00027 #include <sys/mman.h>
00028 #include <sys/stat.h>
00029 #include <sys/types.h>
00030 #include <unistd.h>
00031
00032 #include <ccn/btree.h>
00033 #include <ccn/btree_content.h>
00034 #include <ccn/ccn.h>
00035 #include <ccn/charbuf.h>
00036 #include <ccn/indexbuf.h>
00037 #include <ccn/hashtb.h>
00038 #include <ccn/uri.h>
00039
00040 #define FAILIF(cond) do {} while ((cond) && fatal(__func__, __LINE__))
00041 #define CHKSYS(res) FAILIF((res) == -1)
00042 #define CHKPTR(p) FAILIF((p) == NULL)
00043
00044 static int
00045 fatal(const char *fn, int lineno)
00046 {
00047 char buf[80] = {0};
00048 snprintf(buf, sizeof(buf)-1, "OOPS - function %s, line %d", fn, lineno);
00049 perror(buf);
00050 exit(1);
00051 return(0);
00052 }
00053
00054
00055
00056
00057
00058
00059 static int
00060 test_directory_creation(void)
00061 {
00062 int res;
00063 struct ccn_charbuf *dirbuf;
00064 char *temp;
00065
00066 dirbuf = ccn_charbuf_create();
00067 CHKPTR(dirbuf);
00068 res = ccn_charbuf_putf(dirbuf, "./%s", "_bt_XXXXXX");
00069 CHKSYS(res);
00070 temp = mkdtemp(ccn_charbuf_as_string(dirbuf));
00071 CHKPTR(temp);
00072 res = ccn_charbuf_putf(dirbuf, "/%s", "_test");
00073 CHKSYS(res);
00074 res = mkdir(ccn_charbuf_as_string(dirbuf), 0777);
00075 CHKSYS(res);
00076 printf("Created directory %s\n", ccn_charbuf_as_string(dirbuf));
00077 setenv("TEST_DIRECTORY", ccn_charbuf_as_string(dirbuf), 1);
00078 ccn_charbuf_destroy(&dirbuf);
00079 return(res);
00080 }
00081
00082
00083
00084
00085
00086
00087 static int
00088 test_btree_io(void)
00089 {
00090 int res;
00091 struct ccn_btree_node nodespace = {0};
00092 struct ccn_btree_node *node = &nodespace;
00093 struct ccn_btree_io *io = NULL;
00094
00095
00096 io = ccn_btree_io_from_directory(getenv("TEST_DIRECTORY"), NULL);
00097 CHKPTR(io);
00098 node->buf = ccn_charbuf_create();
00099 CHKPTR(node->buf);
00100 node->nodeid = 12345;
00101 res = io->btopen(io, node);
00102 CHKSYS(res);
00103 FAILIF(node->iodata == NULL);
00104 ccn_charbuf_putf(node->buf, "smoke");
00105 res = io->btwrite(io, node);
00106 CHKSYS(res);
00107 node->buf->length = 0;
00108 ccn_charbuf_putf(node->buf, "garbage");
00109 res = io->btread(io, node, 500000);
00110 CHKSYS(res);
00111 FAILIF(node->buf->length != 5);
00112 FAILIF(node->buf->limit > 10000);
00113 node->clean = 5;
00114 ccn_charbuf_putf(node->buf, "r");
00115 res = io->btwrite(io, node);
00116 CHKSYS(res);
00117 node->buf->length--;
00118 ccn_charbuf_putf(node->buf, "d");
00119 res = io->btread(io, node, 1000);
00120 CHKSYS(res);
00121 FAILIF(0 != strcmp("smoker", ccn_charbuf_as_string(node->buf)));
00122 node->buf->length--;
00123 res = io->btwrite(io, node);
00124 CHKSYS(res);
00125 node->buf->length = 0;
00126 ccn_charbuf_putf(node->buf, "garbage");
00127 node->clean = 0;
00128 res = io->btread(io, node, 1000);
00129 CHKSYS(res);
00130 res = io->btclose(io, node);
00131 CHKSYS(res);
00132 FAILIF(node->iodata != NULL);
00133 FAILIF(0 != strcmp("smoke", ccn_charbuf_as_string(node->buf)));
00134 res = io->btdestroy(&io);
00135 CHKSYS(res);
00136 ccn_charbuf_destroy(&node->buf);
00137 return(res);
00138 }
00139
00140
00141
00142
00143
00144
00145 static void
00146 check_structure_size(const char *what, int sz)
00147 {
00148 printf("%s size is %d bytes\n", what, sz);
00149 errno=EINVAL;
00150 FAILIF(sz % CCN_BT_SIZE_UNITS != 0);
00151 }
00152
00153
00154
00155
00156
00157
00158
00159 int
00160 test_structure_sizes(void)
00161 {
00162 check_structure_size("ccn_btree_entry_trailer",
00163 sizeof(struct ccn_btree_entry_trailer));
00164 check_structure_size("ccn_btree_internal_entry",
00165 sizeof(struct ccn_btree_internal_entry));
00166 check_structure_size("ccn_btree_content_entry",
00167 sizeof(struct ccn_btree_content_entry));
00168 return(0);
00169 }
00170
00171
00172
00173
00174 int
00175 test_btree_lockfile(void)
00176 {
00177 int res;
00178 struct ccn_btree_io *io = NULL;
00179 struct ccn_btree_io *io2 = NULL;
00180
00181 io = ccn_btree_io_from_directory(getenv("TEST_DIRECTORY"), NULL);
00182 CHKPTR(io);
00183
00184 errno = 0;
00185 io2 = ccn_btree_io_from_directory(getenv("TEST_DIRECTORY"), NULL);
00186 FAILIF(io2 != NULL || errno == 0);
00187 errno=EINVAL;
00188 res = io->btdestroy(&io);
00189 CHKSYS(res);
00190 FAILIF(io != NULL);
00191 return(res);
00192 }
00193
00194 struct entry_example {
00195 unsigned char p[CCN_BT_SIZE_UNITS];
00196 struct ccn_btree_entry_trailer t;
00197 };
00198
00199 struct node_example {
00200 struct ccn_btree_node_header hdr;
00201 unsigned char ss[64];
00202 struct entry_example e[3];
00203 } ex1 = {
00204 {{0x05, 0x3a, 0xde, 0x78}, {1}},
00205 "goodstuff<------ WASTE---------->d<----><-------------- free -->",
00206
00207 {
00208 {.t={.koff0={0,0,0,33+8}, .ksiz0={0,1}, .entdx={0,0}, .entsz={3}}},
00209 {.t={.koff0={0,0,0,0+8}, .ksiz0={0,9}, .entdx={0,1}, .entsz={3}}},
00210 {.t={.koff0={0,0,0,2+8}, .ksiz0={0,2}, .entdx={0,2}, .entsz={3},
00211 .koff1={0,0,0,3+8}, .ksiz1={0,1}}},
00212 }
00213 };
00214
00215 struct node_example ex2 = {
00216 {{0x05, 0x3a, 0xde, 0x78}, {1}},
00217 "struthiomimus",
00218 {
00219 {.t={.koff1={0,0,0,2+8}, .ksiz1={0,3}, .entdx={0,0}, .entsz={3}}},
00220 {.t={.koff0={0,0,0,0+8}, .ksiz0={0,5}, .entdx={0,1}, .entsz={3}}},
00221 {.t={.koff0={0,0,0,1+8}, .ksiz0={0,5}, .entdx={0,2}, .entsz={3}}},
00222 }
00223 };
00224
00225 struct root_example {
00226 struct ccn_btree_node_header hdr;
00227 unsigned char ss[CCN_BT_SIZE_UNITS];
00228 struct ccn_btree_internal_entry e[2];
00229 } rootex1 = {
00230 {{0x05, 0x3a, 0xde, 0x78}, {1}, {'R'}, {1}},
00231 "ru",
00232 {
00233 { {.magic={0xcc}, .child={0,0,0,2}},
00234 {.entdx={0,0}, .level={1}, .entsz={3}}},
00235 { {.magic={0xcc}, .child={0,0,0,3}},
00236 {.koff1={0,0,0,0+8}, .ksiz1={0,2},
00237 .entdx={0,1}, .level={1}, .entsz={3}}},
00238 }
00239 };
00240
00241 int
00242 test_btree_chknode(void)
00243 {
00244 int res;
00245 struct ccn_btree_node *node = NULL;
00246 struct node_example *ex = NULL;
00247
00248 node = calloc(1, sizeof(*node));
00249 CHKPTR(node);
00250 node->buf = ccn_charbuf_create();
00251 CHKPTR(node->buf);
00252 ccn_charbuf_append(node->buf, &ex1, sizeof(ex1));
00253 res = ccn_btree_chknode(node);
00254 CHKSYS(res);
00255 FAILIF(node->corrupt != 0);
00256 FAILIF(node->freelow != 8 + 34);
00257 ex = (void *)node->buf->buf;
00258 ex->e[1].t.ksiz0[1] = 100;
00259 res = ccn_btree_chknode(node);
00260 FAILIF(res != -1);
00261 FAILIF(node->corrupt == 0);
00262 ccn_charbuf_destroy(&node->buf);
00263 free(node);
00264 return(0);
00265 }
00266
00267 int
00268 test_btree_key_fetch(void)
00269 {
00270 int i;
00271 int res;
00272 struct ccn_charbuf *cb = NULL;
00273 struct ccn_btree_node *node = NULL;
00274 struct node_example ex = ex1;
00275
00276 const char *expect[3] = { "d", "goodstuff", "odd" };
00277
00278 node = calloc(1, sizeof(*node));
00279 CHKPTR(node);
00280 node->buf = ccn_charbuf_create();
00281 CHKPTR(node->buf);
00282 ccn_charbuf_append(node->buf, &ex, sizeof(ex));
00283
00284 cb = ccn_charbuf_create();
00285
00286 for (i = 0; i < 3; i++) {
00287 res = ccn_btree_key_fetch(cb, node, i);
00288 CHKSYS(res);
00289 FAILIF(cb->length != strlen(expect[i]));
00290 FAILIF(0 != memcmp(cb->buf, expect[i], cb->length));
00291 }
00292
00293 res = ccn_btree_key_fetch(cb, node, i);
00294 FAILIF(res != -1);
00295 res = ccn_btree_key_fetch(cb, node, -1);
00296 FAILIF(res != -1);
00297 FAILIF(node->corrupt);
00298
00299 ex.e[1].t.koff0[2] = 1;
00300 node->buf->length = 0;
00301 ccn_charbuf_append(node->buf, &ex, sizeof(ex));
00302
00303 res = ccn_btree_key_append(cb, node, 0);
00304 CHKSYS(res);
00305
00306 res = ccn_btree_key_append(cb, node, 1);
00307 FAILIF(res != -1);
00308 FAILIF(!node->corrupt);
00309 printf("line %d code = %d\n", __LINE__, node->corrupt);
00310
00311 ccn_charbuf_destroy(&cb);
00312 ccn_charbuf_destroy(&node->buf);
00313 free(node);
00314 return(0);
00315 }
00316
00317 int
00318 test_btree_compare(void)
00319 {
00320 int i, j;
00321 int res;
00322 struct ccn_btree_node *node = NULL;
00323 struct node_example ex = ex1;
00324
00325 const char *expect[3] = { "d", "goodstuff", "odd" };
00326
00327 node = calloc(1, sizeof(*node));
00328 CHKPTR(node);
00329 node->buf = ccn_charbuf_create();
00330 CHKPTR(node->buf);
00331 ccn_charbuf_append(node->buf, &ex, sizeof(ex));
00332
00333 for (i = 0; i < 3; i++) {
00334 for (j = 0; j < 3; j++) {
00335 res = ccn_btree_compare((const void *)expect[i], strlen(expect[i]),
00336 node, j);
00337 FAILIF( (i < j) != (res < 0));
00338 FAILIF( (i > j) != (res > 0));
00339 FAILIF( (i == j) != (res == 0));
00340 }
00341 }
00342 ccn_charbuf_destroy(&node->buf);
00343 free(node);
00344 return(0);
00345 }
00346
00347 int
00348 test_btree_searchnode(void)
00349 {
00350 int i;
00351 int res;
00352 struct ccn_btree_node *node = NULL;
00353 struct node_example ex = ex1;
00354 const int yes = 1;
00355 const int no = 0;
00356
00357 struct {
00358 const char *s;
00359 int expect;
00360 } testvec[] = {
00361 {"", CCN_BT_ENCRES(0, no)},
00362 {"c", CCN_BT_ENCRES(0, no)},
00363 {"d", CCN_BT_ENCRES(0, yes)},
00364 {"d1", CCN_BT_ENCRES(1, no)},
00365 {"goodstuff", CCN_BT_ENCRES(1, yes)},
00366 {"goodstuff1", CCN_BT_ENCRES(2, no)},
00367 {"odc++++++", CCN_BT_ENCRES(2, no)},
00368 {"odd", CCN_BT_ENCRES(2, yes)},
00369 {"odd1", CCN_BT_ENCRES(3, no)},
00370 {"ode", CCN_BT_ENCRES(3, no)}
00371 };
00372
00373 node = calloc(1, sizeof(*node));
00374 CHKPTR(node);
00375 node->buf = ccn_charbuf_create();
00376 CHKPTR(node->buf);
00377 ccn_charbuf_append(node->buf, &ex, sizeof(ex));
00378
00379 res = ccn_btree_node_nent(node);
00380 FAILIF(res != 3);
00381
00382 for (i = 0; i < sizeof(testvec)/sizeof(testvec[0]); i++) {
00383 const char *s = testvec[i].s;
00384 res = ccn_btree_searchnode((const void *)s, strlen(s), node);
00385 printf("search %s => %d, expected %d\n", s, res, testvec[i].expect);
00386 FAILIF(res != testvec[i].expect);
00387 }
00388 ccn_charbuf_destroy(&node->buf);
00389 free(node);
00390 return(0);
00391 }
00392
00393 int
00394 test_btree_init(void)
00395 {
00396 struct ccn_btree *btree = NULL;
00397 int res;
00398 struct ccn_btree_node *node = NULL;
00399 struct ccn_btree_node *node0 = NULL;
00400 struct ccn_btree_node *node1 = NULL;
00401
00402 btree = ccn_btree_create();
00403 CHKPTR(btree);
00404 node0 = ccn_btree_getnode(btree, 0, 0);
00405 CHKPTR(node0);
00406 node1 = ccn_btree_getnode(btree, 1, 0);
00407 FAILIF(node0 == node1);
00408 FAILIF(hashtb_n(btree->resident) != 2);
00409 node = ccn_btree_rnode(btree, 0);
00410 FAILIF(node != node0);
00411 node = ccn_btree_rnode(btree, 1);
00412 FAILIF(node != node1);
00413 node = ccn_btree_rnode(btree, 2);
00414 FAILIF(node != NULL);
00415 res = ccn_btree_destroy(&btree);
00416 FAILIF(btree != NULL);
00417 return(res);
00418 }
00419
00420 struct ccn_btree *
00421 example_btree_small(void)
00422 {
00423 struct ccn_btree *btree = NULL;
00424 struct ccn_btree_node *root = NULL;
00425 struct ccn_btree_node *leaf = NULL;
00426 int res = 0;
00427
00428 btree = ccn_btree_create();
00429 CHKPTR(btree);
00430 leaf = ccn_btree_getnode(btree, 2, 0);
00431 CHKPTR(leaf);
00432 ccn_charbuf_append(leaf->buf, &ex1, sizeof(ex1));
00433 res = ccn_btree_chknode(leaf);
00434 CHKSYS(res);
00435 leaf = ccn_btree_getnode(btree, 3, 0);
00436 CHKPTR(leaf);
00437 ccn_charbuf_append(leaf->buf, &ex2, sizeof(ex2));
00438 res = ccn_btree_chknode(leaf);
00439 CHKSYS(res);
00440 root = ccn_btree_getnode(btree, 1, 0);
00441 CHKPTR(root);
00442 ccn_charbuf_append(root->buf, &rootex1, sizeof(rootex1));
00443 res = ccn_btree_chknode(root);
00444 CHKSYS(res);
00445 btree->nextnodeid = 4;
00446 return(btree);
00447 }
00448
00449 int
00450 test_btree_lookup(void)
00451 {
00452 const int yes = 1;
00453 const int no = 0;
00454 struct ccn_btree *btree = NULL;
00455 struct ccn_btree_node *leaf = NULL;
00456 int i;
00457 int res;
00458 struct {
00459 const char *s;
00460 int expectnode;
00461 int expectres;
00462 } testvec[] = {
00463 {"d", 2, CCN_BT_ENCRES(0, yes)},
00464 {"goodstuff", 2, CCN_BT_ENCRES(1, yes)},
00465 {"odd", 2, CCN_BT_ENCRES(2, yes)},
00466 {"truth", 3, CCN_BT_ENCRES(2, yes)},
00467 {"tooth", 3, CCN_BT_ENCRES(2, no)},
00468 };
00469
00470 btree = example_btree_small();
00471 CHKPTR(btree);
00472
00473 for (i = 0; i < sizeof(testvec)/sizeof(testvec[0]); i++) {
00474 const char *s = testvec[i].s;
00475 res = ccn_btree_lookup(btree, (const void *)s, strlen(s), &leaf);
00476 printf("lookup %s => %d, %d, expected %d, %d\n", s,
00477 leaf->nodeid, res,
00478 testvec[i].expectnode, testvec[i].expectres);
00479 FAILIF(res != testvec[i].expectres);
00480 FAILIF(leaf->nodeid != testvec[i].expectnode);
00481 FAILIF(leaf->parent != 1);
00482 res = ccn_btree_node_level(leaf);
00483 FAILIF(res != 0);
00484 }
00485 res = ccn_btree_check(btree, stderr);
00486 res = ccn_btree_destroy(&btree);
00487 FAILIF(btree != NULL);
00488 return(res);
00489 }
00490
00491 int
00492 test_basic_btree_insert_entry(void)
00493 {
00494 struct ccn_btree *btree = NULL;
00495 struct ccn_btree_node *leaf = NULL;
00496 int res;
00497 int ndx;
00498 const char *s = "";
00499 unsigned char payload[6] = "@12345";
00500 unsigned char *c = NULL;
00501 unsigned char canary = 42;
00502 unsigned cage = 10000;
00503 unsigned perch = 1000;
00504
00505 btree = example_btree_small();
00506 CHKPTR(btree);
00507 s = "beauty";
00508 res = ccn_btree_lookup(btree, (const void *)s, strlen(s), &leaf);
00509 CHKSYS(res);
00510 FAILIF(CCN_BT_SRCH_FOUND(res));
00511 ndx = CCN_BT_SRCH_INDEX(res);
00512 FAILIF(ndx != 0);
00513 memset(ccn_charbuf_reserve(leaf->buf, cage), canary, cage);
00514 res = ccn_btree_chknode(leaf);
00515 CHKSYS(res);
00516 res = ccn_btree_insert_entry(leaf, ndx,
00517 (const void *)s, strlen(s),
00518 payload, sizeof(payload));
00519 CHKSYS(res);
00520 res = ccn_btree_chknode(leaf);
00521 CHKSYS(res);
00522 c = &leaf->buf->buf[leaf->buf->length];
00523 FAILIF(c[0] != canary);
00524 FAILIF(0 != memcmp(c, c + 1, perch - 1));
00525 res = ccn_btree_lookup(btree, (const void *)s, strlen(s), &leaf);
00526 FAILIF(res != 1);
00527 res = ccn_btree_lookup(btree, (const void *)"d", 1, &leaf);
00528 FAILIF(res != 3);
00529 s = "age";
00530 payload[0] = 'A';
00531 res = ccn_btree_lookup(btree, (const void *)s, strlen(s), &leaf);
00532 FAILIF(res != 0);
00533 res = ccn_btree_insert_entry(leaf, ndx,
00534 (const void *)s, strlen(s),
00535 payload, sizeof(payload));
00536 CHKSYS(res);
00537 res = ccn_btree_lookup(btree, (const void *)s, strlen(s), &leaf);
00538 FAILIF(res != 1);
00539 res = ccn_btree_lookup(btree, (const void *)"d", 1, &leaf);
00540 FAILIF(res != 5);
00541 c = &leaf->buf->buf[leaf->buf->length];
00542 FAILIF(c[0] != canary);
00543 FAILIF(0 != memcmp(c, c + 1, perch - 1));
00544
00545 btree->nextnodeid = 101;
00546 res = ccn_btree_split(btree, leaf);
00547 CHKSYS(res);
00548 FAILIF(btree->errors != 0);
00549 res = ccn_btree_destroy(&btree);
00550 FAILIF(btree != NULL);
00551 return(res);
00552 }
00553
00554 int
00555 test_basic_btree_delete_entry(void)
00556 {
00557 struct ccn_btree *btree = NULL;
00558 struct ccn_btree_node *leaf = NULL;
00559 int res;
00560 int i;
00561 int j;
00562 int ndx;
00563 const char *s = "";
00564 const char *ex[4] = {"d", "goodstuff", "odd", "odder"};
00565
00566 for (i = 0; i < 4; i++) {
00567 btree = example_btree_small();
00568 CHKPTR(btree);
00569 s = ex[i];
00570 res = ccn_btree_lookup(btree, (const void *)s, strlen(s), &leaf);
00571 CHKSYS(res);
00572 FAILIF(CCN_BT_SRCH_FOUND(res) != (i < 3));
00573 ndx = CCN_BT_SRCH_INDEX(res);
00574 FAILIF(ndx != i);
00575 res = ccn_btree_chknode(leaf);
00576 CHKSYS(res);
00577 res = ccn_btree_delete_entry(leaf, i);
00578 FAILIF((res < 0) != (i == 3));
00579 for (j = 0; j < 3; j++) {
00580 s = ex[j];
00581 res = ccn_btree_lookup(btree, (const void *)s, strlen(s), &leaf);
00582 CHKSYS(res);
00583 FAILIF(CCN_BT_SRCH_FOUND(res) == (i == j));
00584 }
00585 FAILIF(btree->errors != 0);
00586 res = ccn_btree_destroy(&btree);
00587 FAILIF(btree != NULL);
00588 }
00589 return(res);
00590 }
00591
00592 int
00593 test_btree_inserts_from_stdin(void)
00594 {
00595 struct ccn_charbuf *c;
00596 char payload[8] = "TestTree";
00597 int res;
00598 int delete;
00599 int item = 0;
00600 int dups = 0;
00601 int unique = 0;
00602 int deleted = 0;
00603 int missing = 0;
00604 struct ccn_btree *btree = NULL;
00605 struct ccn_btree_node *node = NULL;
00606 struct ccn_btree_node *leaf = NULL;
00607
00608
00609 btree = ccn_btree_create();
00610 CHKPTR(btree);
00611 FAILIF(btree->nextnodeid != 1);
00612 node = ccn_btree_getnode(btree, btree->nextnodeid++, 0);
00613 CHKPTR(node);
00614 res = ccn_btree_init_node(node, 0, 'R', 0);
00615 CHKPTR(node);
00616 FAILIF(btree->nextnodeid < 2);
00617 res = ccn_btree_chknode(node);
00618 CHKSYS(res);
00619 btree->full = 5;
00620 btree->full0 = 7;
00621
00622 c = ccn_charbuf_create();
00623 CHKPTR(c);
00624 CHKPTR(ccn_charbuf_reserve(c, 8800));
00625 while (fgets((char *)c->buf, c->limit, stdin)) {
00626 item++;
00627 c->length = strlen((char *)c->buf);
00628 if (c->length > 0 && c->buf[c->length - 1] == '\n')
00629 c->length--;
00630
00631 delete = 0;
00632 if (c->length > 0 && c->buf[c->length - 1] == '!') {
00633 delete = 1;
00634 c->length--;
00635 }
00636 res = ccn_btree_lookup(btree, c->buf, c->length, &leaf);
00637 CHKSYS(res);
00638 if (delete) {
00639 if (CCN_BT_SRCH_FOUND(res)) {
00640 res = ccn_btree_delete_entry(leaf, CCN_BT_SRCH_INDEX(res));
00641 CHKSYS(res);
00642 if (res < btree->full0 / 2) {
00643 int limit = 20;
00644 res = ccn_btree_spill(btree, leaf);
00645 CHKSYS(res);
00646 while (btree->nextspill != 0) {
00647 node = ccn_btree_rnode(btree, btree->nextspill);
00648 CHKPTR(node);
00649 res = ccn_btree_spill(btree, node);
00650 CHKSYS(res);
00651 FAILIF(!--limit);
00652 }
00653 while (btree->nextsplit != 0) {
00654 node = ccn_btree_rnode(btree, btree->nextsplit);
00655 CHKPTR(node);
00656 res = ccn_btree_split(btree, node);
00657 CHKSYS(res);
00658 FAILIF(!--limit);
00659 }
00660 }
00661 deleted++;
00662 }
00663 else
00664 missing++;
00665 continue;
00666 }
00667
00668 if (CCN_BT_SRCH_FOUND(res)) {
00669 dups++;
00670 }
00671 else {
00672 unique++;
00673 res = ccn_btree_insert_entry(leaf, CCN_BT_SRCH_INDEX(res),
00674 c->buf, c->length,
00675 payload, sizeof(payload));
00676 CHKSYS(res);
00677 if (res > btree->full0) {
00678 int limit = 20;
00679 res = ccn_btree_split(btree, leaf);
00680 CHKSYS(res);
00681 while (btree->nextsplit != 0) {
00682 node = ccn_btree_rnode(btree, btree->nextsplit);
00683 CHKPTR(node);
00684 res = ccn_btree_split(btree, node);
00685 CHKSYS(res);
00686 FAILIF(!--limit);
00687 }
00688 FAILIF(btree->missedsplit);
00689 }
00690 }
00691 }
00692 res = ccn_btree_check(btree, stderr);
00693 CHKSYS(res);
00694 printf("%d unique, %d duplicate, %d deleted, %d missing, %d errors\n",
00695 unique, dups, deleted, missing, btree->errors);
00696 FAILIF(btree->errors != 0);
00697 res = ccn_btree_lookup(btree, c->buf, 0, &leaf);
00698 CHKSYS(res);
00699 printf("Leaf nodes:");
00700 while (leaf != NULL) {
00701 printf(" %u", leaf->nodeid);
00702 node = leaf;
00703 res = ccn_btree_next_leaf(btree, leaf, &leaf);
00704 CHKSYS(res);
00705 }
00706 printf("\n");
00707 printf("Reversed leaf nodes:");
00708 for (leaf = node; leaf != NULL;) {
00709 printf(" %u", leaf->nodeid);
00710 res = ccn_btree_prev_leaf(btree, leaf, &leaf);
00711 CHKSYS(res);
00712 }
00713 printf("\n");
00714 res = ccn_btree_destroy(&btree);
00715 FAILIF(btree != NULL);
00716 return(res);
00717 }
00718
00719 int
00720 test_flatname(void)
00721 {
00722 unsigned char L0[1] = { 0x00 };
00723 unsigned char A[2] = { 0x01, 'A' };
00724 unsigned char C1[128] = { 0x7F, 0xC1, '.', 'x', '~'};
00725 unsigned char XL[130] = { 0x81, 0x00, 0x39, ' ', 'e', 't', 'c' };
00726 struct {unsigned char *x; size_t l;} ex[] = {
00727 {L0, 0},
00728 {L0, sizeof(L0)},
00729 {A, sizeof(A)},
00730 {C1, sizeof(C1)},
00731 {XL, sizeof(XL)},
00732 {0,0}
00733 };
00734 struct ccn_charbuf *flat;
00735 struct ccn_charbuf *flatout;
00736 struct ccn_charbuf *ccnb;
00737 struct ccn_charbuf *uri;
00738 int i;
00739 int res;
00740 const char *expect = NULL;
00741
00742 flat = ccn_charbuf_create();
00743 flatout = ccn_charbuf_create();
00744 ccnb = ccn_charbuf_create();
00745 uri = ccn_charbuf_create();
00746
00747 res = ccn_flatname_ncomps(flat->buf, flat->length);
00748 FAILIF(res != 0);
00749 for (i = 0; ex[i].x != NULL; i++) {
00750 res = ccn_name_init(ccnb);
00751 FAILIF(res < 0);
00752 flat->length = 0;
00753 ccn_charbuf_append(flat, ex[i].x, ex[i].l);
00754 res = ccn_flatname_ncomps(flat->buf, flat->length);
00755 FAILIF(res != (i > 0));
00756 res = ccn_name_append_flatname(ccnb, flat->buf, flat->length, 0, -1);
00757 FAILIF(res < 0);
00758 res = ccn_flatname_from_ccnb(flatout, ccnb->buf, ccnb->length);
00759 FAILIF(res < 0);
00760 FAILIF(flatout->length != flat->length);
00761 FAILIF(0 != memcmp(flatout->buf, flat->buf,flat->length));
00762 uri->length = 0;
00763 res = ccn_uri_append(uri, ccnb->buf, ccnb->length, 1);
00764 printf("flatname %d: %s\n", i, ccn_charbuf_as_string(uri));
00765 }
00766 ccnb->length = 0;
00767 res = ccn_name_from_uri(ccnb, "ccnx:/10/9/8/7/6/5/4/3/2/1/...");
00768 FAILIF(res < 0);
00769 flat->length = 0;
00770 for (i = 12; i >= 0; i--) {
00771 res = ccn_flatname_append_from_ccnb(flat, ccnb->buf, ccnb->length, i, 1);
00772 FAILIF(res != (i < 11));
00773 }
00774 res = ccn_flatname_append_from_ccnb(flat, ccnb->buf, ccnb->length, 1, 30);
00775 FAILIF(res != 10);
00776 uri->length = 0;
00777 res = ccn_uri_append_flatname(uri, flat->buf, flat->length, 0);
00778 printf("palindrome: %s\n", ccn_charbuf_as_string(uri));
00779 FAILIF(res < 0);
00780 expect = "/.../1/2/3/4/5/6/7/8/9/10/9/8/7/6/5/4/3/2/1/...";
00781 FAILIF(0 != strcmp(ccn_charbuf_as_string(uri), expect));
00782 res = ccn_flatname_ncomps(flat->buf, flat->length);
00783 FAILIF(res != 21);
00784 res = ccn_flatname_ncomps(flat->buf, flat->length - 2);
00785 FAILIF(res != -1);
00786 ccn_charbuf_reserve(flat, 1)[0] = 0x80;
00787 res = ccn_flatname_ncomps(flat->buf, flat->length + 1);
00788 FAILIF(res != -1);
00789 ccn_charbuf_reserve(flat, 1)[0] = 1;
00790 res = ccn_flatname_ncomps(flat->buf, flat->length + 1);
00791 FAILIF(res != -1);
00792 ccn_charbuf_destroy(&flat);
00793 ccn_charbuf_destroy(&flatout);
00794 ccn_charbuf_destroy(&ccnb);
00795 ccn_charbuf_destroy(&uri);
00796 return(0);
00797 }
00798
00799
00800
00801
00802
00803
00804 static int
00805 testhelp_count_matches(struct ccn_btree *btree,
00806 unsigned char *msg, size_t size)
00807 {
00808 struct ccn_btree_node *leaf = NULL;
00809 struct ccn_charbuf *flat = NULL;
00810 struct ccn_charbuf *scratch = NULL;
00811 struct ccn_parsed_interest parsed_interest = {0};
00812 struct ccn_parsed_interest *pi = &parsed_interest;
00813 int cmp;
00814 int i;
00815 int matches;
00816 int n;
00817 int res;
00818
00819 flat = ccn_charbuf_create();
00820 CHKPTR(flat);
00821 res = ccn_flatname_from_ccnb(flat, msg, size);
00822 if (res < 0)
00823 goto Bail;
00824 res = ccn_parse_interest(msg, size, pi, NULL);
00825 if (res < 0) {
00826 if (flat->length > 0)
00827 pi = NULL;
00828 else
00829 goto Bail;
00830 }
00831 res = ccn_btree_lookup(btree, flat->buf, flat->length, &leaf);
00832 CHKSYS(res);
00833 matches = 0;
00834
00835 scratch = ccn_charbuf_create();
00836 n = ccn_btree_node_nent(leaf);
00837 for (i = CCN_BT_SRCH_INDEX(res); i < n; i++) {
00838 cmp = ccn_btree_compare(flat->buf, flat->length, leaf, i);
00839 if (cmp == 0 || cmp == -9999) {
00840
00841 if (pi == NULL)
00842 res = 0;
00843 else
00844 res = ccn_btree_match_interest(leaf, i, msg, pi, scratch);
00845 CHKSYS(res);
00846 if (res == 1) {
00847
00848 matches++;
00849 }
00850 }
00851 else if (cmp > 0) {
00852
00853 FAILIF(1);
00854 }
00855 else {
00856
00857 break;
00858 }
00859 }
00860 res = matches;
00861 Bail:
00862 ccn_charbuf_destroy(&flat);
00863 return(res);
00864 }
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874 int
00875 test_insert_content(void)
00876 {
00877 const char *filename = NULL;
00878 unsigned char *cb = NULL;
00879 unsigned char *cob = NULL;
00880 struct stat statbuf;
00881 int dres;
00882 int fd;
00883 int i;
00884 int res;
00885 size_t cob_offset;
00886 size_t cob_size;
00887 size_t size;
00888 struct ccn_skeleton_decoder decoder = {0};
00889 struct ccn_skeleton_decoder *d = &decoder;
00890 struct ccn_parsed_ContentObject pcobject = {0};
00891 struct ccn_parsed_ContentObject *pc = &pcobject;
00892 struct ccn_charbuf *flatname = NULL;
00893 struct ccn_charbuf *temp = NULL;
00894 struct ccn_indexbuf *comps = NULL;
00895 struct ccn_btree *btree = NULL;
00896 struct ccn_btree_node *node = NULL;
00897 struct ccn_btree_node *leaf = NULL;
00898
00899 filename = getenv("TEST_CONTENT");
00900 if (filename == NULL || filename[0] == 0)
00901 return(1);
00902 printf("Opening %s\n", filename);
00903 fd = open(filename, O_RDONLY, 0);
00904 CHKSYS(fd);
00905 res = fstat(fd, &statbuf);
00906 CHKSYS(res);
00907 size = statbuf.st_size;
00908 printf("Mapping %zd bytes from file %s\n", size, filename);
00909 cb = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
00910 FAILIF(cb == MAP_FAILED && size != 0);
00911
00912
00913 btree = ccn_btree_create();
00914 CHKPTR(btree);
00915 FAILIF(btree->nextnodeid != 1);
00916 node = ccn_btree_getnode(btree, btree->nextnodeid++, 0);
00917 CHKPTR(node);
00918 res = ccn_btree_init_node(node, 0, 'R', 0);
00919 CHKPTR(node);
00920 FAILIF(btree->nextnodeid < 2);
00921 res = ccn_btree_chknode(node);
00922 CHKSYS(res);
00923 btree->full = 50;
00924
00925 flatname = ccn_charbuf_create();
00926 CHKPTR(flatname);
00927 temp = ccn_charbuf_create();
00928 CHKPTR(temp);
00929 comps = ccn_indexbuf_create();
00930 CHKPTR(comps);
00931 while (d->index < size) {
00932 dres = ccn_skeleton_decode(d, cb + d->index, size - d->index);
00933 if (!CCN_FINAL_DSTATE(d->state))
00934 break;
00935 cob_offset = d->index - dres;
00936 cob = cb + cob_offset;
00937 cob_size = dres;
00938 printf("offset %zd, size %zd\n", cob_offset, cob_size);
00939 res = ccn_parse_ContentObject(cob, cob_size, pc, comps);
00940 if (res < 0) {
00941 res = testhelp_count_matches(btree, cob, cob_size);
00942 if (res < 0) {
00943 printf(" . . . skipping non-ContentObject\n");
00944 }
00945 else {
00946 printf(" . . . interest processing res = %d\n", res);
00947 }
00948 }
00949 else {
00950 res = ccn_flatname_from_ccnb(flatname, cob, cob_size);
00951 FAILIF(res != comps->n - 1);
00952 ccn_digest_ContentObject(cob, pc);
00953 FAILIF(pc->digest_bytes != 32);
00954 res = ccn_flatname_append_component(flatname,
00955 pc->digest, pc->digest_bytes);
00956 CHKSYS(res);
00957 temp->length = 0;
00958 ccn_uri_append_flatname(temp, flatname->buf, flatname->length, 1);
00959 res = ccn_btree_lookup(btree, flatname->buf, flatname->length, &leaf);
00960 CHKSYS(res);
00961 if (CCN_BT_SRCH_FOUND(res)) {
00962 printf("FOUND %s\n", ccn_charbuf_as_string(temp));
00963 }
00964 else {
00965 i = CCN_BT_SRCH_INDEX(res);
00966 res = ccn_btree_insert_content(leaf, i,
00967 cob_offset + 1,
00968 cob,
00969 pc,
00970 flatname);
00971 CHKSYS(res);
00972 printf("INSERTED %s\n", ccn_charbuf_as_string(temp));
00973
00974 }
00975 }
00976 }
00977 FAILIF(d->index != size);
00978 FAILIF(!CCN_FINAL_DSTATE(d->state));
00979 if (cb != MAP_FAILED) {
00980 res = munmap(cb, size);
00981 CHKSYS(res);
00982 cb = NULL;
00983 size = 0;
00984 }
00985 res = close(fd);
00986 CHKSYS(res);
00987 ccn_charbuf_destroy(&flatname);
00988 ccn_charbuf_destroy(&temp);
00989 ccn_indexbuf_destroy(&comps);
00990 return(0);
00991 }
00992
00993 int
00994 ccnbtreetest_main(int argc, char **argv)
00995 {
00996 int res;
00997
00998 if (argv[1] && 0 == strcmp(argv[1], "-")) {
00999 res = test_btree_inserts_from_stdin();
01000 CHKSYS(res);
01001 exit(0);
01002 }
01003 res = test_directory_creation();
01004 CHKSYS(res);
01005 res = test_btree_io();
01006 CHKSYS(res);
01007 res = test_btree_lockfile();
01008 CHKSYS(res);
01009 res = test_structure_sizes();
01010 CHKSYS(res);
01011 res = test_btree_chknode();
01012 CHKSYS(res);
01013 res = test_btree_key_fetch();
01014 CHKSYS(res);
01015 res = test_btree_compare();
01016 CHKSYS(res);
01017 res = test_btree_searchnode();
01018 CHKSYS(res);
01019 res = test_btree_init();
01020 CHKSYS(res);
01021 res = test_btree_lookup();
01022 CHKSYS(res);
01023 res = test_basic_btree_insert_entry();
01024 CHKSYS(res);
01025 test_basic_btree_delete_entry();
01026 CHKSYS(res);
01027 res = test_flatname();
01028 CHKSYS(res);
01029 res = test_insert_content();
01030 CHKSYS(res);
01031 if (res != 0)
01032 fprintf(stderr, "test_insert_content() => %d\n", res);
01033 return(0);
01034 }