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

Side by Side Diff: chrome/browser/sync/syncable/syncable.cc

Issue 371029: Remove unique naming. (Closed)
Patch Set: Ready and about to go in! Created 11 years, 1 month 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/sync/syncable/syncable.h" 5 #include "chrome/browser/sync/syncable/syncable.h"
6 6
7 #include "build/build_config.h" 7 #include "build/build_config.h"
8 8
9 #include <sys/stat.h> 9 #include <sys/stat.h>
10 #if defined(OS_POSIX) 10 #if defined(OS_POSIX)
11 #include <sys/time.h> 11 #include <sys/time.h>
12 #endif 12 #endif
13 #include <sys/types.h> 13 #include <sys/types.h>
14 #include <time.h> 14 #include <time.h>
15 #if defined(OS_MACOSX) 15 #if defined(OS_MACOSX)
16 #include <CoreFoundation/CoreFoundation.h> 16 #include <CoreFoundation/CoreFoundation.h>
17 #elif defined(OS_WIN) 17 #elif defined(OS_WIN)
18 #include <shlwapi.h> // for PathMatchSpec 18 #include <shlwapi.h> // for PathMatchSpec
19 #endif 19 #endif
20 20
21 #include <algorithm> 21 #include <algorithm>
22 #include <functional> 22 #include <functional>
23 #include <iomanip> 23 #include <iomanip>
24 #include <iterator> 24 #include <iterator>
25 #include <limits>
25 #include <set> 26 #include <set>
26 #include <string> 27 #include <string>
27 28
28 #include "base/hash_tables.h" 29 #include "base/hash_tables.h"
29 #include "base/file_util.h" 30 #include "base/file_util.h"
30 #include "base/logging.h" 31 #include "base/logging.h"
31 #include "base/perftimer.h" 32 #include "base/perftimer.h"
32 #include "base/scoped_ptr.h" 33 #include "base/scoped_ptr.h"
33 #include "base/string_util.h" 34 #include "base/string_util.h"
34 #include "base/time.h" 35 #include "base/time.h"
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 return static_cast<int64>(tv.tv_sec); 82 return static_cast<int64>(tv.tv_sec);
82 #else 83 #else
83 #error NEED OS SPECIFIC Now() implementation 84 #error NEED OS SPECIFIC Now() implementation
84 #endif 85 #endif
85 } 86 }
86 87
87 /////////////////////////////////////////////////////////////////////////// 88 ///////////////////////////////////////////////////////////////////////////
88 // Compare functions and hashes for the indices. 89 // Compare functions and hashes for the indices.
89 90
90 // Callback for sqlite3 91 // Callback for sqlite3
92 // TODO(chron): This should be somewhere else
91 int ComparePathNames16(void*, int a_bytes, const void* a, int b_bytes, 93 int ComparePathNames16(void*, int a_bytes, const void* a, int b_bytes,
92 const void* b) { 94 const void* b) {
93 int result = base::strncasecmp(reinterpret_cast<const char *>(a), 95 int result = base::strncasecmp(reinterpret_cast<const char *>(a),
94 reinterpret_cast<const char *>(b), 96 reinterpret_cast<const char *>(b),
95 std::min(a_bytes, b_bytes)); 97 std::min(a_bytes, b_bytes));
96 if (result != 0) { 98 if (result != 0) {
97 return result; 99 return result;
98 } else { 100 } else {
99 return a_bytes > b_bytes ? 1 : b_bytes > a_bytes ? -1 : 0; 101 return a_bytes > b_bytes ? 1 : b_bytes > a_bytes ? -1 : 0;
100 } 102 }
(...skipping 10 matching lines...) Expand all
111 113
112 template <Int64Field field_index> 114 template <Int64Field field_index>
113 class HashField { 115 class HashField {
114 public: 116 public:
115 inline size_t operator()(const syncable::EntryKernel* a) const { 117 inline size_t operator()(const syncable::EntryKernel* a) const {
116 return hasher_(a->ref(field_index)); 118 return hasher_(a->ref(field_index));
117 } 119 }
118 base::hash_set<int64> hasher_; 120 base::hash_set<int64> hasher_;
119 }; 121 };
120 122
121 // TODO(ncarter): Rename! 123 // TODO(chron): Remove this function.
122 int ComparePathNames(const PathString& a, const PathString& b) { 124 int ComparePathNames(const PathString& a, const PathString& b) {
123 const size_t val_size = sizeof(PathString::value_type); 125 const size_t val_size = sizeof(PathString::value_type);
124 return ComparePathNames16(NULL, a.size() * val_size, a.data(), 126 return ComparePathNames16(NULL, a.size() * val_size, a.data(),
125 b.size() * val_size, b.data()); 127 b.size() * val_size, b.data());
126 } 128 }
127 129
128 class LessParentIdAndNames { 130 class LessParentIdAndHandle {
129 public: 131 public:
130 bool operator() (const syncable::EntryKernel* a, 132 bool operator() (const syncable::EntryKernel* a,
131 const syncable::EntryKernel* b) const { 133 const syncable::EntryKernel* b) const {
132 if (a->ref(PARENT_ID) != b->ref(PARENT_ID)) 134 if (a->ref(PARENT_ID) != b->ref(PARENT_ID)) {
133 return a->ref(PARENT_ID) < b->ref(PARENT_ID); 135 return a->ref(PARENT_ID) < b->ref(PARENT_ID);
134 return ComparePathNames(a->ref(NAME), b->ref(NAME)) < 0; 136 }
137
138 // Meta handles are immutable per entry so this is ideal.
139 return a->ref(META_HANDLE) < b->ref(META_HANDLE);
135 } 140 }
136 }; 141 };
137 142
143 // TODO(chron): Remove this function.
138 bool LessPathNames::operator() (const PathString& a, 144 bool LessPathNames::operator() (const PathString& a,
139 const PathString& b) const { 145 const PathString& b) const {
140 return ComparePathNames(a, b) < 0; 146 return ComparePathNames(a, b) < 0;
141 } 147 }
142 148
143 // static
144 Name Name::FromEntryKernel(EntryKernel* kernel) {
145 PathString& sync_name_ref = kernel->ref(UNSANITIZED_NAME).empty() ?
146 kernel->ref(NAME) : kernel->ref(UNSANITIZED_NAME);
147 return Name(kernel->ref(NAME), sync_name_ref, kernel->ref(NON_UNIQUE_NAME));
148 }
149
150 /////////////////////////////////////////////////////////////////////////// 149 ///////////////////////////////////////////////////////////////////////////
151 // Directory 150 // Directory
152 151
153 static const DirectoryChangeEvent kShutdownChangesEvent = 152 static const DirectoryChangeEvent kShutdownChangesEvent =
154 { DirectoryChangeEvent::SHUTDOWN, 0, 0 }; 153 { DirectoryChangeEvent::SHUTDOWN, 0, 0 };
155 154
156 Directory::Kernel::Kernel(const FilePath& db_path, 155 Directory::Kernel::Kernel(const FilePath& db_path,
157 const PathString& name, 156 const PathString& name,
158 const KernelLoadInfo& info) 157 const KernelLoadInfo& info)
159 : db_path(db_path), 158 : db_path(db_path),
160 refcount(1), 159 refcount(1),
161 name_(name), 160 name_(name),
162 metahandles_index(new Directory::MetahandlesIndex), 161 metahandles_index(new Directory::MetahandlesIndex),
163 ids_index(new Directory::IdsIndex), 162 ids_index(new Directory::IdsIndex),
164 parent_id_and_names_index(new Directory::ParentIdAndNamesIndex), 163 parent_id_child_index(new Directory::ParentIdChildIndex),
165 extended_attributes(new ExtendedAttributes), 164 extended_attributes(new ExtendedAttributes),
166 unapplied_update_metahandles(new MetahandleSet), 165 unapplied_update_metahandles(new MetahandleSet),
167 unsynced_metahandles(new MetahandleSet), 166 unsynced_metahandles(new MetahandleSet),
168 channel(new Directory::Channel(syncable::DIRECTORY_DESTROYED)), 167 channel(new Directory::Channel(syncable::DIRECTORY_DESTROYED)),
169 changes_channel(new Directory::ChangesChannel(kShutdownChangesEvent)), 168 changes_channel(new Directory::ChangesChannel(kShutdownChangesEvent)),
170 last_sync_timestamp_(info.kernel_info.last_sync_timestamp), 169 last_sync_timestamp_(info.kernel_info.last_sync_timestamp),
171 initial_sync_ended_(info.kernel_info.initial_sync_ended), 170 initial_sync_ended_(info.kernel_info.initial_sync_ended),
172 store_birthday_(info.kernel_info.store_birthday), 171 store_birthday_(info.kernel_info.store_birthday),
173 cache_guid_(info.cache_guid), 172 cache_guid_(info.cache_guid),
174 next_metahandle(info.max_metahandle + 1), 173 next_metahandle(info.max_metahandle + 1),
(...skipping 14 matching lines...) Expand all
189 delete this; 188 delete this;
190 } 189 }
191 190
192 Directory::Kernel::~Kernel() { 191 Directory::Kernel::~Kernel() {
193 CHECK(0 == refcount); 192 CHECK(0 == refcount);
194 delete channel; 193 delete channel;
195 delete changes_channel; 194 delete changes_channel;
196 delete unsynced_metahandles; 195 delete unsynced_metahandles;
197 delete unapplied_update_metahandles; 196 delete unapplied_update_metahandles;
198 delete extended_attributes; 197 delete extended_attributes;
199 delete parent_id_and_names_index; 198 delete parent_id_child_index;
200 delete ids_index; 199 delete ids_index;
201 for_each(metahandles_index->begin(), metahandles_index->end(), DeleteEntry); 200 for_each(metahandles_index->begin(), metahandles_index->end(), DeleteEntry);
202 delete metahandles_index; 201 delete metahandles_index;
203 } 202 }
204 203
205 Directory::Directory() : kernel_(NULL), store_(NULL) { 204 Directory::Directory() : kernel_(NULL), store_(NULL) {
206 } 205 }
207 206
208 Directory::~Directory() { 207 Directory::~Directory() {
209 Close(); 208 Close();
210 } 209 }
211 210
212 BOOL PathNameMatch(const PathString& pathname, const PathString& pathspec) {
213 #if defined(OS_WIN)
214 // Note that if we go Vista only this is easier:
215 // http://msdn2.microsoft.com/en-us/library/ms628611.aspx
216
217 // PathMatchSpec strips spaces from the start of pathspec, so we compare those
218 // ourselves.
219 const PathChar* pathname_ptr = pathname.c_str();
220 const PathChar* pathspec_ptr = pathspec.c_str();
221
222 while (*pathname_ptr == ' ' && *pathspec_ptr == ' ')
223 ++pathname_ptr, ++pathspec_ptr;
224
225 // If we have more inital spaces in the pathspec than in the pathname then the
226 // result from PathMatchSpec will be erroneous.
227 if (*pathspec_ptr == ' ')
228 return FALSE;
229
230 // PathMatchSpec also gets "confused" when there are ';' characters in name or
231 // in spec. So, if we match (f.i.) ";" with ";" PathMatchSpec will return
232 // FALSE (which is wrong). Luckily for us, we can easily fix this by
233 // substituting ';' with ':' which is illegal character in file name and
234 // we're not going to see it there. With ':' in path name and spec
235 // PathMatchSpec works fine.
236 if ((NULL == strchr(pathname_ptr, ';')) &&
237 (NULL == strchr(pathspec_ptr, ';'))) {
238 // No ';' in file name and in spec. Just pass it as it is.
239 return ::PathMatchSpecA(pathname_ptr, pathspec_ptr);
240 }
241
242 // We need to subst ';' with ':' in both, name and spec.
243 PathString name_subst(pathname_ptr);
244 PathString spec_subst(pathspec_ptr);
245
246 PathString::size_type index = name_subst.find(L';');
247 while (PathString::npos != index) {
248 name_subst[index] = ':';
249 index = name_subst.find(';', index + 1);
250 }
251
252 index = spec_subst.find(L';');
253 while (PathString::npos != index) {
254 spec_subst[index] = ':';
255 index = spec_subst.find(';', index + 1);
256 }
257
258 return ::PathMatchSpecA(name_subst.c_str(), spec_subst.c_str());
259 #else
260 return 0 == ComparePathNames(pathname, pathspec);
261 #endif
262 }
263
264 DirOpenResult Directory::Open(const FilePath& file_path, 211 DirOpenResult Directory::Open(const FilePath& file_path,
265 const PathString& name) { 212 const PathString& name) {
266 const DirOpenResult result = OpenImpl(file_path, name); 213 const DirOpenResult result = OpenImpl(file_path, name);
267 if (OPENED != result) 214 if (OPENED != result)
268 Close(); 215 Close();
269 return result; 216 return result;
270 } 217 }
271 218
272 void Directory::InitializeIndices() { 219 void Directory::InitializeIndices() {
273 MetahandlesIndex::iterator it = kernel_->metahandles_index->begin(); 220 MetahandlesIndex::iterator it = kernel_->metahandles_index->begin();
274 for (; it != kernel_->metahandles_index->end(); ++it) { 221 for (; it != kernel_->metahandles_index->end(); ++it) {
275 EntryKernel* entry = *it; 222 EntryKernel* entry = *it;
276 if (!entry->ref(IS_DEL)) 223 if (!entry->ref(IS_DEL))
277 kernel_->parent_id_and_names_index->insert(entry); 224 kernel_->parent_id_child_index->insert(entry);
278 kernel_->ids_index->insert(entry); 225 kernel_->ids_index->insert(entry);
279 if (entry->ref(IS_UNSYNCED)) 226 if (entry->ref(IS_UNSYNCED))
280 kernel_->unsynced_metahandles->insert(entry->ref(META_HANDLE)); 227 kernel_->unsynced_metahandles->insert(entry->ref(META_HANDLE));
281 if (entry->ref(IS_UNAPPLIED_UPDATE)) 228 if (entry->ref(IS_UNAPPLIED_UPDATE))
282 kernel_->unapplied_update_metahandles->insert(entry->ref(META_HANDLE)); 229 kernel_->unapplied_update_metahandles->insert(entry->ref(META_HANDLE));
283 } 230 }
284 } 231 }
285 232
286 DirectoryBackingStore* Directory::CreateBackingStore( 233 DirectoryBackingStore* Directory::CreateBackingStore(
287 const PathString& dir_name, const FilePath& backing_filepath) { 234 const PathString& dir_name, const FilePath& backing_filepath) {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 kernel_->needle.ref(META_HANDLE) = metahandle; 317 kernel_->needle.ref(META_HANDLE) = metahandle;
371 MetahandlesIndex::iterator found = 318 MetahandlesIndex::iterator found =
372 kernel_->metahandles_index->find(&kernel_->needle); 319 kernel_->metahandles_index->find(&kernel_->needle);
373 if (found != kernel_->metahandles_index->end()) { 320 if (found != kernel_->metahandles_index->end()) {
374 // Found it in memory. Easy. 321 // Found it in memory. Easy.
375 return *found; 322 return *found;
376 } 323 }
377 return NULL; 324 return NULL;
378 } 325 }
379 326
380 EntryKernel* Directory::GetChildWithName(const Id& parent_id,
381 const PathString& name) {
382 ScopedKernelLock lock(this);
383 return GetChildWithName(parent_id, name, &lock);
384 }
385
386 // Will return child entry if the folder is opened,
387 // otherwise it will return NULL.
388 EntryKernel* Directory::GetChildWithName(const Id& parent_id,
389 const PathString& name,
390 ScopedKernelLock* const lock) {
391 PathString dbname = name;
392 EntryKernel* parent = GetEntryById(parent_id, lock);
393 if (parent == NULL)
394 return NULL;
395 return GetChildWithNameImpl(parent_id, dbname, lock);
396 }
397
398 // Will return child entry even when the folder is not opened. This is used by
399 // syncer to apply update when folder is closed.
400 EntryKernel* Directory::GetChildWithDBName(const Id& parent_id,
401 const PathString& name) {
402 ScopedKernelLock lock(this);
403 return GetChildWithNameImpl(parent_id, name, &lock);
404 }
405
406 EntryKernel* Directory::GetChildWithNameImpl(const Id& parent_id,
407 const PathString& name,
408 ScopedKernelLock* const lock) {
409 // First look up in memory:
410 kernel_->needle.ref(NAME) = name;
411 kernel_->needle.ref(PARENT_ID) = parent_id;
412 ParentIdAndNamesIndex::iterator found =
413 kernel_->parent_id_and_names_index->find(&kernel_->needle);
414 if (found != kernel_->parent_id_and_names_index->end()) {
415 // Found it in memory. Easy.
416 return *found;
417 }
418 return NULL;
419 }
420
421 // An interface to specify the details of which children 327 // An interface to specify the details of which children
422 // GetChildHandles() is looking for. 328 // GetChildHandles() is looking for.
329 // TODO(chron): Clean this up into one function to get child handles
423 struct PathMatcher { 330 struct PathMatcher {
424 explicit PathMatcher(const Id& parent_id) : parent_id_(parent_id) { } 331 explicit PathMatcher(const Id& parent_id) : parent_id_(parent_id) { }
425 virtual ~PathMatcher() { } 332 virtual ~PathMatcher() { }
426 enum MatchType { 333
427 NO_MATCH, 334 typedef Directory::ParentIdChildIndex Index;
428 MATCH,
429 // Means we found the only entry we're looking for in
430 // memory so we don't need to check the DB.
431 EXACT_MATCH
432 };
433 virtual MatchType PathMatches(const PathString& path) = 0;
434 typedef Directory::ParentIdAndNamesIndex Index;
435 virtual Index::iterator lower_bound(Index* index) = 0; 335 virtual Index::iterator lower_bound(Index* index) = 0;
436 virtual Index::iterator upper_bound(Index* index) = 0; 336 virtual Index::iterator upper_bound(Index* index) = 0;
437 const Id parent_id_; 337 const Id parent_id_;
438 EntryKernel needle_; 338 EntryKernel needle_;
439 }; 339 };
440 340
441 // Matches all children. 341 // Matches all children.
342 // TODO(chron): Unit test this by itself
442 struct AllPathsMatcher : public PathMatcher { 343 struct AllPathsMatcher : public PathMatcher {
443 explicit AllPathsMatcher(const Id& parent_id) : PathMatcher(parent_id) { 344 explicit AllPathsMatcher(const Id& parent_id) : PathMatcher(parent_id) {
444 } 345 }
445 virtual MatchType PathMatches(const PathString& path) { 346
446 return MATCH;
447 }
448 virtual Index::iterator lower_bound(Index* index) { 347 virtual Index::iterator lower_bound(Index* index) {
449 needle_.ref(PARENT_ID) = parent_id_; 348 needle_.ref(PARENT_ID) = parent_id_;
450 needle_.ref(NAME).clear(); 349 needle_.ref(META_HANDLE) = std::numeric_limits<int64>::min();
451 return index->lower_bound(&needle_); 350 return index->lower_bound(&needle_);
452 } 351 }
453 352
454 virtual Index::iterator upper_bound(Index* index) { 353 virtual Index::iterator upper_bound(Index* index) {
455 needle_.ref(PARENT_ID) = parent_id_; 354 needle_.ref(PARENT_ID) = parent_id_;
456 needle_.ref(NAME).clear(); 355 needle_.ref(META_HANDLE) = std::numeric_limits<int64>::max();
457 Index::iterator i = index->upper_bound(&needle_), 356 return index->upper_bound(&needle_);
458 end = index->end();
459 while (i != end && (*i)->ref(PARENT_ID) == parent_id_)
460 ++i;
461 return i;
462 } 357 }
463 }; 358 };
464 359
465 // Matches an exact filename only; no wildcards.
466 struct ExactPathMatcher : public PathMatcher {
467 ExactPathMatcher(const PathString& pathspec, const Id& parent_id)
468 : PathMatcher(parent_id), pathspec_(pathspec) {
469 }
470 virtual MatchType PathMatches(const PathString& path) {
471 return 0 == ComparePathNames(path, pathspec_) ? EXACT_MATCH : NO_MATCH;
472 }
473 virtual Index::iterator lower_bound(Index* index) {
474 needle_.ref(PARENT_ID) = parent_id_;
475 needle_.ref(NAME) = pathspec_;
476 return index->lower_bound(&needle_);
477 }
478 virtual Index::iterator upper_bound(Index* index) {
479 needle_.ref(PARENT_ID) = parent_id_;
480 needle_.ref(NAME) = pathspec_;
481 return index->upper_bound(&needle_);
482 }
483 const PathString pathspec_;
484 };
485
486 void Directory::GetChildHandles(BaseTransaction* trans, const Id& parent_id, 360 void Directory::GetChildHandles(BaseTransaction* trans, const Id& parent_id,
487 Directory::ChildHandles* result) { 361 Directory::ChildHandles* result) {
488 AllPathsMatcher matcher(parent_id); 362 AllPathsMatcher matcher(parent_id);
489 return GetChildHandlesImpl(trans, parent_id, &matcher, result); 363 return GetChildHandlesImpl(trans, parent_id, &matcher, result);
490 } 364 }
491 365
492 void Directory::GetChildHandlesImpl(BaseTransaction* trans, const Id& parent_id, 366 void Directory::GetChildHandlesImpl(BaseTransaction* trans, const Id& parent_id,
493 PathMatcher* matcher, 367 PathMatcher* matcher,
494 Directory::ChildHandles* result) { 368 Directory::ChildHandles* result) {
495 CHECK(this == trans->directory()); 369 CHECK(this == trans->directory());
496 result->clear(); 370 result->clear();
497 { 371 {
498 ScopedKernelLock lock(this); 372 ScopedKernelLock lock(this);
499 ParentIdAndNamesIndex* const index = 373
500 kernel_->parent_id_and_names_index; 374 // This index is sorted by parent id and metahandle.
501 typedef ParentIdAndNamesIndex::iterator iterator; 375 ParentIdChildIndex* const index = kernel_->parent_id_child_index;
376 typedef ParentIdChildIndex::iterator iterator;
502 for (iterator i = matcher->lower_bound(index), 377 for (iterator i = matcher->lower_bound(index),
503 end = matcher->upper_bound(index); i != end; ++i) { 378 end = matcher->upper_bound(index); i != end; ++i) {
504 // root's parent_id is NULL in the db but 0 in memory, so 379 // root's parent_id is NULL in the db but 0 in memory, so
505 // have avoid listing the root as its own child. 380 // have avoid listing the root as its own child.
506 if ((*i)->ref(ID) == (*i)->ref(PARENT_ID)) 381 if ((*i)->ref(ID) == (*i)->ref(PARENT_ID))
507 continue; 382 continue;
508 PathMatcher::MatchType match = matcher->PathMatches((*i)->ref(NAME));
509 if (PathMatcher::NO_MATCH == match)
510 continue;
511 result->push_back((*i)->ref(META_HANDLE)); 383 result->push_back((*i)->ref(META_HANDLE));
512 if (PathMatcher::EXACT_MATCH == match)
513 return;
514 } 384 }
515 } 385 }
516 } 386 }
517 387
518 EntryKernel* Directory::GetRootEntry() { 388 EntryKernel* Directory::GetRootEntry() {
519 return GetEntryById(Id()); 389 return GetEntryById(Id());
520 } 390 }
521 391
522 EntryKernel* Directory::GetEntryByPath(const PathString& path) {
523 CHECK(kernel_);
524 EntryKernel* result = GetRootEntry();
525 CHECK(result) << "There should always be a root node.";
526 for (PathSegmentIterator<PathString> i(path), end;
527 i != end && NULL != result; ++i) {
528 result = GetChildWithName(result->ref(ID), *i);
529 }
530 return result;
531 }
532
533 void ZeroFields(EntryKernel* entry, int first_field) { 392 void ZeroFields(EntryKernel* entry, int first_field) {
534 int i = first_field; 393 int i = first_field;
535 // Note that bitset<> constructor sets all bits to zero, and strings 394 // Note that bitset<> constructor sets all bits to zero, and strings
536 // initialize to empty. 395 // initialize to empty.
537 for ( ; i < INT64_FIELDS_END; ++i) 396 for ( ; i < INT64_FIELDS_END; ++i)
538 entry->ref(static_cast<Int64Field>(i)) = 0; 397 entry->ref(static_cast<Int64Field>(i)) = 0;
539 for ( ; i < ID_FIELDS_END; ++i) 398 for ( ; i < ID_FIELDS_END; ++i)
540 entry->ref(static_cast<IdField>(i)).Clear(); 399 entry->ref(static_cast<IdField>(i)).Clear();
541 for ( ; i < BIT_FIELDS_END; ++i) 400 for ( ; i < BIT_FIELDS_END; ++i)
542 entry->ref(static_cast<BitField>(i)) = false; 401 entry->ref(static_cast<BitField>(i)) = false;
543 if (i < BLOB_FIELDS_END) 402 if (i < BLOB_FIELDS_END)
544 i = BLOB_FIELDS_END; 403 i = BLOB_FIELDS_END;
545 } 404 }
546 405
547 void Directory::InsertEntry(EntryKernel* entry) { 406 void Directory::InsertEntry(EntryKernel* entry) {
548 ScopedKernelLock lock(this); 407 ScopedKernelLock lock(this);
549 InsertEntry(entry, &lock); 408 InsertEntry(entry, &lock);
550 } 409 }
551 410
552 void Directory::InsertEntry(EntryKernel* entry, ScopedKernelLock* lock) { 411 void Directory::InsertEntry(EntryKernel* entry, ScopedKernelLock* lock) {
553 DCHECK(NULL != lock); 412 DCHECK(NULL != lock);
554 CHECK(NULL != entry); 413 CHECK(NULL != entry);
555 static const char error[] = "Entry already in memory index."; 414 static const char error[] = "Entry already in memory index.";
556 CHECK(kernel_->metahandles_index->insert(entry).second) << error; 415 CHECK(kernel_->metahandles_index->insert(entry).second) << error;
557 if (!entry->ref(IS_DEL)) 416
558 CHECK(kernel_->parent_id_and_names_index->insert(entry).second) << error; 417 if (!entry->ref(IS_DEL)) {
418 CHECK(kernel_->parent_id_child_index->insert(entry).second) << error;
419 }
559 CHECK(kernel_->ids_index->insert(entry).second) << error; 420 CHECK(kernel_->ids_index->insert(entry).second) << error;
560 } 421 }
561 422
562 bool Directory::Undelete(EntryKernel* const entry) { 423 void Directory::Undelete(EntryKernel* const entry) {
563 DCHECK(entry->ref(IS_DEL)); 424 DCHECK(entry->ref(IS_DEL));
564 ScopedKernelLock lock(this); 425 ScopedKernelLock lock(this);
565 if (NULL != GetChildWithName(entry->ref(PARENT_ID), entry->ref(NAME), &lock))
566 return false; // Would have duplicated existing entry.
567 entry->ref(IS_DEL) = false; 426 entry->ref(IS_DEL) = false;
568 entry->dirty[IS_DEL] = true; 427 entry->dirty[IS_DEL] = true;
569 CHECK(kernel_->parent_id_and_names_index->insert(entry).second); 428 CHECK(kernel_->parent_id_child_index->insert(entry).second);
570 return true;
571 } 429 }
572 430
573 bool Directory::Delete(EntryKernel* const entry) { 431 void Directory::Delete(EntryKernel* const entry) {
574 DCHECK(!entry->ref(IS_DEL)); 432 DCHECK(!entry->ref(IS_DEL));
575 entry->ref(IS_DEL) = true; 433 entry->ref(IS_DEL) = true;
576 entry->dirty[IS_DEL] = true; 434 entry->dirty[IS_DEL] = true;
577 ScopedKernelLock lock(this); 435 ScopedKernelLock lock(this);
578 CHECK(1 == kernel_->parent_id_and_names_index->erase(entry)); 436 CHECK(1 == kernel_->parent_id_child_index->erase(entry));
579 return true;
580 } 437 }
581 438
582 bool Directory::ReindexId(EntryKernel* const entry, const Id& new_id) { 439 bool Directory::ReindexId(EntryKernel* const entry, const Id& new_id) {
583 ScopedKernelLock lock(this); 440 ScopedKernelLock lock(this);
584 if (NULL != GetEntryById(new_id, &lock)) 441 if (NULL != GetEntryById(new_id, &lock))
585 return false; 442 return false;
586 CHECK(1 == kernel_->ids_index->erase(entry)); 443 CHECK(1 == kernel_->ids_index->erase(entry));
587 entry->ref(ID) = new_id; 444 entry->ref(ID) = new_id;
588 CHECK(kernel_->ids_index->insert(entry).second); 445 CHECK(kernel_->ids_index->insert(entry).second);
589 return true; 446 return true;
590 } 447 }
591 448
592 bool Directory::ReindexParentIdAndName(EntryKernel* const entry, 449 void Directory::ReindexParentId(EntryKernel* const entry,
593 const Id& new_parent_id, 450 const Id& new_parent_id) {
594 const PathString& new_name) { 451
595 ScopedKernelLock lock(this); 452 ScopedKernelLock lock(this);
596 PathString new_indexed_name = new_name;
597 if (entry->ref(IS_DEL)) { 453 if (entry->ref(IS_DEL)) {
598 entry->ref(PARENT_ID) = new_parent_id; 454 entry->ref(PARENT_ID) = new_parent_id;
599 entry->ref(NAME) = new_indexed_name; 455 return;
600 return true;
601 } 456 }
602 457
603 // check for a case changing rename 458 if (entry->ref(PARENT_ID) == new_parent_id) {
604 if (entry->ref(PARENT_ID) == new_parent_id && 459 return;
605 0 == ComparePathNames(entry->ref(NAME), new_indexed_name)) {
606 entry->ref(NAME) = new_indexed_name;
607 } else {
608 if (NULL != GetChildWithName(new_parent_id, new_indexed_name, &lock))
609 return false;
610 CHECK(1 == kernel_->parent_id_and_names_index->erase(entry));
611 entry->ref(PARENT_ID) = new_parent_id;
612 entry->ref(NAME) = new_indexed_name;
613 CHECK(kernel_->parent_id_and_names_index->insert(entry).second);
614 } 460 }
615 return true; 461
462 CHECK(1 == kernel_->parent_id_child_index->erase(entry));
463 entry->ref(PARENT_ID) = new_parent_id;
464 CHECK(kernel_->parent_id_child_index->insert(entry).second);
616 } 465 }
617 466
618 // static 467 // static
619 bool Directory::SafeToPurgeFromMemory(const EntryKernel* const entry) { 468 bool Directory::SafeToPurgeFromMemory(const EntryKernel* const entry) {
620 return entry->ref(IS_DEL) && !entry->dirty.any() && !entry->ref(SYNCING) && 469 return entry->ref(IS_DEL) && !entry->dirty.any() && !entry->ref(SYNCING) &&
621 !entry->ref(IS_UNAPPLIED_UPDATE) && !entry->ref(IS_UNSYNCED); 470 !entry->ref(IS_UNAPPLIED_UPDATE) && !entry->ref(IS_UNSYNCED);
622 } 471 }
623 472
624 void Directory::TakeSnapshotForSaveChanges(SaveChangesSnapshot* snapshot) { 473 void Directory::TakeSnapshotForSaveChanges(SaveChangesSnapshot* snapshot) {
625 ReadTransaction trans(this, __FILE__, __LINE__); 474 ReadTransaction trans(this, __FILE__, __LINE__);
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
964 813
965 if (id.IsRoot()) { 814 if (id.IsRoot()) {
966 CHECK(e.Get(IS_DIR)) << e; 815 CHECK(e.Get(IS_DIR)) << e;
967 CHECK(parentid.IsRoot()) << e; 816 CHECK(parentid.IsRoot()) << e;
968 CHECK(!e.Get(IS_UNSYNCED)) << e; 817 CHECK(!e.Get(IS_UNSYNCED)) << e;
969 ++entries_done; 818 ++entries_done;
970 continue; 819 continue;
971 } 820 }
972 if (!e.Get(IS_DEL)) { 821 if (!e.Get(IS_DEL)) {
973 CHECK(id != parentid) << e; 822 CHECK(id != parentid) << e;
974 CHECK(!e.Get(NAME).empty()) << e; 823 CHECK(!e.Get(NON_UNIQUE_NAME).empty()) << e;
975 int safety_count = handles.size() + 1; 824 int safety_count = handles.size() + 1;
976 while (!parentid.IsRoot()) { 825 while (!parentid.IsRoot()) {
977 if (!idfilter.ShouldConsider(parentid)) 826 if (!idfilter.ShouldConsider(parentid))
978 break; 827 break;
979 Entry parent(trans, GET_BY_ID, parentid); 828 Entry parent(trans, GET_BY_ID, parentid);
980 CHECK(parent.good()) << e; 829 CHECK(parent.good()) << e;
981 CHECK(parent.Get(IS_DIR)) << parent << e; 830 CHECK(parent.Get(IS_DIR)) << parent << e;
982 CHECK(!parent.Get(IS_DEL)) << parent << e; 831 CHECK(!parent.Get(IS_DEL)) << parent << e;
983 CHECK(handles.end() != handles.find(parent.Get(META_HANDLE))) 832 CHECK(handles.end() != handles.find(parent.Get(META_HANDLE)))
984 << e << parent; 833 << e << parent;
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
1141 Entry::Entry(BaseTransaction* trans, GetByTag, const PathString& tag) 990 Entry::Entry(BaseTransaction* trans, GetByTag, const PathString& tag)
1142 : basetrans_(trans) { 991 : basetrans_(trans) {
1143 kernel_ = trans->directory()->GetEntryByTag(tag); 992 kernel_ = trans->directory()->GetEntryByTag(tag);
1144 } 993 }
1145 994
1146 Entry::Entry(BaseTransaction* trans, GetByHandle, int64 metahandle) 995 Entry::Entry(BaseTransaction* trans, GetByHandle, int64 metahandle)
1147 : basetrans_(trans) { 996 : basetrans_(trans) {
1148 kernel_ = trans->directory()->GetEntryByHandle(metahandle); 997 kernel_ = trans->directory()->GetEntryByHandle(metahandle);
1149 } 998 }
1150 999
1151 Entry::Entry(BaseTransaction* trans, GetByPath, const PathString& path)
1152 : basetrans_(trans) {
1153 kernel_ = trans->directory()->GetEntryByPath(path);
1154 }
1155
1156 Entry::Entry(BaseTransaction* trans, GetByParentIdAndName, const Id& parentid,
1157 const PathString& name)
1158 : basetrans_(trans) {
1159 kernel_ = trans->directory()->GetChildWithName(parentid, name);
1160 }
1161
1162 Entry::Entry(BaseTransaction* trans, GetByParentIdAndDBName, const Id& parentid,
1163 const PathString& name)
1164 : basetrans_(trans) {
1165 kernel_ = trans->directory()->GetChildWithDBName(parentid, name);
1166 }
1167
1168
1169 Directory* Entry::dir() const { 1000 Directory* Entry::dir() const {
1170 return basetrans_->directory(); 1001 return basetrans_->directory();
1171 } 1002 }
1172 1003
1173 PathString Entry::Get(StringField field) const { 1004 PathString Entry::Get(StringField field) const {
1174 DCHECK(kernel_); 1005 DCHECK(kernel_);
1175 return kernel_->ref(field); 1006 return kernel_->ref(field);
1176 } 1007 }
1177 1008
1178 void Entry::GetAllExtendedAttributes(BaseTransaction* trans, 1009 void Entry::GetAllExtendedAttributes(BaseTransaction* trans,
1179 std::set<ExtendedAttribute> *result) { 1010 std::set<ExtendedAttribute> *result) {
1180 dir()->GetAllExtendedAttributes(trans, kernel_->ref(META_HANDLE), result); 1011 dir()->GetAllExtendedAttributes(trans, kernel_->ref(META_HANDLE), result);
1181 } 1012 }
1182 1013
1183 void Entry::GetExtendedAttributesList(BaseTransaction* trans, 1014 void Entry::GetExtendedAttributesList(BaseTransaction* trans,
1184 AttributeKeySet* result) { 1015 AttributeKeySet* result) {
1185 dir()->GetExtendedAttributesList(trans, kernel_->ref(META_HANDLE), result); 1016 dir()->GetExtendedAttributesList(trans, kernel_->ref(META_HANDLE), result);
1186 } 1017 }
1187 1018
1188 void Entry::DeleteAllExtendedAttributes(WriteTransaction *trans) { 1019 void Entry::DeleteAllExtendedAttributes(WriteTransaction *trans) {
1189 dir()->DeleteAllExtendedAttributes(trans, kernel_->ref(META_HANDLE)); 1020 dir()->DeleteAllExtendedAttributes(trans, kernel_->ref(META_HANDLE));
1190 } 1021 }
1191 1022
1192 /////////////////////////////////////////////////////////////////////////// 1023 ///////////////////////////////////////////////////////////////////////////
1193 // MutableEntry 1024 // MutableEntry
1194 1025
1195 MutableEntry::MutableEntry(WriteTransaction* trans, Create, 1026 MutableEntry::MutableEntry(WriteTransaction* trans, Create,
1196 const Id& parent_id, const PathString& name) 1027 const Id& parent_id, const PathString& name)
1197 : Entry(trans), write_transaction_(trans) { 1028 : Entry(trans),
1198 if (NULL != trans->directory()->GetChildWithName(parent_id, name)) { 1029 write_transaction_(trans) {
1199 kernel_ = NULL; // would have duplicated an existing entry.
1200 return;
1201 }
1202 Init(trans, parent_id, name); 1030 Init(trans, parent_id, name);
1203 } 1031 }
1204 1032
1205 1033
1206 void MutableEntry::Init(WriteTransaction* trans, const Id& parent_id, 1034 void MutableEntry::Init(WriteTransaction* trans, const Id& parent_id,
1207 const PathString& name) { 1035 const PathString& name) {
1208 kernel_ = new EntryKernel; 1036 kernel_ = new EntryKernel;
1209 ZeroFields(kernel_, BEGIN_FIELDS); 1037 ZeroFields(kernel_, BEGIN_FIELDS);
1210 kernel_->ref(ID) = trans->directory_->NextId(); 1038 kernel_->ref(ID) = trans->directory_->NextId();
1211 kernel_->dirty[ID] = true; 1039 kernel_->dirty[ID] = true;
1212 kernel_->ref(META_HANDLE) = trans->directory_->NextMetahandle(); 1040 kernel_->ref(META_HANDLE) = trans->directory_->NextMetahandle();
1213 kernel_->dirty[META_HANDLE] = true; 1041 kernel_->dirty[META_HANDLE] = true;
1214 kernel_->ref(PARENT_ID) = parent_id; 1042 kernel_->ref(PARENT_ID) = parent_id;
1215 kernel_->dirty[PARENT_ID] = true; 1043 kernel_->dirty[PARENT_ID] = true;
1216 kernel_->ref(NAME) = name;
1217 kernel_->dirty[NAME] = true;
1218 kernel_->ref(NON_UNIQUE_NAME) = name; 1044 kernel_->ref(NON_UNIQUE_NAME) = name;
1219 kernel_->dirty[NON_UNIQUE_NAME] = true; 1045 kernel_->dirty[NON_UNIQUE_NAME] = true;
1220 kernel_->ref(IS_NEW) = true; 1046 kernel_->ref(IS_NEW) = true;
1221 const int64 now = Now(); 1047 const int64 now = Now();
1222 kernel_->ref(CTIME) = now; 1048 kernel_->ref(CTIME) = now;
1223 kernel_->dirty[CTIME] = true; 1049 kernel_->dirty[CTIME] = true;
1224 kernel_->ref(MTIME) = now; 1050 kernel_->ref(MTIME) = now;
1225 kernel_->dirty[MTIME] = true; 1051 kernel_->dirty[MTIME] = true;
1226 // We match the database defaults here 1052 // We match the database defaults here
1227 kernel_->ref(BASE_VERSION) = CHANGES_VERSION; 1053 kernel_->ref(BASE_VERSION) = CHANGES_VERSION;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1259 : Entry(trans, GET_BY_ID, id), write_transaction_(trans) { 1085 : Entry(trans, GET_BY_ID, id), write_transaction_(trans) {
1260 trans->SaveOriginal(kernel_); 1086 trans->SaveOriginal(kernel_);
1261 } 1087 }
1262 1088
1263 MutableEntry::MutableEntry(WriteTransaction* trans, GetByHandle, 1089 MutableEntry::MutableEntry(WriteTransaction* trans, GetByHandle,
1264 int64 metahandle) 1090 int64 metahandle)
1265 : Entry(trans, GET_BY_HANDLE, metahandle), write_transaction_(trans) { 1091 : Entry(trans, GET_BY_HANDLE, metahandle), write_transaction_(trans) {
1266 trans->SaveOriginal(kernel_); 1092 trans->SaveOriginal(kernel_);
1267 } 1093 }
1268 1094
1269 MutableEntry::MutableEntry(WriteTransaction* trans, GetByPath,
1270 const PathString& path)
1271 : Entry(trans, GET_BY_PATH, path), write_transaction_(trans) {
1272 trans->SaveOriginal(kernel_);
1273 }
1274
1275 MutableEntry::MutableEntry(WriteTransaction* trans, GetByParentIdAndName,
1276 const Id& parentid, const PathString& name)
1277 : Entry(trans, GET_BY_PARENTID_AND_NAME, parentid, name),
1278 write_transaction_(trans) {
1279 trans->SaveOriginal(kernel_);
1280 }
1281
1282 MutableEntry::MutableEntry(WriteTransaction* trans, GetByParentIdAndDBName,
1283 const Id& parentid, const PathString& name)
1284 : Entry(trans, GET_BY_PARENTID_AND_DBNAME, parentid, name),
1285 write_transaction_(trans) {
1286 trans->SaveOriginal(kernel_);
1287 }
1288
1289 bool MutableEntry::PutIsDel(bool is_del) { 1095 bool MutableEntry::PutIsDel(bool is_del) {
1290 DCHECK(kernel_); 1096 DCHECK(kernel_);
1291 if (is_del == kernel_->ref(IS_DEL)) 1097 if (is_del == kernel_->ref(IS_DEL)) {
1292 return true; 1098 return true;
1099 }
1293 if (is_del) { 1100 if (is_del) {
1294 UnlinkFromOrder(); 1101 UnlinkFromOrder();
1295 if (!dir()->Delete(kernel_)) 1102 dir()->Delete(kernel_);
1296 return false;
1297 return true; 1103 return true;
1298 } else { 1104 } else {
1299 if (!dir()->Undelete(kernel_)) 1105 dir()->Undelete(kernel_);
1300 return false;
1301 PutPredecessor(Id()); // Restores position to the 0th index. 1106 PutPredecessor(Id()); // Restores position to the 0th index.
1302 return true; 1107 return true;
1303 } 1108 }
1304 } 1109 }
1305 1110
1306 bool MutableEntry::Put(Int64Field field, const int64& value) { 1111 bool MutableEntry::Put(Int64Field field, const int64& value) {
1307 DCHECK(kernel_); 1112 DCHECK(kernel_);
1308 if (kernel_->ref(field) != value) { 1113 if (kernel_->ref(field) != value) {
1309 kernel_->ref(field) = value; 1114 kernel_->ref(field) = value;
1310 kernel_->dirty[static_cast<int>(field)] = true; 1115 kernel_->dirty[static_cast<int>(field)] = true;
1311 } 1116 }
1312 return true; 1117 return true;
1313 } 1118 }
1314 1119
1315 bool MutableEntry::Put(IdField field, const Id& value) { 1120 bool MutableEntry::Put(IdField field, const Id& value) {
1316 DCHECK(kernel_); 1121 DCHECK(kernel_);
1317 if (kernel_->ref(field) != value) { 1122 if (kernel_->ref(field) != value) {
1318 if (ID == field) { 1123 if (ID == field) {
1319 if (!dir()->ReindexId(kernel_, value)) 1124 if (!dir()->ReindexId(kernel_, value))
1320 return false; 1125 return false;
1321 } else if (PARENT_ID == field) { 1126 } else if (PARENT_ID == field) {
1322 if (!dir()->ReindexParentIdAndName(kernel_, value, kernel_->ref(NAME))) 1127 dir()->ReindexParentId(kernel_, value);
1323 return false; 1128 PutPredecessor(Id());
1324 } else { 1129 } else {
1325 kernel_->ref(field) = value; 1130 kernel_->ref(field) = value;
1326 } 1131 }
1327 kernel_->dirty[static_cast<int>(field)] = true; 1132 kernel_->dirty[static_cast<int>(field)] = true;
1328 } 1133 }
1329 return true; 1134 return true;
1330 } 1135 }
1331 1136
1332 bool MutableEntry::Put(BaseVersion field, int64 value) { 1137 bool MutableEntry::Put(BaseVersion field, int64 value) {
1333 DCHECK(kernel_); 1138 DCHECK(kernel_);
1334 if (kernel_->ref(field) != value) { 1139 if (kernel_->ref(field) != value) {
1335 kernel_->ref(field) = value; 1140 kernel_->ref(field) = value;
1336 kernel_->dirty[static_cast<int>(field)] = true; 1141 kernel_->dirty[static_cast<int>(field)] = true;
1337 } 1142 }
1338 return true; 1143 return true;
1339 } 1144 }
1340 1145
1341 bool MutableEntry::Put(StringField field, const PathString& value) { 1146 bool MutableEntry::Put(StringField field, const PathString& value) {
1342 return PutImpl(field, value); 1147 return PutImpl(field, value);
1343 } 1148 }
1344 1149
1345 bool MutableEntry::PutImpl(StringField field, const PathString& value) { 1150 bool MutableEntry::PutImpl(StringField field, const PathString& value) {
1346 DCHECK(kernel_); 1151 DCHECK(kernel_);
1347 if (kernel_->ref(field) != value) { 1152 if (kernel_->ref(field) != value) {
1348 if (NAME == field) { 1153 kernel_->ref(field) = value;
1349 if (!dir()->ReindexParentIdAndName(kernel_, kernel_->ref(PARENT_ID),
1350 value))
1351 return false;
1352 } else {
1353 kernel_->ref(field) = value;
1354 }
1355 kernel_->dirty[static_cast<int>(field)] = true; 1154 kernel_->dirty[static_cast<int>(field)] = true;
1356 } 1155 }
1357 return true; 1156 return true;
1358 } 1157 }
1359 1158
1360 bool MutableEntry::Put(IndexedBitField field, bool value) { 1159 bool MutableEntry::Put(IndexedBitField field, bool value) {
1361 DCHECK(kernel_); 1160 DCHECK(kernel_);
1362 if (kernel_->ref(field) != value) { 1161 if (kernel_->ref(field) != value) {
1363 MetahandleSet* index; 1162 MetahandleSet* index;
1364 if (IS_UNSYNCED == field) 1163 if (IS_UNSYNCED == field)
1365 index = dir()->kernel_->unsynced_metahandles; 1164 index = dir()->kernel_->unsynced_metahandles;
1366 else 1165 else
1367 index = dir()->kernel_->unapplied_update_metahandles; 1166 index = dir()->kernel_->unapplied_update_metahandles;
1368 1167
1369 ScopedKernelLock lock(dir()); 1168 ScopedKernelLock lock(dir());
1370 if (value) 1169 if (value)
1371 CHECK(index->insert(kernel_->ref(META_HANDLE)).second); 1170 CHECK(index->insert(kernel_->ref(META_HANDLE)).second);
1372 else 1171 else
1373 CHECK(1 == index->erase(kernel_->ref(META_HANDLE))); 1172 CHECK(1 == index->erase(kernel_->ref(META_HANDLE)));
1374 kernel_->ref(field) = value; 1173 kernel_->ref(field) = value;
1375 kernel_->dirty[static_cast<int>(field)] = true; 1174 kernel_->dirty[static_cast<int>(field)] = true;
1376 } 1175 }
1377 return true; 1176 return true;
1378 } 1177 }
1379 1178
1380 // Avoids temporary collision in index when renaming a bookmark to another
1381 // folder.
1382 bool MutableEntry::PutParentIdAndName(const Id& parent_id,
1383 const Name& name) {
1384 DCHECK(kernel_);
1385 const bool parent_id_changes = parent_id != kernel_->ref(PARENT_ID);
1386 bool db_name_changes = name.db_value() != kernel_->ref(NAME);
1387 if (parent_id_changes || db_name_changes) {
1388 if (!dir()->ReindexParentIdAndName(kernel_, parent_id,
1389 name.db_value()))
1390 return false;
1391 }
1392 Put(UNSANITIZED_NAME, name.GetUnsanitizedName());
1393 Put(NON_UNIQUE_NAME, name.non_unique_value());
1394 if (db_name_changes)
1395 kernel_->dirty[NAME] = true;
1396 if (parent_id_changes) {
1397 kernel_->dirty[PARENT_ID] = true;
1398 PutPredecessor(Id()); // Put in the 0th position.
1399 }
1400 return true;
1401 }
1402
1403 void MutableEntry::UnlinkFromOrder() { 1179 void MutableEntry::UnlinkFromOrder() {
1404 Id old_previous = Get(PREV_ID); 1180 Id old_previous = Get(PREV_ID);
1405 Id old_next = Get(NEXT_ID); 1181 Id old_next = Get(NEXT_ID);
1406 1182
1407 // Self-looping signifies that this item is not in the order. If we were to 1183 // Self-looping signifies that this item is not in the order. If we were to
1408 // set these to 0, we could get into trouble because this node might look 1184 // set these to 0, we could get into trouble because this node might look
1409 // like the first node in the ordering. 1185 // like the first node in the ordering.
1410 Put(NEXT_ID, Get(ID)); 1186 Put(NEXT_ID, Get(ID));
1411 Put(PREV_ID, Get(ID)); 1187 Put(PREV_ID, Get(ID));
1412 1188
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
1565 while (!ancestor_id.IsRoot()) { 1341 while (!ancestor_id.IsRoot()) {
1566 if (entry_id == ancestor_id) 1342 if (entry_id == ancestor_id)
1567 return false; 1343 return false;
1568 Entry new_parent(trans, GET_BY_ID, ancestor_id); 1344 Entry new_parent(trans, GET_BY_ID, ancestor_id);
1569 CHECK(new_parent.good()); 1345 CHECK(new_parent.good());
1570 ancestor_id = new_parent.Get(PARENT_ID); 1346 ancestor_id = new_parent.Get(PARENT_ID);
1571 } 1347 }
1572 return true; 1348 return true;
1573 } 1349 }
1574 1350
1575 // returns -1 if s contains any non [0-9] characters
1576 static int PathStringToInteger(PathString s) {
1577 PathString::const_iterator i = s.begin();
1578 for (; i != s.end(); ++i) {
1579 if (PathString::npos == PathString(PSTR("0123456789")).find(*i))
1580 return -1;
1581 }
1582 return atoi(s.c_str());
1583 }
1584
1585 // appends ~1 to the end of 's' unless there is already ~#, in which case
1586 // it just increments the number
1587 static PathString FixBasenameInCollision(const PathString s) {
1588 PathString::size_type last_tilde = s.find_last_of(PSTR('~'));
1589 if (PathString::npos == last_tilde) return s + PSTR("~1");
1590 if (s.size() == (last_tilde + 1)) return s + PSTR("1");
1591 // we have ~, but not necessarily ~# (for some number >= 0). check for that
1592 int n;
1593 if ((n = PathStringToInteger(s.substr(last_tilde + 1))) != -1) {
1594 n++;
1595 PathString pre_number = s.substr(0, last_tilde + 1);
1596 return pre_number + IntToString(n);
1597 } else {
1598 // we have a ~, but not a number following it, so we'll add another
1599 // ~ and this time, a number
1600 return s + PSTR("~1");
1601 }
1602 }
1603
1604 void DBName::MakeNoncollidingForEntry(BaseTransaction* trans,
1605 const Id& parent_id,
1606 Entry* e) {
1607 const PathString& desired_name = *this;
1608 CHECK(!desired_name.empty());
1609 PathString::size_type first_dot = desired_name.find_first_of(PSTR('.'));
1610 if (PathString::npos == first_dot)
1611 first_dot = desired_name.size();
1612 PathString basename = desired_name.substr(0, first_dot);
1613 PathString dotextension = desired_name.substr(first_dot);
1614 CHECK(basename + dotextension == desired_name);
1615 for (;;) {
1616 // Check for collision.
1617 PathString testname = basename + dotextension;
1618 Entry same_path_entry(trans, GET_BY_PARENTID_AND_DBNAME,
1619 parent_id, testname);
1620 if (!same_path_entry.good() || (e && same_path_entry.Get(ID) == e->Get(ID)))
1621 break;
1622 // There was a collision, so fix the name.
1623 basename = FixBasenameInCollision(basename);
1624 }
1625 // Set our value to the new value. This invalidates desired_name.
1626 PathString new_value = basename + dotextension;
1627 swap(new_value);
1628 }
1629
1630 const Blob* GetExtendedAttributeValue(const Entry& e, 1351 const Blob* GetExtendedAttributeValue(const Entry& e,
1631 const PathString& attribute_name) { 1352 const PathString& attribute_name) {
1632 ExtendedAttributeKey key(e.Get(META_HANDLE), attribute_name); 1353 ExtendedAttributeKey key(e.Get(META_HANDLE), attribute_name);
1633 ExtendedAttribute extended_attribute(e.trans(), GET_BY_HANDLE, key); 1354 ExtendedAttribute extended_attribute(e.trans(), GET_BY_HANDLE, key);
1634 if (extended_attribute.good() && !extended_attribute.is_deleted()) 1355 if (extended_attribute.good() && !extended_attribute.is_deleted())
1635 return &extended_attribute.value(); 1356 return &extended_attribute.value();
1636 return NULL; 1357 return NULL;
1637 } 1358 }
1638 1359
1639 // This function sets only the flags needed to get this entry to sync. 1360 // This function sets only the flags needed to get this entry to sync.
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1722 return s << std::dec; 1443 return s << std::dec;
1723 } 1444 }
1724 1445
1725 FastDump& operator<<(FastDump& dump, const syncable::Blob& blob) { 1446 FastDump& operator<<(FastDump& dump, const syncable::Blob& blob) {
1726 if (blob.empty()) 1447 if (blob.empty())
1727 return dump; 1448 return dump;
1728 string buffer(HexEncode(&blob[0], blob.size())); 1449 string buffer(HexEncode(&blob[0], blob.size()));
1729 dump.out_->sputn(buffer.c_str(), buffer.size()); 1450 dump.out_->sputn(buffer.c_str(), buffer.size());
1730 return dump; 1451 return dump;
1731 } 1452 }
OLDNEW
« no previous file with comments | « chrome/browser/sync/syncable/syncable.h ('k') | chrome/browser/sync/syncable/syncable_columns.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698