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

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

Issue 18023022: Blob support for IDB [Chromium] (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: More small build fixes. Created 6 years, 6 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) 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_backing_store.h" 5 #include "content/browser/indexed_db/indexed_db_backing_store.h"
6 6
7 #include "base/file_util.h" 7 #include "base/file_util.h"
8 #include "base/files/file_path.h" 8 #include "base/files/file_path.h"
9 #include "base/format_macros.h" 9 #include "base/format_macros.h"
10 #include "base/json/json_reader.h" 10 #include "base/json/json_reader.h"
(...skipping 1302 matching lines...) Expand 10 before | Expand all | Expand 10 after
1313 if (int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION) 1313 if (int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION)
1314 int_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION; 1314 int_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION;
1315 DCHECK_GE(int_version, 0) << "int_version was " << int_version; 1315 DCHECK_GE(int_version, 0) << "int_version was " << int_version;
1316 PutVarInt(transaction->transaction(), 1316 PutVarInt(transaction->transaction(),
1317 DatabaseMetaDataKey::Encode(row_id, 1317 DatabaseMetaDataKey::Encode(row_id,
1318 DatabaseMetaDataKey::USER_INT_VERSION), 1318 DatabaseMetaDataKey::USER_INT_VERSION),
1319 int_version); 1319 int_version);
1320 return true; 1320 return true;
1321 } 1321 }
1322 1322
1323 static leveldb::Status DeleteRange(LevelDBTransaction* transaction, 1323 // If you're deleting a range that contains user keys that have blob info, this
1324 const std::string& begin, 1324 // won't clean up the blobs.
1325 const std::string& end) { 1325 static leveldb::Status DeleteRangeBasic(LevelDBTransaction* transaction,
1326 const std::string& begin,
1327 const std::string& end,
1328 bool upper_open) {
1326 scoped_ptr<LevelDBIterator> it = transaction->CreateIterator(); 1329 scoped_ptr<LevelDBIterator> it = transaction->CreateIterator();
1327 leveldb::Status s; 1330 leveldb::Status s;
1328 for (s = it->Seek(begin); 1331 for (s = it->Seek(begin); s.ok() && it->IsValid() &&
1329 s.ok() && it->IsValid() && CompareKeys(it->Key(), end) < 0; 1332 (upper_open ? CompareKeys(it->Key(), end) < 0
1333 : CompareKeys(it->Key(), end) <= 0);
1330 s = it->Next()) 1334 s = it->Next())
1331 transaction->Remove(it->Key()); 1335 transaction->Remove(it->Key());
1332 return s; 1336 return s;
1333 } 1337 }
1334 1338
1335 static leveldb::Status DeleteBlobsInObjectStore( 1339 static leveldb::Status DeleteBlobsInRange(
1336 IndexedDBBackingStore::Transaction* transaction, 1340 IndexedDBBackingStore::Transaction* transaction,
1337 int64 database_id, 1341 int64 database_id,
1338 int64 object_store_id) { 1342 int64 object_store_id,
1339 std::string start_key, end_key; 1343 const std::string& start_key,
1340 start_key = 1344 const std::string& end_key,
1341 BlobEntryKey::EncodeMinKeyForObjectStore(database_id, object_store_id); 1345 bool upper_open) {
1342 end_key =
1343 BlobEntryKey::EncodeStopKeyForObjectStore(database_id, object_store_id);
1344
1345 scoped_ptr<LevelDBIterator> it = transaction->transaction()->CreateIterator(); 1346 scoped_ptr<LevelDBIterator> it = transaction->transaction()->CreateIterator();
1346
1347 leveldb::Status s = it->Seek(start_key); 1347 leveldb::Status s = it->Seek(start_key);
1348 for (; s.ok() && it->IsValid() && CompareKeys(it->Key(), end_key) < 0; 1348 for (; s.ok() && it->IsValid() &&
1349 (upper_open ? CompareKeys(it->Key(), end_key) < 0
1350 : CompareKeys(it->Key(), end_key) <= 0);
1349 s = it->Next()) { 1351 s = it->Next()) {
1350 StringPiece key_piece(it->Key()); 1352 StringPiece key_piece(it->Key());
1351 std::string user_key = 1353 std::string user_key =
1352 BlobEntryKey::ReencodeToObjectStoreDataKey(&key_piece); 1354 BlobEntryKey::ReencodeToObjectStoreDataKey(&key_piece);
1353 if (!user_key.size()) { 1355 if (!user_key.size()) {
1354 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_IDBDATABASE_METADATA); 1356 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
1355 return InternalInconsistencyStatus(); 1357 return InternalInconsistencyStatus();
1356 } 1358 }
1357 transaction->PutBlobInfo( 1359 transaction->PutBlobInfo(
1358 database_id, object_store_id, user_key, NULL, NULL); 1360 database_id, object_store_id, user_key, NULL, NULL);
1359 } 1361 }
1360 return s; 1362 return s;
1361 } 1363 }
1362 1364
1365 static leveldb::Status DeleteBlobsInObjectStore(
1366 IndexedDBBackingStore::Transaction* transaction,
1367 int64 database_id,
1368 int64 object_store_id) {
1369 std::string start_key, end_key;
cmumford 2014/05/28 20:34:54 Nit: You're already using "stop_key" elsewhere, an
ericu 2014/05/28 22:50:42 Done.
1370 start_key =
1371 BlobEntryKey::EncodeMinKeyForObjectStore(database_id, object_store_id);
1372 end_key =
1373 BlobEntryKey::EncodeStopKeyForObjectStore(database_id, object_store_id);
1374 return DeleteBlobsInRange(
1375 transaction, database_id, object_store_id, start_key, end_key, true);
1376 }
1377
1363 leveldb::Status IndexedDBBackingStore::DeleteDatabase( 1378 leveldb::Status IndexedDBBackingStore::DeleteDatabase(
1364 const base::string16& name) { 1379 const base::string16& name) {
1365 IDB_TRACE("IndexedDBBackingStore::DeleteDatabase"); 1380 IDB_TRACE("IndexedDBBackingStore::DeleteDatabase");
1366 scoped_ptr<LevelDBDirectTransaction> transaction = 1381 scoped_ptr<LevelDBDirectTransaction> transaction =
1367 LevelDBDirectTransaction::Create(db_.get()); 1382 LevelDBDirectTransaction::Create(db_.get());
1368 1383
1369 leveldb::Status s; 1384 leveldb::Status s;
1370 s = CleanUpBlobJournal(BlobJournalKey::Encode()); 1385 s = CleanUpBlobJournal(BlobJournalKey::Encode());
1371 if (!s.ok()) 1386 if (!s.ok())
1372 return s; 1387 return s;
(...skipping 27 matching lines...) Expand all
1400 if (active_blob_registry()->MarkDeletedCheckIfUsed( 1415 if (active_blob_registry()->MarkDeletedCheckIfUsed(
1401 metadata.id, DatabaseMetaDataKey::kAllBlobsKey)) { 1416 metadata.id, DatabaseMetaDataKey::kAllBlobsKey)) {
1402 s = MergeDatabaseIntoLiveBlobJournal(transaction.get(), metadata.id); 1417 s = MergeDatabaseIntoLiveBlobJournal(transaction.get(), metadata.id);
1403 if (!s.ok()) 1418 if (!s.ok())
1404 return s; 1419 return s;
1405 } else { 1420 } else {
1406 UpdateBlobJournalWithDatabase(transaction.get(), metadata.id); 1421 UpdateBlobJournalWithDatabase(transaction.get(), metadata.id);
1407 need_cleanup = true; 1422 need_cleanup = true;
1408 } 1423 }
1409 1424
1410 // TODO(ericu): Remove these fake calls, added to avoid "defined but unused"
1411 // compiler errors until the code that makes the real calls can be added.
1412 if (false) {
1413 std::vector<IndexedDBBlobInfo*> fake;
1414 EncodeBlobData(fake);
1415
1416 scoped_refptr<LevelDBTransaction> fake_transaction =
1417 new LevelDBTransaction(NULL);
1418 BlobJournalType fake_journal;
1419 MergeBlobsIntoLiveBlobJournal(fake_transaction.get(), fake_journal);
1420 UpdateBlobKeyGeneratorCurrentNumber(fake_transaction.get(), 0, 0);
1421 int64 arg;
1422 GetBlobKeyGeneratorCurrentNumber(fake_transaction.get(), 0, &arg);
1423 }
1424
1425 s = transaction->Commit(); 1425 s = transaction->Commit();
1426 if (!s.ok()) { 1426 if (!s.ok()) {
1427 INTERNAL_WRITE_ERROR_UNTESTED(DELETE_DATABASE); 1427 INTERNAL_WRITE_ERROR_UNTESTED(DELETE_DATABASE);
1428 return s; 1428 return s;
1429 } 1429 }
1430 1430
1431 if (need_cleanup) 1431 if (need_cleanup)
1432 CleanUpBlobJournal(BlobJournalKey::Encode()); 1432 CleanUpBlobJournal(BlobJournalKey::Encode());
1433 1433
1434 db_->Compact(start_key, stop_key); 1434 db_->Compact(start_key, stop_key);
1435 return s; 1435 return s;
1436 } 1436 }
1437 1437
1438 static bool CheckObjectStoreAndMetaDataType(const LevelDBIterator* it, 1438 static bool CheckObjectStoreAndMetaDataType(const LevelDBIterator* it,
1439 const std::string& stop_key, 1439 const std::string& stop_key,
1440 int64 object_store_id, 1440 int64 object_store_id,
1441 int64 meta_data_type) { 1441 int64 meta_data_type) {
1442 if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0) 1442 if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0)
1443 return false; 1443 return false;
1444 1444
1445 StringPiece slice(it->Key()); 1445 StringPiece slice(it->Key());
1446 ObjectStoreMetaDataKey meta_data_key; 1446 ObjectStoreMetaDataKey meta_data_key;
1447 bool ok = ObjectStoreMetaDataKey::Decode(&slice, &meta_data_key); 1447 bool ok =
1448 ObjectStoreMetaDataKey::Decode(&slice, &meta_data_key) && slice.empty();
1448 DCHECK(ok); 1449 DCHECK(ok);
1449 if (meta_data_key.ObjectStoreId() != object_store_id) 1450 if (meta_data_key.ObjectStoreId() != object_store_id)
1450 return false; 1451 return false;
1451 if (meta_data_key.MetaDataType() != meta_data_type) 1452 if (meta_data_key.MetaDataType() != meta_data_type)
1452 return false; 1453 return false;
1453 return true; 1454 return ok;
1454 } 1455 }
1455 1456
1456 // TODO(jsbell): This should do some error handling rather than 1457 // TODO(jsbell): This should do some error handling rather than
1457 // plowing ahead when bad data is encountered. 1458 // plowing ahead when bad data is encountered.
1458 leveldb::Status IndexedDBBackingStore::GetObjectStores( 1459 leveldb::Status IndexedDBBackingStore::GetObjectStores(
1459 int64 database_id, 1460 int64 database_id,
1460 IndexedDBDatabaseMetadata::ObjectStoreMap* object_stores) { 1461 IndexedDBDatabaseMetadata::ObjectStoreMap* object_stores) {
1461 IDB_TRACE("IndexedDBBackingStore::GetObjectStores"); 1462 IDB_TRACE("IndexedDBBackingStore::GetObjectStores");
1462 if (!KeyPrefix::IsValidDatabaseId(database_id)) 1463 if (!KeyPrefix::IsValidDatabaseId(database_id))
1463 return InvalidDBKeyStatus(); 1464 return InvalidDBKeyStatus();
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
1738 INTERNAL_CONSISTENCY_ERROR_UNTESTED(DELETE_OBJECT_STORE); 1739 INTERNAL_CONSISTENCY_ERROR_UNTESTED(DELETE_OBJECT_STORE);
1739 return InternalInconsistencyStatus(); 1740 return InternalInconsistencyStatus();
1740 } 1741 }
1741 1742
1742 s = DeleteBlobsInObjectStore(transaction, database_id, object_store_id); 1743 s = DeleteBlobsInObjectStore(transaction, database_id, object_store_id);
1743 if (!s.ok()) { 1744 if (!s.ok()) {
1744 INTERNAL_CONSISTENCY_ERROR_UNTESTED(DELETE_OBJECT_STORE); 1745 INTERNAL_CONSISTENCY_ERROR_UNTESTED(DELETE_OBJECT_STORE);
1745 return s; 1746 return s;
1746 } 1747 }
1747 1748
1748 s = DeleteRange( 1749 s = DeleteRangeBasic(
1749 leveldb_transaction, 1750 leveldb_transaction,
1750 ObjectStoreMetaDataKey::Encode(database_id, object_store_id, 0), 1751 ObjectStoreMetaDataKey::Encode(database_id, object_store_id, 0),
1751 ObjectStoreMetaDataKey::EncodeMaxKey(database_id, object_store_id)); 1752 ObjectStoreMetaDataKey::EncodeMaxKey(database_id, object_store_id),
1753 true);
1752 1754
1753 if (s.ok()) { 1755 if (s.ok()) {
1754 leveldb_transaction->Remove( 1756 leveldb_transaction->Remove(
1755 ObjectStoreNamesKey::Encode(database_id, object_store_name)); 1757 ObjectStoreNamesKey::Encode(database_id, object_store_name));
1756 1758
1757 s = DeleteRange( 1759 s = DeleteRangeBasic(
1758 leveldb_transaction, 1760 leveldb_transaction,
1759 IndexFreeListKey::Encode(database_id, object_store_id, 0), 1761 IndexFreeListKey::Encode(database_id, object_store_id, 0),
1760 IndexFreeListKey::EncodeMaxKey(database_id, object_store_id)); 1762 IndexFreeListKey::EncodeMaxKey(database_id, object_store_id),
1763 true);
1761 } 1764 }
1762 1765
1763 if (s.ok()) { 1766 if (s.ok()) {
1764 s = DeleteRange( 1767 s = DeleteRangeBasic(
1765 leveldb_transaction, 1768 leveldb_transaction,
1766 IndexMetaDataKey::Encode(database_id, object_store_id, 0, 0), 1769 IndexMetaDataKey::Encode(database_id, object_store_id, 0, 0),
1767 IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id)); 1770 IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id),
1771 true);
1768 } 1772 }
1769 1773
1770 if (!s.ok()) { 1774 if (!s.ok()) {
1771 INTERNAL_WRITE_ERROR_UNTESTED(DELETE_OBJECT_STORE); 1775 INTERNAL_WRITE_ERROR_UNTESTED(DELETE_OBJECT_STORE);
1772 return s; 1776 return s;
1773 } 1777 }
1774 1778
1775 return ClearObjectStore(transaction, database_id, object_store_id); 1779 return ClearObjectStore(transaction, database_id, object_store_id);
1776 } 1780 }
1777 1781
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
1901 int64 object_store_id) { 1905 int64 object_store_id) {
1902 IDB_TRACE("IndexedDBBackingStore::ClearObjectStore"); 1906 IDB_TRACE("IndexedDBBackingStore::ClearObjectStore");
1903 if (!KeyPrefix::ValidIds(database_id, object_store_id)) 1907 if (!KeyPrefix::ValidIds(database_id, object_store_id))
1904 return InvalidDBKeyStatus(); 1908 return InvalidDBKeyStatus();
1905 const std::string start_key = 1909 const std::string start_key =
1906 KeyPrefix(database_id, object_store_id).Encode(); 1910 KeyPrefix(database_id, object_store_id).Encode();
1907 const std::string stop_key = 1911 const std::string stop_key =
1908 KeyPrefix(database_id, object_store_id + 1).Encode(); 1912 KeyPrefix(database_id, object_store_id + 1).Encode();
1909 1913
1910 leveldb::Status s = 1914 leveldb::Status s =
1911 DeleteRange(transaction->transaction(), start_key, stop_key); 1915 DeleteRangeBasic(transaction->transaction(), start_key, stop_key, true);
1912 if (!s.ok()) { 1916 if (!s.ok()) {
1913 INTERNAL_WRITE_ERROR(CLEAR_OBJECT_STORE); 1917 INTERNAL_WRITE_ERROR(CLEAR_OBJECT_STORE);
1914 return s; 1918 return s;
1915 } 1919 }
1916 return DeleteBlobsInObjectStore(transaction, database_id, object_store_id); 1920 return DeleteBlobsInObjectStore(transaction, database_id, object_store_id);
1917 } 1921 }
1918 1922
1919 leveldb::Status IndexedDBBackingStore::DeleteRecord( 1923 leveldb::Status IndexedDBBackingStore::DeleteRecord(
1920 IndexedDBBackingStore::Transaction* transaction, 1924 IndexedDBBackingStore::Transaction* transaction,
1921 int64 database_id, 1925 int64 database_id,
1922 int64 object_store_id, 1926 int64 object_store_id,
1923 const RecordIdentifier& record_identifier) { 1927 const RecordIdentifier& record_identifier) {
1924 IDB_TRACE("IndexedDBBackingStore::DeleteRecord"); 1928 IDB_TRACE("IndexedDBBackingStore::DeleteRecord");
1925 if (!KeyPrefix::ValidIds(database_id, object_store_id)) 1929 if (!KeyPrefix::ValidIds(database_id, object_store_id))
1926 return InvalidDBKeyStatus(); 1930 return InvalidDBKeyStatus();
1927 LevelDBTransaction* leveldb_transaction = transaction->transaction(); 1931 LevelDBTransaction* leveldb_transaction = transaction->transaction();
1928 1932
1929 const std::string object_store_data_key = ObjectStoreDataKey::Encode( 1933 const std::string object_store_data_key = ObjectStoreDataKey::Encode(
1930 database_id, object_store_id, record_identifier.primary_key()); 1934 database_id, object_store_id, record_identifier.primary_key());
1931 leveldb_transaction->Remove(object_store_data_key); 1935 leveldb_transaction->Remove(object_store_data_key);
1932 transaction->PutBlobInfo( 1936 transaction->PutBlobInfo(
1933 database_id, object_store_id, object_store_data_key, NULL, NULL); 1937 database_id, object_store_id, object_store_data_key, NULL, NULL);
1934 1938
1935 const std::string exists_entry_key = ExistsEntryKey::Encode( 1939 const std::string exists_entry_key = ExistsEntryKey::Encode(
1936 database_id, object_store_id, record_identifier.primary_key()); 1940 database_id, object_store_id, record_identifier.primary_key());
1937 leveldb_transaction->Remove(exists_entry_key); 1941 leveldb_transaction->Remove(exists_entry_key);
1938 return leveldb::Status::OK(); 1942 return leveldb::Status::OK();
1939 } 1943 }
1940 1944
1945 leveldb::Status IndexedDBBackingStore::DeleteRange(
1946 IndexedDBBackingStore::Transaction* transaction,
1947 int64 database_id,
1948 int64 object_store_id,
1949 const IndexedDBKeyRange& key_range) {
1950 leveldb::Status s;
1951 scoped_ptr<IndexedDBBackingStore::Cursor> start_cursor =
1952 OpenObjectStoreCursor(transaction,
1953 database_id,
1954 object_store_id,
1955 key_range,
1956 indexed_db::CURSOR_NEXT,
1957 &s);
1958 if (!s.ok())
1959 return s;
1960 if (!start_cursor)
1961 return leveldb::Status::OK(); // Empty range == delete success.
1962
1963 scoped_ptr<IndexedDBBackingStore::Cursor> end_cursor =
cmumford 2014/05/28 20:34:54 Nit: Same "stop" vs. "end" question.
ericu 2014/05/28 22:50:42 Done.
1964 OpenObjectStoreCursor(transaction,
1965 database_id,
1966 object_store_id,
1967 key_range,
1968 indexed_db::CURSOR_PREV,
1969 &s);
1970
1971 if (!s.ok())
1972 return s;
1973 if (!end_cursor)
1974 return leveldb::Status::OK(); // Empty range == delete success.
1975
1976 BlobEntryKey start_blob_key, end_blob_key;
1977
1978 std::string start_key = ObjectStoreDataKey::Encode(
1979 database_id, object_store_id, start_cursor->key());
1980 base::StringPiece start_key_piece(start_key);
1981 if (!BlobEntryKey::FromObjectStoreDataKey(&start_key_piece, &start_blob_key))
1982 return InternalInconsistencyStatus();
1983 std::string end_key = ObjectStoreDataKey::Encode(
1984 database_id, object_store_id, end_cursor->key());
1985 base::StringPiece end_key_piece(end_key);
1986 if (!BlobEntryKey::FromObjectStoreDataKey(&end_key_piece, &end_blob_key))
1987 return InternalInconsistencyStatus();
1988
1989 s = DeleteBlobsInRange(transaction,
1990 database_id,
1991 object_store_id,
1992 start_blob_key.Encode(),
1993 end_blob_key.Encode(),
1994 false);
cmumford 2014/05/28 20:34:54 Just curious: Why is this one not "upper_open"?
jsbell 2014/05/28 21:29:15 It's found above by the end_cursor, so it's a key
ericu 2014/05/28 22:50:42 The OpenObjectStoreCursor that created end_cursor
1995 if (!s.ok())
1996 return s;
1997 s = DeleteRangeBasic(transaction->transaction(), start_key, end_key, false);
1998 if (!s.ok())
cmumford 2014/05/28 20:34:54 Should we bail on the first error, or instead do a
jsbell 2014/05/28 21:29:15 We should bail, since we will abort the whole tran
ericu 2014/05/28 22:50:42 The Blob entries often won't be there, if there ar
1999 return s;
2000 start_key =
2001 ExistsEntryKey::Encode(database_id, object_store_id, start_cursor->key());
jsbell 2014/05/28 21:29:15 Were we "leaking" ExistsEntryKeys before in some c
ericu 2014/05/28 22:50:42 I don't think so--we didn't have a DeleteRange at
jsbell 2014/05/28 23:35:18 Nothing specific. I thought when poking around tha
2002 end_key =
2003 ExistsEntryKey::Encode(database_id, object_store_id, end_cursor->key());
2004 return DeleteRangeBasic(
2005 transaction->transaction(), start_key, end_key, false);
2006 }
2007
1941 leveldb::Status IndexedDBBackingStore::GetKeyGeneratorCurrentNumber( 2008 leveldb::Status IndexedDBBackingStore::GetKeyGeneratorCurrentNumber(
1942 IndexedDBBackingStore::Transaction* transaction, 2009 IndexedDBBackingStore::Transaction* transaction,
1943 int64 database_id, 2010 int64 database_id,
1944 int64 object_store_id, 2011 int64 object_store_id,
1945 int64* key_generator_current_number) { 2012 int64* key_generator_current_number) {
1946 if (!KeyPrefix::ValidIds(database_id, object_store_id)) 2013 if (!KeyPrefix::ValidIds(database_id, object_store_id))
1947 return InvalidDBKeyStatus(); 2014 return InvalidDBKeyStatus();
1948 LevelDBTransaction* leveldb_transaction = transaction->transaction(); 2015 LevelDBTransaction* leveldb_transaction = transaction->transaction();
1949 2016
1950 const std::string key_generator_current_number_key = 2017 const std::string key_generator_current_number_key =
(...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after
2649 int64 index_id) { 2716 int64 index_id) {
2650 IDB_TRACE("IndexedDBBackingStore::DeleteIndex"); 2717 IDB_TRACE("IndexedDBBackingStore::DeleteIndex");
2651 if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id)) 2718 if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id))
2652 return InvalidDBKeyStatus(); 2719 return InvalidDBKeyStatus();
2653 LevelDBTransaction* leveldb_transaction = transaction->transaction(); 2720 LevelDBTransaction* leveldb_transaction = transaction->transaction();
2654 2721
2655 const std::string index_meta_data_start = 2722 const std::string index_meta_data_start =
2656 IndexMetaDataKey::Encode(database_id, object_store_id, index_id, 0); 2723 IndexMetaDataKey::Encode(database_id, object_store_id, index_id, 0);
2657 const std::string index_meta_data_end = 2724 const std::string index_meta_data_end =
2658 IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id, index_id); 2725 IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id, index_id);
2659 leveldb::Status s = DeleteRange( 2726 leveldb::Status s = DeleteRangeBasic(
2660 leveldb_transaction, index_meta_data_start, index_meta_data_end); 2727 leveldb_transaction, index_meta_data_start, index_meta_data_end, true);
2661 2728
2662 if (s.ok()) { 2729 if (s.ok()) {
2663 const std::string index_data_start = 2730 const std::string index_data_start =
2664 IndexDataKey::EncodeMinKey(database_id, object_store_id, index_id); 2731 IndexDataKey::EncodeMinKey(database_id, object_store_id, index_id);
2665 const std::string index_data_end = 2732 const std::string index_data_end =
2666 IndexDataKey::EncodeMaxKey(database_id, object_store_id, index_id); 2733 IndexDataKey::EncodeMaxKey(database_id, object_store_id, index_id);
2667 s = DeleteRange(leveldb_transaction, index_data_start, index_data_end); 2734 s = DeleteRangeBasic(
2735 leveldb_transaction, index_data_start, index_data_end, true);
2668 } 2736 }
2669 2737
2670 if (!s.ok()) 2738 if (!s.ok())
2671 INTERNAL_WRITE_ERROR_UNTESTED(DELETE_INDEX); 2739 INTERNAL_WRITE_ERROR_UNTESTED(DELETE_INDEX);
2672 2740
2673 return s; 2741 return s;
2674 } 2742 }
2675 2743
2676 leveldb::Status IndexedDBBackingStore::PutIndexDataForRecord( 2744 leveldb::Status IndexedDBBackingStore::PutIndexDataForRecord(
2677 IndexedDBBackingStore::Transaction* transaction, 2745 IndexedDBBackingStore::Transaction* transaction,
(...skipping 1067 matching lines...) Expand 10 before | Expand all | Expand 10 after
3745 3813
3746 // If incognito, this snapshots blobs just as the above transaction_ 3814 // If incognito, this snapshots blobs just as the above transaction_
3747 // constructor snapshots the leveldb. 3815 // constructor snapshots the leveldb.
3748 BlobChangeMap::const_iterator iter; 3816 BlobChangeMap::const_iterator iter;
3749 for (iter = backing_store_->incognito_blob_map_.begin(); 3817 for (iter = backing_store_->incognito_blob_map_.begin();
3750 iter != backing_store_->incognito_blob_map_.end(); 3818 iter != backing_store_->incognito_blob_map_.end();
3751 ++iter) 3819 ++iter)
3752 incognito_blob_map_[iter->first] = iter->second->Clone().release(); 3820 incognito_blob_map_[iter->first] = iter->second->Clone().release();
3753 } 3821 }
3754 3822
3755 leveldb::Status IndexedDBBackingStore::Transaction::Commit() { 3823 static GURL getURLFromUUID(const string& uuid) {
3756 IDB_TRACE("IndexedDBBackingStore::Transaction::Commit"); 3824 return GURL("blob:uuid/" + uuid);
jsbell 2014/05/28 21:29:15 FYI: There's been some blather about standardizing
ericu 2014/05/28 22:50:42 Hmm...I've read most of the blather, but I missed
jsbell 2014/05/28 23:35:18 I haven't even been following the blather enough t
3757 DCHECK(transaction_.get()); 3825 }
3758 leveldb::Status s = transaction_->Commit(); 3826
3827 leveldb::Status IndexedDBBackingStore::Transaction::HandleBlobPreTransaction(
3828 BlobEntryKeyValuePairVec* new_blob_entries,
3829 WriteDescriptorVec* new_files_to_write) {
3830 if (backing_store_->is_incognito())
3831 return leveldb::Status::OK();
3832
3833 BlobChangeMap::iterator iter = blob_change_map_.begin();
3834 new_blob_entries->clear();
3835 new_files_to_write->clear();
3836 if (iter != blob_change_map_.end()) {
3837 // Create LevelDBTransaction for the name generator seed and add-journal.
3838 scoped_refptr<LevelDBTransaction> pre_transaction =
3839 new LevelDBTransaction(backing_store_->db_.get());
3840 BlobJournalType journal;
3841 for (; iter != blob_change_map_.end(); ++iter) {
3842 std::vector<IndexedDBBlobInfo>::iterator info_iter;
3843 std::vector<IndexedDBBlobInfo*> new_blob_keys;
3844 for (info_iter = iter->second->mutable_blob_info().begin();
3845 info_iter != iter->second->mutable_blob_info().end();
3846 ++info_iter) {
3847 int64 next_blob_key = -1;
3848 bool result = GetBlobKeyGeneratorCurrentNumber(
3849 pre_transaction.get(), database_id_, &next_blob_key);
3850 if (!result || next_blob_key < 0)
3851 return InternalInconsistencyStatus();
3852 BlobJournalEntryType journal_entry =
3853 std::make_pair(database_id_, next_blob_key);
3854 journal.push_back(journal_entry);
3855 if (info_iter->is_file()) {
3856 new_files_to_write->push_back(
3857 WriteDescriptor(info_iter->file_path(), next_blob_key));
3858 } else {
3859 new_files_to_write->push_back(WriteDescriptor(
3860 getURLFromUUID(info_iter->uuid()), next_blob_key));
3861 }
3862 info_iter->set_key(next_blob_key);
3863 new_blob_keys.push_back(&*info_iter);
3864 result = UpdateBlobKeyGeneratorCurrentNumber(
3865 pre_transaction.get(), database_id_, next_blob_key + 1);
3866 if (!result)
3867 return InternalInconsistencyStatus();
3868 }
3869 BlobEntryKey blob_entry_key;
3870 StringPiece key_piece(iter->second->key());
3871 if (!BlobEntryKey::FromObjectStoreDataKey(&key_piece, &blob_entry_key)) {
3872 NOTREACHED();
3873 return InternalInconsistencyStatus();
3874 }
3875 new_blob_entries->push_back(
3876 std::make_pair(blob_entry_key, EncodeBlobData(new_blob_keys)));
3877 }
3878 UpdatePrimaryJournalWithBlobList(pre_transaction.get(), journal);
3879 if (!pre_transaction->Commit().ok())
3880 return InternalInconsistencyStatus();
cmumford 2014/05/28 20:34:54 Why not return the actual return value of transact
ericu 2014/05/28 22:50:42 Done.
3881 }
3882 return leveldb::Status::OK();
3883 }
3884
3885 bool IndexedDBBackingStore::Transaction::CollectBlobFilesToRemove() {
cmumford 2014/05/28 20:34:54 Should this method clear blobs_to_remove_, or at l
ericu 2014/05/28 22:50:42 If any error happens, the transaction is aborted.
3886 if (backing_store_->is_incognito())
3887 return true;
3888
3889 BlobChangeMap::const_iterator iter = blob_change_map_.begin();
3890 // Look up all old files to remove as part of the transaction, store their
3891 // names in blobs_to_remove_, and remove their old blob data entries.
3892 if (iter != blob_change_map_.end()) {
3893 scoped_ptr<LevelDBIterator> db_iter = transaction_->CreateIterator();
3894 for (; iter != blob_change_map_.end(); ++iter) {
3895 BlobEntryKey blob_entry_key;
3896 StringPiece key_piece(iter->second->key());
3897 if (!BlobEntryKey::FromObjectStoreDataKey(&key_piece, &blob_entry_key)) {
3898 NOTREACHED();
3899 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
3900 transaction_ = NULL;
3901 return false;
3902 }
3903 if (database_id_ < 0)
3904 database_id_ = blob_entry_key.database_id();
3905 else
3906 DCHECK_EQ(database_id_, blob_entry_key.database_id());
3907 std::string blob_entry_key_bytes = blob_entry_key.Encode();
3908 db_iter->Seek(blob_entry_key_bytes);
3909 if (db_iter->IsValid() &&
3910 !CompareKeys(db_iter->Key(), blob_entry_key_bytes)) {
3911 std::vector<IndexedDBBlobInfo> blob_info;
3912 if (!DecodeBlobData(db_iter->Value().as_string(), &blob_info)) {
3913 INTERNAL_READ_ERROR(TRANSACTION_COMMIT_METHOD);
3914 transaction_ = NULL;
3915 return false;
3916 }
3917 std::vector<IndexedDBBlobInfo>::iterator blob_info_iter;
3918 for (blob_info_iter = blob_info.begin();
3919 blob_info_iter != blob_info.end();
3920 ++blob_info_iter)
3921 blobs_to_remove_.push_back(
3922 std::make_pair(database_id_, blob_info_iter->key()));
3923 transaction_->Remove(blob_entry_key_bytes);
3924 }
3925 }
3926 }
3927 return true;
3928 }
3929
3930 leveldb::Status IndexedDBBackingStore::Transaction::SortBlobsToRemove() {
cmumford 2014/05/28 20:34:54 Does this method actually sort (reorder) anything?
jsbell 2014/05/28 21:29:15 'Sort' is a bit misleading here - can we use anoth
ericu 2014/05/28 22:50:42 No, it's just sorting into two bins [live_blob or
3931 IndexedDBActiveBlobRegistry* registry =
3932 backing_store_->active_blob_registry();
3933 BlobJournalType::iterator iter;
3934 BlobJournalType primary_journal, live_blob_journal;
3935 for (iter = blobs_to_remove_.begin(); iter != blobs_to_remove_.end();
3936 ++iter) {
3937 if (registry->MarkDeletedCheckIfUsed(iter->first, iter->second))
3938 live_blob_journal.push_back(*iter);
3939 else
3940 primary_journal.push_back(*iter);
3941 }
3942 UpdatePrimaryJournalWithBlobList(transaction_.get(), primary_journal);
3943 leveldb::Status s =
3944 MergeBlobsIntoLiveBlobJournal(transaction_.get(), live_blob_journal);
3945 if (!s.ok())
3946 return s;
3947 // To signal how many blobs need attention right now.
3948 blobs_to_remove_.swap(primary_journal);
3949 return leveldb::Status::OK();
3950 }
3951
3952 leveldb::Status IndexedDBBackingStore::Transaction::CommitPhaseOne(
3953 scoped_refptr<BlobWriteCallback> callback) {
3954 IDB_TRACE("IndexedDBBackingStore::Transaction::CommitPhaseOne");
3955 DCHECK(transaction_);
3956 DCHECK(backing_store_->task_runner()->RunsTasksOnCurrentThread());
3957
3958 leveldb::Status s;
3959
3960 s = backing_store_->CleanUpBlobJournal(BlobJournalKey::Encode());
3961 if (!s.ok()) {
3962 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
3963 transaction_ = NULL;
3964 return s;
3965 }
3966
3967 BlobEntryKeyValuePairVec new_blob_entries;
3968 WriteDescriptorVec new_files_to_write;
3969 s = HandleBlobPreTransaction(&new_blob_entries, &new_files_to_write);
3970 if (!s.ok()) {
3971 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
3972 transaction_ = NULL;
3973 return s;
3974 }
3975
3976 DCHECK(!new_files_to_write.size() ||
3977 KeyPrefix::IsValidDatabaseId(database_id_));
3978 if (!CollectBlobFilesToRemove()) {
3979 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
cmumford 2014/05/28 20:34:54 Should use the _UNTESTED versions of this macro in
ericu 2014/05/28 22:50:42 Done; I'll get to the failure unit tests after we'
3980 transaction_ = NULL;
3981 return InternalInconsistencyStatus();
3982 }
3983
3984 if (new_files_to_write.size()) {
3985 // This kicks off the writes of the new blobs, if any.
3986 // This call will zero out new_blob_entries and new_files_to_write.
3987 WriteNewBlobs(new_blob_entries, new_files_to_write, callback);
3988 // Remove the add journal, if any; once the blobs are written, and we
3989 // commit, this will do the cleanup.
3990 ClearBlobJournal(transaction_.get(), BlobJournalKey::Encode());
3991 } else {
3992 callback->Run(true);
3993 }
3994
3995 return leveldb::Status::OK();
3996 }
3997
3998 leveldb::Status IndexedDBBackingStore::Transaction::CommitPhaseTwo() {
3999 IDB_TRACE("IndexedDBBackingStore::Transaction::CommitPhaseTwo");
4000 leveldb::Status s;
4001 if (blobs_to_remove_.size()) {
4002 s = SortBlobsToRemove();
4003 if (!s.ok()) {
4004 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
cmumford 2014/05/28 20:34:54 SortBlobsToRemove doesn't write to the db (does it
ericu 2014/05/28 22:50:42 It writes to the transaction, not the db, so while
4005 transaction_ = NULL;
4006 return s;
4007 }
4008 }
4009
4010 s = transaction_->Commit();
3759 transaction_ = NULL; 4011 transaction_ = NULL;
3760 4012
3761 if (s.ok() && backing_store_->is_incognito() && !blob_change_map_.empty()) { 4013 if (s.ok() && backing_store_->is_incognito() && !blob_change_map_.empty()) {
3762 BlobChangeMap& target_map = backing_store_->incognito_blob_map_; 4014 BlobChangeMap& target_map = backing_store_->incognito_blob_map_;
3763 BlobChangeMap::iterator iter; 4015 BlobChangeMap::iterator iter;
3764 for (iter = blob_change_map_.begin(); iter != blob_change_map_.end(); 4016 for (iter = blob_change_map_.begin(); iter != blob_change_map_.end();
3765 ++iter) { 4017 ++iter) {
3766 BlobChangeMap::iterator target_record = target_map.find(iter->first); 4018 BlobChangeMap::iterator target_record = target_map.find(iter->first);
3767 if (target_record != target_map.end()) { 4019 if (target_record != target_map.end()) {
3768 delete target_record->second; 4020 delete target_record->second;
3769 target_map.erase(target_record); 4021 target_map.erase(target_record);
3770 } 4022 }
3771 if (iter->second) { 4023 if (iter->second) {
3772 target_map[iter->first] = iter->second; 4024 target_map[iter->first] = iter->second;
3773 iter->second = NULL; 4025 iter->second = NULL;
3774 } 4026 }
3775 } 4027 }
3776 } 4028 }
3777 if (!s.ok()) 4029 if (!s.ok())
3778 INTERNAL_WRITE_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD); 4030 INTERNAL_WRITE_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD);
4031 else if (blobs_to_remove_.size())
4032 s = backing_store_->CleanUpBlobJournal(BlobJournalKey::Encode());
4033
3779 return s; 4034 return s;
3780 } 4035 }
3781 4036
3782 4037
3783 class IndexedDBBackingStore::Transaction::BlobWriteCallbackWrapper 4038 class IndexedDBBackingStore::Transaction::BlobWriteCallbackWrapper
3784 : public IndexedDBBackingStore::BlobWriteCallback { 4039 : public IndexedDBBackingStore::BlobWriteCallback {
3785 public: 4040 public:
3786 BlobWriteCallbackWrapper(IndexedDBBackingStore::Transaction* transaction, 4041 BlobWriteCallbackWrapper(IndexedDBBackingStore::Transaction* transaction,
3787 scoped_refptr<BlobWriteCallback> callback) 4042 scoped_refptr<BlobWriteCallback> callback)
3788 : transaction_(transaction), callback_(callback) {} 4043 : transaction_(transaction), callback_(callback) {}
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
3904 const GURL& url, 4159 const GURL& url,
3905 int64_t key) 4160 int64_t key)
3906 : is_file_(false), url_(url), key_(key) {} 4161 : is_file_(false), url_(url), key_(key) {}
3907 4162
3908 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor( 4163 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor(
3909 const FilePath& file_path, 4164 const FilePath& file_path,
3910 int64_t key) 4165 int64_t key)
3911 : is_file_(true), file_path_(file_path), key_(key) {} 4166 : is_file_(true), file_path_(file_path), key_(key) {}
3912 4167
3913 } // namespace content 4168 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698