⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 test_merkle_tree.c

📁 基于DHT的对等协议
💻 C
字号:
#include <sys/types.h>#include <sys/wait.h>#include <db.h>#include <chord_types.h>#include <qhash.h>#include "merkle.h"#include "merkle_tree_disk.h"#include "merkle_tree_bdb.h"#include <misc_utils.h>#include <id_utils.h>typedef bhash<chordID, hashID> keys_t;static char *indexpath = "./index.mrk";static char *internalpath = "./internal.mrk";static char *leafpath  = "./leaf.mrk";static char *indexpathro = "./index.mrk.ro";static char *internalpathro = "./internal.mrk.ro";static char *leafpathro  = "./leaf.mrk.ro";// Better be careful here!  We call rm -rf on this later.static char *bdbpath = "./mtree.bdb";typedef callback<merkle_tree *, bool>::ref merkle_allocator_t;merkle_tree *allocate_disk (bool master){  // Master should be read-write  return    New merkle_tree_disk (indexpath, internalpath, leafpath, master);}merkle_tree *allocate_bdb (bool master){  return    New merkle_tree_bdb (bdbpath, !master, !master);  // slaves should join and be read-only;  // master should not join and be read-write.}voidcleanup (){  unlink (indexpath);  unlink (internalpath);  unlink (leafpath);  unlink (indexpathro);  unlink (internalpathro);  unlink (leafpathro);  char buf[80];  sprintf (buf, "rm -rf %s", bdbpath);  system (buf);}boolreap (int pid, bool wait = true){  int wpid, status, options = 0;  if (!wait)    options = WNOHANG;  wpid = waitpid (pid, &status, options);  if (wpid < 0) {    perror("waitpid");    exit (1);  }  if (!wait && (wpid == 0))    return false;  if (wpid != pid)    fatal ("unexpected pid reaped: %d\n", wpid);  if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)    fatal << "child exited unhappily\n";  return true;}voidinsert_blocks (merkle_tree *mtree, int upto, bool random,    keys_t *keys = NULL){  for (int i = 1; i <= upto; i++) {    merkle_hash key;    if (random)       key.randomize ();    else      key = i;    if (keys)      keys->insert (static_cast<bigint> (key));    int r = mtree->insert (key);    if (r)      fatal << "Unexpected Merkle tree error: " << r << " (" << strerror (r) << ")\n";  }}voidtest_numkeys (merkle_tree *tree, unsigned int cnt){  merkle_node *root = tree->get_root ();  assert (root->count == cnt);  tree->lookup_release (root);}voidtest_insertions (str msg,    merkle_tree *mtree, uint nkeys, bool rand, keys_t &keys){  uint okeyssz = keys.size ();  warn << msg << " bulk insertion... ";  u_int64_t start = getusec (true);  mtree->set_rehash_on_modification (false);  insert_blocks (mtree, nkeys, rand, &keys);  warn << "completed in: " << (getusec (true)-start)/1000 << "ms... ";  assert ((keys.size () - okeyssz) == nkeys);  warn << "OK\n";  warn << msg << " hash full tree... ";  start = getusec (true);  mtree->hash_tree ();  warn << "completed in: " << (getusec (true)-start)/1000 << "ms... ";  test_numkeys (mtree, keys.size ());  warn << "OK\n";  warn << msg << " check invariants... ";  mtree->check_invariants ();  warn << "OK.\n";  mtree->set_rehash_on_modification (true);}const vec<chordID> &test_reads (merkle_tree *mtree, const keys_t &keys){  static vec<chordID> intree;  intree.clear ();  unsigned int nkeys = keys.size ();  warn << "All key read (get_keyrange)... ";  intree = mtree->get_keyrange (      0, (chordID (1) << 160) - 1, nkeys + 1);  assert (intree.size () == nkeys);  for (uint i = 0; i < intree.size (); i++) {    assert (keys[intree[i]]);  }  warn << "OK\n";  warn << "Randomized key lookups... ";  uint limit = 128 + int(nkeys * 0.2);  if (limit > nkeys)    limit = nkeys;  uint order[nkeys];  for (uint i=0; i<nkeys; i++) order[i] = i;  for (uint i = 0; i < limit; i++) {    uint j = i + random() % (nkeys-i);    uint key = order[j]; order[j] = order[i]; order[i] = key;    assert (mtree->key_exists (intree[key]));    merkle_node *n = mtree->lookup (intree[key]);    assert (n);    assert (n->isleaf ());    mtree->lookup_release (n);  }  warn << "OK\n";  warn << "Missing key lookups... ";  int todo = limit;  while (todo) {    chordID c = make_randomID ();    if (keys[c])      continue;    todo--;    assert (!mtree->key_exists (c));    merkle_node *n = mtree->lookup (c);    assert (n);    mtree->lookup_release (n);  }  warn << "OK\n";  warn << "Random range reads... ";  chordID highest = (((chordID) 1) << 160) - 1;  for (int i = 0; i < 32; i++) {    chordID min = make_randomID ();    chordID max = make_randomID ();    //warn << "  get_keyrange (" << min << ", " << max << ", " << nkeys << ")\n";    vec<chordID> rangekeys = mtree->get_keyrange (min, max, nkeys);    keys_t subset;    for (uint j = 0; j < nkeys; j++)      if (betweenbothincl (min, max, intree[j]))	subset.insert (intree[j]);    assert (subset.size () == rangekeys.size ());    for (uint j = 0; j < rangekeys.size (); j++)      assert (subset[rangekeys[j]]);  }  warn << "OK\n";  return intree;}voidtest (str msg, merkle_tree *mtree, uint nkeys, bool rand = true){  warn << "\n=================== " << msg        << " test_" << (rand ? "rand" : "incr")       << " nkeys " << nkeys << "\n";  keys_t keys;  keys.clear ();  test_insertions ("Initial", mtree, nkeys, rand, keys);  const vec<chordID> intree = test_reads (mtree, keys);  uint limit = (nkeys < 128) ? nkeys : (128 + int (nkeys * 0.2));  warn << "Removing " << limit << " keys... ";  uint order[nkeys];  for (uint i=0; i<nkeys; i++) order[i] = i;  for (uint i = 0; i < limit; i++) {    // warnx << "  " << i+1 << "/" << limit << ".\n";    uint j = i + random() % (nkeys-i);    uint key = order[j]; order[j] = order[i]; order[i] = key;    int r = mtree->remove (intree[key]);    if (r)      fatal << "Unexpected Merkle tree error: " << r << " (" << strerror (r) << ")\n";    keys.remove (intree[key]);    test_numkeys (mtree, nkeys - (i + 1));    assert (keys.size () == (nkeys - (i + 1)));  }  warn << "OK\n";  warn << "Post-remove tree contents check... ";  for (uint i = 0; i < nkeys; i++) {    if (i < limit)      assert (!mtree->key_exists (intree[order[i]]));    else      assert (mtree->key_exists (intree[order[i]]));  }  mtree->check_invariants ();  warn << "OK\n";  if (rand)    test_insertions ("Post-remove", mtree, 2*limit, rand, keys);  test_reads (mtree, keys);}voidtest_merkle_disk_specific (str desc, merkle_allocator_t alloc){  warn << "\n=================== Disk specific tests for " << desc << "\n";  merkle_tree *mtree = alloc (true);  keys_t keys;  keys.clear ();  test_insertions ("Initial", mtree, 256, true, keys);  delete mtree;  warn << "Static child read... \n";  int pid = fork ();  if (pid < 0)    fatal ("fork: %m\n");  if (pid == 0) {    // Child    mtree = alloc (false);    const vec<chordID> intree = test_reads (mtree, keys);    delete mtree;    exit (0);  }  reap (pid);  warn << "Static child read OK\n";  warn << "Dynamic child reads... \n";  vec<chordID> tobeinserted;  for (int i = 0; i < 3200; i++)    tobeinserted.push_back (make_randomID ());  pid = fork ();  if (pid > 0) {    // Parent    bool reaped = false;    mtree = alloc (true);    for (int i = 0; i < 32; i++) {      warn << "  Parent insertion burst " << i+1 << "\n";      for (int j = 0; j < 100; j++) {	mtree->insert (tobeinserted[100*i + j]);	keys.insert (tobeinserted[100*i + j]);      }      if (!reaped)	reaped = reap (pid, false);      mtree->sync ();      sleep (1);    }    delete mtree;    if (!reaped)      reap (pid);  } else {    sleep (1);    chordID highest = (((chordID) 1) << 160) - 1;    mtree = alloc (false);    for (int i = 0; i < 32; i++) {      warn << "  Child read-range " << i+1 << "\n";      chordID min = make_randomID ();      chordID max = min + make_randomID () % (highest - min);      vec<chordID> rangekeys = mtree->get_keyrange (min, max, 10000);      for (uint j = 0; j < rangekeys.size (); j++)	assert (betweenbothincl (min, max, rangekeys[j]));      mtree->check_invariants ();      mtree->sync ();      sleep (1);    }    delete mtree;    exit (0);  }   warn << "Dynamic child reads seem OK\n";}intmain (int argc, char *argv[]){  // Make sure no confusion from previous crashes.  cleanup ();  // Any arguments mean we skip the "normal" tests.  if (argc == 1) {    int sz[] = { 1, 64, 256, 64*64+1, 10000 };    for (uint i = 0; i < sizeof (sz) / sizeof (sz[0]); i++) {      merkle_tree *t =	New merkle_tree_bdb (bdbpath, false, false);      test ("BDB", t, sz[i], false);      delete t; t = NULL;      cleanup ();      t = New merkle_tree_bdb (bdbpath, false, false);      test ("BDB", t, sz[i], true);      delete t; t = NULL;      cleanup ();    }    for (uint i = 0; i < sizeof (sz) / sizeof (sz[0]); i++) {      merkle_tree *t = New merkle_tree_mem ();      test ("In-memory", t, sz[i], false);      delete t; t = NULL;      t = New merkle_tree_mem ();      test ("In-memory", t, sz[i], true);      delete t; t = NULL;    }#if 0    for (uint i = 0; i < sizeof (sz) / sizeof (sz[0]); i++) {      merkle_tree *t = 	New merkle_tree_disk (indexpath, internalpath, leafpath, true);      test ("Disk", t, sz[i]);      delete t; t = NULL;      cleanup ();    }#endif /* 0 */  }  test_merkle_disk_specific ("bdb", wrap (&allocate_bdb));  cleanup ();#if 0  test_merkle_disk_specific ("disk", wrap (&allocate_disk));  cleanup ();#endif /* 0 */}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -