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; | |
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 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 = | |
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 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); |
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 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 |