Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1531)

Unified Diff: sync/syncable/directory_backing_store.cc

Issue 11441026: [Sync] Add support for loading, updating and querying delete journals in (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: sync/syncable/directory_backing_store.cc
diff --git a/sync/syncable/directory_backing_store.cc b/sync/syncable/directory_backing_store.cc
index e9ba0acc57c0bd945b1010f3f230a288f64999cb..6918936ba930524ae2a5a255d8f2741729c6fa08 100644
--- a/sync/syncable/directory_backing_store.cc
+++ b/sync/syncable/directory_backing_store.cc
@@ -40,7 +40,7 @@ static const string::size_type kUpdateStatementBufferSize = 2048;
// Increment this version whenever updating DB tables.
extern const int32 kCurrentDBVersion; // Global visibility for our unittest.
-const int32 kCurrentDBVersion = 83;
+const int32 kCurrentDBVersion = 84;
// Iterate over the fields of |entry| and bind each to |statement| for
// updating. Returns the number of args bound.
@@ -172,12 +172,21 @@ DirectoryBackingStore::DirectoryBackingStore(const string& dir_name,
DirectoryBackingStore::~DirectoryBackingStore() {
}
-bool DirectoryBackingStore::DeleteEntries(const MetahandleSet& handles) {
+bool DirectoryBackingStore::DeleteEntries(bool meta_delete,
+ const MetahandleSet& handles) {
if (handles.empty())
return true;
- sql::Statement statement(db_->GetCachedStatement(
- SQL_FROM_HERE, "DELETE FROM metas WHERE metahandle = ?"));
+ sql::Statement statement;
+ // Call GetCachedStatement() separately to get different statements for
+ // different tables.
+ if (meta_delete) {
+ statement.Assign(db_->GetCachedStatement(
+ SQL_FROM_HERE, "DELETE FROM metas WHERE metahandle = ?"));
+ } else {
+ statement.Assign(db_->GetCachedStatement(
+ SQL_FROM_HERE, "DELETE FROM deleted_metas WHERE metahandle = ?"));
+ }
for (MetahandleSet::const_iterator i = handles.begin(); i != handles.end();
++i) {
@@ -197,21 +206,34 @@ bool DirectoryBackingStore::SaveChanges(
// Back out early if there is nothing to write.
bool save_info =
(Directory::KERNEL_SHARE_INFO_DIRTY == snapshot.kernel_info_status);
- if (snapshot.dirty_metas.size() < 1 && !save_info)
+ if (snapshot.dirty_metas.empty() && snapshot.metahandles_to_purge.empty() &&
+ snapshot.delete_journals.empty() &&
+ snapshot.delete_journals_to_purge.empty() && !save_info)
tim (not reviewing) 2012/12/13 23:41:30 Braces around if body
haitaol1 2012/12/14 19:22:38 Done.
return true;
sql::Transaction transaction(db_.get());
if (!transaction.Begin())
return false;
+ PrepareSaveEntryStatement("metas", &save_meta_statment_);
for (EntryKernelSet::const_iterator i = snapshot.dirty_metas.begin();
i != snapshot.dirty_metas.end(); ++i) {
- DCHECK(i->is_dirty());
- if (!SaveEntryToDB(*i))
+ DCHECK((*i)->is_dirty());
+ if (!SaveEntryToDB(&save_meta_statment_, **i))
+ return false;
+ }
+
+ if (!DeleteEntries(true, snapshot.metahandles_to_purge))
+ return false;
+
+ PrepareSaveEntryStatement("deleted_metas", &save_delete_journal_statment_);
+ for (EntryKernelSet::const_iterator i = snapshot.delete_journals.begin();
+ i != snapshot.delete_journals.end(); ++i) {
+ if (!SaveEntryToDB(&save_delete_journal_statment_, **i))
return false;
}
- if (!DeleteEntries(snapshot.metahandles_to_purge))
+ if (!DeleteEntries(false, snapshot.delete_journals_to_purge))
return false;
if (save_info) {
@@ -364,6 +386,12 @@ bool DirectoryBackingStore::InitializeTables() {
version_on_disk = 83;
}
+ // Version 84 migration added deleted_metas table.
+ if (version_on_disk == 83) {
+ if (MigrateVersion83To84())
+ version_on_disk = 84;
+ }
+
// If one of the migrations requested it, drop columns that aren't current.
// It's only safe to do this after migrating all the way to the current
// version.
@@ -460,22 +488,12 @@ bool DirectoryBackingStore::RefreshColumns() {
}
bool DirectoryBackingStore::LoadEntries(MetahandlesIndex* entry_bucket) {
- string select;
- select.reserve(kUpdateStatementBufferSize);
- select.append("SELECT ");
- AppendColumnList(&select);
- select.append(" FROM metas ");
-
- sql::Statement s(db_->GetUniqueStatement(select.c_str()));
+ return LoadEntriesInternal("metas", entry_bucket);
+}
- while (s.Step()) {
- scoped_ptr<EntryKernel> kernel = UnpackEntry(&s);
- // A null kernel is evidence of external data corruption.
- if (!kernel.get())
- return false;
- entry_bucket->insert(kernel.release());
- }
- return s.Succeeded();
+bool DirectoryBackingStore::LoadDeleteJournals(
+ IdsIndex* delete_journals) {
+ return LoadEntriesInternal("deleted_metas", delete_journals);
}
bool DirectoryBackingStore::LoadInfo(Directory::KernelLoadInfo* info) {
@@ -535,38 +553,12 @@ bool DirectoryBackingStore::LoadInfo(Directory::KernelLoadInfo* info) {
return true;
}
-bool DirectoryBackingStore::SaveEntryToDB(const EntryKernel& entry) {
- // This statement is constructed at runtime, so we can't use
- // GetCachedStatement() to let the Connection cache it. We will construct
- // and cache it ourselves the first time this function is called.
- if (!save_entry_statement_.is_valid()) {
- string query;
- query.reserve(kUpdateStatementBufferSize);
- query.append("INSERT OR REPLACE INTO metas ");
- string values;
- values.reserve(kUpdateStatementBufferSize);
- values.append("VALUES ");
- const char* separator = "( ";
- int i = 0;
- for (i = BEGIN_FIELDS; i < FIELD_COUNT; ++i) {
- query.append(separator);
- values.append(separator);
- separator = ", ";
- query.append(ColumnName(i));
- values.append("?");
- }
- query.append(" ) ");
- values.append(" )");
- query.append(values);
-
- save_entry_statement_.Assign(
- db_->GetUniqueStatement(query.c_str()));
- } else {
- save_entry_statement_.Reset(true);
- }
-
- BindFields(entry, &save_entry_statement_);
- return save_entry_statement_.Run();
+/* static */
+bool DirectoryBackingStore::SaveEntryToDB(sql::Statement* save_statement,
+ const EntryKernel& entry) {
+ save_statement->Reset(true);
+ BindFields(entry, save_statement);
+ return save_statement->Run();
}
bool DirectoryBackingStore::DropDeletedEntries() {
@@ -1091,6 +1083,17 @@ bool DirectoryBackingStore::MigrateVersion82To83() {
return true;
}
+bool DirectoryBackingStore::MigrateVersion83To84() {
+ // Version 84 added deleted_metas table to store deleted metas until we know
+ // for sure that the deletions are persisted in native models.
+ string query = "CREATE TABLE deleted_metas ";
+ query.append(ComposeCreateTableColumnSpecs());
+ if (!db_->Execute(query.c_str()))
+ return false;
+ SetVersion(84);
+ return true;
+}
+
bool DirectoryBackingStore::CreateTables() {
DVLOG(1) << "First run, creating tables";
// Create two little tables share_version and share_info
@@ -1169,9 +1172,17 @@ bool DirectoryBackingStore::CreateTables() {
}
bool DirectoryBackingStore::CreateMetasTable(bool is_temporary) {
- const char* name = is_temporary ? "temp_metas" : "metas";
string query = "CREATE TABLE ";
- query.append(name);
+ query.append(is_temporary ? "temp_metas" : "metas");
+ query.append(ComposeCreateTableColumnSpecs());
+ if (!db_->Execute(query.c_str()))
+ return false;
+
+ // Create a deleted_metas table to save copies of deleted metas until the
+ // deletions are persisted. For simplicity, don't try to migrate existing
+ // data because it's rarely used.
+ SafeDropTable("deleted_metas");
+ query = "CREATE TABLE deleted_metas ";
query.append(ComposeCreateTableColumnSpecs());
return db_->Execute(query.c_str());
}
@@ -1271,5 +1282,53 @@ bool DirectoryBackingStore::VerifyReferenceIntegrity(
return is_ok;
}
+template<class T>
+bool DirectoryBackingStore::LoadEntriesInternal(const std::string& table,
+ T* bucket) {
+ string select;
+ select.reserve(kUpdateStatementBufferSize);
+ select.append("SELECT ");
+ AppendColumnList(&select);
+ select.append(" FROM " + table);
+
+ sql::Statement s(db_->GetUniqueStatement(select.c_str()));
+
+ while (s.Step()) {
+ scoped_ptr<EntryKernel> kernel = UnpackEntry(&s);
+ // A null kernel is evidence of external data corruption.
+ if (!kernel.get())
+ return false;
+ bucket->insert(kernel.release());
+ }
+ return s.Succeeded();
+}
+
+void DirectoryBackingStore::PrepareSaveEntryStatement(
+ const std::string& table, sql::Statement* save_statement) {
+ if (save_statement->is_valid())
+ return;
+
+ string query;
+ query.reserve(kUpdateStatementBufferSize);
+ query.append("INSERT OR REPLACE INTO " + table);
+ string values;
+ values.reserve(kUpdateStatementBufferSize);
+ values.append(" VALUES ");
+ const char* separator = "( ";
+ int i = 0;
+ for (i = BEGIN_FIELDS; i < FIELD_COUNT; ++i) {
+ query.append(separator);
+ values.append(separator);
+ separator = ", ";
+ query.append(ColumnName(i));
+ values.append("?");
+ }
+ query.append(" ) ");
+ values.append(" )");
+ query.append(values);
+ save_statement->Assign(db_->GetUniqueStatement(
+ base::StringPrintf(query.c_str(), "metas").c_str()));
+}
+
} // namespace syncable
} // namespace syncer

Powered by Google App Engine
This is Rietveld 408576698