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

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

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

Powered by Google App Engine
This is Rietveld 408576698