diff options
author | isherman@chromium.org <isherman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-17 02:23:18 +0000 |
---|---|---|
committer | isherman@chromium.org <isherman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-17 02:23:18 +0000 |
commit | 2e79ac55e21eb17d9afd33e40d9c0fe70272d10a (patch) | |
tree | 0cdb485746bf906dea75cb55422ab579f19e9567 | |
parent | 48c48280d9bba44ff14c3c665e9ef63c32c0e173 (diff) | |
download | chromium_src-2e79ac55e21eb17d9afd33e40d9c0fe70272d10a.zip chromium_src-2e79ac55e21eb17d9afd33e40d9c0fe70272d10a.tar.gz chromium_src-2e79ac55e21eb17d9afd33e40d9c0fe70272d10a.tar.bz2 |
Add additional error logging to investigate Autocomplete Sync failures.
BUG=122687
TEST=none
Review URL: https://chromiumcodereview.appspot.com/10310113
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@137617 0039d316-1c4b-4281-b951-d872f2087c98
15 files changed, 152 insertions, 68 deletions
diff --git a/chrome/browser/sync/glue/generic_change_processor.cc b/chrome/browser/sync/glue/generic_change_processor.cc index 0c9ac04..3cde180 100644 --- a/chrome/browser/sync/glue/generic_change_processor.cc +++ b/chrome/browser/sync/glue/generic_change_processor.cc @@ -253,16 +253,43 @@ SyncError GenericChangeProcessor::ProcessSyncChanges( error.message()); return error; } - if (!sync_node.InitUniqueByCreation(change.sync_data().GetDataType(), + sync_api::WriteNode::InitUniqueByCreationResult result = + sync_node.InitUniqueByCreation(change.sync_data().GetDataType(), root_node, - change.sync_data().GetTag())) { + change.sync_data().GetTag()); + if (result != sync_api::WriteNode::INIT_SUCCESS) { NOTREACHED(); - SyncError error(FROM_HERE, - "Failed to create " + type_str + " node.", + std::string error_prefix = "Failed to create " + type_str + " node: "; + SyncError error; + switch (result) { + case sync_api::WriteNode::INIT_FAILED_EMPTY_TAG: + error.Reset(FROM_HERE, error_prefix + "empty tag", type); + error_handler()->OnSingleDatatypeUnrecoverableError( + error.location(), error.message()); + return error; + case sync_api::WriteNode::INIT_FAILED_ENTRY_ALREADY_EXISTS: + error.Reset(FROM_HERE, error_prefix + "entry already exists", type); + error_handler()->OnSingleDatatypeUnrecoverableError( + error.location(), error.message()); + return error; + case sync_api::WriteNode::INIT_FAILED_COULD_NOT_CREATE_ENTRY: + error.Reset(FROM_HERE, error_prefix + "failed to create entry", type); - error_handler()->OnSingleDatatypeUnrecoverableError(error.location(), - error.message()); - return error; + error_handler()->OnSingleDatatypeUnrecoverableError( + error.location(), error.message()); + return error; + case sync_api::WriteNode::INIT_FAILED_SET_PREDECESSOR: + error.Reset(FROM_HERE, error_prefix + "failed to set predecessor", + type); + error_handler()->OnSingleDatatypeUnrecoverableError( + error.location(), error.message()); + return error; + default: + error.Reset(FROM_HERE, error_prefix + "unknown error", type); + error_handler()->OnSingleDatatypeUnrecoverableError( + error.location(), error.message()); + return error; + } } sync_node.SetTitle(UTF8ToWide(change.sync_data().GetTitle())); sync_node.SetEntitySpecifics(change.sync_data().GetSpecifics()); diff --git a/chrome/browser/sync/glue/password_change_processor.cc b/chrome/browser/sync/glue/password_change_processor.cc index ad3572c..870d3a3 100644 --- a/chrome/browser/sync/glue/password_change_processor.cc +++ b/chrome/browser/sync/glue/password_change_processor.cc @@ -82,8 +82,10 @@ void PasswordChangeProcessor::Observe( switch (change->type()) { case PasswordStoreChange::ADD: { sync_api::WriteNode sync_node(&trans); - if (sync_node.InitUniqueByCreation(syncable::PASSWORDS, - password_root, tag)) { + sync_api::WriteNode::InitUniqueByCreationResult result = + sync_node.InitUniqueByCreation(syncable::PASSWORDS, password_root, + tag); + if (result == sync_api::WriteNode::INIT_SUCCESS) { PasswordModelAssociator::WriteToSyncNode(change->form(), &sync_node); model_associator_->Associate(&tag, sync_node.GetId()); break; diff --git a/chrome/browser/sync/glue/password_model_associator.cc b/chrome/browser/sync/glue/password_model_associator.cc index 6565c27..8836f67 100644 --- a/chrome/browser/sync/glue/password_model_associator.cc +++ b/chrome/browser/sync/glue/password_model_associator.cc @@ -117,8 +117,9 @@ SyncError PasswordModelAssociator::AssociateModels() { Associate(&tag, node.GetId()); } else { sync_api::WriteNode node(&trans); - if (!node.InitUniqueByCreation(syncable::PASSWORDS, - password_root, tag)) { + sync_api::WriteNode::InitUniqueByCreationResult result = + node.InitUniqueByCreation(syncable::PASSWORDS, password_root, tag); + if (result != sync_api::WriteNode::INIT_SUCCESS) { STLDeleteElements(&passwords); return error_handler_->CreateAndUploadError( FROM_HERE, diff --git a/chrome/browser/sync/glue/session_model_associator.cc b/chrome/browser/sync/glue/session_model_associator.cc index d89576b..d7f58b0 100644 --- a/chrome/browser/sync/glue/session_model_associator.cc +++ b/chrome/browser/sync/glue/session_model_associator.cc @@ -765,9 +765,9 @@ SyncError SessionModelAssociator::AssociateModels() { if (local_session_syncid_ == sync_api::kInvalidId) { // The sync db didn't have a header node for us, we need to create one. sync_api::WriteNode write_node(&trans); - if (!write_node.InitUniqueByCreation(SESSIONS, - root, - current_machine_tag_)) { + sync_api::WriteNode::InitUniqueByCreationResult result = + write_node.InitUniqueByCreation(SESSIONS, root, current_machine_tag_); + if (result != sync_api::WriteNode::INIT_SUCCESS) { // If we can't look it up, and we can't create it, chances are there's // a pre-existing node that has encryption issues. But, since we can't // load the item, we can't remove it, and error out at this point. @@ -1354,7 +1354,9 @@ int64 SessionModelAssociator::TabNodePool::GetFreeTabNode() { size_t tab_node_id = tab_syncid_pool_.size(); std::string tab_node_tag = TabIdToTag(machine_tag_, tab_node_id); sync_api::WriteNode tab_node(&trans); - if (!tab_node.InitUniqueByCreation(SESSIONS, root, tab_node_tag)) { + sync_api::WriteNode::InitUniqueByCreationResult result = + tab_node.InitUniqueByCreation(SESSIONS, root, tab_node_tag); + if (result != sync_api::WriteNode::INIT_SUCCESS) { LOG(ERROR) << "Could not create new node with tag " << tab_node_tag << "!"; return sync_api::kInvalidId; diff --git a/chrome/browser/sync/glue/theme_model_associator.cc b/chrome/browser/sync/glue/theme_model_associator.cc index 8ea538a3..1d9682e 100644 --- a/chrome/browser/sync/glue/theme_model_associator.cc +++ b/chrome/browser/sync/glue/theme_model_associator.cc @@ -68,8 +68,10 @@ SyncError ThemeModelAssociator::AssociateModels() { } else { // Set the sync data from the current theme. sync_api::WriteNode node(&trans); - if (!node.InitUniqueByCreation(syncable::THEMES, root, - kCurrentThemeClientTag)) { + sync_api::WriteNode::InitUniqueByCreationResult result = + node.InitUniqueByCreation(syncable::THEMES, root, + kCurrentThemeClientTag); + if (result != sync_api::WriteNode::INIT_SUCCESS) { return error_handler_->CreateAndUploadError( FROM_HERE, "Could not create current theme node.", diff --git a/chrome/browser/sync/glue/typed_url_change_processor.cc b/chrome/browser/sync/glue/typed_url_change_processor.cc index b1fdd59..34b1223 100644 --- a/chrome/browser/sync/glue/typed_url_change_processor.cc +++ b/chrome/browser/sync/glue/typed_url_change_processor.cc @@ -162,8 +162,10 @@ bool TypedUrlChangeProcessor::CreateOrUpdateSyncNode( } } else { sync_api::WriteNode create_node(trans); - if (!create_node.InitUniqueByCreation(syncable::TYPED_URLS, - typed_url_root, tag)) { + sync_api::WriteNode::InitUniqueByCreationResult result = + create_node.InitUniqueByCreation(syncable::TYPED_URLS, + typed_url_root, tag); + if (result != sync_api::WriteNode::INIT_SUCCESS) { error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, "Failed to create typed_url sync node."); return false; diff --git a/chrome/browser/sync/glue/typed_url_model_associator.cc b/chrome/browser/sync/glue/typed_url_model_associator.cc index ad90e63..45e9b79 100644 --- a/chrome/browser/sync/glue/typed_url_model_associator.cc +++ b/chrome/browser/sync/glue/typed_url_model_associator.cc @@ -273,8 +273,10 @@ SyncError TypedUrlModelAssociator::DoAssociateModels() { } else { // Sync has never seen this URL before. sync_api::WriteNode node(&trans); - if (!node.InitUniqueByCreation(syncable::TYPED_URLS, - typed_url_root, tag)) { + sync_api::WriteNode::InitUniqueByCreationResult result = + node.InitUniqueByCreation(syncable::TYPED_URLS, + typed_url_root, tag); + if (result != sync_api::WriteNode::INIT_SUCCESS) { return error_handler_->CreateAndUploadError( FROM_HERE, "Failed to create typed_url sync node: " + tag, diff --git a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc index 2e42c17..12126d0 100644 --- a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc @@ -460,7 +460,9 @@ class ProfileSyncServiceAutofillTest : public AbstractProfileSyncServiceTest { sync_api::WriteNode node(&trans); std::string tag = AutocompleteSyncableService::KeyToTag( UTF16ToUTF8(entry.key().name()), UTF16ToUTF8(entry.key().value())); - if (!node.InitUniqueByCreation(syncable::AUTOFILL, autofill_root, tag)) + sync_api::WriteNode::InitUniqueByCreationResult result = + node.InitUniqueByCreation(syncable::AUTOFILL, autofill_root, tag); + if (result != sync_api::WriteNode::INIT_SUCCESS) return false; sync_pb::EntitySpecifics specifics; @@ -480,9 +482,12 @@ class ProfileSyncServiceAutofillTest : public AbstractProfileSyncServiceTest { } sync_api::WriteNode node(&trans); std::string tag = profile.guid(); - if (!node.InitUniqueByCreation(syncable::AUTOFILL_PROFILE, - autofill_root, tag)) + sync_api::WriteNode::InitUniqueByCreationResult result = + node.InitUniqueByCreation(syncable::AUTOFILL_PROFILE, + autofill_root, tag); + if (result != sync_api::WriteNode::INIT_SUCCESS) return false; + sync_pb::EntitySpecifics specifics; AutofillProfileSyncableService::WriteAutofillProfile(profile, &specifics); sync_pb::AutofillProfileSpecifics* profile_specifics = diff --git a/chrome/browser/sync/profile_sync_service_password_unittest.cc b/chrome/browser/sync/profile_sync_service_password_unittest.cc index 7185ea9..caf789c 100644 --- a/chrome/browser/sync/profile_sync_service_password_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_password_unittest.cc @@ -146,9 +146,9 @@ class ProfileSyncServicePasswordTest : public AbstractProfileSyncServiceTest { sync_api::WriteNode node(&trans); std::string tag = PasswordModelAssociator::MakeTag(entry); - ASSERT_TRUE(node.InitUniqueByCreation(syncable::PASSWORDS, - password_root, - tag)); + sync_api::WriteNode::InitUniqueByCreationResult result = + node.InitUniqueByCreation(syncable::PASSWORDS, password_root, tag); + ASSERT_EQ(sync_api::WriteNode::INIT_SUCCESS, result); PasswordModelAssociator::WriteToSyncNode(entry, &node); } diff --git a/chrome/browser/sync/profile_sync_service_preference_unittest.cc b/chrome/browser/sync/profile_sync_service_preference_unittest.cc index 618ccbd..d85830f 100644 --- a/chrome/browser/sync/profile_sync_service_preference_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_preference_unittest.cc @@ -75,7 +75,10 @@ class ProfileSyncServicePreferenceTest sync_api::BaseNode::INIT_OK) { return WriteSyncedValue(name, value, &tag_node); } - if (node.InitUniqueByCreation(syncable::PREFERENCES, root, name)) + + sync_api::WriteNode::InitUniqueByCreationResult result = + node.InitUniqueByCreation(syncable::PREFERENCES, root, name); + if (result == sync_api::WriteNode::INIT_SUCCESS) return WriteSyncedValue(name, value, &node); return sync_api::kInvalidId; diff --git a/chrome/browser/sync/profile_sync_service_session_unittest.cc b/chrome/browser/sync/profile_sync_service_session_unittest.cc index 87287fb..368613c 100644 --- a/chrome/browser/sync/profile_sync_service_session_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_session_unittest.cc @@ -1025,8 +1025,9 @@ TEST_F(ProfileSyncServiceSessionTest, DISABLED_MissingHeaderAndTab) { sync_api::ReadNode root(&trans); root.InitByTagLookup(syncable::ModelTypeToRootTag(syncable::SESSIONS)); sync_api::WriteNode extra_header(&trans); - ASSERT_TRUE(extra_header.InitUniqueByCreation(syncable::SESSIONS, - root, "new_tag")); + sync_api::WriteNode::InitUniqueByCreationResult result = + extra_header.InitUniqueByCreation(syncable::SESSIONS, root, "new_tag"); + ASSERT_EQ(sync_api::WriteNode::INIT_SUCCESS, result); sync_pb::SessionSpecifics specifics; specifics.set_session_tag(local_tag); extra_header.SetSessionSpecifics(specifics); @@ -1055,8 +1056,10 @@ TEST_F(ProfileSyncServiceSessionTest, DISABLED_MultipleHeaders) { sync_api::ReadNode root(&trans); root.InitByTagLookup(syncable::ModelTypeToRootTag(syncable::SESSIONS)); sync_api::WriteNode extra_header(&trans); - ASSERT_TRUE(extra_header.InitUniqueByCreation(syncable::SESSIONS, - root, local_tag + "_")); + sync_api::WriteNode::InitUniqueByCreationResult result = + extra_header.InitUniqueByCreation(syncable::SESSIONS, + root, local_tag + "_"); + ASSERT_EQ(sync_api::WriteNode::INIT_SUCCESS, result); sync_pb::SessionSpecifics specifics; specifics.set_session_tag(local_tag); specifics.mutable_header(); @@ -1086,8 +1089,10 @@ TEST_F(ProfileSyncServiceSessionTest, DISABLED_CorruptedForeign) { sync_api::ReadNode root(&trans); root.InitByTagLookup(syncable::ModelTypeToRootTag(syncable::SESSIONS)); sync_api::WriteNode extra_header(&trans); - ASSERT_TRUE(extra_header.InitUniqueByCreation(syncable::SESSIONS, - root, foreign_tag)); + sync_api::WriteNode::InitUniqueByCreationResult result = + extra_header.InitUniqueByCreation(syncable::SESSIONS, + root, foreign_tag); + ASSERT_EQ(sync_api::WriteNode::INIT_SUCCESS, result); sync_pb::SessionSpecifics specifics; specifics.set_session_tag(foreign_tag); extra_header.SetSessionSpecifics(specifics); diff --git a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc index 9a472b5..a51c24f 100644 --- a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc @@ -172,9 +172,9 @@ class ProfileSyncServiceTypedUrlTest : public AbstractProfileSyncServiceTest { sync_api::WriteNode node(&trans); std::string tag = url.url().spec(); - ASSERT_TRUE(node.InitUniqueByCreation(syncable::TYPED_URLS, - typed_url_root, - tag)); + sync_api::WriteNode::InitUniqueByCreationResult result = + node.InitUniqueByCreation(syncable::TYPED_URLS, typed_url_root, tag); + ASSERT_EQ(sync_api::WriteNode::INIT_SUCCESS, result); TypedUrlModelAssociator::WriteToSyncNode(url, visits, &node); } diff --git a/sync/internal_api/syncapi_unittest.cc b/sync/internal_api/syncapi_unittest.cc index 27bb115..6b38a4f 100644 --- a/sync/internal_api/syncapi_unittest.cc +++ b/sync/internal_api/syncapi_unittest.cc @@ -131,7 +131,9 @@ int64 MakeNode(UserShare* share, ReadNode root_node(&trans); root_node.InitByRootLookup(); WriteNode node(&trans); - EXPECT_TRUE(node.InitUniqueByCreation(model_type, root_node, client_tag)); + sync_api::WriteNode::InitUniqueByCreationResult result = + node.InitUniqueByCreation(model_type, root_node, client_tag); + EXPECT_EQ(sync_api::WriteNode::INIT_SUCCESS, result); node.SetIsFolder(false); return node.GetId(); } @@ -146,7 +148,9 @@ int64 MakeNodeWithParent(UserShare* share, ReadNode parent_node(&trans); EXPECT_EQ(BaseNode::INIT_OK, parent_node.InitByIdLookup(parent_id)); WriteNode node(&trans); - EXPECT_TRUE(node.InitUniqueByCreation(model_type, parent_node, client_tag)); + sync_api::WriteNode::InitUniqueByCreationResult result = + node.InitUniqueByCreation(model_type, parent_node, client_tag); + EXPECT_EQ(sync_api::WriteNode::INIT_SUCCESS, result); node.SetIsFolder(false); return node.GetId(); } @@ -375,8 +379,9 @@ TEST_F(SyncApiTest, TestDeleteBehavior) { folder_id = folder_node.GetId(); WriteNode wnode(&trans); - EXPECT_TRUE(wnode.InitUniqueByCreation(syncable::BOOKMARKS, - root_node, "testtag")); + sync_api::WriteNode::InitUniqueByCreationResult result = + wnode.InitUniqueByCreation(syncable::BOOKMARKS, root_node, "testtag"); + EXPECT_EQ(sync_api::WriteNode::INIT_SUCCESS, result); wnode.SetIsFolder(false); wnode.SetTitle(UTF8ToWide(test_title)); @@ -416,8 +421,9 @@ TEST_F(SyncApiTest, TestDeleteBehavior) { WriteNode wnode(&trans); // This will undelete the tag. - EXPECT_TRUE(wnode.InitUniqueByCreation(syncable::BOOKMARKS, - folder_node, "testtag")); + sync_api::WriteNode::InitUniqueByCreationResult result = + wnode.InitUniqueByCreation(syncable::BOOKMARKS, folder_node, "testtag"); + EXPECT_EQ(sync_api::WriteNode::INIT_SUCCESS, result); EXPECT_EQ(wnode.GetIsFolder(), false); EXPECT_EQ(wnode.GetParentId(), folder_node.GetId()); EXPECT_EQ(wnode.GetId(), node_id); @@ -449,8 +455,10 @@ TEST_F(SyncApiTest, WriteAndReadPassword) { root_node.InitByRootLookup(); WriteNode password_node(&trans); - EXPECT_TRUE(password_node.InitUniqueByCreation(syncable::PASSWORDS, - root_node, "foo")); + sync_api::WriteNode::InitUniqueByCreationResult result = + password_node.InitUniqueByCreation(syncable::PASSWORDS, + root_node, "foo"); + EXPECT_EQ(sync_api::WriteNode::INIT_SUCCESS, result); sync_pb::PasswordSpecificsData data; data.set_password_value("secret"); password_node.SetPasswordSpecifics(data); @@ -483,13 +491,16 @@ TEST_F(SyncApiTest, WriteEncryptedTitle) { root_node.InitByRootLookup(); WriteNode bookmark_node(&trans); - EXPECT_TRUE(bookmark_node.InitUniqueByCreation(syncable::BOOKMARKS, - root_node, "foo")); + sync_api::WriteNode::InitUniqueByCreationResult result = + bookmark_node.InitUniqueByCreation(syncable::BOOKMARKS, + root_node, "foo"); + EXPECT_EQ(sync_api::WriteNode::INIT_SUCCESS, result); bookmark_node.SetTitle(UTF8ToWide("foo")); WriteNode pref_node(&trans); - EXPECT_TRUE(pref_node.InitUniqueByCreation(syncable::PREFERENCES, - root_node, "bar")); + result = + pref_node.InitUniqueByCreation(syncable::PREFERENCES, root_node, "bar"); + EXPECT_EQ(sync_api::WriteNode::INIT_SUCCESS, result); pref_node.SetTitle(UTF8ToWide("bar")); } { @@ -627,8 +638,9 @@ TEST_F(SyncApiTest, EmptyTags) { root_node.InitByRootLookup(); WriteNode node(&trans); std::string empty_tag; - EXPECT_FALSE(node.InitUniqueByCreation( - syncable::TYPED_URLS, root_node, empty_tag)); + sync_api::WriteNode::InitUniqueByCreationResult result = + node.InitUniqueByCreation(syncable::TYPED_URLS, root_node, empty_tag); + EXPECT_NE(sync_api::WriteNode::INIT_SUCCESS, result); EXPECT_EQ(BaseNode::INIT_FAILED_PRECONDITION, node.InitByTagLookup(empty_tag)); } @@ -1586,8 +1598,10 @@ TEST_F(SyncManagerTest, SetPassphraseWithPassword) { root_node.InitByRootLookup(); WriteNode password_node(&trans); - EXPECT_TRUE(password_node.InitUniqueByCreation(syncable::PASSWORDS, - root_node, "foo")); + sync_api::WriteNode::InitUniqueByCreationResult result = + password_node.InitUniqueByCreation(syncable::PASSWORDS, + root_node, "foo"); + EXPECT_EQ(sync_api::WriteNode::INIT_SUCCESS, result); sync_pb::PasswordSpecificsData data; data.set_password_value("secret"); password_node.SetPasswordSpecifics(data); @@ -1818,8 +1832,9 @@ TEST_F(SyncManagerTest, SetPassphraseWithEmptyPasswordNode) { root_node.InitByRootLookup(); WriteNode password_node(&trans); - EXPECT_TRUE(password_node.InitUniqueByCreation(syncable::PASSWORDS, - root_node, tag)); + sync_api::WriteNode::InitUniqueByCreationResult result = + password_node.InitUniqueByCreation(syncable::PASSWORDS, root_node, tag); + EXPECT_EQ(sync_api::WriteNode::INIT_SUCCESS, result); node_id = password_node.GetId(); } EXPECT_CALL(observer_, OnBootstrapTokenUpdated(_)); diff --git a/sync/internal_api/write_node.cc b/sync/internal_api/write_node.cc index ce20e31..68d3db7 100644 --- a/sync/internal_api/write_node.cc +++ b/sync/internal_api/write_node.cc @@ -364,13 +364,15 @@ bool WriteNode::InitByCreation(syncable::ModelType model_type, // we will attempt to undelete the node. // TODO(chron): Code datatype into hash tag. // TODO(chron): Is model type ever lost? -bool WriteNode::InitUniqueByCreation(syncable::ModelType model_type, - const BaseNode& parent, - const std::string& tag) { - DCHECK(!entry_) << "Init called twice"; +WriteNode::InitUniqueByCreationResult WriteNode::InitUniqueByCreation( + syncable::ModelType model_type, + const BaseNode& parent, + const std::string& tag) { + // This DCHECK will only fail if init is called twice. + DCHECK(!entry_); if (tag.empty()) { LOG(WARNING) << "InitUniqueByCreation failed due to empty tag."; - return false; + return INIT_FAILED_EMPTY_TAG; } const std::string hash = GenerateSyncableHash(model_type, tag); @@ -415,14 +417,13 @@ bool WriteNode::InitUniqueByCreation(syncable::ModelType model_type, existing_entry->Put(syncable::PARENT_ID, parent_id); entry_ = existing_entry.release(); } else { - return false; + return INIT_FAILED_ENTRY_ALREADY_EXISTS; } } else { entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), syncable::CREATE, parent_id, dummy); - if (!entry_->good()) { - return false; - } + if (!entry_->good()) + return INIT_FAILED_COULD_NOT_CREATE_ENTRY; // Only set IS_DIR for new entries. Don't bitflip undeleted ones. entry_->Put(syncable::UNIQUE_CLIENT_TAG, hash); @@ -435,7 +436,11 @@ bool WriteNode::InitUniqueByCreation(syncable::ModelType model_type, PutModelType(model_type); // Now set the predecessor, which sets IS_UNSYNCED as necessary. - return PutPredecessor(NULL); + bool success = PutPredecessor(NULL); + if (!success) + return INIT_FAILED_SET_PREDECESSOR; + + return INIT_SUCCESS; } bool WriteNode::SetPosition(const BaseNode& new_parent, diff --git a/sync/internal_api/write_node.h b/sync/internal_api/write_node.h index a070a5c..a87a377 100644 --- a/sync/internal_api/write_node.h +++ b/sync/internal_api/write_node.h @@ -46,6 +46,18 @@ class WriteTransaction; // syncable::MutableEntry. A WriteTransaction is needed to create a WriteNode. class WriteNode : public BaseNode { public: + enum InitUniqueByCreationResult { + INIT_SUCCESS, + // The tag passed into this method was empty. + INIT_FAILED_EMPTY_TAG, + // An entry with this tag already exists. + INIT_FAILED_ENTRY_ALREADY_EXISTS, + // The constructor for a new MutableEntry with the specified data failed. + INIT_FAILED_COULD_NOT_CREATE_ENTRY, + // Setting the predecessor failed + INIT_FAILED_SET_PREDECESSOR, + }; + // Create a WriteNode using the given transaction. explicit WriteNode(WriteTransaction* transaction); virtual ~WriteNode(); @@ -75,9 +87,10 @@ class WriteNode : public BaseNode { // Most importantly, if it exists locally, this function will // actually undelete it // Client unique tagged nodes must NOT be folders. - bool InitUniqueByCreation(syncable::ModelType model_type, - const BaseNode& parent, - const std::string& client_tag); + InitUniqueByCreationResult InitUniqueByCreation( + syncable::ModelType model_type, + const BaseNode& parent, + const std::string& client_tag); // Each server-created permanent node is tagged with a unique string. // Look up the node with the particular tag. If it does not exist, |