# # # patch "database.cc" # from [4ae4c79a2a7fba4f39b072de6edc52625e1f69c0] # to [6e277fdc18625a6b1c2bb3c3b54dcc42f1549691] # # patch "database.hh" # from [7eb9a59905d0c790a5f76cb6fd1c35b538b7af60] # to [bbc894507ad90df8976509cc9ac746ae0802bc69] # # patch "revision.cc" # from [4fcc44663ce844747a92a235ba529b1cbb091451] # to [1ee7dd8d3389bd1721ec281f5f296ae2bb5c68db] # # patch "schema.sql" # from [c093f206468fcc6663167a57258c07adb9c33880] # to [8817731ceabe14a3a3212acd5cd5d1017812c075] # # patch "schema_migration.cc" # from [769321d3bb854322d9de25354e9e240396cf1096] # to [4b53913ae93495cf529d04f1edb62b5ecc25f9dd] # ============================================================ --- database.cc 4ae4c79a2a7fba4f39b072de6edc52625e1f69c0 +++ database.cc 6e277fdc18625a6b1c2bb3c3b54dcc42f1549691 @@ -160,15 +160,13 @@ database::check_format() { results res; - // Check for manifests, revisions, rosters, and heights. + // Check for manifests, revisions and rosters. fetch(res, one_col, any_rows, query("SELECT 1 FROM manifests LIMIT 1")); bool have_manifests = !res.empty(); fetch(res, one_col, any_rows, query("SELECT 1 FROM revisions LIMIT 1")); bool have_revisions = !res.empty(); fetch(res, one_col, any_rows, query("SELECT 1 FROM rosters LIMIT 1")); bool have_rosters = !res.empty(); - fetch(res, one_col, any_rows, query("SELECT 1 FROM heights LIMIT 1")); - bool have_heights = !res.empty(); if (!have_manifests) @@ -176,15 +174,15 @@ database::check_format() // Must have been changesetified and rosterified already. // Or else the database was just created. // Do we need to regenerate cached data? - E(!have_revisions || (have_rosters && have_heights), + E((!have_revisions || have_rosters), F("database %s lacks some cached data\n" "run '%s db regenerate_caches' to restore use of this database") % filename % ui.prog_name); } else { - // The rosters and heights tables should be empty. - I(!have_rosters && !have_heights); + // The rosters tables should be empty. + I(!have_rosters); // they need to either changesetify or rosterify. which? if (have_revisions) @@ -604,8 +602,6 @@ database::info(ostream & out) "length(hash) + length(id) + length(name)" "+ length(value) + length(keypair)" "+ length(signature)", total)); - bytes.push_back(space("heights", "length(revision) + length(height)", - total)); bytes.push_back((F("%u") % total).str()); } @@ -644,7 +640,6 @@ database::info(ostream & out) " revisions : %s\n" " cached ancestry : %s\n" " certs : %s\n" - " heights : %s\n" " total : %s\n" "database:\n" " page size : %s\n" @@ -1919,7 +1914,7 @@ database::get_rev_height(revision_id con { results res; fetch(res, one_col, one_row, - query("SELECT height FROM heights WHERE revision = ?") + query("SELECT height FROM revisions WHERE id = ?") % text(id.inner()())); I(res.size() == 1); @@ -1936,8 +1931,8 @@ void } void -database::put_rev_height(revision_id const & id, - rev_height const & height) +database::update_rev_height(revision_id const & id, + rev_height const & height) { I(!null_id(id)); I(revision_exists(id)); @@ -1945,9 +1940,9 @@ database::put_rev_height(revision_id con height_cache.erase(id); - execute(query("INSERT INTO heights VALUES(?, ?)") - % text(id.inner()()) - % blob(height())); + execute(query("UPDATE revisions SET height = ? WHERE id = ?") + % blob(height()) + % text(id.inner()())); } bool @@ -1955,7 +1950,7 @@ database::has_rev_height(rev_height cons { results res; fetch(res, one_col, any_rows, - query("SELECT height FROM heights WHERE height = ?") + query("SELECT height FROM revisions WHERE height = ?") % blob(height())); I((res.size() == 1) || (res.size() == 0)); return res.size() == 1; @@ -2076,9 +2071,15 @@ database::put_revision(revision_id const write_revision(rev, d); gzip d_packed; encode_gzip(d.inner(), d_packed); - execute(query("INSERT INTO revisions VALUES(?, ?)") + rev_height height; + + // determine the revision height + calc_height_for_revision(new_id, rev, height); + + execute(query("INSERT INTO revisions (id, data, height) VALUES(?, ?, ?)") % text(new_id.inner()()) - % blob(d_packed())); + % blob(d_packed()) + % blob(height())); for (edge_map::const_iterator e = rev.edges.begin(); e != rev.edges.end(); ++e) @@ -2107,10 +2108,6 @@ database::put_revision(revision_id const deltify_revision(new_id); - // Phase 5: determine the revision height - - put_height_for_revision(new_id, rev); - // Finally, commit. guard.commit(); @@ -2118,8 +2115,9 @@ void } void -database::put_height_for_revision(revision_id const & new_id, - revision_t const & rev) +database::calc_height_for_revision(revision_id const & new_id, + revision_t const & rev, + rev_height & height) { I(!null_id(new_id)); @@ -2138,18 +2136,17 @@ database::put_height_for_revision(revisi // ... then find the first unused child u32 childnr(0); - rev_height candidate; MM(candidate); + MM(height); while(true) { - candidate = highest_parent.child_height(childnr); - if (!has_rev_height(candidate)) + height = highest_parent.child_height(childnr); + if (!has_rev_height(height)) { break; } I(childnr < std::numeric_limits::max()); ++childnr; } - put_rev_height(new_id, candidate); } void @@ -2207,7 +2204,7 @@ database::delete_existing_heights() void database::delete_existing_heights() { - execute(query("DELETE FROM heights")); + execute(query("UPDATE revisions SET height = NULL")); } /// Deletes one revision from the local database. @@ -2234,9 +2231,6 @@ database::delete_existing_rev_and_certs( execute(query("DELETE from revision_ancestry WHERE child = ?") % text(rid.inner()())); - execute(query("DELETE from heights WHERE revision = ?") - % text(rid.inner()())); - execute(query("DELETE from revisions WHERE id = ?") % text(rid.inner()())); ============================================================ --- database.hh 7eb9a59905d0c790a5f76cb6fd1c35b538b7af60 +++ database.hh bbc894507ad90df8976509cc9ac746ae0802bc69 @@ -581,14 +581,15 @@ public: void get_rev_height(revision_id const & id, rev_height & height); - void put_rev_height(revision_id const & id, - rev_height const & height); - + void update_rev_height(revision_id const & id, + rev_height const & height); + bool has_rev_height(rev_height const & height); void delete_existing_heights(); - void put_height_for_revision(revision_id const & new_id, - revision_t const & rev); + void calc_height_for_revision(revision_id const & new_id, + revision_t const & rev, + rev_height & height); // for regenerate_rosters void delete_existing_rosters(); ============================================================ --- revision.cc 4fcc44663ce844747a92a235ba529b1cbb091451 +++ revision.cc 1ee7dd8d3389bd1721ec281f5f296ae2bb5c68db @@ -1773,7 +1773,11 @@ regenerate_caches(app_state & app) revision_id const & rev_id = *i; app.db.get_revision(rev_id, rev); app.db.put_roster_for_revision(rev_id, rev); - app.db.put_height_for_revision(rev_id, rev); + + rev_height height; + app.db.calc_height_for_revision(rev_id, rev, height); + app.db.update_rev_height(rev_id, height); + ++done; } ============================================================ --- schema.sql c093f206468fcc6663167a57258c07adb9c33880 +++ schema.sql 8817731ceabe14a3a3212acd5cd5d1017812c075 @@ -38,9 +38,12 @@ CREATE TABLE revisions CREATE TABLE revisions ( id primary key, -- SHA1(text of revision) - data not null -- compressed, encoded contents of a revision + data not null, -- compressed, encoded contents of a revision + height not null -- complex height, array of big endian u32 integers ); +CREATE INDEX revisions__height ON revisions (height); + CREATE TABLE revision_ancestry ( parent not null, -- joins with revisions.id @@ -50,15 +53,6 @@ CREATE INDEX revision_ancestry__child ON CREATE INDEX revision_ancestry__child ON revision_ancestry (child); -CREATE TABLE heights - ( - revision not null, -- joins with revisions.id - height not null, -- complex height, array of big endian u32 integers - unique(revision, height) - ); - -CREATE INDEX heights__height ON heights (height); - CREATE TABLE rosters ( id primary key, -- a revision id ============================================================ --- schema_migration.cc 769321d3bb854322d9de25354e9e240396cf1096 +++ schema_migration.cc 4b53913ae93495cf529d04f1edb62b5ecc25f9dd @@ -706,7 +706,29 @@ const migration_event migration_events[] // The last entry in this table should always be the current // schema ID, with 0 for the migrators. - { "7ca81b45279403419581d7fde31ed888a80bd34e", 0, 0, upgrade_none } + { "7ca81b45279403419581d7fde31ed888a80bd34e", 0, 0, upgrade_none }, + + // I'm too lazy to write the real migration step. Here's the SQL needed: + /* + +ALTER TABLE revisions RENAME TO tmp; +CREATE TABLE revisions + ( + id primary key, -- SHA1(text of revision) + data not null, -- compressed, encoded contents of a revision + height not null -- complex height, array of big endian u32 integers + ); + +CREATE INDEX revisions__height ON revisions (height); + +INSERT INTO revisions SELECT id, data, h.height FROM tmp r JOIN heights h on r.id = h.revision; +DROP TABLE heights; +DROP TABLE tmp; + +*/ + + + { "0cb25df66803fe7c6e333d6b6db3ac112d0aa3c8", 0, 0, upgrade_none } }; const size_t n_migration_events = (sizeof migration_events / sizeof migration_events[0]);