Commit 8d56b3a9 authored by stanisc's avatar stanisc Committed by Commit bot

Sync: support implicit permanent folders in commits.

Traversal::AddUncommittedParentsAndTheirPredecessors walks the
hierarchy to sort commits which is not necessary for any types
except bookmarks.
We've seen some crashes here when implicit permanent folders
were turned on alpha server. I reproduced the crash by planting
an empty parent ID in the database.

The fix avoids traversing the hierarchy for committed items with
unset parent IDs. Verified that this has stopped the crash
locally and successfully committed the item.

BUG=438313

Review URL: https://codereview.chromium.org/1023843002

Cr-Commit-Position: refs/heads/master@{#321472}
parent ff9d79e7
...@@ -38,13 +38,15 @@ class DirectoryCommitContributionTest : public ::testing::Test { ...@@ -38,13 +38,15 @@ class DirectoryCommitContributionTest : public ::testing::Test {
ModelType type, ModelType type,
const std::string& tag, const std::string& tag,
const sync_pb::AttachmentMetadata& attachment_metadata) { const sync_pb::AttachmentMetadata& attachment_metadata) {
// For bookmarks specify the Bookmarks root folder as the parent;
// for other types leave the parent ID empty
syncable::Id parent_id;
if (type == BOOKMARKS) {
syncable::Entry parent_entry(trans, syncable::GET_TYPE_ROOT, type); syncable::Entry parent_entry(trans, syncable::GET_TYPE_ROOT, type);
syncable::MutableEntry entry( parent_id = parent_entry.GetId();
trans, }
syncable::CREATE,
type, syncable::MutableEntry entry(trans, syncable::CREATE, type, parent_id, tag);
parent_entry.GetId(),
tag);
if (attachment_metadata.record_size() > 0) { if (attachment_metadata.record_size() > 0) {
entry.PutAttachmentMetadata(attachment_metadata); entry.PutAttachmentMetadata(attachment_metadata);
} }
......
...@@ -254,6 +254,8 @@ class Traversal { ...@@ -254,6 +254,8 @@ class Traversal {
const syncable::Directory::Metahandles& traversed, const syncable::Directory::Metahandles& traversed,
syncable::Directory::Metahandles* result) const; syncable::Directory::Metahandles* result) const;
bool SupportsHierarchy(const syncable::Entry& item) const;
// Returns true if we've collected enough items. // Returns true if we've collected enough items.
bool IsFull() const; bool IsFull() const;
...@@ -288,6 +290,7 @@ bool Traversal::AddUncommittedParentsAndTheirPredecessors( ...@@ -288,6 +290,7 @@ bool Traversal::AddUncommittedParentsAndTheirPredecessors(
const std::set<int64>& ready_unsynced_set, const std::set<int64>& ready_unsynced_set,
const syncable::Entry& item, const syncable::Entry& item,
syncable::Directory::Metahandles* result) const { syncable::Directory::Metahandles* result) const {
DCHECK(SupportsHierarchy(item));
syncable::Directory::Metahandles dependencies; syncable::Directory::Metahandles dependencies;
syncable::Id parent_id = item.GetParentId(); syncable::Id parent_id = item.GetParentId();
...@@ -393,6 +396,7 @@ bool Traversal::AddDeletedParents( ...@@ -393,6 +396,7 @@ bool Traversal::AddDeletedParents(
const syncable::Entry& item, const syncable::Entry& item,
const syncable::Directory::Metahandles& traversed, const syncable::Directory::Metahandles& traversed,
syncable::Directory::Metahandles* result) const { syncable::Directory::Metahandles* result) const {
DCHECK(SupportsHierarchy(item));
syncable::Directory::Metahandles dependencies; syncable::Directory::Metahandles dependencies;
syncable::Id parent_id = item.GetParentId(); syncable::Id parent_id = item.GetParentId();
...@@ -448,6 +452,10 @@ bool Traversal::HaveItem(int64 handle) const { ...@@ -448,6 +452,10 @@ bool Traversal::HaveItem(int64 handle) const {
return added_handles_.find(handle) != added_handles_.end(); return added_handles_.find(handle) != added_handles_.end();
} }
bool Traversal::SupportsHierarchy(const syncable::Entry& item) const {
return !item.GetParentId().IsNull();
}
void Traversal::AppendManyToTraversal( void Traversal::AppendManyToTraversal(
const syncable::Directory::Metahandles& handles) { const syncable::Directory::Metahandles& handles) {
out_->insert(out_->end(), handles.begin(), handles.end()); out_->insert(out_->end(), handles.begin(), handles.end());
...@@ -472,18 +480,20 @@ void Traversal::AddCreatesAndMoves( ...@@ -472,18 +480,20 @@ void Traversal::AddCreatesAndMoves(
syncable::GET_BY_HANDLE, syncable::GET_BY_HANDLE,
metahandle); metahandle);
if (!entry.GetIsDel()) { if (!entry.GetIsDel()) {
if (SupportsHierarchy(entry)) {
// We only commit an item + its dependencies if it and all its // We only commit an item + its dependencies if it and all its
// dependencies are not in conflict. // dependencies are not in conflict.
syncable::Directory::Metahandles item_dependencies; syncable::Directory::Metahandles item_dependencies;
if (AddUncommittedParentsAndTheirPredecessors( if (AddUncommittedParentsAndTheirPredecessors(ready_unsynced_set, entry,
ready_unsynced_set,
entry,
&item_dependencies)) { &item_dependencies)) {
AddPredecessorsThenItem(ready_unsynced_set, AddPredecessorsThenItem(ready_unsynced_set, entry,
entry,
&item_dependencies); &item_dependencies);
AppendManyToTraversal(item_dependencies); AppendManyToTraversal(item_dependencies);
} }
} else {
// No hierarchy dependencies, just commit the item itself.
AppendToTraversal(metahandle);
}
} }
} }
...@@ -515,15 +525,18 @@ void Traversal::AddDeletes(const std::set<int64>& ready_unsynced_set) { ...@@ -515,15 +525,18 @@ void Traversal::AddDeletes(const std::set<int64>& ready_unsynced_set) {
metahandle); metahandle);
if (entry.GetIsDel()) { if (entry.GetIsDel()) {
if (SupportsHierarchy(entry)) {
syncable::Directory::Metahandles parents; syncable::Directory::Metahandles parents;
if (AddDeletedParents( if (AddDeletedParents(ready_unsynced_set, entry, deletion_list,
ready_unsynced_set, entry, deletion_list, &parents)) { &parents)) {
// Append parents and chilren in top to bottom order. // Append parents and chilren in top to bottom order.
deletion_list.insert(deletion_list.end(), deletion_list.insert(deletion_list.end(), parents.begin(),
parents.begin(),
parents.end()); parents.end());
deletion_list.push_back(metahandle); deletion_list.push_back(metahandle);
} }
} else {
deletion_list.push_back(metahandle);
}
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment