| Index: chrome/browser/sync/syncable/syncable.cc
|
| diff --git a/chrome/browser/sync/syncable/syncable.cc b/chrome/browser/sync/syncable/syncable.cc
|
| old mode 100644
|
| new mode 100755
|
| index af2cf286a216a45a35fa553993fdda801d4a5d10..97dd525224daa43a1dc018568db88ffda5bd8711
|
| --- a/chrome/browser/sync/syncable/syncable.cc
|
| +++ b/chrome/browser/sync/syncable/syncable.cc
|
| @@ -22,6 +22,7 @@
|
| #include <functional>
|
| #include <iomanip>
|
| #include <iterator>
|
| +#include <limits>
|
| #include <set>
|
| #include <string>
|
|
|
| @@ -88,6 +89,7 @@ int64 Now() {
|
| // Compare functions and hashes for the indices.
|
|
|
| // Callback for sqlite3
|
| +// TODO(chron): This should be somewhere else
|
| int ComparePathNames16(void*, int a_bytes, const void* a, int b_bytes,
|
| const void* b) {
|
| int result = base::strncasecmp(reinterpret_cast<const char *>(a),
|
| @@ -118,35 +120,32 @@ class HashField {
|
| base::hash_set<int64> hasher_;
|
| };
|
|
|
| -// TODO(ncarter): Rename!
|
| +// TODO(chron): Remove this function.
|
| int ComparePathNames(const PathString& a, const PathString& b) {
|
| const size_t val_size = sizeof(PathString::value_type);
|
| return ComparePathNames16(NULL, a.size() * val_size, a.data(),
|
| b.size() * val_size, b.data());
|
| }
|
|
|
| -class LessParentIdAndNames {
|
| +class LessParentIdAndHandle {
|
| public:
|
| bool operator() (const syncable::EntryKernel* a,
|
| const syncable::EntryKernel* b) const {
|
| - if (a->ref(PARENT_ID) != b->ref(PARENT_ID))
|
| + if (a->ref(PARENT_ID) != b->ref(PARENT_ID)) {
|
| return a->ref(PARENT_ID) < b->ref(PARENT_ID);
|
| - return ComparePathNames(a->ref(NAME), b->ref(NAME)) < 0;
|
| + }
|
| +
|
| + // Meta handles are immutable per entry so this is ideal.
|
| + return a->ref(META_HANDLE) < b->ref(META_HANDLE);
|
| }
|
| };
|
|
|
| +// TODO(chron): Remove this function.
|
| bool LessPathNames::operator() (const PathString& a,
|
| const PathString& b) const {
|
| return ComparePathNames(a, b) < 0;
|
| }
|
|
|
| -// static
|
| -Name Name::FromEntryKernel(EntryKernel* kernel) {
|
| - PathString& sync_name_ref = kernel->ref(UNSANITIZED_NAME).empty() ?
|
| - kernel->ref(NAME) : kernel->ref(UNSANITIZED_NAME);
|
| - return Name(kernel->ref(NAME), sync_name_ref, kernel->ref(NON_UNIQUE_NAME));
|
| -}
|
| -
|
| ///////////////////////////////////////////////////////////////////////////
|
| // Directory
|
|
|
| @@ -161,7 +160,7 @@ Directory::Kernel::Kernel(const FilePath& db_path,
|
| name_(name),
|
| metahandles_index(new Directory::MetahandlesIndex),
|
| ids_index(new Directory::IdsIndex),
|
| - parent_id_and_names_index(new Directory::ParentIdAndNamesIndex),
|
| + parent_id_child_index(new Directory::ParentIdChildIndex),
|
| extended_attributes(new ExtendedAttributes),
|
| unapplied_update_metahandles(new MetahandleSet),
|
| unsynced_metahandles(new MetahandleSet),
|
| @@ -196,7 +195,7 @@ Directory::Kernel::~Kernel() {
|
| delete unsynced_metahandles;
|
| delete unapplied_update_metahandles;
|
| delete extended_attributes;
|
| - delete parent_id_and_names_index;
|
| + delete parent_id_child_index;
|
| delete ids_index;
|
| for_each(metahandles_index->begin(), metahandles_index->end(), DeleteEntry);
|
| delete metahandles_index;
|
| @@ -209,58 +208,6 @@ Directory::~Directory() {
|
| Close();
|
| }
|
|
|
| -BOOL PathNameMatch(const PathString& pathname, const PathString& pathspec) {
|
| -#if defined(OS_WIN)
|
| - // Note that if we go Vista only this is easier:
|
| - // http://msdn2.microsoft.com/en-us/library/ms628611.aspx
|
| -
|
| - // PathMatchSpec strips spaces from the start of pathspec, so we compare those
|
| - // ourselves.
|
| - const PathChar* pathname_ptr = pathname.c_str();
|
| - const PathChar* pathspec_ptr = pathspec.c_str();
|
| -
|
| - while (*pathname_ptr == ' ' && *pathspec_ptr == ' ')
|
| - ++pathname_ptr, ++pathspec_ptr;
|
| -
|
| - // If we have more inital spaces in the pathspec than in the pathname then the
|
| - // result from PathMatchSpec will be erroneous.
|
| - if (*pathspec_ptr == ' ')
|
| - return FALSE;
|
| -
|
| - // PathMatchSpec also gets "confused" when there are ';' characters in name or
|
| - // in spec. So, if we match (f.i.) ";" with ";" PathMatchSpec will return
|
| - // FALSE (which is wrong). Luckily for us, we can easily fix this by
|
| - // substituting ';' with ':' which is illegal character in file name and
|
| - // we're not going to see it there. With ':' in path name and spec
|
| - // PathMatchSpec works fine.
|
| - if ((NULL == strchr(pathname_ptr, ';')) &&
|
| - (NULL == strchr(pathspec_ptr, ';'))) {
|
| - // No ';' in file name and in spec. Just pass it as it is.
|
| - return ::PathMatchSpecA(pathname_ptr, pathspec_ptr);
|
| - }
|
| -
|
| - // We need to subst ';' with ':' in both, name and spec.
|
| - PathString name_subst(pathname_ptr);
|
| - PathString spec_subst(pathspec_ptr);
|
| -
|
| - PathString::size_type index = name_subst.find(L';');
|
| - while (PathString::npos != index) {
|
| - name_subst[index] = ':';
|
| - index = name_subst.find(';', index + 1);
|
| - }
|
| -
|
| - index = spec_subst.find(L';');
|
| - while (PathString::npos != index) {
|
| - spec_subst[index] = ':';
|
| - index = spec_subst.find(';', index + 1);
|
| - }
|
| -
|
| - return ::PathMatchSpecA(name_subst.c_str(), spec_subst.c_str());
|
| -#else
|
| - return 0 == ComparePathNames(pathname, pathspec);
|
| -#endif
|
| -}
|
| -
|
| DirOpenResult Directory::Open(const FilePath& file_path,
|
| const PathString& name) {
|
| const DirOpenResult result = OpenImpl(file_path, name);
|
| @@ -274,7 +221,7 @@ void Directory::InitializeIndices() {
|
| for (; it != kernel_->metahandles_index->end(); ++it) {
|
| EntryKernel* entry = *it;
|
| if (!entry->ref(IS_DEL))
|
| - kernel_->parent_id_and_names_index->insert(entry);
|
| + kernel_->parent_id_child_index->insert(entry);
|
| kernel_->ids_index->insert(entry);
|
| if (entry->ref(IS_UNSYNCED))
|
| kernel_->unsynced_metahandles->insert(entry->ref(META_HANDLE));
|
| @@ -377,61 +324,14 @@ EntryKernel* Directory::GetEntryByHandle(const int64 metahandle,
|
| return NULL;
|
| }
|
|
|
| -EntryKernel* Directory::GetChildWithName(const Id& parent_id,
|
| - const PathString& name) {
|
| - ScopedKernelLock lock(this);
|
| - return GetChildWithName(parent_id, name, &lock);
|
| -}
|
| -
|
| -// Will return child entry if the folder is opened,
|
| -// otherwise it will return NULL.
|
| -EntryKernel* Directory::GetChildWithName(const Id& parent_id,
|
| - const PathString& name,
|
| - ScopedKernelLock* const lock) {
|
| - PathString dbname = name;
|
| - EntryKernel* parent = GetEntryById(parent_id, lock);
|
| - if (parent == NULL)
|
| - return NULL;
|
| - return GetChildWithNameImpl(parent_id, dbname, lock);
|
| -}
|
| -
|
| -// Will return child entry even when the folder is not opened. This is used by
|
| -// syncer to apply update when folder is closed.
|
| -EntryKernel* Directory::GetChildWithDBName(const Id& parent_id,
|
| - const PathString& name) {
|
| - ScopedKernelLock lock(this);
|
| - return GetChildWithNameImpl(parent_id, name, &lock);
|
| -}
|
| -
|
| -EntryKernel* Directory::GetChildWithNameImpl(const Id& parent_id,
|
| - const PathString& name,
|
| - ScopedKernelLock* const lock) {
|
| - // First look up in memory:
|
| - kernel_->needle.ref(NAME) = name;
|
| - kernel_->needle.ref(PARENT_ID) = parent_id;
|
| - ParentIdAndNamesIndex::iterator found =
|
| - kernel_->parent_id_and_names_index->find(&kernel_->needle);
|
| - if (found != kernel_->parent_id_and_names_index->end()) {
|
| - // Found it in memory. Easy.
|
| - return *found;
|
| - }
|
| - return NULL;
|
| -}
|
| -
|
| // An interface to specify the details of which children
|
| // GetChildHandles() is looking for.
|
| +// TODO(chron): Clean this up into one function to get child handles
|
| struct PathMatcher {
|
| explicit PathMatcher(const Id& parent_id) : parent_id_(parent_id) { }
|
| virtual ~PathMatcher() { }
|
| - enum MatchType {
|
| - NO_MATCH,
|
| - MATCH,
|
| - // Means we found the only entry we're looking for in
|
| - // memory so we don't need to check the DB.
|
| - EXACT_MATCH
|
| - };
|
| - virtual MatchType PathMatches(const PathString& path) = 0;
|
| - typedef Directory::ParentIdAndNamesIndex Index;
|
| +
|
| + typedef Directory::ParentIdChildIndex Index;
|
| virtual Index::iterator lower_bound(Index* index) = 0;
|
| virtual Index::iterator upper_bound(Index* index) = 0;
|
| const Id parent_id_;
|
| @@ -439,48 +339,22 @@ struct PathMatcher {
|
| };
|
|
|
| // Matches all children.
|
| +// TODO(chron): Unit test this by itself
|
| struct AllPathsMatcher : public PathMatcher {
|
| explicit AllPathsMatcher(const Id& parent_id) : PathMatcher(parent_id) {
|
| }
|
| - virtual MatchType PathMatches(const PathString& path) {
|
| - return MATCH;
|
| - }
|
| - virtual Index::iterator lower_bound(Index* index) {
|
| - needle_.ref(PARENT_ID) = parent_id_;
|
| - needle_.ref(NAME).clear();
|
| - return index->lower_bound(&needle_);
|
| - }
|
|
|
| - virtual Index::iterator upper_bound(Index* index) {
|
| - needle_.ref(PARENT_ID) = parent_id_;
|
| - needle_.ref(NAME).clear();
|
| - Index::iterator i = index->upper_bound(&needle_),
|
| - end = index->end();
|
| - while (i != end && (*i)->ref(PARENT_ID) == parent_id_)
|
| - ++i;
|
| - return i;
|
| - }
|
| -};
|
| -
|
| -// Matches an exact filename only; no wildcards.
|
| -struct ExactPathMatcher : public PathMatcher {
|
| - ExactPathMatcher(const PathString& pathspec, const Id& parent_id)
|
| - : PathMatcher(parent_id), pathspec_(pathspec) {
|
| - }
|
| - virtual MatchType PathMatches(const PathString& path) {
|
| - return 0 == ComparePathNames(path, pathspec_) ? EXACT_MATCH : NO_MATCH;
|
| - }
|
| virtual Index::iterator lower_bound(Index* index) {
|
| needle_.ref(PARENT_ID) = parent_id_;
|
| - needle_.ref(NAME) = pathspec_;
|
| + needle_.ref(META_HANDLE) = std::numeric_limits<int64>::min();
|
| return index->lower_bound(&needle_);
|
| }
|
| +
|
| virtual Index::iterator upper_bound(Index* index) {
|
| needle_.ref(PARENT_ID) = parent_id_;
|
| - needle_.ref(NAME) = pathspec_;
|
| + needle_.ref(META_HANDLE) = std::numeric_limits<int64>::max();
|
| return index->upper_bound(&needle_);
|
| }
|
| - const PathString pathspec_;
|
| };
|
|
|
| void Directory::GetChildHandles(BaseTransaction* trans, const Id& parent_id,
|
| @@ -496,21 +370,17 @@ void Directory::GetChildHandlesImpl(BaseTransaction* trans, const Id& parent_id,
|
| result->clear();
|
| {
|
| ScopedKernelLock lock(this);
|
| - ParentIdAndNamesIndex* const index =
|
| - kernel_->parent_id_and_names_index;
|
| - typedef ParentIdAndNamesIndex::iterator iterator;
|
| +
|
| + // This index is sorted by parent id and metahandle.
|
| + ParentIdChildIndex* const index = kernel_->parent_id_child_index;
|
| + typedef ParentIdChildIndex::iterator iterator;
|
| for (iterator i = matcher->lower_bound(index),
|
| end = matcher->upper_bound(index); i != end; ++i) {
|
| // root's parent_id is NULL in the db but 0 in memory, so
|
| // have avoid listing the root as its own child.
|
| if ((*i)->ref(ID) == (*i)->ref(PARENT_ID))
|
| continue;
|
| - PathMatcher::MatchType match = matcher->PathMatches((*i)->ref(NAME));
|
| - if (PathMatcher::NO_MATCH == match)
|
| - continue;
|
| result->push_back((*i)->ref(META_HANDLE));
|
| - if (PathMatcher::EXACT_MATCH == match)
|
| - return;
|
| }
|
| }
|
| }
|
| @@ -519,17 +389,6 @@ EntryKernel* Directory::GetRootEntry() {
|
| return GetEntryById(Id());
|
| }
|
|
|
| -EntryKernel* Directory::GetEntryByPath(const PathString& path) {
|
| - CHECK(kernel_);
|
| - EntryKernel* result = GetRootEntry();
|
| - CHECK(result) << "There should always be a root node.";
|
| - for (PathSegmentIterator<PathString> i(path), end;
|
| - i != end && NULL != result; ++i) {
|
| - result = GetChildWithName(result->ref(ID), *i);
|
| - }
|
| - return result;
|
| -}
|
| -
|
| void ZeroFields(EntryKernel* entry, int first_field) {
|
| int i = first_field;
|
| // Note that bitset<> constructor sets all bits to zero, and strings
|
| @@ -554,29 +413,27 @@ void Directory::InsertEntry(EntryKernel* entry, ScopedKernelLock* lock) {
|
| CHECK(NULL != entry);
|
| static const char error[] = "Entry already in memory index.";
|
| CHECK(kernel_->metahandles_index->insert(entry).second) << error;
|
| - if (!entry->ref(IS_DEL))
|
| - CHECK(kernel_->parent_id_and_names_index->insert(entry).second) << error;
|
| +
|
| + if (!entry->ref(IS_DEL)) {
|
| + CHECK(kernel_->parent_id_child_index->insert(entry).second) << error;
|
| + }
|
| CHECK(kernel_->ids_index->insert(entry).second) << error;
|
| }
|
|
|
| -bool Directory::Undelete(EntryKernel* const entry) {
|
| +void Directory::Undelete(EntryKernel* const entry) {
|
| DCHECK(entry->ref(IS_DEL));
|
| ScopedKernelLock lock(this);
|
| - if (NULL != GetChildWithName(entry->ref(PARENT_ID), entry->ref(NAME), &lock))
|
| - return false; // Would have duplicated existing entry.
|
| entry->ref(IS_DEL) = false;
|
| entry->dirty[IS_DEL] = true;
|
| - CHECK(kernel_->parent_id_and_names_index->insert(entry).second);
|
| - return true;
|
| + CHECK(kernel_->parent_id_child_index->insert(entry).second);
|
| }
|
|
|
| -bool Directory::Delete(EntryKernel* const entry) {
|
| +void Directory::Delete(EntryKernel* const entry) {
|
| DCHECK(!entry->ref(IS_DEL));
|
| entry->ref(IS_DEL) = true;
|
| entry->dirty[IS_DEL] = true;
|
| ScopedKernelLock lock(this);
|
| - CHECK(1 == kernel_->parent_id_and_names_index->erase(entry));
|
| - return true;
|
| + CHECK(1 == kernel_->parent_id_child_index->erase(entry));
|
| }
|
|
|
| bool Directory::ReindexId(EntryKernel* const entry, const Id& new_id) {
|
| @@ -589,30 +446,22 @@ bool Directory::ReindexId(EntryKernel* const entry, const Id& new_id) {
|
| return true;
|
| }
|
|
|
| -bool Directory::ReindexParentIdAndName(EntryKernel* const entry,
|
| - const Id& new_parent_id,
|
| - const PathString& new_name) {
|
| +void Directory::ReindexParentId(EntryKernel* const entry,
|
| + const Id& new_parent_id) {
|
| +
|
| ScopedKernelLock lock(this);
|
| - PathString new_indexed_name = new_name;
|
| if (entry->ref(IS_DEL)) {
|
| entry->ref(PARENT_ID) = new_parent_id;
|
| - entry->ref(NAME) = new_indexed_name;
|
| - return true;
|
| + return;
|
| }
|
|
|
| - // check for a case changing rename
|
| - if (entry->ref(PARENT_ID) == new_parent_id &&
|
| - 0 == ComparePathNames(entry->ref(NAME), new_indexed_name)) {
|
| - entry->ref(NAME) = new_indexed_name;
|
| - } else {
|
| - if (NULL != GetChildWithName(new_parent_id, new_indexed_name, &lock))
|
| - return false;
|
| - CHECK(1 == kernel_->parent_id_and_names_index->erase(entry));
|
| - entry->ref(PARENT_ID) = new_parent_id;
|
| - entry->ref(NAME) = new_indexed_name;
|
| - CHECK(kernel_->parent_id_and_names_index->insert(entry).second);
|
| + if (entry->ref(PARENT_ID) == new_parent_id) {
|
| + return;
|
| }
|
| - return true;
|
| +
|
| + CHECK(1 == kernel_->parent_id_child_index->erase(entry));
|
| + entry->ref(PARENT_ID) = new_parent_id;
|
| + CHECK(kernel_->parent_id_child_index->insert(entry).second);
|
| }
|
|
|
| // static
|
| @@ -971,7 +820,7 @@ void Directory::CheckTreeInvariants(syncable::BaseTransaction* trans,
|
| }
|
| if (!e.Get(IS_DEL)) {
|
| CHECK(id != parentid) << e;
|
| - CHECK(!e.Get(NAME).empty()) << e;
|
| + CHECK(!e.Get(NON_UNIQUE_NAME).empty()) << e;
|
| int safety_count = handles.size() + 1;
|
| while (!parentid.IsRoot()) {
|
| if (!idfilter.ShouldConsider(parentid))
|
| @@ -1148,24 +997,6 @@ Entry::Entry(BaseTransaction* trans, GetByHandle, int64 metahandle)
|
| kernel_ = trans->directory()->GetEntryByHandle(metahandle);
|
| }
|
|
|
| -Entry::Entry(BaseTransaction* trans, GetByPath, const PathString& path)
|
| - : basetrans_(trans) {
|
| - kernel_ = trans->directory()->GetEntryByPath(path);
|
| -}
|
| -
|
| -Entry::Entry(BaseTransaction* trans, GetByParentIdAndName, const Id& parentid,
|
| - const PathString& name)
|
| - : basetrans_(trans) {
|
| - kernel_ = trans->directory()->GetChildWithName(parentid, name);
|
| -}
|
| -
|
| -Entry::Entry(BaseTransaction* trans, GetByParentIdAndDBName, const Id& parentid,
|
| - const PathString& name)
|
| - : basetrans_(trans) {
|
| - kernel_ = trans->directory()->GetChildWithDBName(parentid, name);
|
| -}
|
| -
|
| -
|
| Directory* Entry::dir() const {
|
| return basetrans_->directory();
|
| }
|
| @@ -1194,11 +1025,8 @@ void Entry::DeleteAllExtendedAttributes(WriteTransaction *trans) {
|
|
|
| MutableEntry::MutableEntry(WriteTransaction* trans, Create,
|
| const Id& parent_id, const PathString& name)
|
| - : Entry(trans), write_transaction_(trans) {
|
| - if (NULL != trans->directory()->GetChildWithName(parent_id, name)) {
|
| - kernel_ = NULL; // would have duplicated an existing entry.
|
| - return;
|
| - }
|
| + : Entry(trans),
|
| + write_transaction_(trans) {
|
| Init(trans, parent_id, name);
|
| }
|
|
|
| @@ -1213,8 +1041,6 @@ void MutableEntry::Init(WriteTransaction* trans, const Id& parent_id,
|
| kernel_->dirty[META_HANDLE] = true;
|
| kernel_->ref(PARENT_ID) = parent_id;
|
| kernel_->dirty[PARENT_ID] = true;
|
| - kernel_->ref(NAME) = name;
|
| - kernel_->dirty[NAME] = true;
|
| kernel_->ref(NON_UNIQUE_NAME) = name;
|
| kernel_->dirty[NON_UNIQUE_NAME] = true;
|
| kernel_->ref(IS_NEW) = true;
|
| @@ -1266,38 +1092,17 @@ MutableEntry::MutableEntry(WriteTransaction* trans, GetByHandle,
|
| trans->SaveOriginal(kernel_);
|
| }
|
|
|
| -MutableEntry::MutableEntry(WriteTransaction* trans, GetByPath,
|
| - const PathString& path)
|
| - : Entry(trans, GET_BY_PATH, path), write_transaction_(trans) {
|
| - trans->SaveOriginal(kernel_);
|
| -}
|
| -
|
| -MutableEntry::MutableEntry(WriteTransaction* trans, GetByParentIdAndName,
|
| - const Id& parentid, const PathString& name)
|
| - : Entry(trans, GET_BY_PARENTID_AND_NAME, parentid, name),
|
| - write_transaction_(trans) {
|
| - trans->SaveOriginal(kernel_);
|
| -}
|
| -
|
| -MutableEntry::MutableEntry(WriteTransaction* trans, GetByParentIdAndDBName,
|
| - const Id& parentid, const PathString& name)
|
| - : Entry(trans, GET_BY_PARENTID_AND_DBNAME, parentid, name),
|
| - write_transaction_(trans) {
|
| - trans->SaveOriginal(kernel_);
|
| -}
|
| -
|
| bool MutableEntry::PutIsDel(bool is_del) {
|
| DCHECK(kernel_);
|
| - if (is_del == kernel_->ref(IS_DEL))
|
| + if (is_del == kernel_->ref(IS_DEL)) {
|
| return true;
|
| + }
|
| if (is_del) {
|
| UnlinkFromOrder();
|
| - if (!dir()->Delete(kernel_))
|
| - return false;
|
| + dir()->Delete(kernel_);
|
| return true;
|
| } else {
|
| - if (!dir()->Undelete(kernel_))
|
| - return false;
|
| + dir()->Undelete(kernel_);
|
| PutPredecessor(Id()); // Restores position to the 0th index.
|
| return true;
|
| }
|
| @@ -1319,8 +1124,8 @@ bool MutableEntry::Put(IdField field, const Id& value) {
|
| if (!dir()->ReindexId(kernel_, value))
|
| return false;
|
| } else if (PARENT_ID == field) {
|
| - if (!dir()->ReindexParentIdAndName(kernel_, value, kernel_->ref(NAME)))
|
| - return false;
|
| + dir()->ReindexParentId(kernel_, value);
|
| + PutPredecessor(Id());
|
| } else {
|
| kernel_->ref(field) = value;
|
| }
|
| @@ -1345,13 +1150,7 @@ bool MutableEntry::Put(StringField field, const PathString& value) {
|
| bool MutableEntry::PutImpl(StringField field, const PathString& value) {
|
| DCHECK(kernel_);
|
| if (kernel_->ref(field) != value) {
|
| - if (NAME == field) {
|
| - if (!dir()->ReindexParentIdAndName(kernel_, kernel_->ref(PARENT_ID),
|
| - value))
|
| - return false;
|
| - } else {
|
| - kernel_->ref(field) = value;
|
| - }
|
| + kernel_->ref(field) = value;
|
| kernel_->dirty[static_cast<int>(field)] = true;
|
| }
|
| return true;
|
| @@ -1377,29 +1176,6 @@ bool MutableEntry::Put(IndexedBitField field, bool value) {
|
| return true;
|
| }
|
|
|
| -// Avoids temporary collision in index when renaming a bookmark to another
|
| -// folder.
|
| -bool MutableEntry::PutParentIdAndName(const Id& parent_id,
|
| - const Name& name) {
|
| - DCHECK(kernel_);
|
| - const bool parent_id_changes = parent_id != kernel_->ref(PARENT_ID);
|
| - bool db_name_changes = name.db_value() != kernel_->ref(NAME);
|
| - if (parent_id_changes || db_name_changes) {
|
| - if (!dir()->ReindexParentIdAndName(kernel_, parent_id,
|
| - name.db_value()))
|
| - return false;
|
| - }
|
| - Put(UNSANITIZED_NAME, name.GetUnsanitizedName());
|
| - Put(NON_UNIQUE_NAME, name.non_unique_value());
|
| - if (db_name_changes)
|
| - kernel_->dirty[NAME] = true;
|
| - if (parent_id_changes) {
|
| - kernel_->dirty[PARENT_ID] = true;
|
| - PutPredecessor(Id()); // Put in the 0th position.
|
| - }
|
| - return true;
|
| -}
|
| -
|
| void MutableEntry::UnlinkFromOrder() {
|
| Id old_previous = Get(PREV_ID);
|
| Id old_next = Get(NEXT_ID);
|
| @@ -1572,61 +1348,6 @@ bool IsLegalNewParent(BaseTransaction* trans, const Id& entry_id,
|
| return true;
|
| }
|
|
|
| -// returns -1 if s contains any non [0-9] characters
|
| -static int PathStringToInteger(PathString s) {
|
| - PathString::const_iterator i = s.begin();
|
| - for (; i != s.end(); ++i) {
|
| - if (PathString::npos == PathString(PSTR("0123456789")).find(*i))
|
| - return -1;
|
| - }
|
| - return atoi(s.c_str());
|
| -}
|
| -
|
| -// appends ~1 to the end of 's' unless there is already ~#, in which case
|
| -// it just increments the number
|
| -static PathString FixBasenameInCollision(const PathString s) {
|
| - PathString::size_type last_tilde = s.find_last_of(PSTR('~'));
|
| - if (PathString::npos == last_tilde) return s + PSTR("~1");
|
| - if (s.size() == (last_tilde + 1)) return s + PSTR("1");
|
| - // we have ~, but not necessarily ~# (for some number >= 0). check for that
|
| - int n;
|
| - if ((n = PathStringToInteger(s.substr(last_tilde + 1))) != -1) {
|
| - n++;
|
| - PathString pre_number = s.substr(0, last_tilde + 1);
|
| - return pre_number + IntToString(n);
|
| - } else {
|
| - // we have a ~, but not a number following it, so we'll add another
|
| - // ~ and this time, a number
|
| - return s + PSTR("~1");
|
| - }
|
| -}
|
| -
|
| -void DBName::MakeNoncollidingForEntry(BaseTransaction* trans,
|
| - const Id& parent_id,
|
| - Entry* e) {
|
| - const PathString& desired_name = *this;
|
| - CHECK(!desired_name.empty());
|
| - PathString::size_type first_dot = desired_name.find_first_of(PSTR('.'));
|
| - if (PathString::npos == first_dot)
|
| - first_dot = desired_name.size();
|
| - PathString basename = desired_name.substr(0, first_dot);
|
| - PathString dotextension = desired_name.substr(first_dot);
|
| - CHECK(basename + dotextension == desired_name);
|
| - for (;;) {
|
| - // Check for collision.
|
| - PathString testname = basename + dotextension;
|
| - Entry same_path_entry(trans, GET_BY_PARENTID_AND_DBNAME,
|
| - parent_id, testname);
|
| - if (!same_path_entry.good() || (e && same_path_entry.Get(ID) == e->Get(ID)))
|
| - break;
|
| - // There was a collision, so fix the name.
|
| - basename = FixBasenameInCollision(basename);
|
| - }
|
| - // Set our value to the new value. This invalidates desired_name.
|
| - PathString new_value = basename + dotextension;
|
| - swap(new_value);
|
| -}
|
| -
|
| const Blob* GetExtendedAttributeValue(const Entry& e,
|
| const PathString& attribute_name) {
|
| ExtendedAttributeKey key(e.Get(META_HANDLE), attribute_name);
|
|
|