# # patch "database.cc" # from [f5d7b0365d1cf8c64542ce5e072b0b82942442e8] # to [375b41de0123b0e22c4e46b3c90d441fcf54cd01] # # patch "roster4.cc" # from [7f611745c3909e997d1d1a2df261ed09170f1111] # to [600f447ec1fac592432f0952b9b477c234d8881e] # # patch "roster4.hh" # from [99cc4c7912600a93876d270ac8af516b24f1c818] # to [511de3285fb474b535d59d20c8268ad2288e2260] # # patch "schema.sql" # from [62dc6c62cf12db05829c9dac9713eb1dcdec9986] # to [ffd19f5f8c13788f78dfae5e70308f1b8448c08d] # # patch "schema_migration.cc" # from [80bcca9958dc4c04852ccec8fcf9f9589f0b85c3] # to [ef7456835bb18ea78b9b64033cc855588049a094] # # patch "transforms.cc" # from [a575f032108baee7827d56805ebc05f8fb4005ce] # to [d51477ece27a0157f815c04241ef72375175f56c] # ======================================================================== --- database.cc f5d7b0365d1cf8c64542ce5e072b0b82942442e8 +++ database.cc 375b41de0123b0e22c4e46b3c90d441fcf54cd01 @@ -69,7 +69,7 @@ // non-alphabetic ordering of tables in sql source files. we could create // a temporary db, write our intended schema into it, and read it back, // but this seems like it would be too rude. possibly revisit this issue. - schema("1509fd75019aebef5ac3da3a5edf1312393b70e9"), + schema("0f537561d65e8561b66134dee5ad12c5e73ebb91"), __sql(NULL), transaction_level(0) {} @@ -1429,8 +1429,6 @@ void database::delete_existing_revs_and_certs() { - execute("DELETE FROM rosters"); - execute("DELETE FROM roster_deltas"); execute("DELETE FROM revisions"); execute("DELETE FROM revision_ancestry"); execute("DELETE FROM revision_certs"); @@ -2525,7 +2523,7 @@ hexenc ident; base64 > new_data_packed; - write_roster_and_marking(roster, marks, new_data, true); + write_roster_and_marking(roster, marks, new_data); calculate_ident(new_data, ident); pack(new_data, new_data_packed); @@ -2656,37 +2654,31 @@ node_id database::next_node_id() { - // If you acquire a new ID, we require that you write the new roster - // that uses the ID atomically with the counter update. A - // half-measure to meet this requirement is to require that we're at - // least inside a transaction when called. - I(transaction_level > 0); + transaction_guard guard(*this); results res; // We implement this as a fixed db var. - string domain = "system"; - string name = "next_roster_id"; - - fetch(res, 1, any_rows, - "SELECT value FROM db_vars WHERE domain = ? AND name = ?", - domain.c_str(), name.c_str()); - - node_id n = 0; + fetch(res, one_col, any_rows, + "SELECT node FROM next_roster_node_number"); + + node_id n; if (res.empty()) { n = 1; - execute ("INSERT INTO db_vars VALUES(?, ?, ?)", - domain.c_str(), name.c_str(), lexical_cast(n).c_str()); + execute ("INSERT INTO next_roster_node_number VALUES(?)", + lexical_cast(n).c_str()); } else { + I(res.size() == 1); n = lexical_cast(res[0][0]); ++n; - execute ("UPDATE db_vars SET value = ? WHERE domain = ? and name = ?", - lexical_cast(n).c_str(), domain.c_str(), name.c_str()); + execute ("UPDATE next_roster_node_number SET node = ?", + lexical_cast(n).c_str()); } + guard.commit(); return n; } ======================================================================== --- roster4.cc 7f611745c3909e997d1d1a2df261ed09170f1111 +++ roster4.cc 600f447ec1fac592432f0952b9b477c234d8881e @@ -742,20 +742,16 @@ I(maxdepth-- > 0); } - void -roster_t::check_sane(marking_map const & marking) const +roster_t::check_sane() const { + I(has_root()); node_map::const_iterator ri; - marking_map::const_iterator mi; - I(has_root()); - - for (ri = nodes.begin(), mi = marking.begin(); - ri != nodes.end() && mi != marking.end(); - ++ri, ++mi) + for (ri = nodes.begin(); + ri != nodes.end(); + ++ri) { - I(ri->first == mi->first); node_id nid = ri->first; I(!null_node(nid) && !temp_node(nid)); node_t n = ri->second; @@ -772,15 +768,33 @@ I(!null_name(n->name) && !null_node(n->parent)); !null_id(downcast_to_file_t(n)->content); } - I(!null_id(mi->second.birth_revision)); for (full_attr_map_t::const_iterator i = n->attrs.begin(); i != n->attrs.end(); ++i) I(i->second.first || i->second.second().empty()); if (n != root_dir) I(downcast_to_dir_t(get_node(n->parent))->get_child(n->name) == n); + } + check_finite_depth(); +} + +void +roster_t::check_sane_against(marking_map const & marking) const +{ + + check_sane(); + + node_map::const_iterator ri; + marking_map::const_iterator mi; + + for (ri = nodes.begin(), mi = marking.begin(); + ri != nodes.end() && mi != marking.end(); + ++ri, ++mi) + { + I(!null_id(mi->second.birth_revision)); + } + I(ri == nodes.end() && mi == marking.end()); - check_finite_depth(); } @@ -1475,7 +1489,7 @@ } else I(false); - result.check_sane(marking); + result.check_sane_against(marking); } @@ -1937,17 +1951,20 @@ basic_io::parser pars(tok); ros.parse_from(pars, mm); I(src.lookahead == EOF); - ros.check_sane(mm); + ros.check_sane_against(mm); } -void +static void write_roster_and_marking(roster_t const & ros, marking_map const & mm, data & dat, bool print_local_parts) { - ros.check_sane(mm); + if (print_local_parts) + ros.check_sane_against(mm); + else + ros.check_sane(); std::ostringstream oss; basic_io::printer pr(oss); ros.print_to(pr, mm, print_local_parts); @@ -1955,7 +1972,24 @@ } +void +write_roster_and_marking(roster_t const & ros, + marking_map const & mm, + data & dat) +{ + write_roster_and_marking(ros, mm, dat, true); +} + +void +write_manifest_of_roster(roster_t const & ros, + data & dat) +{ + marking_map mm; + write_roster_and_marking(ros, mm, dat, false); +} + + //////////////////////////////////////////////////////////////////// // testing //////////////////////////////////////////////////////////////////// @@ -2008,14 +2042,14 @@ data r_dat; MM(r_dat); marking_map fm; make_fake_marking_for(r, fm); - write_roster_and_marking(r, fm, r_dat, true); + write_roster_and_marking(r, fm, r_dat); roster_t r2; MM(r2); marking_map fm2; read_roster_and_marking(r_dat, r2, fm2); I(r == r2); I(fm == fm2); data r2_dat; MM(r2_dat); - write_roster_and_marking(r2, fm2, r2_dat, true); + write_roster_and_marking(r2, fm2, r2_dat); I(r_dat == r2_dat); } @@ -2102,19 +2136,14 @@ data a2_dat; MM(a2_dat); data b_dat; MM(b_dat); data b2_dat; MM(b2_dat); - marking_map a_map, a2_map, b_map, b2_map; - make_fake_marking_for(a, a_map); - make_fake_marking_for(a2, a2_map); - make_fake_marking_for(b, b_map); - make_fake_marking_for(b2, b2_map); if (a.has_root()) - write_roster_and_marking(a, a_map, a_dat, false); + write_manifest_of_roster(a, a_dat); if (a2.has_root()) - write_roster_and_marking(a2, a2_map, a2_dat, false); + write_manifest_of_roster(a2, a2_dat); if (b.has_root()) - write_roster_and_marking(b, b_map, b_dat, false); + write_manifest_of_roster(b, b_dat); if (b2.has_root()) - write_roster_and_marking(b2, b2_map, b2_dat, false); + write_manifest_of_roster(b2, b2_dat); I(a_dat == a2_dat); I(b_dat == b2_dat); ======================================================================== --- roster4.hh 99cc4c7912600a93876d270ac8af516b24f1c818 +++ roster4.hh 511de3285fb474b535d59d20c8268ad2288e2260 @@ -199,9 +199,11 @@ bool operator==(roster_t const & other) const; + void check_sane() const; + // verify that this roster is sane, and corresponds to the given // marking map - void check_sane(marking_map const & marks) const; + void check_sane_against(marking_map const & marks) const; void print_to(basic_io::printer & pr, marking_map const & mm, @@ -268,8 +270,11 @@ void write_roster_and_marking(roster_t const & ros, marking_map const & mm, - data & dat, - bool print_local_parts); + data & dat); +void +write_manifest_of_roster(roster_t const & ros, + data & dat); + #endif ======================================================================== --- schema.sql 62dc6c62cf12db05829c9dac9713eb1dcdec9986 +++ schema.sql ffd19f5f8c13788f78dfae5e70308f1b8448c08d @@ -75,6 +75,10 @@ unique(rev_id, base) ); +CREATE TABLE next_roster_node_number + ( + node primary key -- only one entry in this table, ever + ); CREATE INDEX revision_ancestry__child ON revision_ancestry (child); ======================================================================== --- schema_migration.cc 80bcca9958dc4c04852ccec8fcf9f9589f0b85c3 +++ schema_migration.cc ef7456835bb18ea78b9b64033cc855588049a094 @@ -795,6 +795,15 @@ if (res != SQLITE_OK) return false; + res = sqlite3_exec(sql, + "CREATE TABLE next_roster_node_number\n" + "(\n" + "node primary key -- only one entry in this table, ever\n" + ");", + NULL, NULL, errmsg); + if (res != SQLITE_OK) + return false; + return true; } @@ -823,9 +832,12 @@ m.add("e372b508bea9b991816d1c74680f7ae10d2a6d94", &migrate_client_to_add_indexes); + m.add("1509fd75019aebef5ac3da3a5edf1312393b70e9", + &migrate_client_to_add_rosters); + // IMPORTANT: whenever you modify this to add a new schema version, you must // also add a new migration test for the new schema version. See // tests/t_migrate_schema.at for details. - m.migrate(sql, "1509fd75019aebef5ac3da3a5edf1312393b70e9"); + m.migrate(sql, "0f537561d65e8561b66134dee5ad12c5e73ebb91"); } ======================================================================== --- transforms.cc a575f032108baee7827d56805ebc05f8fb4005ce +++ transforms.cc d51477ece27a0157f815c04241ef72375175f56c @@ -330,8 +330,7 @@ { data tmp; hexenc tid; - marking_map mm; - write_roster_and_marking(ros, mm, tmp, false); + write_manifest_of_roster(ros, tmp); calculate_ident(tmp, tid); ident = tid; }