maint_policy.t
来自「基于DHT的对等协议」· T 代码 · 共 824 行 · 第 1/2 页
T
824 行
void carbonite::init_ltree (cbv cb, adb_status err, str path, bool hasaux){ if (err) { warn << "carbonite::init_ltree: Unexpected adbd error: " << err << "\n"; return; } ltree = New refcounted<merkle_tree_bdb> (path.cstr (), /* join = */ true, /* ro = */ true); cb ();}carbonite::~carbonite (){}void carbonite::handle_missing (ptr<locationcc> from, ptr<merkle_tree> t, chordID key, bool missing_local){ // Make the local tree look identical to the remote tree. // For now, also keep the adbd register up to date. ptr<location> rfrom = New refcounted<location> (from->chordnode ()); if (db->hasaux ()) { chordID aux = (key & 0xFFFFFFFF); chordID dbkey = (key >> 32) << 32; if (missing_local) { t->insert (dbkey, aux.getui ()); } else { t->remove (dbkey, aux.getui ()); } } else { if (missing_local) { t->insert (key); } else { t->remove (key); } }}TAMED voidcarbonite::process_neighbors ( const vec<ptr<locationcc> > &preds, const vec<ptr<locationcc> > &osuccs, cbv cb){ VARS { chordID rngmin, rngmax; } rngmin = preds[0]->id (); rngmax = host.x; if (db->hasaux ()) { rngmin = ((rngmin >> 32) << 32) | 0xFFFFFFFF; rngmax = ((rngmax >> 32) << 32) | 0xFFFFFFFF; } BLOCK { // Merkle data structures for remote nodes are private to maintd. // We want to sync with self, but just once. This is to avoid // having newer information about self than successors, which // can cause spurious repairs of objects written between // sync and getrepairs. vec<ptr<locationcc> > succs = osuccs; if (succs.back ()->id () != host.x) succs.push_back (locationcc::alloc (host)); // We only want to read each tree off the disk once // per sync period. We initialize treedone here and it // gets flipped to true in getrepairs. treedone.clear (); for (unsigned int i=0; i < succs.size(); i++) { str succtreepath = strbuf () << private_path << "/" << host.vnode_num << "-" << succs[i]->id () << "." << ctype2ext (ctype); treedone.push_back (false); ptr<merkle_tree> t = New refcounted<merkle_tree_bdb> (succtreepath.cstr (), /* join = */ false, /* ro = */ false); sync->sync_with (succs[i], rngmin, rngmax, t, wrap (this, &carbonite::handle_missing, succs[i], t), @()); } } cb ();}struct keycounter { chordID id; unsigned int presence; unsigned int count; itree_entry<keycounter> ik; static const unsigned int psz = 8*sizeof (unsigned int); keycounter (chordID id) : id (id), presence (0), count (0) {} void add (unsigned int i) { assert (i < psz); unsigned int x = 1 << i; if ((presence & x) == x) return; presence |= x; count++; } int firstvoid () { unsigned int t = presence; unsigned int i = 0; while (i < psz) { if (!(t & 1)) return i; i++; t >>= 1; } return psz; } int firstpresent () { unsigned int t = presence; unsigned int i = 0; while (i < psz) { if (t & 1) return i; i++; t >>= 1; } return psz; }};// Find the first leaf page that includes 'start'.// For each tree, read in the next leaf page and place the keys// in that page into a tree that counts replicas.// Maintain a last key read for each tree (lastread).// Find the min key in highcount.// Iterate over the rbcounttree up until min(lastread) to find// possible things to repair.// If we have found at least 'count' objects, return!// Otherwise, loop.voidcarbonite::getrepairs (chordID start, int thresh, int count, rpc_vec<maint_repair_t, RPC_INFINITY> &repairs){ repairs.setsize (0); get_global_repairs (count/2, repairs); if (in_progress) { if (!get_global_repairs (count, repairs)) warn << host << ": Not returning repairs while sync is active.\n"; return; } warn << host << ": Starting getrepairs " << start << " " << count << "\n"; // No point in doing any work if there are no successors. if (!succs.size ()) return; vec<ptr<merkle_tree> > trees; vec<chordID> lastread; chordID stop = host.x; if (db->hasaux ()) stop = ((stop << 32) >> 32) | 0xFFFFFFFF; itree<chordID, keycounter, &keycounter::id, &keycounter::ik> keymap; // 0 is self, 1 and on are actual successors. // Make sure to use private copy of tree to avoid spurious repairs. vec<ptr<locationcc> > nsuccs; nsuccs.push_back (locationcc::alloc (host)); nsuccs += succs; // Exclude dup self if self on successor list (small ring case). if (succs.back ()->id () == host.x) nsuccs.pop_back (); // Because all vnodes share a database, we only need to // consider one database per physical host. bhash<str> hosts; vec<bool> treeskip; for (unsigned int i = 0; i < nsuccs.size (); i++) { str succtreepath = strbuf () << private_path << "/" << host.vnode_num << "-" << nsuccs[i]->id () << "." << ctype2ext (ctype); if (!merkle_tree_bdb::tree_exists (succtreepath.cstr ())) { warn << host << ": Not returning repairs due to missing tree " << succtreepath << "\n"; return; } ptr<merkle_tree> t = New refcounted<merkle_tree_bdb> (succtreepath.cstr (), /* join = */ false, /* ro = */ true); trees.push_back (t); lastread.push_back (start); str host = strbuf () << nsuccs[i]->chordnode ().r; treeskip.push_back (hosts[host]); hosts.insert (host); } assert (treedone.size () == nsuccs.size ()); while ((int) repairs.size () < count) { bool addedany = false; for (unsigned int i = 0; i < trees.size (); i++) { if (treedone[i] || treeskip[i]) continue; addedany = true; // Aim to read about one leaf page at a time. vec<chordID> keys = trees[i]->get_keyrange (lastread[i], stop, 64); if (keys.size () < 64) treedone[i] = true; for (unsigned int j = 0; j < keys.size (); j++) { keycounter *k = keymap[keys[j]]; if (!k) { k = New keycounter (keys[j]); k->add (i); keymap.insert (k); } else { k->add (i); } } if (keys.size ()) lastread[i] = incID (keys.back ()); } // if we've read all the keys in the responsible range // in all trees, it's time to quit. if (!addedany) break; // Find the smallest range for which we have read everything chordID minimax = stop; for (unsigned int i = 0; i < trees.size (); i++) if (betweenleftincl (start, minimax, lastread[i])) minimax = lastread[i]; keycounter *k = NULL; for (k = keymap.first (); (k && (int) repairs.size () < count); k = keymap.next (k)) { if (!between (start, minimax, k->id)) { // warn << "carbonite " << host << " rejects " << k->id << " not between\n"; continue; } if (k->count < (unsigned) thresh) { maint_repair_t repair; repair.responsible = true; repair.id = k->id; repair.src_ipv4_addr = 0; repair.src_port_vnnum = 0; // aux is an indicator of mutability if (db->hasaux ()) { unsigned int src = k->firstpresent (); assert (src < nsuccs.size ()); nsuccs[src]->fill_ipportvn (repair.src_ipv4_addr, repair.src_port_vnnum); } unsigned int dst = k->firstvoid (); if (dst < nsuccs.size ()) { warn << "carbonite " << host << " adds " << k->id << " to successor " << dst << "\n"; nsuccs[dst]->fill_ipportvn (repair.dst_ipv4_addr, repair.dst_port_vnnum); repairs.push_back (repair); } else { // warn << "carbonite " << host << " rejects " << k->id // << " no dst " << dst << " >= " << nsuccs.size () << "\n"; continue; } } else { // warn << "carbonite " << host << " rejects " << k->id // << " enough copies " << k->count << "\n"; } } } keymap.deleteall_correct ();}// How to figure out what the ip.port.vnnum is for a given tree?// Build up trees from the recorded successor list which includes// ip addresses.// }}}// {{{ Passing Toneref<maintainer> passingtone::produce_maintainer (str path, maint_dhashinfo_t *hostinfo, ptr<syncer> s, cbv cb){ return New refcounted<passingtone> (path, hostinfo, s, cb);}passingtone::passingtone (str path, maint_dhashinfo_t *hostinfo, ptr<syncer> s, cbv cb) : maintainer (path, hostinfo, s){ db->getspaceinfo (wrap (this, &passingtone::init_ltree, cb));}void passingtone::init_ltree (cbv cb, adb_status err, str path, bool hasaux){ if (err) { warn << "passingtone::init_ltree: Unexpected adbd error: " << err << "\n"; return; } ltree = New refcounted<merkle_tree_bdb> (path.cstr (), /* join = */ true, /* ro = */ true); cb ();}passingtone::~passingtone (){}void passingtone::handle_missing (ptr<locationcc> from, ptr<merkle_tree> t, chordID key, bool missing_local){ // for key on succ/pred: // if key in responsible range and not locally present: // replicate key locally if (!missing_local) return; // XXX Should do better than linear scan here... for (size_t i = 0; i < repairqueue.size (); i++) { if (repairqueue[i].key == key) return; } warn << "passingtone " << host << " needs " << key << "\n"; struct pt_repair_t r (key, from, timenow); repairqueue.push_back (r);}TAMED voidpassingtone::process_neighbors ( const vec<ptr<locationcc> > &preds, const vec<ptr<locationcc> > &succs, cbv cb){ VARS { chordID rngmin, rngmax; } if (!stable) { warn << "passingtone " << host << " neighbors changed; flushing queue.\n"; repairqueue.clear (); } // If there are repairs queued, don't bother re-syncing. if (repairqueue.size ()) { cb (); return; } // Our range starts before our efrag-th predecessor. // Unless there are so few nodes that all objects are fully replicated. if (preds.size() > efrags) rngmin = preds[efrags-1]->id (); else rngmin = incID (host.x); rngmax = host.x; if (db->hasaux ()) { rngmin = ((rngmin >> 32) << 32) | 0xFFFFFFFF; rngmax = ((rngmax >> 32) << 32) | 0xFFFFFFFF; } // merkle_sync with first non-self succ and pred. // If any keys missing locally, fetch them. BLOCK { // Sync the entire tree range using the current live tree. size_t i = 0; for (i = 0; i < succs.size (); i++) if (succs[i]->chordnode ().r.hostname != host.r.hostname || succs[i]->chordnode ().r.port != host.r.port) break; if (i != succs.size ()) sync->sync_with (succs[i], rngmin, rngmax, ltree, wrap (this, &passingtone::handle_missing, succs[i], ltree), @()); for (i = 0; i < preds.size (); i++) if (preds[i]->chordnode ().r.hostname != host.r.hostname || preds[i]->chordnode ().r.port != host.r.port) break; if (i != preds.size ()) sync->sync_with (preds[i], rngmin, rngmax, ltree, wrap (this, &passingtone::handle_missing, preds[i], ltree), @()); } cb ();}voidpassingtone::getrepairs (chordID start, int thresh, int count, rpc_vec<maint_repair_t, RPC_INFINITY> &repairs){ get_global_repairs (count/2, repairs); // ignore thresh. // ignore start. sockaddr_in saddr; bzero (&saddr, sizeof(sockaddr_in)); // saddr.sin_family = AF_INET; inet_aton (host.r.hostname.cstr (), &saddr.sin_addr); saddr.sin_port = htons (host.r.port); /* saddr fields are in network byte order */ u_int32_t a = ntohl (saddr.sin_addr.s_addr); u_int32_t b = (ntohs (saddr.sin_port) << 16) | host.vnode_num; while (repairqueue.size () && (int) repairs.size () < count) { pt_repair_t rq = repairqueue.pop_front (); maint_repair_t r; r.responsible = true; r.id = rq.key; rq.from->fill_ipportvn (r.src_ipv4_addr, r.src_port_vnnum); r.dst_ipv4_addr = a; r.dst_port_vnnum = b; repairs.push_back (r); warn << "passingtone " << host << " unqueued " << rq.key << " after " << timenow - rq.add_time << "s.\n"; }}// }}}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?