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) {
syncable::Entry parent_entry(trans, syncable::GET_TYPE_ROOT, type); // For bookmarks specify the Bookmarks root folder as the parent;
syncable::MutableEntry entry( // for other types leave the parent ID empty
trans, syncable::Id parent_id;
syncable::CREATE, if (type == BOOKMARKS) {
type, syncable::Entry parent_entry(trans, syncable::GET_TYPE_ROOT, type);
parent_entry.GetId(), parent_id = parent_entry.GetId();
tag); }
syncable::MutableEntry entry(trans, syncable::CREATE, type, parent_id, 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,17 +480,19 @@ void Traversal::AddCreatesAndMoves( ...@@ -472,17 +480,19 @@ void Traversal::AddCreatesAndMoves(
syncable::GET_BY_HANDLE, syncable::GET_BY_HANDLE,
metahandle); metahandle);
if (!entry.GetIsDel()) { if (!entry.GetIsDel()) {
// We only commit an item + its dependencies if it and all its if (SupportsHierarchy(entry)) {
// dependencies are not in conflict. // We only commit an item + its dependencies if it and all its
syncable::Directory::Metahandles item_dependencies; // dependencies are not in conflict.
if (AddUncommittedParentsAndTheirPredecessors( syncable::Directory::Metahandles item_dependencies;
ready_unsynced_set, if (AddUncommittedParentsAndTheirPredecessors(ready_unsynced_set, entry,
entry, &item_dependencies)) {
&item_dependencies)) { AddPredecessorsThenItem(ready_unsynced_set, entry,
AddPredecessorsThenItem(ready_unsynced_set, &item_dependencies);
entry, AppendManyToTraversal(item_dependencies);
&item_dependencies); }
AppendManyToTraversal(item_dependencies); } else {
// No hierarchy dependencies, just commit the item itself.
AppendToTraversal(metahandle);
} }
} }
} }
...@@ -515,13 +525,16 @@ void Traversal::AddDeletes(const std::set<int64>& ready_unsynced_set) { ...@@ -515,13 +525,16 @@ void Traversal::AddDeletes(const std::set<int64>& ready_unsynced_set) {
metahandle); metahandle);
if (entry.GetIsDel()) { if (entry.GetIsDel()) {
syncable::Directory::Metahandles parents; if (SupportsHierarchy(entry)) {
if (AddDeletedParents( syncable::Directory::Metahandles parents;
ready_unsynced_set, entry, deletion_list, &parents)) { if (AddDeletedParents(ready_unsynced_set, entry, deletion_list,
// Append parents and chilren in top to bottom order. &parents)) {
deletion_list.insert(deletion_list.end(), // Append parents and chilren in top to bottom order.
parents.begin(), deletion_list.insert(deletion_list.end(), parents.begin(),
parents.end()); parents.end());
deletion_list.push_back(metahandle);
}
} else {
deletion_list.push_back(metahandle); 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