OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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 "sync/syncable/directory_backing_store.h" | 5 #include "sync/syncable/directory_backing_store.h" |
6 | 6 |
7 #include "build/build_config.h" | 7 #include "build/build_config.h" |
8 | 8 |
9 #include <limits> | 9 #include <limits> |
10 | 10 |
(...skipping 17 matching lines...) Expand all Loading... |
28 using std::string; | 28 using std::string; |
29 | 29 |
30 namespace syncer { | 30 namespace syncer { |
31 namespace syncable { | 31 namespace syncable { |
32 | 32 |
33 // This just has to be big enough to hold an UPDATE or INSERT statement that | 33 // This just has to be big enough to hold an UPDATE or INSERT statement that |
34 // modifies all the columns in the entry table. | 34 // modifies all the columns in the entry table. |
35 static const string::size_type kUpdateStatementBufferSize = 2048; | 35 static const string::size_type kUpdateStatementBufferSize = 2048; |
36 | 36 |
37 // Increment this version whenever updating DB tables. | 37 // Increment this version whenever updating DB tables. |
38 const int32 kCurrentDBVersion = 87; | 38 const int32 kCurrentDBVersion = 88; |
39 | 39 |
40 // Iterate over the fields of |entry| and bind each to |statement| for | 40 // Iterate over the fields of |entry| and bind each to |statement| for |
41 // updating. Returns the number of args bound. | 41 // updating. Returns the number of args bound. |
42 void BindFields(const EntryKernel& entry, | 42 void BindFields(const EntryKernel& entry, |
43 sql::Statement* statement) { | 43 sql::Statement* statement) { |
44 int index = 0; | 44 int index = 0; |
45 int i = 0; | 45 int i = 0; |
46 for (i = BEGIN_FIELDS; i < INT64_FIELDS_END; ++i) { | 46 for (i = BEGIN_FIELDS; i < INT64_FIELDS_END; ++i) { |
47 statement->BindInt64(index++, entry.ref(static_cast<Int64Field>(i))); | 47 statement->BindInt64(index++, entry.ref(static_cast<Int64Field>(i))); |
48 } | 48 } |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
251 s1.BindInt64(1, info.next_id); | 251 s1.BindInt64(1, info.next_id); |
252 s1.BindBlob(2, info.bag_of_chips.data(), info.bag_of_chips.size()); | 252 s1.BindBlob(2, info.bag_of_chips.data(), info.bag_of_chips.size()); |
253 | 253 |
254 if (!s1.Run()) | 254 if (!s1.Run()) |
255 return false; | 255 return false; |
256 DCHECK_EQ(db_->GetLastChangeCount(), 1); | 256 DCHECK_EQ(db_->GetLastChangeCount(), 1); |
257 | 257 |
258 sql::Statement s2(db_->GetCachedStatement( | 258 sql::Statement s2(db_->GetCachedStatement( |
259 SQL_FROM_HERE, | 259 SQL_FROM_HERE, |
260 "INSERT OR REPLACE " | 260 "INSERT OR REPLACE " |
261 "INTO models (model_id, progress_marker, transaction_version) " | 261 "INTO models (model_id, " |
262 "VALUES (?, ?, ?)")); | 262 "progress_marker, " |
| 263 "transaction_version, " |
| 264 "context) " |
| 265 "VALUES (?, ?, ?, ?)")); |
263 | 266 |
264 ModelTypeSet protocol_types = ProtocolTypes(); | 267 ModelTypeSet protocol_types = ProtocolTypes(); |
265 for (ModelTypeSet::Iterator iter = protocol_types.First(); iter.Good(); | 268 for (ModelTypeSet::Iterator iter = protocol_types.First(); iter.Good(); |
266 iter.Inc()) { | 269 iter.Inc()) { |
267 ModelType type = iter.Get(); | 270 ModelType type = iter.Get(); |
268 // We persist not ModelType but rather a protobuf-derived ID. | 271 // We persist not ModelType but rather a protobuf-derived ID. |
269 string model_id = ModelTypeEnumToModelId(type); | 272 string model_id = ModelTypeEnumToModelId(type); |
270 string progress_marker; | 273 string progress_marker; |
271 info.download_progress[type].SerializeToString(&progress_marker); | 274 info.download_progress[type].SerializeToString(&progress_marker); |
272 s2.BindBlob(0, model_id.data(), model_id.length()); | 275 s2.BindBlob(0, model_id.data(), model_id.length()); |
273 s2.BindBlob(1, progress_marker.data(), progress_marker.length()); | 276 s2.BindBlob(1, progress_marker.data(), progress_marker.length()); |
274 s2.BindInt64(2, info.transaction_version[type]); | 277 s2.BindInt64(2, info.transaction_version[type]); |
| 278 string context; |
| 279 info.datatype_context[type].SerializeToString(&context); |
| 280 s2.BindBlob(3, context.data(), context.length()); |
275 if (!s2.Run()) | 281 if (!s2.Run()) |
276 return false; | 282 return false; |
277 DCHECK_EQ(db_->GetLastChangeCount(), 1); | 283 DCHECK_EQ(db_->GetLastChangeCount(), 1); |
278 s2.Reset(true); | 284 s2.Reset(true); |
279 } | 285 } |
280 } | 286 } |
281 | 287 |
282 return transaction.Commit(); | 288 return transaction.Commit(); |
283 } | 289 } |
284 | 290 |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
405 if (MigrateVersion85To86()) | 411 if (MigrateVersion85To86()) |
406 version_on_disk = 86; | 412 version_on_disk = 86; |
407 } | 413 } |
408 | 414 |
409 // Version 87 migration adds a collection of attachment ids per sync entry. | 415 // Version 87 migration adds a collection of attachment ids per sync entry. |
410 if (version_on_disk == 86) { | 416 if (version_on_disk == 86) { |
411 if (MigrateVersion86To87()) | 417 if (MigrateVersion86To87()) |
412 version_on_disk = 87; | 418 version_on_disk = 87; |
413 } | 419 } |
414 | 420 |
| 421 // Version 88 migration adds datatype contexts to the models table. |
| 422 if (version_on_disk == 87) { |
| 423 if (MigrateVersion87To88()) |
| 424 version_on_disk = 88; |
| 425 } |
| 426 |
415 // If one of the migrations requested it, drop columns that aren't current. | 427 // If one of the migrations requested it, drop columns that aren't current. |
416 // It's only safe to do this after migrating all the way to the current | 428 // It's only safe to do this after migrating all the way to the current |
417 // version. | 429 // version. |
418 if (version_on_disk == kCurrentDBVersion && needs_column_refresh_) { | 430 if (version_on_disk == kCurrentDBVersion && needs_column_refresh_) { |
419 if (!RefreshColumns()) | 431 if (!RefreshColumns()) |
420 version_on_disk = 0; | 432 version_on_disk = 0; |
421 } | 433 } |
422 | 434 |
423 // A final, alternative catch-all migration to simply re-sync everything. | 435 // A final, alternative catch-all migration to simply re-sync everything. |
424 if (version_on_disk != kCurrentDBVersion) { | 436 if (version_on_disk != kCurrentDBVersion) { |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
559 | 571 |
560 // Verify there was only one row returned. | 572 // Verify there was only one row returned. |
561 DCHECK(!s.Step()); | 573 DCHECK(!s.Step()); |
562 DCHECK(s.Succeeded()); | 574 DCHECK(s.Succeeded()); |
563 } | 575 } |
564 | 576 |
565 { | 577 { |
566 sql::Statement s( | 578 sql::Statement s( |
567 db_->GetUniqueStatement( | 579 db_->GetUniqueStatement( |
568 "SELECT model_id, progress_marker, " | 580 "SELECT model_id, progress_marker, " |
569 "transaction_version FROM models")); | 581 "transaction_version, context FROM models")); |
570 | 582 |
571 while (s.Step()) { | 583 while (s.Step()) { |
572 ModelType type = ModelIdToModelTypeEnum(s.ColumnBlob(0), | 584 ModelType type = ModelIdToModelTypeEnum(s.ColumnBlob(0), |
573 s.ColumnByteLength(0)); | 585 s.ColumnByteLength(0)); |
574 if (type != UNSPECIFIED && type != TOP_LEVEL_FOLDER) { | 586 if (type != UNSPECIFIED && type != TOP_LEVEL_FOLDER) { |
575 info->kernel_info.download_progress[type].ParseFromArray( | 587 info->kernel_info.download_progress[type].ParseFromArray( |
576 s.ColumnBlob(1), s.ColumnByteLength(1)); | 588 s.ColumnBlob(1), s.ColumnByteLength(1)); |
577 info->kernel_info.transaction_version[type] = s.ColumnInt64(2); | 589 info->kernel_info.transaction_version[type] = s.ColumnInt64(2); |
| 590 info->kernel_info.datatype_context[type].ParseFromArray( |
| 591 s.ColumnBlob(3), s.ColumnByteLength(3)); |
578 } | 592 } |
579 } | 593 } |
580 if (!s.Succeeded()) | 594 if (!s.Succeeded()) |
581 return false; | 595 return false; |
582 } | 596 } |
583 { | 597 { |
584 sql::Statement s( | 598 sql::Statement s( |
585 db_->GetUniqueStatement( | 599 db_->GetUniqueStatement( |
586 "SELECT MAX(metahandle) FROM metas")); | 600 "SELECT MAX(metahandle) FROM metas")); |
587 if (!s.Step()) | 601 if (!s.Step()) |
(...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1127 if (!db_->Execute(query.c_str())) | 1141 if (!db_->Execute(query.c_str())) |
1128 return false; | 1142 return false; |
1129 SetVersion(84); | 1143 SetVersion(84); |
1130 return true; | 1144 return true; |
1131 } | 1145 } |
1132 | 1146 |
1133 bool DirectoryBackingStore::MigrateVersion84To85() { | 1147 bool DirectoryBackingStore::MigrateVersion84To85() { |
1134 // Version 85 removes the initial_sync_ended flag. | 1148 // Version 85 removes the initial_sync_ended flag. |
1135 if (!db_->Execute("ALTER TABLE models RENAME TO temp_models")) | 1149 if (!db_->Execute("ALTER TABLE models RENAME TO temp_models")) |
1136 return false; | 1150 return false; |
1137 if (!CreateModelsTable()) | 1151 if (!CreateV81ModelsTable()) |
1138 return false; | 1152 return false; |
1139 if (!db_->Execute("INSERT INTO models SELECT " | 1153 if (!db_->Execute("INSERT INTO models SELECT " |
1140 "model_id, progress_marker, transaction_version " | 1154 "model_id, progress_marker, transaction_version " |
1141 "FROM temp_models")) { | 1155 "FROM temp_models")) { |
1142 return false; | 1156 return false; |
1143 } | 1157 } |
1144 SafeDropTable("temp_models"); | 1158 SafeDropTable("temp_models"); |
1145 | 1159 |
1146 SetVersion(85); | 1160 SetVersion(85); |
1147 return true; | 1161 return true; |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1277 if (!db_->Execute( | 1291 if (!db_->Execute( |
1278 "ALTER TABLE metas ADD COLUMN " | 1292 "ALTER TABLE metas ADD COLUMN " |
1279 "attachment_metadata BLOB")) { | 1293 "attachment_metadata BLOB")) { |
1280 return false; | 1294 return false; |
1281 } | 1295 } |
1282 SetVersion(87); | 1296 SetVersion(87); |
1283 needs_column_refresh_ = true; | 1297 needs_column_refresh_ = true; |
1284 return true; | 1298 return true; |
1285 } | 1299 } |
1286 | 1300 |
| 1301 bool DirectoryBackingStore::MigrateVersion87To88() { |
| 1302 // Version 88 adds the datatype context to the models table. |
| 1303 if (!db_->Execute("ALTER TABLE models ADD COLUMN context blob")) |
| 1304 return false; |
| 1305 |
| 1306 SetVersion(88); |
| 1307 return true; |
| 1308 } |
| 1309 |
1287 bool DirectoryBackingStore::CreateTables() { | 1310 bool DirectoryBackingStore::CreateTables() { |
1288 DVLOG(1) << "First run, creating tables"; | 1311 DVLOG(1) << "First run, creating tables"; |
1289 // Create two little tables share_version and share_info | 1312 // Create two little tables share_version and share_info |
1290 if (!db_->Execute( | 1313 if (!db_->Execute( |
1291 "CREATE TABLE share_version (" | 1314 "CREATE TABLE share_version (" |
1292 "id VARCHAR(128) primary key, data INT)")) { | 1315 "id VARCHAR(128) primary key, data INT)")) { |
1293 return false; | 1316 return false; |
1294 } | 1317 } |
1295 | 1318 |
1296 { | 1319 { |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1393 return db_->Execute( | 1416 return db_->Execute( |
1394 "CREATE TABLE models (" | 1417 "CREATE TABLE models (" |
1395 "model_id BLOB primary key, " | 1418 "model_id BLOB primary key, " |
1396 "progress_marker BLOB, " | 1419 "progress_marker BLOB, " |
1397 // Gets set if the syncer ever gets updates from the | 1420 // Gets set if the syncer ever gets updates from the |
1398 // server and the server returns 0. Lets us detect the | 1421 // server and the server returns 0. Lets us detect the |
1399 // end of the initial sync. | 1422 // end of the initial sync. |
1400 "initial_sync_ended BOOLEAN default 0)"); | 1423 "initial_sync_ended BOOLEAN default 0)"); |
1401 } | 1424 } |
1402 | 1425 |
| 1426 bool DirectoryBackingStore::CreateV81ModelsTable() { |
| 1427 // This is an old schema for the Models table, used from versions 81 to 87. |
| 1428 return db_->Execute( |
| 1429 "CREATE TABLE models (" |
| 1430 "model_id BLOB primary key, " |
| 1431 "progress_marker BLOB, " |
| 1432 // Gets set if the syncer ever gets updates from the |
| 1433 // server and the server returns 0. Lets us detect the |
| 1434 // end of the initial sync. |
| 1435 "transaction_version BIGINT default 0)"); |
| 1436 } |
| 1437 |
1403 bool DirectoryBackingStore::CreateModelsTable() { | 1438 bool DirectoryBackingStore::CreateModelsTable() { |
1404 // This is the current schema for the Models table, from version 81 | 1439 // This is the current schema for the Models table, from version 88 |
1405 // onward. If you change the schema, you'll probably want to double-check | 1440 // onward. If you change the schema, you'll probably want to double-check |
1406 // the use of this function in the v84-v85 migration. | 1441 // the use of this function in the v84-v85 migration. |
1407 return db_->Execute( | 1442 return db_->Execute( |
1408 "CREATE TABLE models (" | 1443 "CREATE TABLE models (" |
1409 "model_id BLOB primary key, " | 1444 "model_id BLOB primary key, " |
1410 "progress_marker BLOB, " | 1445 "progress_marker BLOB, " |
1411 // Gets set if the syncer ever gets updates from the | 1446 // Gets set if the syncer ever gets updates from the |
1412 // server and the server returns 0. Lets us detect the | 1447 // server and the server returns 0. Lets us detect the |
1413 // end of the initial sync. | 1448 // end of the initial sync. |
1414 "transaction_version BIGINT default 0)"); | 1449 "transaction_version BIGINT default 0," |
| 1450 "context BLOB)"); |
1415 } | 1451 } |
1416 | 1452 |
1417 bool DirectoryBackingStore::CreateShareInfoTable(bool is_temporary) { | 1453 bool DirectoryBackingStore::CreateShareInfoTable(bool is_temporary) { |
1418 const char* name = is_temporary ? "temp_share_info" : "share_info"; | 1454 const char* name = is_temporary ? "temp_share_info" : "share_info"; |
1419 string query = "CREATE TABLE "; | 1455 string query = "CREATE TABLE "; |
1420 query.append(name); | 1456 query.append(name); |
1421 // This is the current schema for the ShareInfo table, from version 76 | 1457 // This is the current schema for the ShareInfo table, from version 76 |
1422 // onward. | 1458 // onward. |
1423 query.append(" (" | 1459 query.append(" (" |
1424 "id TEXT primary key, " | 1460 "id TEXT primary key, " |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1513 } | 1549 } |
1514 query.append(" ) "); | 1550 query.append(" ) "); |
1515 values.append(" )"); | 1551 values.append(" )"); |
1516 query.append(values); | 1552 query.append(values); |
1517 save_statement->Assign(db_->GetUniqueStatement( | 1553 save_statement->Assign(db_->GetUniqueStatement( |
1518 base::StringPrintf(query.c_str(), "metas").c_str())); | 1554 base::StringPrintf(query.c_str(), "metas").c_str())); |
1519 } | 1555 } |
1520 | 1556 |
1521 } // namespace syncable | 1557 } // namespace syncable |
1522 } // namespace syncer | 1558 } // namespace syncer |
OLD | NEW |