OLD | NEW |
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 Loading... |
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; |
| 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 Loading... |
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 Loading... |
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 Loading... |
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 = |
| 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); |
| 1995 if (!s.ok()) |
| 1996 return s; |
| 1997 s = DeleteRangeBasic(transaction->transaction(), start_key, end_key, false); |
| 1998 if (!s.ok()) |
| 1999 return s; |
| 2000 start_key = |
| 2001 ExistsEntryKey::Encode(database_id, object_store_id, start_cursor->key()); |
| 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 Loading... |
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 Loading... |
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); |
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(); |
| 3881 } |
| 3882 return leveldb::Status::OK(); |
| 3883 } |
| 3884 |
| 3885 bool IndexedDBBackingStore::Transaction::CollectBlobFilesToRemove() { |
| 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() { |
| 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); |
| 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); |
| 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 Loading... |
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 |
OLD | NEW |