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

Side by Side Diff: content/browser/indexed_db/indexed_db_database.cc

Issue 197333009: Handling LevelDB errors encountered after open. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 9 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
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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 "content/browser/indexed_db/indexed_db_database.h" 5 #include "content/browser/indexed_db/indexed_db_database.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 #include <set> 8 #include <set>
9 9
10 #include "base/auto_reset.h" 10 #include "base/auto_reset.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h" 12 #include "base/memory/scoped_ptr.h"
13 #include "base/stl_util.h" 13 #include "base/stl_util.h"
14 #include "base/strings/string_number_conversions.h" 14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/utf_string_conversions.h" 15 #include "base/strings/utf_string_conversions.h"
16 #include "content/browser/indexed_db/indexed_db_connection.h" 16 #include "content/browser/indexed_db/indexed_db_connection.h"
17 #include "content/browser/indexed_db/indexed_db_context_impl.h"
17 #include "content/browser/indexed_db/indexed_db_cursor.h" 18 #include "content/browser/indexed_db/indexed_db_cursor.h"
18 #include "content/browser/indexed_db/indexed_db_factory.h" 19 #include "content/browser/indexed_db/indexed_db_factory.h"
19 #include "content/browser/indexed_db/indexed_db_index_writer.h" 20 #include "content/browser/indexed_db/indexed_db_index_writer.h"
20 #include "content/browser/indexed_db/indexed_db_pending_connection.h" 21 #include "content/browser/indexed_db/indexed_db_pending_connection.h"
21 #include "content/browser/indexed_db/indexed_db_tracing.h" 22 #include "content/browser/indexed_db/indexed_db_tracing.h"
22 #include "content/browser/indexed_db/indexed_db_transaction.h" 23 #include "content/browser/indexed_db/indexed_db_transaction.h"
23 #include "content/browser/indexed_db/indexed_db_value.h" 24 #include "content/browser/indexed_db/indexed_db_value.h"
24 #include "content/common/indexed_db/indexed_db_key_path.h" 25 #include "content/common/indexed_db/indexed_db_key_path.h"
25 #include "content/common/indexed_db/indexed_db_key_range.h" 26 #include "content/common/indexed_db/indexed_db_key_range.h"
26 #include "third_party/WebKit/public/platform/WebIDBDatabaseException.h" 27 #include "third_party/WebKit/public/platform/WebIDBDatabaseException.h"
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 this, 288 this,
288 object_store_id)); 289 object_store_id));
289 290
290 AddObjectStore(object_store_metadata, object_store_id); 291 AddObjectStore(object_store_metadata, object_store_id);
291 } 292 }
292 293
293 void IndexedDBDatabase::CreateObjectStoreOperation( 294 void IndexedDBDatabase::CreateObjectStoreOperation(
294 const IndexedDBObjectStoreMetadata& object_store_metadata, 295 const IndexedDBObjectStoreMetadata& object_store_metadata,
295 IndexedDBTransaction* transaction) { 296 IndexedDBTransaction* transaction) {
296 IDB_TRACE("IndexedDBDatabase::CreateObjectStoreOperation"); 297 IDB_TRACE("IndexedDBDatabase::CreateObjectStoreOperation");
297 if (!backing_store_->CreateObjectStore( 298 leveldb::Status s =
298 transaction->BackingStoreTransaction(), 299 backing_store_->CreateObjectStore(transaction->BackingStoreTransaction(),
299 transaction->database()->id(), 300 transaction->database()->id(),
300 object_store_metadata.id, 301 object_store_metadata.id,
301 object_store_metadata.name, 302 object_store_metadata.name,
302 object_store_metadata.key_path, 303 object_store_metadata.key_path,
303 object_store_metadata.auto_increment).ok()) { 304 object_store_metadata.auto_increment);
304 transaction->Abort(IndexedDBDatabaseError( 305 if (!s.ok()) {
306 IndexedDBDatabaseError error(
305 blink::WebIDBDatabaseExceptionUnknownError, 307 blink::WebIDBDatabaseExceptionUnknownError,
306 ASCIIToUTF16("Internal error creating object store '") + 308 ASCIIToUTF16("Internal error creating object store '") +
307 object_store_metadata.name + ASCIIToUTF16("'."))); 309 object_store_metadata.name + ASCIIToUTF16("'."));
310 transaction->Abort(error);
311 if (s.IsCorruption())
312 factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
313 error);
308 return; 314 return;
309 } 315 }
310 } 316 }
311 317
312 void IndexedDBDatabase::DeleteObjectStore(int64 transaction_id, 318 void IndexedDBDatabase::DeleteObjectStore(int64 transaction_id,
313 int64 object_store_id) { 319 int64 object_store_id) {
314 IDB_TRACE("IndexedDBDatabase::DeleteObjectStore"); 320 IDB_TRACE("IndexedDBDatabase::DeleteObjectStore");
315 IndexedDBTransaction* transaction = GetTransaction(transaction_id); 321 IndexedDBTransaction* transaction = GetTransaction(transaction_id);
316 if (!transaction) 322 if (!transaction)
317 return; 323 return;
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
429 IDB_TRACE("IndexedDBDatabase::DeleteIndexOperation"); 435 IDB_TRACE("IndexedDBDatabase::DeleteIndexOperation");
430 leveldb::Status s = 436 leveldb::Status s =
431 backing_store_->DeleteIndex(transaction->BackingStoreTransaction(), 437 backing_store_->DeleteIndex(transaction->BackingStoreTransaction(),
432 transaction->database()->id(), 438 transaction->database()->id(),
433 object_store_id, 439 object_store_id,
434 index_metadata.id); 440 index_metadata.id);
435 if (!s.ok()) { 441 if (!s.ok()) {
436 base::string16 error_string = 442 base::string16 error_string =
437 ASCIIToUTF16("Internal error deleting index '") + 443 ASCIIToUTF16("Internal error deleting index '") +
438 index_metadata.name + ASCIIToUTF16("'."); 444 index_metadata.name + ASCIIToUTF16("'.");
439 transaction->Abort(IndexedDBDatabaseError( 445 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
440 blink::WebIDBDatabaseExceptionUnknownError, error_string)); 446 error_string);
447 transaction->Abort(error);
448 if (s.IsCorruption())
449 factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
450 error);
441 } 451 }
442 } 452 }
443 453
444 void IndexedDBDatabase::DeleteIndexAbortOperation( 454 void IndexedDBDatabase::DeleteIndexAbortOperation(
445 int64 object_store_id, 455 int64 object_store_id,
446 const IndexedDBIndexMetadata& index_metadata, 456 const IndexedDBIndexMetadata& index_metadata,
447 IndexedDBTransaction* transaction) { 457 IndexedDBTransaction* transaction) {
448 IDB_TRACE("IndexedDBDatabase::DeleteIndexAbortOperation"); 458 IDB_TRACE("IndexedDBDatabase::DeleteIndexAbortOperation");
449 DCHECK(!transaction); 459 DCHECK(!transaction);
450 AddIndex(object_store_id, index_metadata, IndexedDBIndexMetadata::kInvalidId); 460 AddIndex(object_store_id, index_metadata, IndexedDBIndexMetadata::kInvalidId);
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
562 leveldb::Status s; 572 leveldb::Status s;
563 if (index_id == IndexedDBIndexMetadata::kInvalidId) { 573 if (index_id == IndexedDBIndexMetadata::kInvalidId) {
564 // Object Store Retrieval Operation 574 // Object Store Retrieval Operation
565 IndexedDBValue value; 575 IndexedDBValue value;
566 s = backing_store_->GetRecord(transaction->BackingStoreTransaction(), 576 s = backing_store_->GetRecord(transaction->BackingStoreTransaction(),
567 id(), 577 id(),
568 object_store_id, 578 object_store_id,
569 *key, 579 *key,
570 &value); 580 &value);
571 if (!s.ok()) { 581 if (!s.ok()) {
572 callbacks->OnError( 582 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
573 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, 583 "Internal error in GetRecord.");
574 "Internal error in GetRecord.")); 584 callbacks->OnError(error);
585
586 if (s.IsCorruption())
587 factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
588 error);
575 return; 589 return;
576 } 590 }
577 591
578 if (value.empty()) { 592 if (value.empty()) {
579 callbacks->OnSuccess(); 593 callbacks->OnSuccess();
580 return; 594 return;
581 } 595 }
582 596
583 if (object_store_metadata.auto_increment && 597 if (object_store_metadata.auto_increment &&
584 !object_store_metadata.key_path.IsNull()) { 598 !object_store_metadata.key_path.IsNull()) {
585 callbacks->OnSuccess(&value, *key, object_store_metadata.key_path); 599 callbacks->OnSuccess(&value, *key, object_store_metadata.key_path);
586 return; 600 return;
587 } 601 }
588 602
589 callbacks->OnSuccess(&value); 603 callbacks->OnSuccess(&value);
590 return; 604 return;
591 } 605 }
592 606
593 // From here we are dealing only with indexes. 607 // From here we are dealing only with indexes.
594 s = backing_store_->GetPrimaryKeyViaIndex( 608 s = backing_store_->GetPrimaryKeyViaIndex(
595 transaction->BackingStoreTransaction(), 609 transaction->BackingStoreTransaction(),
596 id(), 610 id(),
597 object_store_id, 611 object_store_id,
598 index_id, 612 index_id,
599 *key, 613 *key,
600 &primary_key); 614 &primary_key);
601 if (!s.ok()) { 615 if (!s.ok()) {
602 callbacks->OnError( 616 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
603 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, 617 "Internal error in GetPrimaryKeyViaIndex.");
604 "Internal error in GetPrimaryKeyViaIndex.")); 618 callbacks->OnError(error);
619 if (s.IsCorruption())
620 factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
621 error);
605 return; 622 return;
606 } 623 }
607 if (!primary_key) { 624 if (!primary_key) {
608 callbacks->OnSuccess(); 625 callbacks->OnSuccess();
609 return; 626 return;
610 } 627 }
611 if (cursor_type == indexed_db::CURSOR_KEY_ONLY) { 628 if (cursor_type == indexed_db::CURSOR_KEY_ONLY) {
612 // Index Value Retrieval Operation 629 // Index Value Retrieval Operation
613 callbacks->OnSuccess(*primary_key); 630 callbacks->OnSuccess(*primary_key);
614 return; 631 return;
615 } 632 }
616 633
617 // Index Referenced Value Retrieval Operation 634 // Index Referenced Value Retrieval Operation
618 IndexedDBValue value; 635 IndexedDBValue value;
619 s = backing_store_->GetRecord(transaction->BackingStoreTransaction(), 636 s = backing_store_->GetRecord(transaction->BackingStoreTransaction(),
620 id(), 637 id(),
621 object_store_id, 638 object_store_id,
622 *primary_key, 639 *primary_key,
623 &value); 640 &value);
624 if (!s.ok()) { 641 if (!s.ok()) {
625 callbacks->OnError( 642 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
626 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, 643 "Internal error in GetRecord.");
627 "Internal error in GetRecord.")); 644 callbacks->OnError(error);
645 if (s.IsCorruption())
646 factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
647 error);
628 return; 648 return;
629 } 649 }
630 650
631 if (value.empty()) { 651 if (value.empty()) {
632 callbacks->OnSuccess(); 652 callbacks->OnSuccess();
633 return; 653 return;
634 } 654 }
635 if (object_store_metadata.auto_increment && 655 if (object_store_metadata.auto_increment &&
636 !object_store_metadata.key_path.IsNull()) { 656 !object_store_metadata.key_path.IsNull()) {
637 callbacks->OnSuccess(&value, *primary_key, object_store_metadata.key_path); 657 callbacks->OnSuccess(&value, *primary_key, object_store_metadata.key_path);
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
754 if (params->put_mode == IndexedDBDatabase::ADD_ONLY) { 774 if (params->put_mode == IndexedDBDatabase::ADD_ONLY) {
755 bool found = false; 775 bool found = false;
756 leveldb::Status s = backing_store_->KeyExistsInObjectStore( 776 leveldb::Status s = backing_store_->KeyExistsInObjectStore(
757 transaction->BackingStoreTransaction(), 777 transaction->BackingStoreTransaction(),
758 id(), 778 id(),
759 params->object_store_id, 779 params->object_store_id,
760 *key, 780 *key,
761 &record_identifier, 781 &record_identifier,
762 &found); 782 &found);
763 if (!s.ok()) { 783 if (!s.ok()) {
764 params->callbacks->OnError( 784 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
765 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, 785 "Internal error checking key existence.");
766 "Internal error checking key existence.")); 786 params->callbacks->OnError(error);
787 if (s.IsCorruption())
788 factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
789 error);
767 return; 790 return;
768 } 791 }
769 if (found) { 792 if (found) {
770 params->callbacks->OnError( 793 params->callbacks->OnError(
771 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionConstraintError, 794 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionConstraintError,
772 "Key already exists in the object store.")); 795 "Key already exists in the object store."));
773 return; 796 return;
774 } 797 }
775 } 798 }
776 799
(...skipping 25 matching lines...) Expand all
802 // Before this point, don't do any mutation. After this point, rollback the 825 // Before this point, don't do any mutation. After this point, rollback the
803 // transaction in case of error. 826 // transaction in case of error.
804 leveldb::Status s = 827 leveldb::Status s =
805 backing_store_->PutRecord(transaction->BackingStoreTransaction(), 828 backing_store_->PutRecord(transaction->BackingStoreTransaction(),
806 id(), 829 id(),
807 params->object_store_id, 830 params->object_store_id,
808 *key, 831 *key,
809 params->value, 832 params->value,
810 &record_identifier); 833 &record_identifier);
811 if (!s.ok()) { 834 if (!s.ok()) {
812 params->callbacks->OnError(IndexedDBDatabaseError( 835 IndexedDBDatabaseError error(
813 blink::WebIDBDatabaseExceptionUnknownError, 836 blink::WebIDBDatabaseExceptionUnknownError,
814 "Internal error: backing store error performing put/add.")); 837 "Internal error: backing store error performing put/add.");
838 params->callbacks->OnError(error);
839 if (s.IsCorruption())
840 factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
841 error);
815 return; 842 return;
816 } 843 }
817 844
818 for (size_t i = 0; i < index_writers.size(); ++i) { 845 for (size_t i = 0; i < index_writers.size(); ++i) {
819 IndexWriter* index_writer = index_writers[i]; 846 IndexWriter* index_writer = index_writers[i];
820 index_writer->WriteIndexKeys(record_identifier, 847 index_writer->WriteIndexKeys(record_identifier,
821 backing_store_.get(), 848 backing_store_.get(),
822 transaction->BackingStoreTransaction(), 849 transaction->BackingStoreTransaction(),
823 id(), 850 id(),
824 params->object_store_id); 851 params->object_store_id);
825 } 852 }
826 853
827 if (object_store.auto_increment && 854 if (object_store.auto_increment &&
828 params->put_mode != IndexedDBDatabase::CURSOR_UPDATE && 855 params->put_mode != IndexedDBDatabase::CURSOR_UPDATE &&
829 key->type() == WebIDBKeyTypeNumber) { 856 key->type() == WebIDBKeyTypeNumber) {
830 leveldb::Status s = UpdateKeyGenerator(backing_store_.get(), 857 leveldb::Status s = UpdateKeyGenerator(backing_store_.get(),
831 transaction, 858 transaction,
832 id(), 859 id(),
833 params->object_store_id, 860 params->object_store_id,
834 *key, 861 *key,
835 !key_was_generated); 862 !key_was_generated);
836 if (!s.ok()) { 863 if (!s.ok()) {
837 params->callbacks->OnError( 864 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
838 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, 865 "Internal error updating key generator.");
839 "Internal error updating key generator.")); 866 params->callbacks->OnError(error);
867 if (s.IsCorruption())
868 factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
869 error);
840 return; 870 return;
841 } 871 }
842 } 872 }
843 873
844 params->callbacks->OnSuccess(*key); 874 params->callbacks->OnSuccess(*key);
845 } 875 }
846 876
847 void IndexedDBDatabase::SetIndexKeys(int64 transaction_id, 877 void IndexedDBDatabase::SetIndexKeys(int64 transaction_id,
848 int64 object_store_id, 878 int64 object_store_id,
849 scoped_ptr<IndexedDBKey> primary_key, 879 scoped_ptr<IndexedDBKey> primary_key,
850 const std::vector<IndexKeys>& index_keys) { 880 const std::vector<IndexKeys>& index_keys) {
851 IDB_TRACE("IndexedDBDatabase::SetIndexKeys"); 881 IDB_TRACE("IndexedDBDatabase::SetIndexKeys");
852 IndexedDBTransaction* transaction = GetTransaction(transaction_id); 882 IndexedDBTransaction* transaction = GetTransaction(transaction_id);
853 if (!transaction) 883 if (!transaction)
854 return; 884 return;
855 DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE); 885 DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
856 886
857 // TODO(alecflett): This method could be asynchronous, but we need to 887 // TODO(alecflett): This method could be asynchronous, but we need to
858 // evaluate if it's worth the extra complexity. 888 // evaluate if it's worth the extra complexity.
859 IndexedDBBackingStore::RecordIdentifier record_identifier; 889 IndexedDBBackingStore::RecordIdentifier record_identifier;
860 bool found = false; 890 bool found = false;
861 leveldb::Status s = backing_store_->KeyExistsInObjectStore( 891 leveldb::Status s = backing_store_->KeyExistsInObjectStore(
862 transaction->BackingStoreTransaction(), 892 transaction->BackingStoreTransaction(),
863 metadata_.id, 893 metadata_.id,
864 object_store_id, 894 object_store_id,
865 *primary_key, 895 *primary_key,
866 &record_identifier, 896 &record_identifier,
867 &found); 897 &found);
868 if (!s.ok()) { 898 if (!s.ok()) {
869 transaction->Abort( 899 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
870 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, 900 "Internal error setting index keys.");
871 "Internal error setting index keys.")); 901 transaction->Abort(error);
902 if (s.IsCorruption())
903 factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
904 error);
872 return; 905 return;
873 } 906 }
874 if (!found) { 907 if (!found) {
875 transaction->Abort(IndexedDBDatabaseError( 908 transaction->Abort(IndexedDBDatabaseError(
876 blink::WebIDBDatabaseExceptionUnknownError, 909 blink::WebIDBDatabaseExceptionUnknownError,
877 "Internal error setting index keys for object store.")); 910 "Internal error setting index keys for object store."));
878 return; 911 return;
879 } 912 }
880 913
881 ScopedVector<IndexWriter> index_writers; 914 ScopedVector<IndexWriter> index_writers;
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
1199 IndexedDBTransaction* transaction) { 1232 IndexedDBTransaction* transaction) {
1200 IDB_TRACE("IndexedDBDatabase::DeleteObjectStoreOperation"); 1233 IDB_TRACE("IndexedDBDatabase::DeleteObjectStoreOperation");
1201 leveldb::Status s = 1234 leveldb::Status s =
1202 backing_store_->DeleteObjectStore(transaction->BackingStoreTransaction(), 1235 backing_store_->DeleteObjectStore(transaction->BackingStoreTransaction(),
1203 transaction->database()->id(), 1236 transaction->database()->id(),
1204 object_store_metadata.id); 1237 object_store_metadata.id);
1205 if (!s.ok()) { 1238 if (!s.ok()) {
1206 base::string16 error_string = 1239 base::string16 error_string =
1207 ASCIIToUTF16("Internal error deleting object store '") + 1240 ASCIIToUTF16("Internal error deleting object store '") +
1208 object_store_metadata.name + ASCIIToUTF16("'."); 1241 object_store_metadata.name + ASCIIToUTF16("'.");
1209 transaction->Abort(IndexedDBDatabaseError( 1242 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
1210 blink::WebIDBDatabaseExceptionUnknownError, error_string)); 1243 error_string);
1244 transaction->Abort(error);
1245 if (s.IsCorruption())
1246 factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
1247 error);
1211 } 1248 }
1212 } 1249 }
1213 1250
1214 void IndexedDBDatabase::VersionChangeOperation( 1251 void IndexedDBDatabase::VersionChangeOperation(
1215 int64 version, 1252 int64 version,
1216 scoped_refptr<IndexedDBCallbacks> callbacks, 1253 scoped_refptr<IndexedDBCallbacks> callbacks,
1217 scoped_ptr<IndexedDBConnection> connection, 1254 scoped_ptr<IndexedDBConnection> connection,
1218 IndexedDBTransaction* transaction) { 1255 IndexedDBTransaction* transaction) {
1219 IDB_TRACE("IndexedDBDatabase::VersionChangeOperation"); 1256 IDB_TRACE("IndexedDBDatabase::VersionChangeOperation");
1220 int64 old_version = metadata_.int_version; 1257 int64 old_version = metadata_.int_version;
(...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after
1655 const base::string16& previous_version, 1692 const base::string16& previous_version,
1656 int64 previous_int_version, 1693 int64 previous_int_version,
1657 IndexedDBTransaction* transaction) { 1694 IndexedDBTransaction* transaction) {
1658 IDB_TRACE("IndexedDBDatabase::VersionChangeAbortOperation"); 1695 IDB_TRACE("IndexedDBDatabase::VersionChangeAbortOperation");
1659 DCHECK(!transaction); 1696 DCHECK(!transaction);
1660 metadata_.version = previous_version; 1697 metadata_.version = previous_version;
1661 metadata_.int_version = previous_int_version; 1698 metadata_.int_version = previous_int_version;
1662 } 1699 }
1663 1700
1664 } // namespace content 1701 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698