OLD | NEW |
(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_ |
OLD | NEW |