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

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

Issue 7977034: Revert 102184 - [Sync] use base::Time in sync (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/directory_backing_store.h" 5 #include "chrome/browser/sync/syncable/directory_backing_store.h"
6 6
7 #include "build/build_config.h" 7 #include "build/build_config.h"
8 8
9 #if defined(OS_MACOSX)
10 #include <CoreFoundation/CoreFoundation.h>
11 #endif
12
9 #include <limits> 13 #include <limits>
10 14
11 #include "base/file_util.h" 15 #include "base/file_util.h"
12 #include "base/hash_tables.h" 16 #include "base/hash_tables.h"
13 #include "base/logging.h" 17 #include "base/logging.h"
14 #include "base/metrics/histogram.h" 18 #include "base/metrics/histogram.h"
15 #include "base/stl_util.h" 19 #include "base/stl_util.h"
16 #include "base/string_number_conversions.h" 20 #include "base/string_number_conversions.h"
17 #include "base/stringprintf.h" 21 #include "base/stringprintf.h"
18 #include "base/time.h"
19 #include "chrome/browser/sync/protocol/bookmark_specifics.pb.h" 22 #include "chrome/browser/sync/protocol/bookmark_specifics.pb.h"
20 #include "chrome/browser/sync/protocol/service_constants.h" 23 #include "chrome/browser/sync/protocol/service_constants.h"
21 #include "chrome/browser/sync/protocol/sync.pb.h" 24 #include "chrome/browser/sync/protocol/sync.pb.h"
22 #include "chrome/browser/sync/syncable/syncable-inl.h" 25 #include "chrome/browser/sync/syncable/syncable-inl.h"
23 #include "chrome/browser/sync/syncable/syncable_columns.h" 26 #include "chrome/browser/sync/syncable/syncable_columns.h"
24 #include "chrome/browser/sync/util/sqlite_utils.h" 27 #include "chrome/browser/sync/util/sqlite_utils.h"
25 #include "chrome/browser/sync/util/time.h"
26 #include "chrome/common/random.h" 28 #include "chrome/common/random.h"
27 #include "third_party/sqlite/sqlite3.h" 29 #include "third_party/sqlite/sqlite3.h"
28 30
29 // Sometimes threads contend on the DB lock itself, especially when one thread 31 // Sometimes threads contend on the DB lock itself, especially when one thread
30 // is calling SaveChanges. In the worst case scenario, the user can put his 32 // is calling SaveChanges. In the worst case scenario, the user can put his
31 // laptop to sleep during db contention, and wake up the laptop days later, so 33 // laptop to sleep during db contention, and wake up the laptop days later, so
32 // infinity seems like the best choice here. 34 // infinity seems like the best choice here.
33 const int kDirectoryBackingStoreBusyTimeoutMs = std::numeric_limits<int>::max(); 35 const int kDirectoryBackingStoreBusyTimeoutMs = std::numeric_limits<int>::max();
34 36
35 using std::string; 37 using std::string;
36 38
37 namespace syncable { 39 namespace syncable {
38 40
39 // This just has to be big enough to hold an UPDATE or INSERT statement that 41 // This just has to be big enough to hold an UPDATE or INSERT statement that
40 // modifies all the columns in the entry table. 42 // modifies all the columns in the entry table.
41 static const string::size_type kUpdateStatementBufferSize = 2048; 43 static const string::size_type kUpdateStatementBufferSize = 2048;
42 44
43 // Increment this version whenever updating DB tables. 45 // Increment this version whenever updating DB tables.
44 extern const int32 kCurrentDBVersion; // Global visibility for our unittest. 46 extern const int32 kCurrentDBVersion; // Global visibility for our unittest.
45 const int32 kCurrentDBVersion = 77; 47 const int32 kCurrentDBVersion = 76;
46 48
47 namespace { 49 namespace {
48 50
49 int ExecQuery(sqlite3* dbhandle, const char* query) { 51 int ExecQuery(sqlite3* dbhandle, const char* query) {
50 sqlite_utils::SQLStatement statement; 52 sqlite_utils::SQLStatement statement;
51 int result = statement.prepare(dbhandle, query); 53 int result = statement.prepare(dbhandle, query);
52 if (SQLITE_OK != result) 54 if (SQLITE_OK != result)
53 return result; 55 return result;
54 do { 56 do {
55 result = statement.step(); 57 result = statement.step();
(...skipping 11 matching lines...) Expand all
67 69
68 // Iterate over the fields of |entry| and bind each to |statement| for 70 // Iterate over the fields of |entry| and bind each to |statement| for
69 // updating. Returns the number of args bound. 71 // updating. Returns the number of args bound.
70 int BindFields(const EntryKernel& entry, 72 int BindFields(const EntryKernel& entry,
71 sqlite_utils::SQLStatement* statement) { 73 sqlite_utils::SQLStatement* statement) {
72 int index = 0; 74 int index = 0;
73 int i = 0; 75 int i = 0;
74 for (i = BEGIN_FIELDS; i < INT64_FIELDS_END; ++i) { 76 for (i = BEGIN_FIELDS; i < INT64_FIELDS_END; ++i) {
75 statement->bind_int64(index++, entry.ref(static_cast<Int64Field>(i))); 77 statement->bind_int64(index++, entry.ref(static_cast<Int64Field>(i)));
76 } 78 }
77 for ( ; i < TIME_FIELDS_END; ++i) {
78 statement->bind_int64(index++,
79 browser_sync::TimeToProtoTime(
80 entry.ref(static_cast<TimeField>(i))));
81 }
82 for ( ; i < ID_FIELDS_END; ++i) { 79 for ( ; i < ID_FIELDS_END; ++i) {
83 statement->bind_string(index++, entry.ref(static_cast<IdField>(i)).s_); 80 statement->bind_string(index++, entry.ref(static_cast<IdField>(i)).s_);
84 } 81 }
85 for ( ; i < BIT_FIELDS_END; ++i) { 82 for ( ; i < BIT_FIELDS_END; ++i) {
86 statement->bind_int(index++, entry.ref(static_cast<BitField>(i))); 83 statement->bind_int(index++, entry.ref(static_cast<BitField>(i)));
87 } 84 }
88 for ( ; i < STRING_FIELDS_END; ++i) { 85 for ( ; i < STRING_FIELDS_END; ++i) {
89 statement->bind_string(index++, entry.ref(static_cast<StringField>(i))); 86 statement->bind_string(index++, entry.ref(static_cast<StringField>(i)));
90 } 87 }
91 std::string temp; 88 std::string temp;
92 for ( ; i < PROTO_FIELDS_END; ++i) { 89 for ( ; i < PROTO_FIELDS_END; ++i) {
93 entry.ref(static_cast<ProtoField>(i)).SerializeToString(&temp); 90 entry.ref(static_cast<ProtoField>(i)).SerializeToString(&temp);
94 statement->bind_blob(index++, temp.data(), temp.length()); 91 statement->bind_blob(index++, temp.data(), temp.length());
95 } 92 }
96 return index; 93 return index;
97 } 94 }
98 95
99 // The caller owns the returned EntryKernel*. 96 // The caller owns the returned EntryKernel*.
100 int UnpackEntry(sqlite_utils::SQLStatement* statement, EntryKernel** kernel) { 97 int UnpackEntry(sqlite_utils::SQLStatement* statement, EntryKernel** kernel) {
101 *kernel = NULL; 98 *kernel = NULL;
102 int query_result = statement->step(); 99 int query_result = statement->step();
103 if (query_result == SQLITE_ROW) { 100 if (SQLITE_ROW == query_result) {
104 *kernel = new EntryKernel(); 101 *kernel = new EntryKernel;
105 DCHECK_EQ(statement->column_count(), static_cast<int>(FIELD_COUNT)); 102 (*kernel)->clear_dirty(NULL);
103 DCHECK(statement->column_count() == static_cast<int>(FIELD_COUNT));
106 int i = 0; 104 int i = 0;
107 for (i = BEGIN_FIELDS; i < INT64_FIELDS_END; ++i) { 105 for (i = BEGIN_FIELDS; i < INT64_FIELDS_END; ++i) {
108 (*kernel)->put(static_cast<Int64Field>(i), statement->column_int64(i)); 106 (*kernel)->put(static_cast<Int64Field>(i), statement->column_int64(i));
109 } 107 }
110 for ( ; i < TIME_FIELDS_END; ++i) {
111 (*kernel)->put(static_cast<TimeField>(i),
112 browser_sync::ProtoTimeToTime(
113 statement->column_int64(i)));
114 }
115 for ( ; i < ID_FIELDS_END; ++i) { 108 for ( ; i < ID_FIELDS_END; ++i) {
116 (*kernel)->mutable_ref(static_cast<IdField>(i)).s_ = 109 (*kernel)->mutable_ref(static_cast<IdField>(i)).s_ =
117 statement->column_string(i); 110 statement->column_string(i);
118 } 111 }
119 for ( ; i < BIT_FIELDS_END; ++i) { 112 for ( ; i < BIT_FIELDS_END; ++i) {
120 (*kernel)->put(static_cast<BitField>(i), (0 != statement->column_int(i))); 113 (*kernel)->put(static_cast<BitField>(i), (0 != statement->column_int(i)));
121 } 114 }
122 for ( ; i < STRING_FIELDS_END; ++i) { 115 for ( ; i < STRING_FIELDS_END; ++i) {
123 (*kernel)->put(static_cast<StringField>(i), 116 (*kernel)->put(static_cast<StringField>(i),
124 statement->column_string(i)); 117 statement->column_string(i));
125 } 118 }
126 for ( ; i < PROTO_FIELDS_END; ++i) { 119 for ( ; i < PROTO_FIELDS_END; ++i) {
127 (*kernel)->mutable_ref(static_cast<ProtoField>(i)).ParseFromArray( 120 (*kernel)->mutable_ref(static_cast<ProtoField>(i)).ParseFromArray(
128 statement->column_blob(i), statement->column_bytes(i)); 121 statement->column_blob(i), statement->column_bytes(i));
129 } 122 }
123 ZeroFields((*kernel), i);
130 } else { 124 } else {
131 DCHECK_EQ(query_result, SQLITE_DONE); 125 DCHECK(SQLITE_DONE == query_result);
132 (*kernel) = NULL; 126 (*kernel) = NULL;
133 } 127 }
134 return query_result; 128 return query_result;
135 } 129 }
136 130
137 namespace { 131 namespace {
138 132
139 string ComposeCreateTableColumnSpecs() { 133 string ComposeCreateTableColumnSpecs() {
140 const ColumnSpec* begin = g_metas_columns; 134 const ColumnSpec* begin = g_metas_columns;
141 const ColumnSpec* end = g_metas_columns + arraysize(g_metas_columns); 135 const ColumnSpec* end = g_metas_columns + arraysize(g_metas_columns);
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
477 if (MigrateVersion74To75()) 471 if (MigrateVersion74To75())
478 version_on_disk = 75; 472 version_on_disk = 75;
479 } 473 }
480 474
481 // Version 76 removed all (5) autofill migration related columns. 475 // Version 76 removed all (5) autofill migration related columns.
482 if (version_on_disk == 75) { 476 if (version_on_disk == 75) {
483 if (MigrateVersion75To76()) 477 if (MigrateVersion75To76())
484 version_on_disk = 76; 478 version_on_disk = 76;
485 } 479 }
486 480
487 // Version 77 standardized all time fields to ms since the Unix
488 // epoch.
489 if (version_on_disk == 76) {
490 if (MigrateVersion76To77())
491 version_on_disk = 77;
492 }
493
494 // If one of the migrations requested it, drop columns that aren't current. 481 // If one of the migrations requested it, drop columns that aren't current.
495 // It's only safe to do this after migrating all the way to the current 482 // It's only safe to do this after migrating all the way to the current
496 // version. 483 // version.
497 if (version_on_disk == kCurrentDBVersion && needs_column_refresh_) { 484 if (version_on_disk == kCurrentDBVersion && needs_column_refresh_) {
498 if (!RefreshColumns()) 485 if (!RefreshColumns())
499 version_on_disk = 0; 486 version_on_disk = 0;
500 } 487 }
501 488
502 // A final, alternative catch-all migration to simply re-sync everything. 489 // A final, alternative catch-all migration to simply re-sync everything.
503 if (version_on_disk != kCurrentDBVersion) { 490 if (version_on_disk != kCurrentDBVersion) {
(...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after
1095 // bookmarks_added_during_autofill_migration 1082 // bookmarks_added_during_autofill_migration
1096 // autofill_migration_time 1083 // autofill_migration_time
1097 // autofill_entries_added_during_migration 1084 // autofill_entries_added_during_migration
1098 // autofill_profiles_added_during_migration 1085 // autofill_profiles_added_during_migration
1099 // No data migration is necessary, but we should do a column refresh. 1086 // No data migration is necessary, but we should do a column refresh.
1100 SetVersion(76); 1087 SetVersion(76);
1101 needs_column_refresh_ = true; 1088 needs_column_refresh_ = true;
1102 return true; 1089 return true;
1103 } 1090 }
1104 1091
1105 bool DirectoryBackingStore::MigrateVersion76To77() {
1106 sqlite_utils::SQLStatement update_timestamps;
1107 // This change changes the format of stored timestamps to ms since
1108 // the Unix epoch.
1109 #if defined(OS_WIN)
1110 // On Windows, we used to store timestamps in FILETIME format (100s of
1111 // ns since Jan 1, 1601). Magic numbers taken from
1112 // http://stackoverflow.com/questions/5398557/java-library-for-dealing-with-win3 2-filetime
1113 // .
1114 #define TO_UNIX_TIME_MS(x) #x " = " #x " / 10000 - 11644473600000"
1115 #else
1116 // On other platforms, we used to store timestamps in time_t format (s
1117 // since the Unix epoch).
1118 #define TO_UNIX_TIME_MS(x) #x " = " #x " * 1000"
1119 #endif
1120 update_timestamps.prepare(
1121 load_dbhandle_,
1122 "UPDATE metas SET "
1123 TO_UNIX_TIME_MS(mtime) ", "
1124 TO_UNIX_TIME_MS(server_mtime) ", "
1125 TO_UNIX_TIME_MS(ctime) ", "
1126 TO_UNIX_TIME_MS(server_ctime));
1127 #undef TO_UNIX_TIME_MS
1128 if (update_timestamps.step() != SQLITE_DONE)
1129 return false;
1130 SetVersion(77);
1131 return true;
1132 }
1133
1134 int DirectoryBackingStore::CreateTables() { 1092 int DirectoryBackingStore::CreateTables() {
1135 VLOG(1) << "First run, creating tables"; 1093 VLOG(1) << "First run, creating tables";
1136 // Create two little tables share_version and share_info 1094 // Create two little tables share_version and share_info
1137 int result = ExecQuery(load_dbhandle_, 1095 int result = ExecQuery(load_dbhandle_,
1138 "CREATE TABLE share_version (" 1096 "CREATE TABLE share_version ("
1139 "id VARCHAR(128) primary key, data INT)"); 1097 "id VARCHAR(128) primary key, data INT)");
1140 if (result != SQLITE_DONE) 1098 if (result != SQLITE_DONE)
1141 return result; 1099 return result;
1142 { 1100 {
1143 sqlite_utils::SQLStatement statement; 1101 sqlite_utils::SQLStatement statement;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1178 1136
1179 result = CreateModelsTable(); 1137 result = CreateModelsTable();
1180 if (result != SQLITE_DONE) 1138 if (result != SQLITE_DONE)
1181 return result; 1139 return result;
1182 // Create the big metas table. 1140 // Create the big metas table.
1183 result = CreateMetasTable(false); 1141 result = CreateMetasTable(false);
1184 if (result != SQLITE_DONE) 1142 if (result != SQLITE_DONE)
1185 return result; 1143 return result;
1186 { 1144 {
1187 // Insert the entry for the root into the metas table. 1145 // Insert the entry for the root into the metas table.
1188 const int64 now = browser_sync::TimeToProtoTime(base::Time::Now()); 1146 const int64 now = Now();
1189 sqlite_utils::SQLStatement statement; 1147 sqlite_utils::SQLStatement statement;
1190 statement.prepare(load_dbhandle_, 1148 statement.prepare(load_dbhandle_,
1191 "INSERT INTO metas " 1149 "INSERT INTO metas "
1192 "( id, metahandle, is_dir, ctime, mtime) " 1150 "( id, metahandle, is_dir, ctime, mtime) "
1193 "VALUES ( \"r\", 1, 1, ?, ?)"); 1151 "VALUES ( \"r\", 1, 1, ?, ?)");
1194 statement.bind_int64(0, now); 1152 statement.bind_int64(0, now);
1195 statement.bind_int64(1, now); 1153 statement.bind_int64(1, now);
1196 result = statement.step(); 1154 result = statement.step();
1197 } 1155 }
1198 return result; 1156 return result;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1270 "id TEXT primary key, " 1228 "id TEXT primary key, "
1271 "name TEXT, " 1229 "name TEXT, "
1272 "store_birthday TEXT, " 1230 "store_birthday TEXT, "
1273 "db_create_version TEXT, " 1231 "db_create_version TEXT, "
1274 "db_create_time INT, " 1232 "db_create_time INT, "
1275 "next_id INT default -2, " 1233 "next_id INT default -2, "
1276 "cache_guid TEXT )"); 1234 "cache_guid TEXT )");
1277 return ExecQuery(load_dbhandle_, query.c_str()); 1235 return ExecQuery(load_dbhandle_, query.c_str());
1278 } 1236 }
1279 } // namespace syncable 1237 } // namespace syncable
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698