# # # add_file "gsync.hh" # content [ce72087f6b1b5d34b400b548808596c346f9b594] # # patch "Makefile.am" # from [2175237275af02c1314fecd0fcb42888387bd127] # to [9ce86ec149986e741fd3ed00ed79db4010db59b7] # # patch "cmd_netsync.cc" # from [d1b9aead3c0742a08d4c5035e14ede9743c50831] # to [991ceecf7fa6728da543449fa1162b83da951058] # # patch "gsync.cc" # from [8c41e5fb9705fcef796832316271582acd76c2df] # to [5f8a87f1a21027f3661fbd8b6fbcc9614ef0c201] # # patch "http_client.cc" # from [ebd2d796bfaf1f4e027ad3ff6d2d43c3ac2cc93c] # to [4bd52563930130759bd40ff3d841d00013500d20] # # patch "http_client.hh" # from [454f6074e7408d53b97bca7078c6f7f4c07c2b93] # to [8eac2ba77c84328372e3f2980bac2c91f70a5304] # # patch "netsync.cc" # from [0c2c0074d6b643fe3dd742b0b2bbc5f9b0341008] # to [b5089c12a9b77cdf03d89984fafaf81d783bda9d] # ============================================================ --- gsync.hh ce72087f6b1b5d34b400b548808596c346f9b594 +++ gsync.hh ce72087f6b1b5d34b400b548808596c346f9b594 @@ -0,0 +1,48 @@ +#ifndef __GSYNC_HH__ +#define __GSYNC_HH__ + +// Copyright (C) 2008 Markus Schiltknecht +// +// This program is made available under the GNU GPL version 2.0 or +// greater. See the accompanying file COPYING for details. +// +// This program is distributed WITHOUT ANY WARRANTY; without even the +// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. + +#include "base.hh" + +#include + +#include "vocab.hh" + +struct uri; +struct globish; +class lua_hooks; +class database; + +class +channel +{ +public: + virtual + void inquire_about_revs(std::set const & query_set, + std::set & theirs) const = 0; + virtual + void push_rev(revision_id const & rid) const = 0; +}; + +extern void +run_gsync_protocol(lua_hooks & lua, database & db, channel const & ch, + globish const & include_pattern, + globish const & exclude_pattern); + +// Local Variables: +// mode: C++ +// fill-column: 76 +// c-file-style: "gnu" +// indent-tabs-mode: nil +// End: +// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s: + +#endif // __GSYNC_HH__ ============================================================ --- Makefile.am 2175237275af02c1314fecd0fcb42888387bd127 +++ Makefile.am 9ce86ec149986e741fd3ed00ed79db4010db59b7 @@ -47,7 +47,7 @@ MOST_SOURCES = \ enumerator.cc enumerator.hh \ net_common.cc net_common.hh \ netsync.cc \ - gsync.cc \ + gsync.cc gsync.hh \ netxx_pipe.cc netxx_pipe.hh \ netcmd.cc netcmd.hh \ merkle_tree.cc merkle_tree.hh \ @@ -317,7 +317,7 @@ UNIT_TEST_SRC_SUPPORT = \ # these files do not contain unit tests, but are required for unit testing # and must be recompiled for that purpose UNIT_TEST_SRC_SUPPORT = \ - roster_delta.cc json_msgs.cc http_client.cc net_common.cc + roster_delta.cc # these files do not contain unit tests; they are required for unit # testing, but can be used "as is" from the main build. (many of ============================================================ --- cmd_netsync.cc d1b9aead3c0742a08d4c5035e14ede9743c50831 +++ cmd_netsync.cc 991ceecf7fa6728da543449fa1162b83da951058 @@ -1,9 +1,11 @@ #include "base.hh" #include "cmd.hh" #include "diff_patch.hh" #include "netcmd.hh" #include "globish.hh" +#include "gsync.hh" +#include "http_client.hh" #include "keys.hh" #include "key_store.hh" #include "cert.hh" @@ -491,11 +493,6 @@ CMD_NO_WORKSPACE(serve, "serve", "", CMD globish("*"), globish("")); } -void -run_gsync_protocol(options & opts, lua_hooks & lua, database & db, utf8 const & addr, - globish const & include_pattern, - globish const & exclude_pattern); - CMD(gsync, "gsync", "", CMD_REF(network), N_("[ADDRESS[:PORTNUMBER] [PATTERN ...]]"), N_("Synchronizes branches with a netsync server"), @@ -514,7 +511,11 @@ CMD(gsync, "gsync", "", CMD_REF(network) extract_patterns(app.opts, db, args, include_pattern, exclude_pattern); find_key_if_needed(app.opts, app.lua, db, keys, addr, include_pattern, exclude_pattern); - run_gsync_protocol(app.opts, app.lua, db, addr, include_pattern, exclude_pattern); + uri u; + parse_uri(addr(), u); + http_client h(app.opts, app.lua, u, include_pattern, exclude_pattern); + run_gsync_protocol(app.lua, db, http_channel(h), + include_pattern, exclude_pattern); } ============================================================ --- gsync.cc 8c41e5fb9705fcef796832316271582acd76c2df +++ gsync.cc 5f8a87f1a21027f3661fbd8b6fbcc9614ef0c201 @@ -14,14 +14,13 @@ #include #include +#include "constants.hh" #include "database.hh" #include "globish.hh" -#include "http_client.hh" -#include "json_io.hh" -#include "json_msgs.hh" +#include "graph.hh" +#include "gsync.hh" #include "revision.hh" #include "sanity.hh" -#include "lexical_cast.hh" #include "uri.hh" // @@ -81,9 +80,6 @@ using std::pair; using std::string; using std::pair; -using json_io::json_value_t; -using boost::lexical_cast; - ///////////////////////////////////////////////////////////////////// // core logic of gsync algorithm ///////////////////////////////////////////////////////////////////// @@ -107,20 +103,8 @@ do_set_difference(set const } -static void -inquire_about_revs(http_client & h, - set const & query_set, - set & theirs) -{ - theirs.clear(); - json_value_t query = encode_msg_inquire(query_set); - json_value_t response = h.transact_json(query); - E(decode_msg_confirm(response, theirs), - F("received unexpected reply to 'inquire' message")); -} - static void -determine_common_core(http_client & h, +determine_common_core(channel const & ch, set const & our_revs, rev_ancestry_map const & child_to_parent_map, rev_ancestry_map const & parent_to_child_map, @@ -149,7 +133,7 @@ determine_common_core(http_client & h, set revs_present, present_ancs, present_closure; set revs_absent, absent_descs, absent_closure; - inquire_about_revs(h, query_revs, revs_present); + ch.inquire_about_revs(query_revs, revs_present); do_set_difference(query_revs, revs_present, revs_absent); L(FL("pass #%d: inquired about %d revs, they have %d of them, missing %d of them") @@ -196,7 +180,7 @@ do_missing_playback(database & db, static void do_missing_playback(database & db, - http_client & h, + channel const & ch, set & core_frontier, set & revs_to_push, rev_ancestry_map const & parent_to_child_map) @@ -237,6 +221,8 @@ do_missing_playback(database & db, L(FL(" pushing revision %s (child of rev %s)") % i->second % i->first); + ch.push_rev(i->second); + revs_to_push.erase(i->second); core_frontier.erase(i->first); core_frontier.insert(i->second); @@ -250,22 +236,17 @@ request_missing_playback(database & db, static void request_missing_playback(database & db, - http_client & h, + channel const & ch, set const & core_frontier) { } void -run_gsync_protocol(options & opts, lua_hooks & lua, database & db, - utf8 const & addr, +run_gsync_protocol(lua_hooks & lua, database & db, channel const & ch, globish const & include_pattern, globish const & exclude_pattern) { - uri u; - parse_uri(addr(), u); - http_client h(opts, lua, u, include_pattern, exclude_pattern); - bool pushing = true, pulling = true; rev_ancestry_map parent_to_child_map, child_to_parent_map; @@ -283,7 +264,7 @@ run_gsync_protocol(options & opts, lua_h } set common_core; - determine_common_core(h, our_revs, child_to_parent_map, parent_to_child_map, common_core); + determine_common_core(ch, our_revs, child_to_parent_map, parent_to_child_map, common_core); set ours_alone; do_set_difference(our_revs, common_core, ours_alone); @@ -293,18 +274,88 @@ run_gsync_protocol(options & opts, lua_h erase_ancestors(db, core_frontier); if (pushing) - do_missing_playback(db, h, core_frontier, ours_alone, + do_missing_playback(db, ch, core_frontier, ours_alone, parent_to_child_map); if (pulling) - request_missing_playback(db, h, core_frontier); + request_missing_playback(db, ch, core_frontier); } #ifdef BUILD_UNIT_TESTS #include "unit_tests.hh" -UNIT_TEST(gsync, gsync) +class test_channel + : public channel { + set & theirs; +public: + test_channel(set & theirs) + : theirs(theirs) + { }; + + void inquire_about_revs(set const & query_set, + set & result) const + { + result.clear(); + for (set::const_iterator i = query_set.begin(); + i != query_set.end(); ++i) + if (theirs.find(*i) != theirs.end()) + result.insert(*i); + }; + + void push_rev(revision_id const & rid) const + { + I(false); + } +}; + +UNIT_TEST(gsync, gsync_common_core) +{ + L(FL("TEST: begin checking gsync protocol functions")); + + revision_id rid1("0000000000000000000000000000000000000001"); + revision_id rid2("0000000000000000000000000000000000000002"); + revision_id rid3("0000000000000000000000000000000000000003"); + revision_id rid4("0000000000000000000000000000000000000004"); + revision_id rid5("0000000000000000000000000000000000000005"); + revision_id rid6("0000000000000000000000000000000000000006"); + revision_id rid7("0000000000000000000000000000000000000007"); + revision_id rid8("0000000000000000000000000000000000000008"); + + // simulate having revisions 1, 2, 3, 5, 6 and 8 locally + set ours; + ours.insert(rid1); + ours.insert(rid2); + ours.insert(rid3); + ours.insert(rid5); + ours.insert(rid6); + ours.insert(rid8); + + // prepaire an ancestry map + rev_ancestry_map parent_to_child_map, child_to_parent_map; + parent_to_child_map.insert(make_pair(rid1, rid2)); + parent_to_child_map.insert(make_pair(rid1, rid3)); + parent_to_child_map.insert(make_pair(rid2, rid5)); + parent_to_child_map.insert(make_pair(rid3, rid5)); + parent_to_child_map.insert(make_pair(rid5, rid6)); + parent_to_child_map.insert(make_pair(rid5, rid8)); + invert_ancestry(parent_to_child_map, child_to_parent_map); + + // the other side has revisions 1, 2, 4 and 7 + set theirs; + theirs.insert(rid1); + theirs.insert(rid2); + theirs.insert(rid4); + theirs.insert(rid7); + + // setup the test channel and determine the common core + test_channel ch(theirs); + set common_core; + determine_common_core(ch, ours, child_to_parent_map, parent_to_child_map, common_core); + + I(common_core.size() == 2); + I(common_core.find(rid1) != common_core.end()); + I(common_core.find(rid2) != common_core.end()); } #endif ============================================================ --- http_client.cc ebd2d796bfaf1f4e027ad3ff6d2d43c3ac2cc93c +++ http_client.cc 4bd52563930130759bd40ff3d841d00013500d20 @@ -13,6 +13,7 @@ #include "globish.hh" #include "http_client.hh" #include "json_io.hh" +#include "json_msgs.hh" #include "net_common.hh" #include "sanity.hh" #include "lexical_cast.hh" @@ -26,6 +27,7 @@ #include "netxx_pipe.hh" #include +#include #include #include @@ -34,10 +36,10 @@ using std::vector; using boost::shared_ptr; using boost::lexical_cast; using std::vector; +using std::set; using std::string; using std::iostream; - using Netxx::Netbuf; using Netxx::Timeout; using Netxx::StreamBase; @@ -191,6 +193,23 @@ http_client::parse_http_response(std::st } + +///////////////////////////////////////////////////////////////////// +// http_channel adaptor +///////////////////////////////////////////////////////////////////// + +void +http_channel::inquire_about_revs(set const & query_set, + set & theirs) const +{ + theirs.clear(); + json_value_t query = encode_msg_inquire(query_set); + json_value_t response = client.transact_json(query); + E(decode_msg_confirm(response, theirs), + F("received unexpected reply to 'inquire' message")); +} + + // Local Variables: // mode: C++ // fill-column: 76 ============================================================ --- http_client.hh 454f6074e7408d53b97bca7078c6f7f4c07c2b93 +++ http_client.hh 8eac2ba77c84328372e3f2980bac2c91f70a5304 @@ -15,6 +15,7 @@ #include "base.hh" #include "constants.hh" +#include "gsync.hh" #include "json_io.hh" #include @@ -53,6 +54,19 @@ http_client void crlf(); }; +class http_channel + : public channel +{ + http_client & client; +public: + http_channel(http_client & c) + : client(c) + { }; + virtual void inquire_about_revs(std::set const & query_set, + std::set & theirs) const; + virtual void push_rev(revision_id const & rid) const; +}; + // Local Variables: // mode: C++ // fill-column: 76 ============================================================ --- netsync.cc 0c2c0074d6b643fe3dd742b0b2bbc5f9b0341008 +++ netsync.cc b5089c12a9b77cdf03d89984fafaf81d783bda9d @@ -27,6 +27,7 @@ #include "cert.hh" #include "constants.hh" #include "enumerator.hh" +#include "gsync.hh" #include "keys.hh" #include "lua.hh" #include "merkle_tree.hh"