OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/sync/syncable/syncable.h" | 5 #include "chrome/browser/sync/syncable/syncable.h" |
6 | 6 |
| 7 #include "build/build_config.h" |
| 8 |
| 9 #include <sys/stat.h> |
| 10 #if defined(OS_POSIX) |
| 11 #include <sys/time.h> |
| 12 #endif |
| 13 #include <sys/types.h> |
| 14 #include <time.h> |
| 15 #if defined(OS_MACOSX) |
| 16 #include <CoreFoundation/CoreFoundation.h> |
| 17 #elif defined(OS_WIN) |
| 18 #include <shlwapi.h> // for PathMatchSpec |
| 19 #endif |
| 20 |
7 #include <algorithm> | 21 #include <algorithm> |
8 #include <cstring> | 22 #include <cstring> |
9 #include <functional> | 23 #include <functional> |
10 #include <iomanip> | 24 #include <iomanip> |
11 #include <iterator> | 25 #include <iterator> |
12 #include <limits> | 26 #include <limits> |
13 #include <set> | 27 #include <set> |
14 #include <string> | 28 #include <string> |
15 | 29 |
16 #include "base/compiler_specific.h" | 30 #include "base/compiler_specific.h" |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 ListValue* EntryKernelMutationMapToValue( | 135 ListValue* EntryKernelMutationMapToValue( |
122 const EntryKernelMutationMap& mutations) { | 136 const EntryKernelMutationMap& mutations) { |
123 ListValue* list = new ListValue(); | 137 ListValue* list = new ListValue(); |
124 for (EntryKernelMutationMap::const_iterator it = mutations.begin(); | 138 for (EntryKernelMutationMap::const_iterator it = mutations.begin(); |
125 it != mutations.end(); ++it) { | 139 it != mutations.end(); ++it) { |
126 list->Append(EntryKernelMutationToValue(it->second)); | 140 list->Append(EntryKernelMutationToValue(it->second)); |
127 } | 141 } |
128 return list; | 142 return list; |
129 } | 143 } |
130 | 144 |
| 145 int64 Now() { |
| 146 #if defined(OS_WIN) |
| 147 FILETIME filetime; |
| 148 SYSTEMTIME systime; |
| 149 GetSystemTime(&systime); |
| 150 SystemTimeToFileTime(&systime, &filetime); |
| 151 // MSDN recommends converting via memcpy like this. |
| 152 LARGE_INTEGER n; |
| 153 memcpy(&n, &filetime, sizeof(filetime)); |
| 154 return n.QuadPart; |
| 155 #elif defined(OS_POSIX) |
| 156 struct timeval tv; |
| 157 gettimeofday(&tv, NULL); |
| 158 return static_cast<int64>(tv.tv_sec); |
| 159 #else |
| 160 #error NEED OS SPECIFIC Now() implementation |
| 161 #endif |
| 162 } |
| 163 |
131 namespace { | 164 namespace { |
132 | 165 |
133 // A ScopedIndexUpdater temporarily removes an entry from an index, | 166 // A ScopedIndexUpdater temporarily removes an entry from an index, |
134 // and restores it to the index when the scope exits. This simplifies | 167 // and restores it to the index when the scope exits. This simplifies |
135 // the common pattern where items need to be removed from an index | 168 // the common pattern where items need to be removed from an index |
136 // before updating the field. | 169 // before updating the field. |
137 // | 170 // |
138 // This class is parameterized on the Indexer traits type, which | 171 // This class is parameterized on the Indexer traits type, which |
139 // must define a Comparator and a static bool ShouldInclude | 172 // must define a Comparator and a static bool ShouldInclude |
140 // function for testing whether the item ought to be included | 173 // function for testing whether the item ought to be included |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 bool ParentIdAndHandleIndexer::ShouldInclude(const EntryKernel* a) { | 238 bool ParentIdAndHandleIndexer::ShouldInclude(const EntryKernel* a) { |
206 // This index excludes deleted items and the root item. The root | 239 // This index excludes deleted items and the root item. The root |
207 // item is excluded so that it doesn't show up as a child of itself. | 240 // item is excluded so that it doesn't show up as a child of itself. |
208 return !a->ref(IS_DEL) && !a->ref(ID).IsRoot(); | 241 return !a->ref(IS_DEL) && !a->ref(ID).IsRoot(); |
209 } | 242 } |
210 | 243 |
211 /////////////////////////////////////////////////////////////////////////// | 244 /////////////////////////////////////////////////////////////////////////// |
212 // EntryKernel | 245 // EntryKernel |
213 | 246 |
214 EntryKernel::EntryKernel() : dirty_(false) { | 247 EntryKernel::EntryKernel() : dirty_(false) { |
215 // Everything else should already be default-initialized. | 248 memset(int64_fields, 0, sizeof(int64_fields)); |
216 for (int i = INT64_FIELDS_BEGIN; i < INT64_FIELDS_END; ++i) { | |
217 int64_fields[i] = 0; | |
218 } | |
219 } | 249 } |
220 | 250 |
221 EntryKernel::~EntryKernel() {} | 251 EntryKernel::~EntryKernel() {} |
222 | 252 |
223 bool EntryKernel::ContainsString(const std::string& lowercase_query) const { | 253 bool EntryKernel::ContainsString(const std::string& lowercase_query) const { |
224 // TODO(lipalani) - figure out what to do if the node is encrypted. | 254 // TODO(lipalani) - figure out what to do if the node is encrypted. |
225 const sync_pb::EntitySpecifics& specifics = ref(SPECIFICS); | 255 const sync_pb::EntitySpecifics& specifics = ref(SPECIFICS); |
226 std::string temp; | 256 std::string temp; |
227 // The protobuf serialized string contains the original strings. So | 257 // The protobuf serialized string contains the original strings. So |
228 // we will just serialize it and search it. | 258 // we will just serialize it and search it. |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 dictionary_value->Set(key, value); | 300 dictionary_value->Set(key, value); |
271 } | 301 } |
272 } | 302 } |
273 | 303 |
274 // Helper functions for SetFieldValues(). | 304 // Helper functions for SetFieldValues(). |
275 | 305 |
276 StringValue* Int64ToValue(int64 i) { | 306 StringValue* Int64ToValue(int64 i) { |
277 return Value::CreateStringValue(base::Int64ToString(i)); | 307 return Value::CreateStringValue(base::Int64ToString(i)); |
278 } | 308 } |
279 | 309 |
280 StringValue* TimeToValue(const base::Time& t) { | |
281 return Value::CreateStringValue(browser_sync::GetTimeDebugString(t)); | |
282 } | |
283 | |
284 StringValue* IdToValue(const Id& id) { | 310 StringValue* IdToValue(const Id& id) { |
285 return id.ToValue(); | 311 return id.ToValue(); |
286 } | 312 } |
287 | 313 |
288 } // namespace | 314 } // namespace |
289 | 315 |
290 DictionaryValue* EntryKernel::ToValue() const { | 316 DictionaryValue* EntryKernel::ToValue() const { |
291 DictionaryValue* kernel_info = new DictionaryValue(); | 317 DictionaryValue* kernel_info = new DictionaryValue(); |
292 kernel_info->SetBoolean("isDirty", is_dirty()); | 318 kernel_info->SetBoolean("isDirty", is_dirty()); |
293 | 319 |
294 // Int64 fields. | 320 // Int64 fields. |
295 SetFieldValues(*this, kernel_info, | 321 SetFieldValues(*this, kernel_info, |
296 &GetMetahandleFieldString, &Int64ToValue, | 322 &GetMetahandleFieldString, &Int64ToValue, |
297 INT64_FIELDS_BEGIN, META_HANDLE); | 323 INT64_FIELDS_BEGIN, META_HANDLE); |
298 SetFieldValues(*this, kernel_info, | 324 SetFieldValues(*this, kernel_info, |
299 &GetBaseVersionString, &Int64ToValue, | 325 &GetBaseVersionString, &Int64ToValue, |
300 META_HANDLE + 1, BASE_VERSION); | 326 META_HANDLE + 1, BASE_VERSION); |
301 SetFieldValues(*this, kernel_info, | 327 SetFieldValues(*this, kernel_info, |
302 &GetInt64FieldString, &Int64ToValue, | 328 &GetInt64FieldString, &Int64ToValue, |
303 BASE_VERSION + 1, INT64_FIELDS_END - 1); | 329 BASE_VERSION + 1, INT64_FIELDS_END - 1); |
304 | 330 |
305 // Time fields. | |
306 SetFieldValues(*this, kernel_info, | |
307 &GetTimeFieldString, &TimeToValue, | |
308 TIME_FIELDS_BEGIN, TIME_FIELDS_END - 1); | |
309 | |
310 // ID fields. | 331 // ID fields. |
311 SetFieldValues(*this, kernel_info, | 332 SetFieldValues(*this, kernel_info, |
312 &GetIdFieldString, &IdToValue, | 333 &GetIdFieldString, &IdToValue, |
313 ID_FIELDS_BEGIN, ID_FIELDS_END - 1); | 334 ID_FIELDS_BEGIN, ID_FIELDS_END - 1); |
314 | 335 |
315 // Bit fields. | 336 // Bit fields. |
316 SetFieldValues(*this, kernel_info, | 337 SetFieldValues(*this, kernel_info, |
317 &GetIndexedBitFieldString, &Value::CreateBooleanValue, | 338 &GetIndexedBitFieldString, &Value::CreateBooleanValue, |
318 BIT_FIELDS_BEGIN, INDEXED_BIT_FIELDS_END - 1); | 339 BIT_FIELDS_BEGIN, INDEXED_BIT_FIELDS_END - 1); |
319 SetFieldValues(*this, kernel_info, | 340 SetFieldValues(*this, kernel_info, |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
582 if (!kernel) | 603 if (!kernel) |
583 return; | 604 return; |
584 | 605 |
585 AppendChildHandles(lock, kernel->ref(ID), result); | 606 AppendChildHandles(lock, kernel->ref(ID), result); |
586 } | 607 } |
587 | 608 |
588 EntryKernel* Directory::GetRootEntry() { | 609 EntryKernel* Directory::GetRootEntry() { |
589 return GetEntryById(Id()); | 610 return GetEntryById(Id()); |
590 } | 611 } |
591 | 612 |
| 613 void ZeroFields(EntryKernel* entry, int first_field) { |
| 614 int i = first_field; |
| 615 // Note that bitset<> constructor sets all bits to zero, and strings |
| 616 // initialize to empty. |
| 617 for ( ; i < INT64_FIELDS_END; ++i) |
| 618 entry->put(static_cast<Int64Field>(i), 0); |
| 619 for ( ; i < ID_FIELDS_END; ++i) |
| 620 entry->mutable_ref(static_cast<IdField>(i)).Clear(); |
| 621 for ( ; i < BIT_FIELDS_END; ++i) |
| 622 entry->put(static_cast<BitField>(i), false); |
| 623 if (i < PROTO_FIELDS_END) |
| 624 i = PROTO_FIELDS_END; |
| 625 entry->clear_dirty(NULL); |
| 626 } |
| 627 |
592 void Directory::InsertEntry(EntryKernel* entry) { | 628 void Directory::InsertEntry(EntryKernel* entry) { |
593 ScopedKernelLock lock(this); | 629 ScopedKernelLock lock(this); |
594 InsertEntry(entry, &lock); | 630 InsertEntry(entry, &lock); |
595 } | 631 } |
596 | 632 |
597 void Directory::InsertEntry(EntryKernel* entry, ScopedKernelLock* lock) { | 633 void Directory::InsertEntry(EntryKernel* entry, ScopedKernelLock* lock) { |
598 DCHECK(NULL != lock); | 634 DCHECK(NULL != lock); |
599 CHECK(NULL != entry); | 635 CHECK(NULL != entry); |
600 static const char error[] = "Entry already in memory index."; | 636 static const char error[] = "Entry already in memory index."; |
601 CHECK(kernel_->metahandles_index->insert(entry).second) << error; | 637 CHECK(kernel_->metahandles_index->insert(entry).second) << error; |
(...skipping 794 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1396 MutableEntry::MutableEntry(WriteTransaction* trans, Create, | 1432 MutableEntry::MutableEntry(WriteTransaction* trans, Create, |
1397 const Id& parent_id, const string& name) | 1433 const Id& parent_id, const string& name) |
1398 : Entry(trans), | 1434 : Entry(trans), |
1399 write_transaction_(trans) { | 1435 write_transaction_(trans) { |
1400 Init(trans, parent_id, name); | 1436 Init(trans, parent_id, name); |
1401 } | 1437 } |
1402 | 1438 |
1403 | 1439 |
1404 void MutableEntry::Init(WriteTransaction* trans, const Id& parent_id, | 1440 void MutableEntry::Init(WriteTransaction* trans, const Id& parent_id, |
1405 const string& name) { | 1441 const string& name) { |
1406 kernel_ = new EntryKernel(); | 1442 kernel_ = new EntryKernel; |
| 1443 ZeroFields(kernel_, BEGIN_FIELDS); |
1407 kernel_->put(ID, trans->directory_->NextId()); | 1444 kernel_->put(ID, trans->directory_->NextId()); |
1408 kernel_->put(META_HANDLE, trans->directory_->NextMetahandle()); | 1445 kernel_->put(META_HANDLE, trans->directory_->NextMetahandle()); |
1409 kernel_->mark_dirty(trans->directory_->kernel_->dirty_metahandles); | 1446 kernel_->mark_dirty(trans->directory_->kernel_->dirty_metahandles); |
1410 kernel_->put(PARENT_ID, parent_id); | 1447 kernel_->put(PARENT_ID, parent_id); |
1411 kernel_->put(NON_UNIQUE_NAME, name); | 1448 kernel_->put(NON_UNIQUE_NAME, name); |
1412 const base::Time& now = base::Time::Now(); | 1449 const int64 now = Now(); |
1413 kernel_->put(CTIME, now); | 1450 kernel_->put(CTIME, now); |
1414 kernel_->put(MTIME, now); | 1451 kernel_->put(MTIME, now); |
1415 // We match the database defaults here | 1452 // We match the database defaults here |
1416 kernel_->put(BASE_VERSION, CHANGES_VERSION); | 1453 kernel_->put(BASE_VERSION, CHANGES_VERSION); |
1417 trans->directory()->InsertEntry(kernel_); | 1454 trans->directory()->InsertEntry(kernel_); |
1418 // Because this entry is new, it was originally deleted. | 1455 // Because this entry is new, it was originally deleted. |
1419 kernel_->put(IS_DEL, true); | 1456 kernel_->put(IS_DEL, true); |
1420 trans->SaveOriginal(kernel_); | 1457 trans->SaveOriginal(kernel_); |
1421 kernel_->put(IS_DEL, false); | 1458 kernel_->put(IS_DEL, false); |
1422 } | 1459 } |
1423 | 1460 |
1424 MutableEntry::MutableEntry(WriteTransaction* trans, CreateNewUpdateItem, | 1461 MutableEntry::MutableEntry(WriteTransaction* trans, CreateNewUpdateItem, |
1425 const Id& id) | 1462 const Id& id) |
1426 : Entry(trans), write_transaction_(trans) { | 1463 : Entry(trans), write_transaction_(trans) { |
1427 Entry same_id(trans, GET_BY_ID, id); | 1464 Entry same_id(trans, GET_BY_ID, id); |
1428 if (same_id.good()) { | 1465 if (same_id.good()) { |
1429 kernel_ = NULL; // already have an item with this ID. | 1466 kernel_ = NULL; // already have an item with this ID. |
1430 return; | 1467 return; |
1431 } | 1468 } |
1432 kernel_ = new EntryKernel(); | 1469 kernel_ = new EntryKernel; |
| 1470 ZeroFields(kernel_, BEGIN_FIELDS); |
1433 kernel_->put(ID, id); | 1471 kernel_->put(ID, id); |
1434 kernel_->put(META_HANDLE, trans->directory_->NextMetahandle()); | 1472 kernel_->put(META_HANDLE, trans->directory_->NextMetahandle()); |
1435 kernel_->mark_dirty(trans->directory_->kernel_->dirty_metahandles); | 1473 kernel_->mark_dirty(trans->directory_->kernel_->dirty_metahandles); |
1436 kernel_->put(IS_DEL, true); | 1474 kernel_->put(IS_DEL, true); |
1437 // We match the database defaults here | 1475 // We match the database defaults here |
1438 kernel_->put(BASE_VERSION, CHANGES_VERSION); | 1476 kernel_->put(BASE_VERSION, CHANGES_VERSION); |
1439 trans->directory()->InsertEntry(kernel_); | 1477 trans->directory()->InsertEntry(kernel_); |
1440 trans->SaveOriginal(kernel_); | 1478 trans->SaveOriginal(kernel_); |
1441 } | 1479 } |
1442 | 1480 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1497 dir()->kernel_->parent_id_child_index); | 1535 dir()->kernel_->parent_id_child_index); |
1498 kernel_->put(field, value); | 1536 kernel_->put(field, value); |
1499 } else { | 1537 } else { |
1500 kernel_->put(field, value); | 1538 kernel_->put(field, value); |
1501 } | 1539 } |
1502 kernel_->mark_dirty(dir()->kernel_->dirty_metahandles); | 1540 kernel_->mark_dirty(dir()->kernel_->dirty_metahandles); |
1503 } | 1541 } |
1504 return true; | 1542 return true; |
1505 } | 1543 } |
1506 | 1544 |
1507 bool MutableEntry::Put(TimeField field, const base::Time& value) { | |
1508 DCHECK(kernel_); | |
1509 if (kernel_->ref(field) != value) { | |
1510 kernel_->put(field, value); | |
1511 kernel_->mark_dirty(dir()->kernel_->dirty_metahandles); | |
1512 } | |
1513 return true; | |
1514 } | |
1515 | |
1516 bool MutableEntry::Put(IdField field, const Id& value) { | 1545 bool MutableEntry::Put(IdField field, const Id& value) { |
1517 DCHECK(kernel_); | 1546 DCHECK(kernel_); |
1518 if (kernel_->ref(field) != value) { | 1547 if (kernel_->ref(field) != value) { |
1519 if (ID == field) { | 1548 if (ID == field) { |
1520 if (!dir()->ReindexId(kernel_, value)) | 1549 if (!dir()->ReindexId(kernel_, value)) |
1521 return false; | 1550 return false; |
1522 } else if (PARENT_ID == field) { | 1551 } else if (PARENT_ID == field) { |
1523 PutParentIdPropertyOnly(value); // Makes sibling order inconsistent. | 1552 PutParentIdPropertyOnly(value); // Makes sibling order inconsistent. |
1524 PutPredecessor(Id()); // Fixes up the sibling order inconsistency. | 1553 PutPredecessor(Id()); // Fixes up the sibling order inconsistency. |
1525 } else { | 1554 } else { |
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1878 e->Put(SYNCING, false); | 1907 e->Put(SYNCING, false); |
1879 } | 1908 } |
1880 | 1909 |
1881 std::ostream& operator<<(std::ostream& os, const Entry& entry) { | 1910 std::ostream& operator<<(std::ostream& os, const Entry& entry) { |
1882 int i; | 1911 int i; |
1883 EntryKernel* const kernel = entry.kernel_; | 1912 EntryKernel* const kernel = entry.kernel_; |
1884 for (i = BEGIN_FIELDS; i < INT64_FIELDS_END; ++i) { | 1913 for (i = BEGIN_FIELDS; i < INT64_FIELDS_END; ++i) { |
1885 os << g_metas_columns[i].name << ": " | 1914 os << g_metas_columns[i].name << ": " |
1886 << kernel->ref(static_cast<Int64Field>(i)) << ", "; | 1915 << kernel->ref(static_cast<Int64Field>(i)) << ", "; |
1887 } | 1916 } |
1888 for ( ; i < TIME_FIELDS_END; ++i) { | |
1889 os << g_metas_columns[i].name << ": " | |
1890 << browser_sync::GetTimeDebugString( | |
1891 kernel->ref(static_cast<TimeField>(i))) << ", "; | |
1892 } | |
1893 for ( ; i < ID_FIELDS_END; ++i) { | 1917 for ( ; i < ID_FIELDS_END; ++i) { |
1894 os << g_metas_columns[i].name << ": " | 1918 os << g_metas_columns[i].name << ": " |
1895 << kernel->ref(static_cast<IdField>(i)) << ", "; | 1919 << kernel->ref(static_cast<IdField>(i)) << ", "; |
1896 } | 1920 } |
1897 os << "Flags: "; | 1921 os << "Flags: "; |
1898 for ( ; i < BIT_FIELDS_END; ++i) { | 1922 for ( ; i < BIT_FIELDS_END; ++i) { |
1899 if (kernel->ref(static_cast<BitField>(i))) | 1923 if (kernel->ref(static_cast<BitField>(i))) |
1900 os << g_metas_columns[i].name << ", "; | 1924 os << g_metas_columns[i].name << ", "; |
1901 } | 1925 } |
1902 for ( ; i < STRING_FIELDS_END; ++i) { | 1926 for ( ; i < STRING_FIELDS_END; ++i) { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1962 CHECK(result); | 1986 CHECK(result); |
1963 for (iterator i = GetParentChildIndexLowerBound(lock, parent_id), | 1987 for (iterator i = GetParentChildIndexLowerBound(lock, parent_id), |
1964 end = GetParentChildIndexUpperBound(lock, parent_id); | 1988 end = GetParentChildIndexUpperBound(lock, parent_id); |
1965 i != end; ++i) { | 1989 i != end; ++i) { |
1966 DCHECK_EQ(parent_id, (*i)->ref(PARENT_ID)); | 1990 DCHECK_EQ(parent_id, (*i)->ref(PARENT_ID)); |
1967 result->push_back((*i)->ref(META_HANDLE)); | 1991 result->push_back((*i)->ref(META_HANDLE)); |
1968 } | 1992 } |
1969 } | 1993 } |
1970 | 1994 |
1971 } // namespace syncable | 1995 } // namespace syncable |
OLD | NEW |