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