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

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

Issue 194065: Initial commit of sync engine code to browser/sync.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Fixes to gtest include path, reverted syncapi. Created 11 years, 3 months 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 | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #ifndef CHROME_BROWSER_SYNC_SYNCABLE_SYNCABLE_H_
6 #define CHROME_BROWSER_SYNC_SYNCABLE_SYNCABLE_H_
7
8 #include <algorithm>
9 #include <bitset>
10 #include <iosfwd>
11 #include <map>
12 #include <set>
13 #include <string>
14 #include <vector>
15
16 #include "base/atomicops.h"
17 #include "base/basictypes.h"
18 #include "base/time.h"
19 #include "chrome/browser/sync/syncable/blob.h"
20 #include "chrome/browser/sync/syncable/dir_open_result.h"
21 #include "chrome/browser/sync/syncable/directory_event.h"
22 #include "chrome/browser/sync/syncable/path_name_cmp.h"
23 #include "chrome/browser/sync/syncable/syncable_id.h"
24 #include "chrome/browser/sync/util/compat-file.h"
25 #include "chrome/browser/sync/util/compat-pthread.h"
26 #include "chrome/browser/sync/util/dbgq.h"
27 #include "chrome/browser/sync/util/event_sys.h"
28 #include "chrome/browser/sync/util/path_helpers.h"
29 #include "chrome/browser/sync/util/pthread_helpers.h"
30 #include "chrome/browser/sync/util/row_iterator.h"
31 #include "chrome/browser/sync/util/sync_types.h"
32
33 struct PurgeInfo;
34
35 namespace sync_api {
36 class ReadTransaction;
37 class WriteNode;
38 class ReadNode;
39 }
40
41 namespace syncable {
42 class Entry;
43 }
44
45 std::ostream& operator<<(std::ostream& s, const syncable::Entry& e);
46
47 namespace syncable {
48
49 class DirectoryBackingStore;
50
51 static const int64 kInvalidMetaHandle = 0;
52
53 enum {
54 BEGIN_FIELDS = 0,
55 INT64_FIELDS_BEGIN = BEGIN_FIELDS
56 };
57
58 enum MetahandleField {
59 // Primary key into the table. Keep this as a handle to the meta entry
60 // across transactions.
61 META_HANDLE = INT64_FIELDS_BEGIN
62 };
63
64 enum BaseVersion {
65 // After initial upload, the version is controlled by the server, and is
66 // increased whenever the data or metadata changes on the server.
67 BASE_VERSION = META_HANDLE + 1,
68 };
69
70 enum Int64Field {
71 SERVER_VERSION = BASE_VERSION + 1,
72 MTIME,
73 SERVER_MTIME,
74 CTIME,
75 SERVER_CTIME,
76
77 // A numeric position value that indicates the relative ordering of
78 // this object among its siblings.
79 SERVER_POSITION_IN_PARENT,
80
81 LOCAL_EXTERNAL_ID, // ID of an item in the external local storage that this
82 // entry is associated with. (such as bookmarks.js)
83
84 INT64_FIELDS_END
85 };
86
87 enum {
88 INT64_FIELDS_COUNT = INT64_FIELDS_END,
89 ID_FIELDS_BEGIN = INT64_FIELDS_END,
90 };
91
92 enum IdField {
93 // Code in InitializeTables relies on ID being the first IdField value.
94 ID = ID_FIELDS_BEGIN,
95 PARENT_ID,
96 SERVER_PARENT_ID,
97
98 PREV_ID,
99 NEXT_ID,
100 ID_FIELDS_END
101 };
102
103 enum {
104 ID_FIELDS_COUNT = ID_FIELDS_END - ID_FIELDS_BEGIN,
105 BIT_FIELDS_BEGIN = ID_FIELDS_END
106 };
107
108 enum IndexedBitField {
109 IS_UNSYNCED = BIT_FIELDS_BEGIN,
110 IS_UNAPPLIED_UPDATE,
111 INDEXED_BIT_FIELDS_END,
112 };
113
114 enum IsDelField {
115 IS_DEL = INDEXED_BIT_FIELDS_END,
116 };
117
118 enum BitField {
119 IS_DIR = IS_DEL + 1,
120 IS_BOOKMARK_OBJECT,
121
122 SERVER_IS_DIR,
123 SERVER_IS_DEL,
124 SERVER_IS_BOOKMARK_OBJECT,
125
126 BIT_FIELDS_END
127 };
128
129 enum {
130 BIT_FIELDS_COUNT = BIT_FIELDS_END - BIT_FIELDS_BEGIN,
131 STRING_FIELDS_BEGIN = BIT_FIELDS_END
132 };
133
134 enum StringField {
135 // The name, transformed so as to be suitable for use as a path-element. It
136 // is unique, and legal for this client.
137 NAME = STRING_FIELDS_BEGIN,
138 // The local name, pre-sanitization. It is not necessarily unique. If this
139 // is empty, it means |NAME| did not require sanitization.
140 UNSANITIZED_NAME,
141 // If NAME/UNSANITIZED_NAME are "Foo (2)", then NON_UNIQUE_NAME may be "Foo".
142 NON_UNIQUE_NAME,
143 // The server version of |NAME|. It is uniquified, but not necessarily
144 // OS-legal.
145 SERVER_NAME,
146 // The server version of |NON_UNIQUE_NAME|. Again, if SERVER_NAME is
147 // like "Foo (2)" due to a commit-time name aside, SERVER_NON_UNIQUE_NAME
148 // may hold the value "Foo".
149 SERVER_NON_UNIQUE_NAME,
150 // For bookmark entries, the URL of the bookmark.
151 BOOKMARK_URL,
152 SERVER_BOOKMARK_URL,
153
154 // A tag string which identifies this node as a particular top-level
155 // permanent object. The tag can be thought of as a unique key that
156 // identifies a singleton instance.
157 SINGLETON_TAG,
158 STRING_FIELDS_END,
159 };
160
161 enum {
162 STRING_FIELDS_COUNT = STRING_FIELDS_END - STRING_FIELDS_BEGIN,
163 BLOB_FIELDS_BEGIN = STRING_FIELDS_END
164 };
165
166 // From looking at the sqlite3 docs, it's not directly stated, but it
167 // seems the overhead for storing a NULL blob is very small.
168 enum BlobField {
169 // For bookmark entries, the favicon data. These will be NULL for
170 // non-bookmark items.
171 BOOKMARK_FAVICON = BLOB_FIELDS_BEGIN,
172 SERVER_BOOKMARK_FAVICON,
173 BLOB_FIELDS_END,
174 };
175
176 enum {
177 BLOB_FIELDS_COUNT = BLOB_FIELDS_END - BLOB_FIELDS_BEGIN
178 };
179
180 enum {
181 FIELD_COUNT = BLOB_FIELDS_END,
182 // Past this point we have temporaries, stored in memory only.
183 BEGIN_TEMPS = BLOB_FIELDS_END,
184 BIT_TEMPS_BEGIN = BEGIN_TEMPS,
185 };
186
187 enum BitTemp {
188 SYNCING = BIT_TEMPS_BEGIN,
189 IS_NEW, // Means use INSERT instead of UPDATE to save to db.
190 DEPRECATED_DELETE_ON_CLOSE, // Set by redirector, IS_OPEN must also be set.
191 DEPRECATED_CHANGED_SINCE_LAST_OPEN, // Have we been written to since we've
192 // been opened.
193 BIT_TEMPS_END,
194 };
195
196 enum {
197 BIT_TEMPS_COUNT = BIT_TEMPS_END - BIT_TEMPS_BEGIN
198 };
199
200 class BaseTransaction;
201 class WriteTransaction;
202 class ReadTransaction;
203 class Directory;
204 class ScopedDirLookup;
205 class ExtendedAttribute;
206
207 // Instead of:
208 // Entry e = transaction.GetById(id);
209 // use:
210 // Entry e(transaction, GET_BY_ID, id);
211 //
212 // Why? The former would require a copy constructor, and it would be difficult
213 // to enforce that an entry never outlived its transaction if there were a copy
214 // constructor.
215 enum GetById {
216 GET_BY_ID
217 };
218
219 enum GetByTag {
220 GET_BY_TAG
221 };
222
223 enum GetByHandle {
224 GET_BY_HANDLE
225 };
226
227 enum GetByPath {
228 GET_BY_PATH
229 };
230
231 enum GetByParentIdAndName {
232 GET_BY_PARENTID_AND_NAME
233 };
234
235 // DBName is the name stored in the database.
236 enum GetByParentIdAndDBName {
237 GET_BY_PARENTID_AND_DBNAME
238 };
239
240 enum Create {
241 CREATE
242 };
243
244 enum CreateNewUpdateItem {
245 CREATE_NEW_UPDATE_ITEM
246 };
247
248 typedef std::set<PathString> AttributeKeySet;
249
250 // DBName is a PathString with additional transformation methods that are
251 // useful when trying to derive a unique and legal database name from
252 // an unsanitized sync name.
253 class DBName : public PathString {
254 public:
255 explicit DBName(const PathString& database_name)
256 : PathString(database_name) { }
257
258 // TODO(ncarter): Remove these codepaths to maintain alternate titles
259 // which are OS legal filenames, Chrome doesn't depend on this like some
260 // other browsers do.
261 void MakeOSLegal() {
262 PathString new_value = MakePathComponentOSLegal(*this);
263 if (!new_value.empty())
264 swap(new_value);
265 }
266
267 // Modify the value of this DBName so that it is not in use by any entry
268 // inside |parent_id|, except maybe |e|. |e| may be NULL if you are trying
269 // to compute a name for an entry which has yet to be created.
270 void MakeNoncollidingForEntry(BaseTransaction* trans,
271 const Id& parent_id,
272 Entry *e);
273 };
274
275 // SyncName encapsulates a canonical server name. In general, when we need to
276 // muck around with a name that the server sends us (e.g. to make it OS legal),
277 // we try to preserve the original value in a SyncName,
278 // and distill the new local value into a DBName.
279 // At other times, we need to apply transforms in the
280 // other direction -- that is, to create a server-appropriate SyncName from a
281 // user-updated DBName (which is an OS legal name, but not necessarily in the
282 // format that the server wants it to be). For that sort of thing, you should
283 // initialize a SyncName from the DB name value, and use the methods of
284 // SyncName to canonicalize it. At other times, you have a pair of canonical
285 // server values -- one (the "value") which is unique in the parent, and another
286 // (the "non unique value") which is not unique in the parent -- and you
287 // simply want to create a SyncName to hold them as a pair.
288 class SyncName {
289 public:
290 // Create a SyncName with the initially specified value.
291 explicit SyncName(const PathString& sync_name)
292 : value_(sync_name), non_unique_value_(sync_name) { }
293
294 // Create a SyncName by specifying a value and a non-unique value. If
295 // you use this constructor, the values you provide should already be
296 // acceptable server names. Don't use the mutation/sanitization methods
297 // on the resulting instance -- mutation won't work if you have distinct
298 // values for the unique and non-unique fields.
299 SyncName(const PathString& unique_sync_name,
300 const PathString& non_unique_sync_name)
301 : value_(unique_sync_name), non_unique_value_(non_unique_sync_name) { }
302
303 #ifdef OS_MACOSX
304 // Translate [':' -> '/'] within the sync name. Used on OSX.
305 void ConvertColonsToSlashes() {
306 DCHECK_EQ(value_, non_unique_value_)
307 << "Deriving value_ will overwrite non_unique_value_.";
308 std::string temporary_copy;
309 temporary_copy.reserve(value_.size());
310 StringReplace(value_, ":", "/", true, &temporary_copy);
311 value_.swap(temporary_copy);
312 non_unique_value_ = value_;
313 }
314 #endif
315
316 // Transform |value_| so that it's a legal server name.
317 void MakeServerLegal() {
318 DCHECK_EQ(value_, non_unique_value_)
319 << "Deriving value_ will overwrite non_unique_value_.";
320 // Append a trailing space if the value is one of the server's three
321 // forbidden special cases.
322 if (value_.empty() ||
323 value_ == PSTR(".") ||
324 value_ == PSTR("..")) {
325 value_.append(PSTR(" "));
326 non_unique_value_ = value_;
327 }
328 // TODO(ncarter): Handle server's other requirement: truncation to
329 // 256 bytes in Unicode NFC.
330 }
331
332 const PathString& value() const { return value_; }
333 PathString& value() { return value_; }
334 const PathString& non_unique_value() const { return non_unique_value_; }
335 PathString& non_unique_value() { return non_unique_value_; }
336
337 inline bool operator==(const SyncName& right_hand_side) const {
338 return value_ == right_hand_side.value_ &&
339 non_unique_value_ == right_hand_side.non_unique_value_;
340 }
341 inline bool operator!=(const SyncName& right_hand_side) const {
342 return !(*this == right_hand_side);
343 }
344 private:
345 PathString value_;
346 PathString non_unique_value_;
347 };
348
349 // Name is a SyncName which has an additional DBName that provides a way to
350 // interpolate the "unsanitized name" according to the syncable convention.
351 //
352 // A method might accept a Name as an parameter when the sync and database
353 // names need to be set simultaneously:
354 //
355 // void PutName(const Name& new_name) {
356 // Put(NAME, new_name.db_value());
357 // Put(UNSANITIZED_NAME, new_name.GetUnsanitizedName());
358 // }
359 //
360 // A code point that is trying to convert between local database names and
361 // server sync names can use Name to help with the conversion:
362 //
363 // SyncName server_name = entry->GetServerName();
364 // Name name = Name::FromSyncName(server_name); // Initially, name.value()
365 // // and name.db_value() are
366 // // equal to
367 // // server_name.value().
368 // name.db_value().MakeOSLegal(); // Updates name.db_value in-place,
369 // // leaving name.value() unchanged.
370 // foo->PutName(name);
371 //
372 class Name : public SyncName {
373 public:
374 // Create a Name with an initially specified db_value and value.
375 Name(const PathString& db_name, const PathString& sync_name)
376 : SyncName(sync_name), db_value_(db_name) { }
377
378 // Create a Name by specifying the db name, sync name, and non-unique
379 // sync name values.
380 Name(const PathString& db_name, const PathString& sync_name,
381 const PathString& non_unique_sync_name)
382 : SyncName(sync_name, non_unique_sync_name), db_value_(db_name) { }
383
384 // Create a Name with all name values initially equal to the the single
385 // specified argument.
386 explicit Name(const PathString& sync_and_db_name)
387 : SyncName(sync_and_db_name), db_value_(sync_and_db_name) { }
388
389 // Create a Name using the local (non-SERVER) fields of an EntryKernel.
390 static Name FromEntryKernel(struct EntryKernel*);
391
392 // Create a Name from a SyncName. db_value is initially sync_name.value().
393 // non_unique_value() and value() are copied from |sync_name|.
394 static Name FromSyncName(const SyncName& sync_name) {
395 return Name(sync_name.value(), sync_name.value(),
396 sync_name.non_unique_value());
397 }
398
399 static Name FromDBNameAndSyncName(const PathString& db_name,
400 const SyncName& sync_name) {
401 return Name(db_name, sync_name.value(), sync_name.non_unique_value());
402 }
403
404 // Get the database name. The non-const version is useful for in-place
405 // mutation.
406 const DBName& db_value() const { return db_value_; }
407 DBName& db_value() { return db_value_; }
408
409 // Do the sync names and database names differ? This indicates that
410 // the sync name has been sanitized, and that GetUnsanitizedName() will
411 // be non-empty.
412 bool HasBeenSanitized() const { return db_value_ != value(); }
413
414 // Compute the value of the unsanitized name from the current sync and db
415 // name values. The unsanitized name is the sync name value, unless the sync
416 // name is the same as the db name value, in which case the unsanitized name
417 // is empty.
418 PathString GetUnsanitizedName() const {
419 return HasBeenSanitized() ? value() : PathString();
420 }
421
422 inline bool operator==(const Name& right_hand_side) const {
423 return this->SyncName::operator==(right_hand_side) &&
424 db_value_ == right_hand_side.db_value_;
425 }
426 inline bool operator!=(const Name& right_hand_side) const {
427 return !(*this == right_hand_side);
428 }
429
430 private:
431 // The database name, which is maintained to be a legal and unique-in-parent
432 // name.
433 DBName db_value_;
434 };
435
436 // Why the singular enums? So the code compile-time dispatches instead of
437 // runtime dispatches as it would with a single enum and an if() statement.
438
439 // The EntryKernel class contains the actual data for an entry. It
440 // would be a private class, except the number of required friend
441 // declarations would bloat the code.
442 struct EntryKernel {
443 protected:
444 PathString string_fields[STRING_FIELDS_COUNT];
445 Blob blob_fields[BLOB_FIELDS_COUNT];
446 int64 int64_fields[INT64_FIELDS_COUNT];
447 Id id_fields[ID_FIELDS_COUNT];
448 std::bitset<BIT_FIELDS_COUNT> bit_fields;
449 std::bitset<BIT_TEMPS_COUNT> bit_temps;
450
451 public:
452 std::bitset<FIELD_COUNT> dirty;
453
454 // Contain all this error-prone arithmetic in one place.
455 inline int64& ref(MetahandleField field) {
456 return int64_fields[field - INT64_FIELDS_BEGIN];
457 }
458 inline int64& ref(Int64Field field) {
459 return int64_fields[field - INT64_FIELDS_BEGIN];
460 }
461 inline Id& ref(IdField field) {
462 return id_fields[field - ID_FIELDS_BEGIN];
463 }
464 inline int64& ref(BaseVersion field) {
465 return int64_fields[field - INT64_FIELDS_BEGIN];
466 }
467 inline std::bitset<BIT_FIELDS_COUNT>::reference ref(IndexedBitField field) {
468 return bit_fields[field - BIT_FIELDS_BEGIN];
469 }
470 inline std::bitset<BIT_FIELDS_COUNT>::reference ref(IsDelField field) {
471 return bit_fields[field - BIT_FIELDS_BEGIN];
472 }
473 inline std::bitset<BIT_FIELDS_COUNT>::reference ref(BitField field) {
474 return bit_fields[field - BIT_FIELDS_BEGIN];
475 }
476 inline PathString& ref(StringField field) {
477 return string_fields[field - STRING_FIELDS_BEGIN];
478 }
479 inline Blob& ref(BlobField field) {
480 return blob_fields[field - BLOB_FIELDS_BEGIN];
481 }
482 inline std::bitset<BIT_TEMPS_COUNT>::reference ref(BitTemp field) {
483 return bit_temps[field - BIT_TEMPS_BEGIN];
484 }
485
486 inline int64 ref(MetahandleField field) const {
487 return int64_fields[field - INT64_FIELDS_BEGIN];
488 }
489 inline int64 ref(Int64Field field) const {
490 return int64_fields[field - INT64_FIELDS_BEGIN];
491 }
492 inline const Id& ref(IdField field) const {
493 return id_fields[field - ID_FIELDS_BEGIN];
494 }
495 inline int64 ref(BaseVersion field) const {
496 return int64_fields[field - INT64_FIELDS_BEGIN];
497 }
498 inline bool ref(IndexedBitField field) const {
499 return bit_fields[field - BIT_FIELDS_BEGIN];
500 }
501 inline bool ref(IsDelField field) const {
502 return bit_fields[field - BIT_FIELDS_BEGIN];
503 }
504 inline bool ref(BitField field) const {
505 return bit_fields[field - BIT_FIELDS_BEGIN];
506 }
507 inline PathString ref(StringField field) const {
508 return string_fields[field - STRING_FIELDS_BEGIN];
509 }
510 inline Blob ref(BlobField field) const {
511 return blob_fields[field - BLOB_FIELDS_BEGIN];
512 }
513 inline bool ref(BitTemp field) const {
514 return bit_temps[field - BIT_TEMPS_BEGIN];
515 }
516 };
517
518 // A read-only meta entry.
519 class Entry {
520 friend class Directory;
521 friend std::ostream& ::operator << (std::ostream& s, const Entry& e);
522
523 public:
524 // After constructing, you must check good() to test whether the Get
525 // succeed.
526 Entry(BaseTransaction* trans, GetByHandle, int64 handle);
527 Entry(BaseTransaction* trans, GetById, const Id& id);
528 Entry(BaseTransaction* trans, GetByTag, const PathString& tag);
529 Entry(BaseTransaction* trans, GetByPath, const PathString& path);
530 Entry(BaseTransaction* trans, GetByParentIdAndName, const Id& id,
531 const PathString& name);
532 Entry(BaseTransaction* trans, GetByParentIdAndDBName, const Id& id,
533 const PathString& name);
534
535 bool good() const { return 0 != kernel_; }
536
537 BaseTransaction* trans() const { return basetrans_; }
538
539 // Field accessors.
540 inline int64 Get(MetahandleField field) const {
541 DCHECK(kernel_);
542 return kernel_->ref(field);
543 }
544 inline Id Get(IdField field) const {
545 DCHECK(kernel_);
546 return kernel_->ref(field);
547 }
548 inline int64 Get(Int64Field field) const {
549 DCHECK(kernel_);
550 return kernel_->ref(field);
551 }
552 inline int64 Get(BaseVersion field) const {
553 DCHECK(kernel_);
554 return kernel_->ref(field);
555 }
556 inline bool Get(IndexedBitField field) const {
557 DCHECK(kernel_);
558 return kernel_->ref(field);
559 }
560 inline bool Get(IsDelField field) const {
561 DCHECK(kernel_);
562 return kernel_->ref(field);
563 }
564 inline bool Get(BitField field) const {
565 DCHECK(kernel_);
566 return kernel_->ref(field);
567 }
568 PathString Get(StringField field) const;
569 inline Blob Get(BlobField field) const {
570 DCHECK(kernel_);
571 return kernel_->ref(field);
572 }
573 inline bool Get(BitTemp field) const {
574 DCHECK(kernel_);
575 return kernel_->ref(field);
576 }
577 inline Name GetName() const {
578 DCHECK(kernel_);
579 return Name::FromEntryKernel(kernel_);
580 }
581 inline SyncName GetServerName() const {
582 DCHECK(kernel_);
583 return SyncName(kernel_->ref(SERVER_NAME),
584 kernel_->ref(SERVER_NON_UNIQUE_NAME));
585 }
586 inline bool SyncNameMatchesServerName() const {
587 DCHECK(kernel_);
588 SyncName sync_name(GetName());
589 return sync_name == GetServerName();
590 }
591 inline PathString GetSyncNameValue() const {
592 DCHECK(kernel_);
593 // This should always be equal to GetName().sync_name().value(), but
594 // maybe faster.
595 return kernel_->ref(UNSANITIZED_NAME).empty() ? kernel_->ref(NAME) :
596 kernel_->ref(UNSANITIZED_NAME);
597 }
598 inline bool ExistsOnClientBecauseDatabaseNameIsNonEmpty() const {
599 DCHECK(kernel_);
600 return !kernel_->ref(NAME).empty();
601 }
602 inline bool IsRoot() const {
603 DCHECK(kernel_);
604 return kernel_->ref(ID).IsRoot();
605 }
606
607 void GetAllExtendedAttributes(BaseTransaction* trans,
608 std::set<ExtendedAttribute>* result);
609 void GetExtendedAttributesList(BaseTransaction* trans,
610 AttributeKeySet* result);
611 // Flags all extended attributes for deletion on the next SaveChanges.
612 void DeleteAllExtendedAttributes(WriteTransaction *trans);
613
614 Directory* dir() const;
615
616 const EntryKernel GetKernelCopy() const {
617 return *kernel_;
618 }
619
620
621 protected: // Don't allow creation on heap, except by sync API wrappers.
622 friend class sync_api::ReadNode;
623 void* operator new(size_t size) { return (::operator new)(size); }
624
625 inline Entry(BaseTransaction* trans) : basetrans_(trans) { }
626
627 protected:
628
629 BaseTransaction* const basetrans_;
630
631 EntryKernel* kernel_;
632
633 DISALLOW_COPY_AND_ASSIGN(Entry);
634 };
635
636 // A mutable meta entry. Changes get committed to the database when the
637 // WriteTransaction is destroyed.
638 class MutableEntry : public Entry {
639 friend class WriteTransaction;
640 friend class Directory;
641 void Init(WriteTransaction* trans, const Id& parent_id,
642 const PathString& name);
643 public:
644 MutableEntry(WriteTransaction* trans, Create, const Id& parent_id,
645 const PathString& name);
646 MutableEntry(WriteTransaction* trans, CreateNewUpdateItem, const Id& id);
647 MutableEntry(WriteTransaction* trans, GetByHandle, int64);
648 MutableEntry(WriteTransaction* trans, GetById, const Id&);
649 MutableEntry(WriteTransaction* trans, GetByPath, const PathString& path);
650 MutableEntry(WriteTransaction* trans, GetByParentIdAndName, const Id&,
651 const PathString& name);
652 MutableEntry(WriteTransaction* trans, GetByParentIdAndDBName,
653 const Id& parentid, const PathString& name);
654
655 WriteTransaction* trans() const;
656
657 // Field Accessors. Some of them trigger the re-indexing of the entry.
658 // Return true on success, return false on failure, which means
659 // that putting the value would have caused a duplicate in the index.
660 bool Put(Int64Field field, const int64& value);
661 bool Put(IdField field, const Id& value);
662 bool Put(StringField field, const PathString& value);
663 bool Put(BaseVersion field, int64 value);
664 inline bool PutName(const Name& name) {
665 return (Put(NAME, name.db_value()) &&
666 Put(UNSANITIZED_NAME, name.GetUnsanitizedName()) &&
667 Put(NON_UNIQUE_NAME, name.non_unique_value()));
668 }
669 inline bool PutServerName(const SyncName& server_name) {
670 return (Put(SERVER_NAME, server_name.value()) &&
671 Put(SERVER_NON_UNIQUE_NAME, server_name.non_unique_value()));
672 }
673 inline bool Put(BlobField field, const Blob& value) {
674 return PutField(field, value);
675 }
676 inline bool Put(BitField field, bool value) {
677 return PutField(field, value);
678 }
679 inline bool Put(IsDelField field, bool value) {
680 return PutIsDel(value);
681 }
682 bool Put(IndexedBitField field, bool value);
683
684 // Avoids temporary collision in index when renaming a bookmark
685 // into another folder.
686 bool PutParentIdAndName(const Id& parent_id, const Name& name);
687
688 // Sets the position of this item, and updates the entry kernels of the
689 // adjacent siblings so that list invariants are maintained. Returns false
690 // and fails if |predecessor_id| does not identify a sibling. Pass the root
691 // ID to put the node in first position.
692 bool PutPredecessor(const Id& predecessor_id);
693
694 inline bool Put(BitTemp field, bool value) {
695 return PutTemp(field, value);
696 }
697
698 protected:
699
700 template <typename FieldType, typename ValueType>
701 inline bool PutField(FieldType field, const ValueType& value) {
702 DCHECK(kernel_);
703 if (kernel_->ref(field) != value) {
704 kernel_->ref(field) = value;
705 kernel_->dirty[static_cast<int>(field)] = true;
706 }
707 return true;
708 }
709
710 template <typename TempType, typename ValueType>
711 inline bool PutTemp(TempType field, const ValueType& value) {
712 DCHECK(kernel_);
713 kernel_->ref(field) = value;
714 return true;
715 }
716
717 bool PutIsDel(bool value);
718
719 private: // Don't allow creation on heap, except by sync API wrappers.
720 friend class sync_api::WriteNode;
721 void* operator new(size_t size) { return (::operator new)(size); }
722
723 bool PutImpl(StringField field, const PathString& value);
724
725
726 // Adjusts the successor and predecessor entries so that they no longer
727 // refer to this entry.
728 void UnlinkFromOrder();
729
730 protected:
731 MutableEntry();
732
733 DISALLOW_COPY_AND_ASSIGN(MutableEntry);
734 };
735
736 template <Int64Field field_index>
737 class SameField;
738 template <Int64Field field_index>
739 class HashField;
740 class LessParentIdAndNames;
741 class LessMultiIncusionTargetAndMetahandle;
742 template <typename FieldType, FieldType field_index>
743 class LessField;
744 class LessEntryMetaHandles {
745 public:
746 inline bool operator()(const syncable::EntryKernel& a,
747 const syncable::EntryKernel& b) const {
748 return a.ref(META_HANDLE) < b.ref(META_HANDLE);
749 }
750 };
751 typedef std::set<EntryKernel, LessEntryMetaHandles> OriginalEntries;
752
753 // a WriteTransaction has a writer tag describing which body of code is doing
754 // the write. This is defined up here since DirectoryChangeEvent also contains
755 // one.
756 enum WriterTag {
757 INVALID, SYNCER, AUTHWATCHER, UNITTEST, VACUUM_AFTER_SAVE, SYNCAPI
758 };
759
760 // A separate Event type and channel for very frequent changes, caused
761 // by anything, not just the user.
762 struct DirectoryChangeEvent {
763 enum {
764 // Means listener should go through list of original entries and
765 // calculate what it needs to notify. It should *not* call any
766 // callbacks or attempt to lock anything because a
767 // WriteTransaction is being held until the listener returns.
768 CALCULATE_CHANGES,
769 // Means the WriteTransaction has been released and the listener
770 // can now take action on the changes it calculated.
771 TRANSACTION_COMPLETE,
772 // Channel is closing.
773 SHUTDOWN
774 } todo;
775 // These members are only valid for CALCULATE_CHANGES
776 const OriginalEntries* originals;
777 BaseTransaction* trans;
778 WriterTag writer;
779 typedef DirectoryChangeEvent EventType;
780 static inline bool IsChannelShutdownEvent(const EventType& e) {
781 return SHUTDOWN == e.todo;
782 }
783 };
784
785 struct ExtendedAttributeKey {
786 int64 metahandle;
787 PathString key;
788 inline bool operator < (const ExtendedAttributeKey& x) const {
789 if (metahandle != x.metahandle)
790 return metahandle < x.metahandle;
791 return key.compare(x.key) < 0;
792 }
793 ExtendedAttributeKey(int64 metahandle, PathString key) :
794 metahandle(metahandle), key(key) { }
795 };
796
797 struct ExtendedAttributeValue {
798 Blob value;
799 bool is_deleted;
800 bool dirty;
801 };
802
803 typedef std::map<ExtendedAttributeKey, ExtendedAttributeValue>
804 ExtendedAttributes;
805
806 // Used to maintain our per-thread transaction state and to enforce
807 // our transaction invariants (e.g. no recursive transactions).
808 // Each time a thread enters a transaction by constructing a Read or a
809 // WriteTransaction object, a ThreadNode object is pulled from thread
810 // local storage, or created and stored in thread-local storage if it
811 // doesn't yet exist.
812 struct ThreadNode {
813 const char* file;
814 int line;
815 base::TimeTicks wait_started;
816 ThreadId id;
817 ThreadNode* next;
818 ThreadNode* prev;
819
820 // True when this node is in a linked list. Only accessed from
821 // owner thread so no locking necessary.
822 bool in_list;
823 WriteTransaction* current_write_trans;
824 PThreadCondVar condvar; // Mutex is the kernel's transaction mutex.
825 bool wake_up; // flag for condvar.
826 int tclass; // Really a BaseTransaction::TClass, but no forward enums.
827
828 // Linked list operations.
829 inline ThreadNode() : in_list(false), current_write_trans(NULL),
830 wake_up(false) {
831 next = prev = this;
832 }
833 inline ThreadNode* Remove() {
834 in_list = false;
835 prev->next = next;
836 next->prev = prev;
837 return next = prev = this;
838 }
839 inline void Insert(ThreadNode* node) {
840 in_list = true;
841 prev = node->prev;
842 next = node;
843 next->prev = prev->next = this;
844 }
845 };
846
847 struct ThreadCounts {
848 int waiting;
849 int active;
850 // Also keep a linked list of thread information.
851 ThreadNode waiting_headtail;
852 ThreadNode active_headtail;
853
854 ThreadCounts() : waiting(0), active(0) { }
855
856 DISALLOW_COPY_AND_ASSIGN(ThreadCounts);
857 };
858
859 typedef PThreadScopedLock<PThreadMutex> ScopedTransactionLock;
860 typedef std::set<int64> MetahandleSet;
861
862 // A list of metahandles whose metadata should not be purged.
863 typedef std::multiset<int64> Pegs;
864
865 // The name Directory in this case means the entire directory
866 // structure within a single user account.
867 //
868 // Sqlite is a little goofy, in that each thread must access a database
869 // via its own handle. So, a Directory object should only be accessed
870 // from a single thread. Use DirectoryManager's Open() method to
871 // always get a directory that has been properly initialized on the
872 // current thread.
873 //
874 // The db is protected against concurrent modification by a reader/
875 // writer lock, negotiated by the ReadTransaction and WriteTransaction
876 // friend classes. The in-memory indices are protected against
877 // concurrent modification by the kernel lock.
878 //
879 // All methods which require the reader/writer lock to be held either
880 // are protected and only called from friends in a transaction
881 // or are public and take a Transaction* argument.
882 //
883 // All methods which require the kernel lock to be already held take a
884 // ScopeKernelLock* argument.
885 //
886 // To prevent deadlock, the reader writer transaction lock must always
887 // be held before acquiring the kernel lock.
888 class ScopedKernelLock;
889 class IdFilter;
890 class DirectoryManager;
891 struct PathMatcher;
892
893 class Directory {
894 friend class BaseTransaction;
895 friend class Entry;
896 friend class ExtendedAttribute;
897 friend class MutableEntry;
898 friend class MutableExtendedAttribute;
899 friend class ReadTransaction;
900 friend class ReadTransactionWithoutDB;
901 friend class ScopedKernelLock;
902 friend class ScopedKernelUnlock;
903 friend class WriteTransaction;
904 friend class TestUnsaveableDirectory;
905 public:
906 // Various data that the Directory::Kernel we are backing (persisting data
907 // for) needs saved across runs of the application.
908 struct PersistedKernelInfo {
909 int64 last_sync_timestamp;
910 bool initial_sync_ended;
911 std::string store_birthday;
912 int64 next_id;
913 PersistedKernelInfo() : last_sync_timestamp(0),
914 initial_sync_ended(false),
915 next_id(0) {
916 }
917 };
918
919 // What the Directory needs on initialization to create itself and its Kernel.
920 // Filled by DirectoryBackingStore::Load.
921 struct KernelLoadInfo {
922 PersistedKernelInfo kernel_info;
923 std::string cache_guid; // Created on first initialization, never changes.
924 int64 max_metahandle; // Computed (using sql MAX aggregate) on init.
925 KernelLoadInfo() : max_metahandle(0) {
926 }
927 };
928
929 // The dirty/clean state of kernel fields backed by the share_info table.
930 // This is public so it can be used in SaveChangesSnapshot for persistence.
931 enum KernelShareInfoStatus {
932 KERNEL_SHARE_INFO_INVALID,
933 KERNEL_SHARE_INFO_VALID,
934 KERNEL_SHARE_INFO_DIRTY
935 };
936
937 // When the Directory is told to SaveChanges, a SaveChangesSnapshot is
938 // constructed and forms a consistent snapshot of what needs to be sent to
939 // the backing store.
940 struct SaveChangesSnapshot {
941 KernelShareInfoStatus kernel_info_status;
942 PersistedKernelInfo kernel_info;
943 OriginalEntries dirty_metas;
944 ExtendedAttributes dirty_xattrs;
945 SaveChangesSnapshot() : kernel_info_status(KERNEL_SHARE_INFO_INVALID) {
946 }
947 };
948
949 Directory();
950 virtual ~Directory();
951
952 DirOpenResult Open(const PathString& file_path, const PathString& name);
953
954 void Close();
955
956 int64 NextMetahandle();
957 // Always returns a negative id. Positive client ids are generated
958 // by the server only.
959 Id NextId();
960
961 PathString file_path() const { return kernel_->db_path; }
962 bool good() const { return NULL != store_; }
963
964 // The sync timestamp is an index into the list of changes for an account.
965 // It doesn't actually map to any time scale, it's name is an historical
966 // anomaly.
967 int64 last_sync_timestamp() const;
968 void set_last_sync_timestamp(int64 timestamp);
969
970 bool initial_sync_ended() const;
971 void set_initial_sync_ended(bool value);
972
973 PathString name() const { return kernel_->name_; }
974
975 // (Account) Store birthday is opaque to the client,
976 // so we keep it in the format it is in the proto buffer
977 // in case we switch to a binary birthday later.
978 std::string store_birthday() const;
979 void set_store_birthday(std::string store_birthday);
980
981 // Unique to each account / client pair.
982 std::string cache_guid() const;
983
984 protected: // for friends, mainly used by Entry constructors
985 EntryKernel* GetChildWithName(const Id& parent_id, const PathString& name);
986 EntryKernel* GetChildWithDBName(const Id& parent_id, const PathString& name);
987 EntryKernel* GetEntryByHandle(const int64 handle);
988 EntryKernel* GetEntryByHandle(const int64 metahandle, ScopedKernelLock* lock);
989 EntryKernel* GetEntryById(const Id& id);
990 EntryKernel* GetEntryByTag(const PathString& tag);
991 EntryKernel* GetRootEntry();
992 EntryKernel* GetEntryByPath(const PathString& path);
993 bool ReindexId(EntryKernel* const entry, const Id& new_id);
994 bool ReindexParentIdAndName(EntryKernel* const entry, const Id& new_parent_id,
995 const PathString& new_name);
996 // These don't do the semantic checking that the redirector needs.
997 // The semantic checking is implemented higher up.
998 bool Undelete(EntryKernel* const entry);
999 bool Delete(EntryKernel* const entry);
1000
1001 // Overridden by tests.
1002 virtual DirectoryBackingStore* CreateBackingStore(
1003 const PathString& dir_name,
1004 const PathString& backing_filepath);
1005
1006 private:
1007 // These private versions expect the kernel lock to already be held
1008 // before calling.
1009 EntryKernel* GetEntryById(const Id& id, ScopedKernelLock* const lock);
1010 EntryKernel* GetChildWithName(const Id& parent_id,
1011 const PathString& name,
1012 ScopedKernelLock* const lock);
1013 EntryKernel* GetChildWithNameImpl(const Id& parent_id,
1014 const PathString& name,
1015 ScopedKernelLock* const lock);
1016
1017 DirOpenResult OpenImpl(const PathString& file_path, const PathString& name);
1018
1019 struct DirectoryEventTraits {
1020 typedef DirectoryEvent EventType;
1021 static inline bool IsChannelShutdownEvent(const DirectoryEvent& event) {
1022 return DIRECTORY_DESTROYED == event;
1023 }
1024 };
1025 public:
1026 typedef EventChannel<DirectoryEventTraits, PThreadMutex> Channel;
1027 typedef EventChannel<DirectoryChangeEvent, PThreadMutex> ChangesChannel;
1028 typedef std::vector<int64> ChildHandles;
1029
1030 // Returns the child meta handles for given parent id.
1031 void GetChildHandles(BaseTransaction*, const Id& parent_id,
1032 const PathString& path_spec, ChildHandles* result);
1033 void GetChildHandles(BaseTransaction*, const Id& parent_id,
1034 ChildHandles* result);
1035 void GetChildHandlesImpl(BaseTransaction* trans, const Id& parent_id,
1036 PathMatcher* matcher, ChildHandles* result);
1037
1038 // Find the first or last child in the positional ordering under a parent,
1039 // and return its id. Returns a root Id if parent has no children.
1040 Id GetFirstChildId(BaseTransaction* trans, const Id& parent_id);
1041 Id GetLastChildId(BaseTransaction* trans, const Id& parent_id);
1042
1043 // SaveChanges works by taking a consistent snapshot of the current Directory
1044 // state and indices (by deep copy) under a ReadTransaction, passing this
1045 // snapshot to the backing store under no transaction, and finally cleaning
1046 // up by either purging entries no longer needed (this part done under a
1047 // WriteTransaction) or rolling back dirty and IS_NEW bits. It also uses
1048 // internal locking to enforce SaveChanges operations are mutually exclusive.
1049 //
1050 // WARNING: THIS METHOD PERFORMS SYNCHRONOUS I/O VIA SQLITE.
1051 bool SaveChanges();
1052
1053 // Returns the number of entities with the unsynced bit set.
1054 int64 unsynced_entity_count() const;
1055
1056 // Get GetUnsyncedMetaHandles should only be called after SaveChanges and
1057 // before any new entries have been created. The intention is that the
1058 // syncer should call it from its PerformSyncQueries member.
1059 typedef std::vector<int64> UnsyncedMetaHandles;
1060 void GetUnsyncedMetaHandles(BaseTransaction* trans,
1061 UnsyncedMetaHandles* result);
1062
1063 // Get all the metahandles for unapplied updates
1064 typedef std::vector<int64> UnappliedUpdateMetaHandles;
1065 void GetUnappliedUpdateMetaHandles(BaseTransaction* trans,
1066 UnappliedUpdateMetaHandles* result);
1067
1068 void GetAllExtendedAttributes(BaseTransaction* trans, int64 metahandle,
1069 std::set<ExtendedAttribute>* result);
1070 // Get all extended attribute keys associated with a metahandle
1071 void GetExtendedAttributesList(BaseTransaction* trans, int64 metahandle,
1072 AttributeKeySet* result);
1073 // Flags all extended attributes for deletion on the next SaveChanges.
1074 void DeleteAllExtendedAttributes(WriteTransaction*trans, int64 metahandle);
1075
1076 // Get the channel for post save notification, used by the syncer.
1077 inline Channel* channel() const {
1078 return kernel_->channel;
1079 }
1080 inline ChangesChannel* changes_channel() const {
1081 return kernel_->changes_channel;
1082 }
1083
1084 // Checks tree metadata consistency.
1085 // If full_scan is false, the function will avoid pulling any entries from the
1086 // db and scan entries currently in ram.
1087 // If full_scan is true, all entries will be pulled from the database.
1088 // No return value, CHECKs will be triggered if we're given bad
1089 // information.
1090 void CheckTreeInvariants(syncable::BaseTransaction* trans,
1091 bool full_scan);
1092
1093 void CheckTreeInvariants(syncable::BaseTransaction* trans,
1094 const OriginalEntries* originals);
1095
1096 void CheckTreeInvariants(syncable::BaseTransaction* trans,
1097 const MetahandleSet& handles,
1098 const IdFilter& idfilter);
1099
1100 private:
1101 // Helper to prime ids_index, parent_id_and_names_index, unsynced_metahandles
1102 // and unapplied_metahandles from metahandles_index.
1103 void InitializeIndices();
1104
1105 // Constructs a consistent snapshot of the current Directory state and
1106 // indices (by deep copy) under a ReadTransaction for use in |snapshot|.
1107 // See SaveChanges() for more information.
1108 void TakeSnapshotForSaveChanges(SaveChangesSnapshot* snapshot);
1109
1110 // Purges from memory any unused, safe to remove entries that were
1111 // successfully deleted on disk as a result of the SaveChanges that processed
1112 // |snapshot|. See SaveChanges() for more information.
1113 void VacuumAfterSaveChanges(const SaveChangesSnapshot& snapshot);
1114
1115 // Rolls back dirty and IS_NEW bits in the event that the SaveChanges that
1116 // processed |snapshot| failed, for ex. due to no disk space.
1117 void HandleSaveChangesFailure(const SaveChangesSnapshot& snapshot);
1118
1119 void InsertEntry(EntryKernel* entry, ScopedKernelLock* lock);
1120 void InsertEntry(EntryKernel* entry);
1121
1122 // Used by CheckTreeInvariants
1123 void GetAllMetaHandles(BaseTransaction* trans, MetahandleSet* result);
1124
1125 static bool SafeToPurgeFromMemory(const EntryKernel* const entry);
1126
1127 // Helper method used to implement GetFirstChildId/GetLastChildId.
1128 Id GetChildWithNullIdField(IdField field,
1129 BaseTransaction* trans,
1130 const Id& parent_id);
1131
1132 Directory& operator = (const Directory&);
1133
1134 // TODO(sync): If lookups and inserts in these sets become
1135 // the bottle-neck, then we can use hash-sets instead. But
1136 // that will require using #ifdefs and compiler-specific code,
1137 // so use standard sets for now.
1138 public:
1139 typedef std::set<EntryKernel*, LessField<MetahandleField, META_HANDLE> >
1140 MetahandlesIndex;
1141 typedef std::set<EntryKernel*, LessField<IdField, ID> > IdsIndex;
1142 // All entries in memory must be in both the MetahandlesIndex and
1143 // the IdsIndex, but only non-deleted entries will be the
1144 // ParentIdAndNamesIndex, because there can be multiple deleted
1145 // entries with the same parent id and name.
1146 typedef std::set<EntryKernel*, LessParentIdAndNames> ParentIdAndNamesIndex;
1147 typedef std::vector<int64> MetahandlesToPurge;
1148
1149 private:
1150
1151 struct Kernel {
1152 Kernel(const PathString& db_path, const PathString& name,
1153 const KernelLoadInfo& info);
1154
1155 ~Kernel();
1156
1157 PathString const db_path;
1158 // TODO(timsteele): audit use of the member and remove if possible
1159 volatile base::subtle::AtomicWord refcount;
1160 void AddRef(); // For convenience.
1161 void Release();
1162
1163 // Next 3 members implement the reader/writer lock.
1164 PThreadMutex transaction_mutex; // Protects next member.
1165 ThreadCounts thread_counts;
1166 pthread_key_t thread_node_key;
1167
1168 // The name of this directory, used as a key into open_files_;
1169 PathString const name_;
1170
1171 // Protects all members below.
1172 // The mutex effectively protects all the indices, but not the
1173 // entries themselves. So once a pointer to an entry is pulled
1174 // from the index, the mutex can be unlocked and entry read or written.
1175 //
1176 // Never hold the mutex and do anything with the database or any
1177 // other buffered IO. Violating this rule will result in deadlock.
1178 pthread_mutex_t mutex;
1179 MetahandlesIndex* metahandles_index; // Entries indexed by metahandle
1180 IdsIndex* ids_index; // Entries indexed by id
1181 ParentIdAndNamesIndex* parent_id_and_names_index;
1182 // So we don't have to create an EntryKernel every time we want to
1183 // look something up in an index. Needle in haystack metaphore.
1184 EntryKernel needle;
1185 ExtendedAttributes* const extended_attributes;
1186
1187 // 2 in-memory indices on bits used extremely frequently by the syncer.
1188 MetahandleSet* const unapplied_update_metahandles;
1189 MetahandleSet* const unsynced_metahandles;
1190 // TODO(timsteele): Add a dirty_metahandles index as we now may want to
1191 // optimize the SaveChanges work of scanning all entries to find dirty ones
1192 // due to the entire entry domain now being in-memory.
1193
1194 // TODO(ncarter): Figure out what the hell this is, and comment it.
1195 Channel* const channel;
1196
1197 // The changes channel mutex is explicit because it must be locked
1198 // while holding the transaction mutex and released after
1199 // releasing the transaction mutex.
1200 ChangesChannel* const changes_channel;
1201 PThreadMutex changes_channel_mutex;
1202 KernelShareInfoStatus info_status_;
1203 // These 5 members are backed in the share_info table, and
1204 // their state is marked by the flag above.
1205 // Last sync timestamp fetched from the server.
1206 int64 last_sync_timestamp_;
1207 // true iff we ever reached the end of the changelog.
1208 bool initial_sync_ended_;
1209 // The store birthday we were given by the server. Contents are opaque to
1210 // the client.
1211 std::string store_birthday_;
1212 // A unique identifier for this account's cache db, used to generate
1213 // unique server IDs. No need to lock, only written at init time.
1214 std::string cache_guid_;
1215
1216 // It doesn't make sense for two threads to run SaveChanges at the same
1217 // time; this mutex protects that activity.
1218 PThreadMutex save_changes_mutex;
1219
1220 // The next metahandle and id are protected by kernel mutex.
1221 int64 next_metahandle;
1222 int64 next_id;
1223
1224 // Keep a history of recently flushed metahandles for debugging
1225 // purposes. Protected by the save_changes_mutex.
1226 DebugQueue<int64, 1000> flushed_metahandles_;
1227 };
1228
1229 Kernel* kernel_;
1230
1231 DirectoryBackingStore* store_;
1232 };
1233
1234 class ScopedKernelLock {
1235 public:
1236 explicit ScopedKernelLock(const Directory*);
1237 ~ScopedKernelLock();
1238
1239 Directory* const dir_;
1240 DISALLOW_COPY_AND_ASSIGN(ScopedKernelLock);
1241 };
1242
1243 class ScopedKernelUnlock {
1244 public:
1245 explicit ScopedKernelUnlock(ScopedKernelLock* lock);
1246 ~ScopedKernelUnlock();
1247 ScopedKernelLock* const lock_;
1248 DISALLOW_COPY_AND_ASSIGN(ScopedKernelUnlock);
1249 };
1250
1251 // Transactions are now processed FIFO (+overlapping reads).
1252 class BaseTransaction {
1253 friend class Entry;
1254 public:
1255 enum TransactionClass { READ, WRITE };
1256
1257 protected:
1258 explicit BaseTransaction(Directory* directory, const char* name,
1259 const char* source_file, int line);
1260
1261 // The members below are optionally called by descendants.
1262 void Lock(ThreadCounts* const thread_counts, ThreadNode* thread_node,
1263 TransactionClass tclass);
1264 void AfterLock(ThreadNode* thread_node);
1265 void UnlockAndLog(ThreadCounts* const thread_counts, OriginalEntries*);
1266 void Init(ThreadCounts* const thread_counts, TransactionClass tclass);
1267 ThreadNode* MakeThreadNode();
1268 public:
1269
1270 inline Directory* directory() const { return directory_; }
1271
1272 inline Id root_id() const { return Id(); }
1273
1274 protected:
1275 Directory* const directory_;
1276 Directory::Kernel* const dirkernel_; // for brevity
1277 const char* const name_;
1278 base::TimeTicks time_acquired_;
1279 const char* const source_file_;
1280 const int line_;
1281 WriterTag writer_;
1282
1283 DISALLOW_COPY_AND_ASSIGN(BaseTransaction);
1284 };
1285
1286 // Locks db in constructor, unlocks in destructor.
1287 class ReadTransaction : public BaseTransaction {
1288 public:
1289 ReadTransaction(Directory* directory, const char* source_file,
1290 int line);
1291 ReadTransaction(const ScopedDirLookup& scoped_dir,
1292 const char* source_file, int line);
1293
1294 ~ReadTransaction();
1295
1296 protected: // Don't allow creation on heap, except by sync API wrapper.
1297 friend class sync_api::ReadTransaction;
1298 void* operator new(size_t size) { return (::operator new)(size); }
1299
1300 DISALLOW_COPY_AND_ASSIGN(ReadTransaction);
1301 };
1302
1303 // Locks db in constructor, unlocks in destructor.
1304 class WriteTransaction : public BaseTransaction {
1305 friend class MutableEntry;
1306 public:
1307 explicit WriteTransaction(Directory* directory, WriterTag writer,
1308 const char* source_file, int line);
1309 explicit WriteTransaction(const ScopedDirLookup& directory,
1310 WriterTag writer, const char* source_file,
1311 int line);
1312 virtual ~WriteTransaction();
1313
1314 void SaveOriginal(EntryKernel* entry);
1315
1316 protected:
1317 // If I had had the foresight to create a BaseWriteTransactionClass,
1318 // I would not have needed this pass-through constructor and the
1319 // skip_destructor flag.
1320 explicit WriteTransaction(Directory* directory,
1321 const char* name, WriterTag writer,
1322 const char* source_file,
1323 int line, bool skip_destructor,
1324 OriginalEntries* originals);
1325
1326 const bool skip_destructor_;
1327
1328 // Before an entry gets modified, we copy the original into a list
1329 // so that we can issue change notifications when the transaction
1330 // is done.
1331 OriginalEntries* const originals_;
1332
1333 DISALLOW_COPY_AND_ASSIGN(WriteTransaction);
1334 };
1335
1336 bool IsLegalNewParent(BaseTransaction* trans, const Id& id, const Id& parentid);
1337 int ComparePathNames(const PathString& a, const PathString& b);
1338
1339 // Exposed in header as this is used as a sqlite3 callback.
1340 int ComparePathNames16(void*, int a_bytes, const void* a, int b_bytes,
1341 const void* b);
1342
1343 int64 Now();
1344
1345 // Does wildcard processing.
1346 BOOL PathNameMatch(const PathString& pathname, const PathString& pathspec);
1347
1348 PathString GetFullPath(BaseTransaction* trans, const Entry& e);
1349
1350 inline void ReverseAppend(const PathString& s, PathString* target) {
1351 target->append(s.rbegin(), s.rend());
1352 }
1353
1354 class ExtendedAttribute {
1355 public:
1356 ExtendedAttribute(BaseTransaction* trans, GetByHandle,
1357 const ExtendedAttributeKey& key);
1358 int64 metahandle() const { return i_->first.metahandle; }
1359 const PathString& key() const { return i_->first.key; }
1360 const Blob& value() const { return i_->second.value; }
1361 bool is_deleted() const { return i_->second.is_deleted; }
1362 bool good() const { return good_; }
1363 bool operator < (const ExtendedAttribute& x) const {
1364 return i_->first < x.i_->first;
1365 }
1366 protected:
1367 bool Init(BaseTransaction* trans,
1368 Directory::Kernel* const kernel,
1369 ScopedKernelLock* lock,
1370 const ExtendedAttributeKey& key);
1371 ExtendedAttribute() { }
1372 ExtendedAttributes::iterator i_;
1373 bool good_;
1374 };
1375
1376 class MutableExtendedAttribute : public ExtendedAttribute {
1377 public:
1378 MutableExtendedAttribute(WriteTransaction* trans, GetByHandle,
1379 const ExtendedAttributeKey& key);
1380 MutableExtendedAttribute(WriteTransaction* trans, Create,
1381 const ExtendedAttributeKey& key);
1382
1383 Blob* mutable_value() {
1384 i_->second.dirty = true;
1385 i_->second.is_deleted = false;
1386 return &(i_->second.value);
1387 }
1388
1389 void delete_attribute() {
1390 i_->second.dirty = true;
1391 i_->second.is_deleted = true;
1392 }
1393 };
1394
1395 // Get an extended attribute from an Entry by name. Returns a pointer
1396 // to a const Blob containing the attribute data, or NULL if there is
1397 // no attribute with the given name. The pointer is valid for the
1398 // duration of the Entry's transaction.
1399 const Blob* GetExtendedAttributeValue(const Entry& e,
1400 const PathString& attribute_name);
1401
1402 // This function sets only the flags needed to get this entry to sync.
1403 void MarkForSyncing(syncable::MutableEntry* e);
1404
1405 // This is not a reset. It just sets the numeric fields which are not
1406 // initialized by the constructor to zero.
1407 void ZeroFields(EntryKernel* entry, int first_field);
1408
1409 } // namespace syncable
1410
1411 std::ostream& operator <<(std::ostream&, const syncable::Blob&);
1412
1413 browser_sync::FastDump& operator <<
1414 (browser_sync::FastDump&, const syncable::Blob&);
1415
1416
1417 std::ostream& operator <<(std::ostream&, const syncable::ThreadNode&);
1418
1419 #endif // CHROME_BROWSER_SYNC_SYNCABLE_SYNCABLE_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698