OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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 "chrome/browser/history/thumbnail_database.h" | 5 #include "chrome/browser/history/thumbnail_database.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
268 // want once-only handling? Sqlite.Error.Thumbnail shows | 268 // want once-only handling? Sqlite.Error.Thumbnail shows |
269 // CORRUPT and READONLY as almost 95% of all reports on these | 269 // CORRUPT and READONLY as almost 95% of all reports on these |
270 // channels, so probably easier to just harvest from the field. | 270 // channels, so probably easier to just harvest from the field. |
271 if (rand < kReportsPerMillion) { | 271 if (rand < kReportsPerMillion) { |
272 reported = true; | 272 reported = true; |
273 ReportError(db, extended_error); | 273 ReportError(db, extended_error); |
274 } | 274 } |
275 } | 275 } |
276 } | 276 } |
277 | 277 |
278 // Create v5 schema for recovery code. | |
279 bool InitSchemaV5(sql::Connection* db) { | |
280 // This schema was derived from the strings used when v5 was in | |
281 // force. The [favicons] index and the [icon_mapping] items were | |
282 // copied from the current strings, after verifying that the | |
283 // resulting schema exactly matches the schema created by the | |
284 // original versions of those strings. This allows the linker to | |
285 // share the strings if they match, while preferring correctness of | |
286 // the current versions change. | |
287 | |
288 const char kFaviconsV5[] = | |
289 "CREATE TABLE favicons(" | |
pkotwicz
2013/11/04 02:38:31
Nit: It would be nice if we were consistent in usi
Scott Hess - ex-Googler
2013/11/04 21:41:44
As a general rule, I would prefer if we never ever
| |
290 "id INTEGER PRIMARY KEY," | |
291 "url LONGVARCHAR NOT NULL," | |
292 "last_updated INTEGER DEFAULT 0," | |
293 "image_data BLOB," | |
294 "icon_type INTEGER DEFAULT 1," | |
295 "sizes LONGVARCHAR" | |
296 ")"; | |
297 const char kFaviconsIndexV5[] = | |
298 "CREATE INDEX IF NOT EXISTS favicons_url ON favicons(url)"; | |
299 if (!db->Execute(kFaviconsV5) || !db->Execute(kFaviconsIndexV5)) | |
300 return false; | |
301 | |
302 const char kIconMappingV5[] = | |
303 "CREATE TABLE IF NOT EXISTS icon_mapping" | |
304 "(" | |
305 "id INTEGER PRIMARY KEY," | |
306 "page_url LONGVARCHAR NOT NULL," | |
307 "icon_id INTEGER" | |
308 ")"; | |
309 const char kIconMappingUrlIndexV5[] = | |
310 "CREATE INDEX IF NOT EXISTS icon_mapping_page_url_idx" | |
311 " ON icon_mapping(page_url)"; | |
312 const char kIconMappingIdIndexV5[] = | |
313 "CREATE INDEX IF NOT EXISTS icon_mapping_icon_id_idx" | |
314 " ON icon_mapping(icon_id)"; | |
315 if (!db->Execute(kIconMappingV5) || | |
316 !db->Execute(kIconMappingUrlIndexV5) || | |
317 !db->Execute(kIconMappingIdIndexV5)) { | |
318 return false; | |
319 } | |
320 | |
321 return true; | |
322 } | |
323 | |
324 // TODO(shess): Consider InitSchemaV7(). InitSchemaV5() is worthwhile | |
325 // because there appear to be 10s of thousands of marooned v5 | |
326 // databases in the wild. Once recovery reaches stable, the number of | |
327 // corrupt-but-recoverable databases should drop, possibly to the | |
328 // point where it is not worthwhile to maintain previous-version | |
329 // recovery code. | |
330 // TODO(shess): Alternately, think on a way to more cleanly represent | |
331 // versioned schema going forward. | |
278 bool InitTables(sql::Connection* db) { | 332 bool InitTables(sql::Connection* db) { |
279 const char kIconMappingSql[] = | 333 const char kIconMappingSql[] = |
280 "CREATE TABLE IF NOT EXISTS icon_mapping" | 334 "CREATE TABLE IF NOT EXISTS icon_mapping" |
281 "(" | 335 "(" |
282 "id INTEGER PRIMARY KEY," | 336 "id INTEGER PRIMARY KEY," |
283 "page_url LONGVARCHAR NOT NULL," | 337 "page_url LONGVARCHAR NOT NULL," |
284 "icon_id INTEGER" | 338 "icon_id INTEGER" |
285 ")"; | 339 ")"; |
286 if (!db->Execute(kIconMappingSql)) | 340 if (!db->Execute(kIconMappingSql)) |
287 return false; | 341 return false; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
335 "favicon_bitmaps(icon_id)"; | 389 "favicon_bitmaps(icon_id)"; |
336 if (!db->Execute(kFaviconBitmapsIndexSql)) | 390 if (!db->Execute(kFaviconBitmapsIndexSql)) |
337 return false; | 391 return false; |
338 | 392 |
339 return true; | 393 return true; |
340 } | 394 } |
341 | 395 |
342 enum RecoveryEventType { | 396 enum RecoveryEventType { |
343 RECOVERY_EVENT_RECOVERED = 0, | 397 RECOVERY_EVENT_RECOVERED = 0, |
344 RECOVERY_EVENT_FAILED_SCOPER, | 398 RECOVERY_EVENT_FAILED_SCOPER, |
345 RECOVERY_EVENT_FAILED_META_VERSION_ERROR, | 399 RECOVERY_EVENT_FAILED_META_VERSION_ERROR, // obsolete |
346 RECOVERY_EVENT_FAILED_META_VERSION_NONE, | 400 RECOVERY_EVENT_FAILED_META_VERSION_NONE, // obsolete |
347 RECOVERY_EVENT_FAILED_META_WRONG_VERSION6, // obsolete | 401 RECOVERY_EVENT_FAILED_META_WRONG_VERSION6, // obsolete |
348 RECOVERY_EVENT_FAILED_META_WRONG_VERSION5, | 402 RECOVERY_EVENT_FAILED_META_WRONG_VERSION5, // obsolete |
349 RECOVERY_EVENT_FAILED_META_WRONG_VERSION, | 403 RECOVERY_EVENT_FAILED_META_WRONG_VERSION, |
350 RECOVERY_EVENT_FAILED_RECOVER_META, | 404 RECOVERY_EVENT_FAILED_RECOVER_META, // obsolete |
351 RECOVERY_EVENT_FAILED_META_INSERT, // obsolete | 405 RECOVERY_EVENT_FAILED_META_INSERT, // obsolete |
352 RECOVERY_EVENT_FAILED_INIT, | 406 RECOVERY_EVENT_FAILED_INIT, |
353 RECOVERY_EVENT_FAILED_RECOVER_FAVICONS, | 407 RECOVERY_EVENT_FAILED_RECOVER_FAVICONS, // obsolete |
354 RECOVERY_EVENT_FAILED_FAVICONS_INSERT, | 408 RECOVERY_EVENT_FAILED_FAVICONS_INSERT, // obsolete |
355 RECOVERY_EVENT_FAILED_RECOVER_FAVICON_BITMAPS, | 409 RECOVERY_EVENT_FAILED_RECOVER_FAVICON_BITMAPS, // obsolete |
356 RECOVERY_EVENT_FAILED_FAVICON_BITMAPS_INSERT, | 410 RECOVERY_EVENT_FAILED_FAVICON_BITMAPS_INSERT, // obsolete |
357 RECOVERY_EVENT_FAILED_RECOVER_ICON_MAPPING, | 411 RECOVERY_EVENT_FAILED_RECOVER_ICON_MAPPING, // obsolete |
358 RECOVERY_EVENT_FAILED_ICON_MAPPING_INSERT, | 412 RECOVERY_EVENT_FAILED_ICON_MAPPING_INSERT, // obsolete |
359 RECOVERY_EVENT_RECOVERED_VERSION6, | 413 RECOVERY_EVENT_RECOVERED_VERSION6, |
360 RECOVERY_EVENT_FAILED_META_INIT, | 414 RECOVERY_EVENT_FAILED_META_INIT, |
415 RECOVERY_EVENT_FAILED_META_VERSION, | |
416 RECOVERY_EVENT_DEPRECATED, | |
417 RECOVERY_EVENT_FAILED_V5_INITSCHEMA, | |
418 RECOVERY_EVENT_FAILED_V5_AUTORECOVER_FAVICONS, | |
419 RECOVERY_EVENT_FAILED_V5_AUTORECOVER_ICON_MAPPING, | |
420 RECOVERY_EVENT_RECOVERED_VERSION5, | |
421 RECOVERY_EVENT_FAILED_AUTORECOVER_FAVICONS, | |
422 RECOVERY_EVENT_FAILED_AUTORECOVER_FAVICON_BITMAPS, | |
423 RECOVERY_EVENT_FAILED_AUTORECOVER_ICON_MAPPING, | |
361 | 424 |
362 // Always keep this at the end. | 425 // Always keep this at the end. |
363 RECOVERY_EVENT_MAX, | 426 RECOVERY_EVENT_MAX, |
364 }; | 427 }; |
365 | 428 |
366 void RecordRecoveryEvent(RecoveryEventType recovery_event) { | 429 void RecordRecoveryEvent(RecoveryEventType recovery_event) { |
367 UMA_HISTOGRAM_ENUMERATION("History.FaviconsRecovery", | 430 UMA_HISTOGRAM_ENUMERATION("History.FaviconsRecovery", |
368 recovery_event, RECOVERY_EVENT_MAX); | 431 recovery_event, RECOVERY_EVENT_MAX); |
369 } | 432 } |
370 | 433 |
(...skipping 20 matching lines...) Expand all Loading... | |
391 // | 454 // |
392 // Possible responses are unclear. If the failure relates to a | 455 // Possible responses are unclear. If the failure relates to a |
393 // problem somehow specific to the temporary file used to back the | 456 // problem somehow specific to the temporary file used to back the |
394 // database, then an in-memory database could possibly be used. | 457 // database, then an in-memory database could possibly be used. |
395 // This could potentially allow recovering the main database, and | 458 // This could potentially allow recovering the main database, and |
396 // might be simple to implement w/in Begin(). | 459 // might be simple to implement w/in Begin(). |
397 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_SCOPER); | 460 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_SCOPER); |
398 return; | 461 return; |
399 } | 462 } |
400 | 463 |
401 // Setup the meta recovery table, and check that the version number | 464 // Setup the meta recovery table and fetch the version number from |
402 // is covered by the recovery code. | 465 // the corrupt database. |
403 // TODO(shess): sql::Recovery should provide a helper to handle meta. | 466 int version = 0; |
404 int version = 0; // For reporting which version was recovered. | 467 if (!recovery->SetupMeta() || !recovery->GetMetaVersionNumber(&version)) { |
405 { | 468 // TODO(shess): Prior histograms indicate all failures are in |
406 const char kRecoverySql[] = | 469 // creating the recover virtual table for corrupt.meta. The table |
407 "CREATE VIRTUAL TABLE temp.recover_meta USING recover" | 470 // may not exist, or the database may be too far gone. Either |
408 "(" | 471 // way, unclear how to resolve. |
409 "corrupt.meta," | 472 sql::Recovery::Rollback(recovery.Pass()); |
410 "key TEXT NOT NULL," | 473 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_META_VERSION); |
411 "value TEXT" // Really? Never int? | 474 return; |
412 ")"; | 475 } |
413 if (!recovery->db()->Execute(kRecoverySql)) { | |
414 // TODO(shess): Failure to create the recover_meta table could | |
415 // mean that the main database is too corrupt to access, or that | |
416 // the meta table doesn't exist. | |
417 sql::Recovery::Rollback(recovery.Pass()); | |
418 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_RECOVER_META); | |
419 return; | |
420 } | |
421 | 476 |
422 { | 477 // Recover v5 database to v5 schema. Next pass through Init() will |
423 const char kRecoveryVersionSql[] = | 478 // migrate to v7. |
424 "SELECT value FROM recover_meta WHERE key = 'version'"; | 479 if (version == 5) { |
425 sql::Statement recovery_version( | |
426 recovery->db()->GetUniqueStatement(kRecoveryVersionSql)); | |
427 if (!recovery_version.Step()) { | |
428 if (!recovery_version.Succeeded()) { | |
429 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_META_VERSION_ERROR); | |
430 // TODO(shess): An error while processing the statement is | |
431 // probably not recoverable. | |
432 } else { | |
433 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_META_VERSION_NONE); | |
434 // TODO(shess): If a positive version lock cannot be achieved, | |
435 // the database could still be recovered by optimistically | |
436 // attempting to copy things. In the limit, the schema found | |
437 // could be inspected. Less clear is whether optimistic | |
438 // recovery really makes sense. | |
439 } | |
440 recovery_version.Clear(); | |
441 sql::Recovery::Rollback(recovery.Pass()); | |
442 return; | |
443 } | |
444 version = recovery_version.ColumnInt(0); | |
445 | |
446 // Recovery code is generally schema-dependent. Version 7 and | |
447 // version 6 are very similar, so can be handled together. | |
448 // Track version 5, to see whether it's worth writing recovery | |
449 // code for. | |
450 if (version != 7 && version != 6) { | |
451 if (version == 5) { | |
452 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_META_WRONG_VERSION5); | |
453 } else { | |
454 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_META_WRONG_VERSION); | |
455 } | |
456 recovery_version.Clear(); | |
457 sql::Recovery::Rollback(recovery.Pass()); | |
458 return; | |
459 } | |
460 } | |
461 | |
462 // Either version 6 or version 7 recovers to current. | |
463 sql::MetaTable recover_meta_table; | 480 sql::MetaTable recover_meta_table; |
464 if (!recover_meta_table.Init(recovery->db(), kCurrentVersionNumber, | 481 if (!recover_meta_table.Init(recovery->db(), version, version)) { |
465 kCompatibleVersionNumber)) { | |
466 sql::Recovery::Rollback(recovery.Pass()); | 482 sql::Recovery::Rollback(recovery.Pass()); |
467 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_META_INIT); | 483 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_META_INIT); |
468 return; | 484 return; |
469 } | 485 } |
486 | |
487 // TODO(shess): These tests are separate for histogram purposes, | |
488 // but once things look stable it can be tightened up. | |
489 if (!InitSchemaV5(recovery->db())) { | |
490 sql::Recovery::Rollback(recovery.Pass()); | |
491 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_V5_INITSCHEMA); | |
492 return; | |
493 } | |
494 | |
495 if (!recovery->AutoRecoverTable("favicons", 0)) { | |
496 sql::Recovery::Rollback(recovery.Pass()); | |
497 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_V5_AUTORECOVER_FAVICONS); | |
498 return; | |
499 } | |
500 | |
501 if (!recovery->AutoRecoverTable("icon_mapping", 0)) { | |
502 sql::Recovery::Rollback(recovery.Pass()); | |
503 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_V5_AUTORECOVER_ICON_MAPPING); | |
504 return; | |
505 } | |
506 | |
507 ignore_result(sql::Recovery::Recovered(recovery.Pass())); | |
508 RecordRecoveryEvent(RECOVERY_EVENT_RECOVERED_VERSION5); | |
509 return; | |
510 } | |
511 | |
512 // This code may be able to fetch versions that the regular | |
513 // deprecation path cannot. | |
514 if (version <= kDeprecatedVersionNumber) { | |
515 sql::Recovery::Unrecoverable(recovery.Pass()); | |
516 RecordRecoveryEvent(RECOVERY_EVENT_DEPRECATED); | |
517 return; | |
518 } | |
519 | |
520 // TODO(shess): Earlier versions have been handled or deprecated, | |
521 // later versions should be impossible. Unrecoverable() seems | |
522 // reasonable. | |
523 if (version != 6 && version != 7) { | |
524 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_META_WRONG_VERSION); | |
525 sql::Recovery::Rollback(recovery.Pass()); | |
526 return; | |
527 } | |
528 | |
529 // Both v6 and v7 recover to current schema version. | |
530 sql::MetaTable recover_meta_table; | |
531 if (!recover_meta_table.Init(recovery->db(), kCurrentVersionNumber, | |
532 kCompatibleVersionNumber)) { | |
533 sql::Recovery::Rollback(recovery.Pass()); | |
534 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_META_INIT); | |
535 return; | |
470 } | 536 } |
471 | 537 |
472 // Create a fresh version of the database. The recovery code uses | 538 // Create a fresh version of the database. The recovery code uses |
473 // conflict-resolution to handle duplicates, so the indices are | 539 // conflict-resolution to handle duplicates, so the indices are |
474 // necessary. | 540 // necessary. |
475 if (!InitTables(recovery->db()) || !InitIndices(recovery->db())) { | 541 if (!InitTables(recovery->db()) || !InitIndices(recovery->db())) { |
476 // TODO(shess): Unable to create the new schema in the new | 542 // TODO(shess): Unable to create the new schema in the new |
477 // database. The new database should be a temporary file, so | 543 // database. The new database should be a temporary file, so |
478 // being unable to work with it is pretty unclear. | 544 // being unable to work with it is pretty unclear. |
479 // | 545 // |
480 // What are the potential responses, even? The recovery database | 546 // What are the potential responses, even? The recovery database |
481 // could be opened as in-memory. If the temp database had a | 547 // could be opened as in-memory. If the temp database had a |
482 // filesystem problem and the temp filesystem differs from the | 548 // filesystem problem and the temp filesystem differs from the |
483 // main database, then that could fix it. | 549 // main database, then that could fix it. |
484 sql::Recovery::Rollback(recovery.Pass()); | 550 sql::Recovery::Rollback(recovery.Pass()); |
485 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_INIT); | 551 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_INIT); |
486 return; | 552 return; |
487 } | 553 } |
488 | 554 |
489 // Setup favicons table. | 555 // [favicons] differs because v6 had an unused [sizes] column which |
490 { | 556 // was removed in v7. |
491 // Version 6 had the |sizes| column, version 7 removed it. The | 557 if (!recovery->AutoRecoverTable("favicons", 1)) { |
492 // recover virtual table treats more columns than expected as an | 558 sql::Recovery::Rollback(recovery.Pass()); |
493 // error, but if _fewer_ columns are present, they can be treated | 559 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_AUTORECOVER_FAVICONS); |
494 // as NULL. SQLite requires this because ALTER TABLE adds columns | 560 return; |
495 // to the schema, but not to the actual table storage. | |
496 const char kRecoverySql[] = | |
497 "CREATE VIRTUAL TABLE temp.recover_favicons USING recover" | |
498 "(" | |
499 "corrupt.favicons," | |
500 "id ROWID," | |
501 "url TEXT NOT NULL," | |
502 "icon_type INTEGER," | |
503 "sizes TEXT" | |
504 ")"; | |
505 if (!recovery->db()->Execute(kRecoverySql)) { | |
506 // TODO(shess): Failure to create the recovery table probably | |
507 // means unrecoverable. | |
508 sql::Recovery::Rollback(recovery.Pass()); | |
509 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_RECOVER_FAVICONS); | |
510 return; | |
511 } | |
512 | |
513 // TODO(shess): Check if the DEFAULT 1 will just cover the | |
514 // COALESCE(). Either way, the new code has a literal 1 rather | |
515 // than a NULL, right? | |
516 const char kCopySql[] = | |
517 "INSERT OR REPLACE INTO main.favicons " | |
518 "SELECT id, url, COALESCE(icon_type, 1) FROM recover_favicons"; | |
519 if (!recovery->db()->Execute(kCopySql)) { | |
520 // TODO(shess): The recover_favicons table should mask problems | |
521 // with the source file, so this implies failure to write to the | |
522 // recovery database. | |
523 sql::Recovery::Rollback(recovery.Pass()); | |
524 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_FAVICONS_INSERT); | |
525 return; | |
526 } | |
527 } | 561 } |
528 | 562 if (!recovery->AutoRecoverTable("favicon_bitmaps", 0)) { |
529 // Setup favicons_bitmaps table. | 563 sql::Recovery::Rollback(recovery.Pass()); |
530 { | 564 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_AUTORECOVER_FAVICON_BITMAPS); |
531 const char kRecoverySql[] = | 565 return; |
532 "CREATE VIRTUAL TABLE temp.recover_favicons_bitmaps USING recover" | |
533 "(" | |
534 "corrupt.favicon_bitmaps," | |
535 "id ROWID," | |
536 "icon_id INTEGER STRICT NOT NULL," | |
537 "last_updated INTEGER," | |
538 "image_data BLOB," | |
539 "width INTEGER," | |
540 "height INTEGER" | |
541 ")"; | |
542 if (!recovery->db()->Execute(kRecoverySql)) { | |
543 // TODO(shess): Failure to create the recovery table probably | |
544 // means unrecoverable. | |
545 sql::Recovery::Rollback(recovery.Pass()); | |
546 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_RECOVER_FAVICON_BITMAPS); | |
547 return; | |
548 } | |
549 | |
550 const char kCopySql[] = | |
551 "INSERT OR REPLACE INTO main.favicon_bitmaps " | |
552 "SELECT id, icon_id, COALESCE(last_updated, 0), image_data, " | |
553 " COALESCE(width, 0), COALESCE(height, 0) " | |
554 "FROM recover_favicons_bitmaps"; | |
555 if (!recovery->db()->Execute(kCopySql)) { | |
556 // TODO(shess): The recover_faviconbitmaps table should mask | |
557 // problems with the source file, so this implies failure to | |
558 // write to the recovery database. | |
559 sql::Recovery::Rollback(recovery.Pass()); | |
560 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_FAVICON_BITMAPS_INSERT); | |
561 return; | |
562 } | |
563 } | 566 } |
564 | 567 if (!recovery->AutoRecoverTable("icon_mapping", 0)) { |
565 // Setup icon_mapping table. | 568 sql::Recovery::Rollback(recovery.Pass()); |
566 { | 569 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_AUTORECOVER_ICON_MAPPING); |
567 const char kRecoverySql[] = | 570 return; |
568 "CREATE VIRTUAL TABLE temp.recover_icon_mapping USING recover" | |
569 "(" | |
570 "corrupt.icon_mapping," | |
571 "id ROWID," | |
572 "page_url TEXT STRICT NOT NULL," | |
573 "icon_id INTEGER STRICT" | |
574 ")"; | |
575 if (!recovery->db()->Execute(kRecoverySql)) { | |
576 // TODO(shess): Failure to create the recovery table probably | |
577 // means unrecoverable. | |
578 sql::Recovery::Rollback(recovery.Pass()); | |
579 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_RECOVER_ICON_MAPPING); | |
580 return; | |
581 } | |
582 | |
583 const char kCopySql[] = | |
584 "INSERT OR REPLACE INTO main.icon_mapping " | |
585 "SELECT id, page_url, icon_id FROM recover_icon_mapping"; | |
586 if (!recovery->db()->Execute(kCopySql)) { | |
587 // TODO(shess): The recover_icon_mapping table should mask | |
588 // problems with the source file, so this implies failure to | |
589 // write to the recovery database. | |
590 sql::Recovery::Rollback(recovery.Pass()); | |
591 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_ICON_MAPPING_INSERT); | |
592 return; | |
593 } | |
594 } | 571 } |
595 | 572 |
596 // TODO(shess): Is it possible/likely to have broken foreign-key | 573 // TODO(shess): Is it possible/likely to have broken foreign-key |
597 // issues with the tables? | 574 // issues with the tables? |
598 // - icon_mapping.icon_id maps to no favicons.id | 575 // - icon_mapping.icon_id maps to no favicons.id |
599 // - favicon_bitmaps.icon_id maps to no favicons.id | 576 // - favicon_bitmaps.icon_id maps to no favicons.id |
600 // - favicons.id is referenced by no icon_mapping.icon_id | 577 // - favicons.id is referenced by no icon_mapping.icon_id |
601 // - favicons.id is referenced by no favicon_bitmaps.icon_id | 578 // - favicons.id is referenced by no favicon_bitmaps.icon_id |
602 // This step is possibly not worth the effort necessary to develop | 579 // This step is possibly not worth the effort necessary to develop |
603 // and sequence the statements, as it is basically a form of garbage | 580 // and sequence the statements, as it is basically a form of garbage |
(...skipping 666 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1270 ignore_result(db_.Execute("DROP TABLE IF EXISTS temp_icon_mapping")); | 1247 ignore_result(db_.Execute("DROP TABLE IF EXISTS temp_icon_mapping")); |
1271 | 1248 |
1272 // Create the tables. | 1249 // Create the tables. |
1273 if (!meta_table_.Init(&db_, kCurrentVersionNumber, | 1250 if (!meta_table_.Init(&db_, kCurrentVersionNumber, |
1274 kCompatibleVersionNumber) || | 1251 kCompatibleVersionNumber) || |
1275 !InitTables(&db_) || | 1252 !InitTables(&db_) || |
1276 !InitIndices(&db_)) { | 1253 !InitIndices(&db_)) { |
1277 return sql::INIT_FAILURE; | 1254 return sql::INIT_FAILURE; |
1278 } | 1255 } |
1279 | 1256 |
1280 // Version check. We should not encounter a database too old for us to handle | 1257 // Version check. We should not encounter a database too old for us to handle |
pkotwicz
2013/11/04 02:38:31
Unrelated: Shouldn't this comment be "too new for
Scott Hess - ex-Googler
2013/11/04 21:41:44
I think this means that the too-new case fails (wi
| |
1281 // in the wild, so we try to continue in that case. | 1258 // in the wild, so we try to continue in that case. |
1282 if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) { | 1259 if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) { |
1283 LOG(WARNING) << "Thumbnail database is too new."; | 1260 LOG(WARNING) << "Thumbnail database is too new."; |
1284 return sql::INIT_TOO_NEW; | 1261 return sql::INIT_TOO_NEW; |
1285 } | 1262 } |
1286 | 1263 |
1287 int cur_version = meta_table_.GetVersionNumber(); | 1264 int cur_version = meta_table_.GetVersionNumber(); |
1288 | 1265 |
1289 if (!db_.DoesColumnExist("favicons", "icon_type")) { | 1266 if (!db_.DoesColumnExist("favicons", "icon_type")) { |
1290 LOG(ERROR) << "Raze because of missing favicon.icon_type"; | 1267 LOG(ERROR) << "Raze because of missing favicon.icon_type"; |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1392 meta_table_.SetVersionNumber(7); | 1369 meta_table_.SetVersionNumber(7); |
1393 meta_table_.SetCompatibleVersionNumber(std::min(7, kCompatibleVersionNumber)); | 1370 meta_table_.SetCompatibleVersionNumber(std::min(7, kCompatibleVersionNumber)); |
1394 return true; | 1371 return true; |
1395 } | 1372 } |
1396 | 1373 |
1397 bool ThumbnailDatabase::IsFaviconDBStructureIncorrect() { | 1374 bool ThumbnailDatabase::IsFaviconDBStructureIncorrect() { |
1398 return !db_.IsSQLValid("SELECT id, url, icon_type FROM favicons"); | 1375 return !db_.IsSQLValid("SELECT id, url, icon_type FROM favicons"); |
1399 } | 1376 } |
1400 | 1377 |
1401 } // namespace history | 1378 } // namespace history |
OLD | NEW |