| 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/json/json_reader.h" | 9 #include "base/json/json_reader.h" |
| 10 #include "base/json/json_writer.h" | 10 #include "base/json/json_writer.h" |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 71 VERSION_EXISTS, | 71 VERSION_EXISTS, |
| 72 DELETE_OBJECT_STORE, | 72 DELETE_OBJECT_STORE, |
| 73 SET_MAX_OBJECT_STORE_ID, | 73 SET_MAX_OBJECT_STORE_ID, |
| 74 SET_MAX_INDEX_ID, | 74 SET_MAX_INDEX_ID, |
| 75 GET_NEW_DATABASE_ID, | 75 GET_NEW_DATABASE_ID, |
| 76 GET_NEW_VERSION_NUMBER, | 76 GET_NEW_VERSION_NUMBER, |
| 77 CREATE_IDBDATABASE_METADATA, | 77 CREATE_IDBDATABASE_METADATA, |
| 78 DELETE_DATABASE, | 78 DELETE_DATABASE, |
| 79 TRANSACTION_COMMIT_METHOD, // TRANSACTION_COMMIT is a WinNT.h macro | 79 TRANSACTION_COMMIT_METHOD, // TRANSACTION_COMMIT is a WinNT.h macro |
| 80 GET_DATABASE_NAMES, | 80 GET_DATABASE_NAMES, |
| 81 DELETE_INDEX, |
| 82 CLEAR_OBJECT_STORE, |
| 81 INTERNAL_ERROR_MAX, | 83 INTERNAL_ERROR_MAX, |
| 82 }; | 84 }; |
| 83 | 85 |
| 84 static void RecordInternalError(const char* type, | 86 static void RecordInternalError(const char* type, |
| 85 IndexedDBBackingStoreErrorSource location) { | 87 IndexedDBBackingStoreErrorSource location) { |
| 86 std::string name; | 88 std::string name; |
| 87 name.append("WebCore.IndexedDB.BackingStore.").append(type).append("Error"); | 89 name.append("WebCore.IndexedDB.BackingStore.").append(type).append("Error"); |
| 88 base::Histogram::FactoryGet(name, | 90 base::Histogram::FactoryGet(name, |
| 89 1, | 91 1, |
| 90 INTERNAL_ERROR_MAX, | 92 INTERNAL_ERROR_MAX, |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 316 // Upgrade old backing store. | 318 // Upgrade old backing store. |
| 317 DCHECK_LE(db_schema_version, kLatestKnownSchemaVersion); | 319 DCHECK_LE(db_schema_version, kLatestKnownSchemaVersion); |
| 318 if (db_schema_version < 1) { | 320 if (db_schema_version < 1) { |
| 319 db_schema_version = 1; | 321 db_schema_version = 1; |
| 320 PutInt(transaction.get(), schema_version_key, db_schema_version); | 322 PutInt(transaction.get(), schema_version_key, db_schema_version); |
| 321 const std::string start_key = | 323 const std::string start_key = |
| 322 DatabaseNameKey::EncodeMinKeyForOrigin(origin_identifier); | 324 DatabaseNameKey::EncodeMinKeyForOrigin(origin_identifier); |
| 323 const std::string stop_key = | 325 const std::string stop_key = |
| 324 DatabaseNameKey::EncodeStopKeyForOrigin(origin_identifier); | 326 DatabaseNameKey::EncodeStopKeyForOrigin(origin_identifier); |
| 325 scoped_ptr<LevelDBIterator> it = db->CreateIterator(); | 327 scoped_ptr<LevelDBIterator> it = db->CreateIterator(); |
| 326 for (it->Seek(start_key); | 328 for (s = it->Seek(start_key); |
| 327 it->IsValid() && CompareKeys(it->Key(), stop_key) < 0; | 329 s.ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0; |
| 328 it->Next()) { | 330 s = it->Next()) { |
| 329 int64 database_id = 0; | 331 int64 database_id = 0; |
| 330 found = false; | 332 found = false; |
| 331 s = GetInt(transaction.get(), it->Key(), &database_id, &found); | 333 s = GetInt(transaction.get(), it->Key(), &database_id, &found); |
| 332 if (!s.ok()) { | 334 if (!s.ok()) { |
| 333 INTERNAL_READ_ERROR_UNTESTED(SET_UP_METADATA); | 335 INTERNAL_READ_ERROR_UNTESTED(SET_UP_METADATA); |
| 334 return false; | 336 return false; |
| 335 } | 337 } |
| 336 if (!found) { | 338 if (!found) { |
| 337 INTERNAL_CONSISTENCY_ERROR_UNTESTED(SET_UP_METADATA); | 339 INTERNAL_CONSISTENCY_ERROR_UNTESTED(SET_UP_METADATA); |
| 338 return false; | 340 return false; |
| 339 } | 341 } |
| 340 std::string int_version_key = DatabaseMetaDataKey::Encode( | 342 std::string int_version_key = DatabaseMetaDataKey::Encode( |
| 341 database_id, DatabaseMetaDataKey::USER_INT_VERSION); | 343 database_id, DatabaseMetaDataKey::USER_INT_VERSION); |
| 342 PutVarInt(transaction.get(), | 344 PutVarInt(transaction.get(), |
| 343 int_version_key, | 345 int_version_key, |
| 344 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION); | 346 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION); |
| 345 } | 347 } |
| 346 } | 348 } |
| 347 if (db_schema_version < 2) { | 349 if (s.ok() && db_schema_version < 2) { |
| 348 db_schema_version = 2; | 350 db_schema_version = 2; |
| 349 PutInt(transaction.get(), schema_version_key, db_schema_version); | 351 PutInt(transaction.get(), schema_version_key, db_schema_version); |
| 350 db_data_version = blink::kSerializedScriptValueVersion; | 352 db_data_version = blink::kSerializedScriptValueVersion; |
| 351 PutInt(transaction.get(), data_version_key, db_data_version); | 353 PutInt(transaction.get(), data_version_key, db_data_version); |
| 352 } | 354 } |
| 353 } | 355 } |
| 354 | 356 |
| 357 if (!s.ok()) { |
| 358 INTERNAL_READ_ERROR_UNTESTED(SET_UP_METADATA); |
| 359 return false; |
| 360 } |
| 361 |
| 355 // All new values will be written using this serialization version. | 362 // All new values will be written using this serialization version. |
| 356 found = false; | 363 found = false; |
| 357 s = GetInt(transaction.get(), data_version_key, &db_data_version, &found); | 364 s = GetInt(transaction.get(), data_version_key, &db_data_version, &found); |
| 358 if (!s.ok()) { | 365 if (!s.ok()) { |
| 359 INTERNAL_READ_ERROR_UNTESTED(SET_UP_METADATA); | 366 INTERNAL_READ_ERROR_UNTESTED(SET_UP_METADATA); |
| 360 return false; | 367 return false; |
| 361 } | 368 } |
| 362 if (!found) { | 369 if (!found) { |
| 363 INTERNAL_CONSISTENCY_ERROR_UNTESTED(SET_UP_METADATA); | 370 INTERNAL_CONSISTENCY_ERROR_UNTESTED(SET_UP_METADATA); |
| 364 return false; | 371 return false; |
| (...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 803 db.Pass(), | 810 db.Pass(), |
| 804 comparator.Pass(), | 811 comparator.Pass(), |
| 805 task_runner)); | 812 task_runner)); |
| 806 if (!SetUpMetadata(backing_store->db_.get(), | 813 if (!SetUpMetadata(backing_store->db_.get(), |
| 807 backing_store->origin_identifier_)) | 814 backing_store->origin_identifier_)) |
| 808 return scoped_refptr<IndexedDBBackingStore>(); | 815 return scoped_refptr<IndexedDBBackingStore>(); |
| 809 | 816 |
| 810 return backing_store; | 817 return backing_store; |
| 811 } | 818 } |
| 812 | 819 |
| 813 std::vector<base::string16> IndexedDBBackingStore::GetDatabaseNames() { | 820 std::vector<base::string16> IndexedDBBackingStore::GetDatabaseNames( |
| 821 leveldb::Status* s) { |
| 822 *s = leveldb::Status::OK(); |
| 814 std::vector<base::string16> found_names; | 823 std::vector<base::string16> found_names; |
| 815 const std::string start_key = | 824 const std::string start_key = |
| 816 DatabaseNameKey::EncodeMinKeyForOrigin(origin_identifier_); | 825 DatabaseNameKey::EncodeMinKeyForOrigin(origin_identifier_); |
| 817 const std::string stop_key = | 826 const std::string stop_key = |
| 818 DatabaseNameKey::EncodeStopKeyForOrigin(origin_identifier_); | 827 DatabaseNameKey::EncodeStopKeyForOrigin(origin_identifier_); |
| 819 | 828 |
| 820 DCHECK(found_names.empty()); | 829 DCHECK(found_names.empty()); |
| 821 | 830 |
| 822 scoped_ptr<LevelDBIterator> it = db_->CreateIterator(); | 831 scoped_ptr<LevelDBIterator> it = db_->CreateIterator(); |
| 823 for (it->Seek(start_key); | 832 for (*s = it->Seek(start_key); |
| 824 it->IsValid() && CompareKeys(it->Key(), stop_key) < 0; | 833 s->ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0; |
| 825 it->Next()) { | 834 *s = it->Next()) { |
| 826 StringPiece slice(it->Key()); | 835 StringPiece slice(it->Key()); |
| 827 DatabaseNameKey database_name_key; | 836 DatabaseNameKey database_name_key; |
| 828 if (!DatabaseNameKey::Decode(&slice, &database_name_key)) { | 837 if (!DatabaseNameKey::Decode(&slice, &database_name_key)) { |
| 829 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_DATABASE_NAMES); | 838 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_DATABASE_NAMES); |
| 830 continue; | 839 continue; |
| 831 } | 840 } |
| 832 found_names.push_back(database_name_key.database_name()); | 841 found_names.push_back(database_name_key.database_name()); |
| 833 } | 842 } |
| 843 |
| 844 if (!s->ok()) |
| 845 INTERNAL_READ_ERROR_UNTESTED(GET_DATABASE_NAMES); |
| 846 |
| 834 return found_names; | 847 return found_names; |
| 835 } | 848 } |
| 836 | 849 |
| 837 leveldb::Status IndexedDBBackingStore::GetIDBDatabaseMetaData( | 850 leveldb::Status IndexedDBBackingStore::GetIDBDatabaseMetaData( |
| 838 const base::string16& name, | 851 const base::string16& name, |
| 839 IndexedDBDatabaseMetadata* metadata, | 852 IndexedDBDatabaseMetadata* metadata, |
| 840 bool* found) { | 853 bool* found) { |
| 841 const std::string key = DatabaseNameKey::Encode(origin_identifier_, name); | 854 const std::string key = DatabaseNameKey::Encode(origin_identifier_, name); |
| 842 *found = false; | 855 *found = false; |
| 843 | 856 |
| 844 leveldb::Status s = GetInt(db_.get(), key, &metadata->id, found); | 857 leveldb::Status s = GetInt(db_.get(), key, &metadata->id, found); |
| 845 if (!s.ok()) { | 858 if (!s.ok()) { |
| 846 INTERNAL_READ_ERROR_UNTESTED(GET_IDBDATABASE_METADATA); | 859 INTERNAL_READ_ERROR(GET_IDBDATABASE_METADATA); |
| 847 return s; | 860 return s; |
| 848 } | 861 } |
| 849 if (!*found) | 862 if (!*found) |
| 850 return leveldb::Status::OK(); | 863 return leveldb::Status::OK(); |
| 851 | 864 |
| 852 s = GetString(db_.get(), | 865 s = GetString(db_.get(), |
| 853 DatabaseMetaDataKey::Encode(metadata->id, | 866 DatabaseMetaDataKey::Encode(metadata->id, |
| 854 DatabaseMetaDataKey::USER_VERSION), | 867 DatabaseMetaDataKey::USER_VERSION), |
| 855 &metadata->version, | 868 &metadata->version, |
| 856 found); | 869 found); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 952 if (int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION) | 965 if (int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION) |
| 953 int_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION; | 966 int_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION; |
| 954 DCHECK_GE(int_version, 0) << "int_version was " << int_version; | 967 DCHECK_GE(int_version, 0) << "int_version was " << int_version; |
| 955 PutVarInt(transaction->transaction(), | 968 PutVarInt(transaction->transaction(), |
| 956 DatabaseMetaDataKey::Encode(row_id, | 969 DatabaseMetaDataKey::Encode(row_id, |
| 957 DatabaseMetaDataKey::USER_INT_VERSION), | 970 DatabaseMetaDataKey::USER_INT_VERSION), |
| 958 int_version); | 971 int_version); |
| 959 return true; | 972 return true; |
| 960 } | 973 } |
| 961 | 974 |
| 962 static void DeleteRange(LevelDBTransaction* transaction, | 975 static leveldb::Status DeleteRange(LevelDBTransaction* transaction, |
| 963 const std::string& begin, | 976 const std::string& begin, |
| 964 const std::string& end) { | 977 const std::string& end) { |
| 965 scoped_ptr<LevelDBIterator> it = transaction->CreateIterator(); | 978 scoped_ptr<LevelDBIterator> it = transaction->CreateIterator(); |
| 966 for (it->Seek(begin); it->IsValid() && CompareKeys(it->Key(), end) < 0; | 979 leveldb::Status s; |
| 967 it->Next()) | 980 for (s = it->Seek(begin); |
| 981 s.ok() && it->IsValid() && CompareKeys(it->Key(), end) < 0; |
| 982 s = it->Next()) |
| 968 transaction->Remove(it->Key()); | 983 transaction->Remove(it->Key()); |
| 984 return s; |
| 969 } | 985 } |
| 970 | 986 |
| 971 leveldb::Status IndexedDBBackingStore::DeleteDatabase( | 987 leveldb::Status IndexedDBBackingStore::DeleteDatabase( |
| 972 const base::string16& name) { | 988 const base::string16& name) { |
| 973 IDB_TRACE("IndexedDBBackingStore::DeleteDatabase"); | 989 IDB_TRACE("IndexedDBBackingStore::DeleteDatabase"); |
| 974 scoped_ptr<LevelDBDirectTransaction> transaction = | 990 scoped_ptr<LevelDBDirectTransaction> transaction = |
| 975 LevelDBDirectTransaction::Create(db_.get()); | 991 LevelDBDirectTransaction::Create(db_.get()); |
| 976 | 992 |
| 977 IndexedDBDatabaseMetadata metadata; | 993 IndexedDBDatabaseMetadata metadata; |
| 978 bool success = false; | 994 bool success = false; |
| 979 leveldb::Status s = GetIDBDatabaseMetaData(name, &metadata, &success); | 995 leveldb::Status s = GetIDBDatabaseMetaData(name, &metadata, &success); |
| 980 if (!s.ok()) | 996 if (!s.ok()) |
| 981 return s; | 997 return s; |
| 982 if (!success) | 998 if (!success) |
| 983 return leveldb::Status::OK(); | 999 return leveldb::Status::OK(); |
| 984 | 1000 |
| 985 const std::string start_key = DatabaseMetaDataKey::Encode( | 1001 const std::string start_key = DatabaseMetaDataKey::Encode( |
| 986 metadata.id, DatabaseMetaDataKey::ORIGIN_NAME); | 1002 metadata.id, DatabaseMetaDataKey::ORIGIN_NAME); |
| 987 const std::string stop_key = DatabaseMetaDataKey::Encode( | 1003 const std::string stop_key = DatabaseMetaDataKey::Encode( |
| 988 metadata.id + 1, DatabaseMetaDataKey::ORIGIN_NAME); | 1004 metadata.id + 1, DatabaseMetaDataKey::ORIGIN_NAME); |
| 989 scoped_ptr<LevelDBIterator> it = db_->CreateIterator(); | 1005 scoped_ptr<LevelDBIterator> it = db_->CreateIterator(); |
| 990 for (it->Seek(start_key); | 1006 for (s = it->Seek(start_key); |
| 991 it->IsValid() && CompareKeys(it->Key(), stop_key) < 0; | 1007 s.ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0; |
| 992 it->Next()) | 1008 s = it->Next()) |
| 993 transaction->Remove(it->Key()); | 1009 transaction->Remove(it->Key()); |
| 1010 if (!s.ok()) { |
| 1011 INTERNAL_WRITE_ERROR_UNTESTED(DELETE_DATABASE); |
| 1012 return s; |
| 1013 } |
| 994 | 1014 |
| 995 const std::string key = DatabaseNameKey::Encode(origin_identifier_, name); | 1015 const std::string key = DatabaseNameKey::Encode(origin_identifier_, name); |
| 996 transaction->Remove(key); | 1016 transaction->Remove(key); |
| 997 | 1017 |
| 998 s = transaction->Commit(); | 1018 s = transaction->Commit(); |
| 999 if (!s.ok()) { | 1019 if (!s.ok()) { |
| 1000 INTERNAL_WRITE_ERROR_UNTESTED(DELETE_DATABASE); | 1020 INTERNAL_WRITE_ERROR_UNTESTED(DELETE_DATABASE); |
| 1001 return s; | 1021 return s; |
| 1002 } | 1022 } |
| 1003 db_->Compact(start_key, stop_key); | 1023 db_->Compact(start_key, stop_key); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1031 if (!KeyPrefix::IsValidDatabaseId(database_id)) | 1051 if (!KeyPrefix::IsValidDatabaseId(database_id)) |
| 1032 return InvalidDBKeyStatus(); | 1052 return InvalidDBKeyStatus(); |
| 1033 const std::string start_key = | 1053 const std::string start_key = |
| 1034 ObjectStoreMetaDataKey::Encode(database_id, 1, 0); | 1054 ObjectStoreMetaDataKey::Encode(database_id, 1, 0); |
| 1035 const std::string stop_key = | 1055 const std::string stop_key = |
| 1036 ObjectStoreMetaDataKey::EncodeMaxKey(database_id); | 1056 ObjectStoreMetaDataKey::EncodeMaxKey(database_id); |
| 1037 | 1057 |
| 1038 DCHECK(object_stores->empty()); | 1058 DCHECK(object_stores->empty()); |
| 1039 | 1059 |
| 1040 scoped_ptr<LevelDBIterator> it = db_->CreateIterator(); | 1060 scoped_ptr<LevelDBIterator> it = db_->CreateIterator(); |
| 1041 it->Seek(start_key); | 1061 leveldb::Status s = it->Seek(start_key); |
| 1042 while (it->IsValid() && CompareKeys(it->Key(), stop_key) < 0) { | 1062 while (s.ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0) { |
| 1043 StringPiece slice(it->Key()); | 1063 StringPiece slice(it->Key()); |
| 1044 ObjectStoreMetaDataKey meta_data_key; | 1064 ObjectStoreMetaDataKey meta_data_key; |
| 1045 bool ok = ObjectStoreMetaDataKey::Decode(&slice, &meta_data_key); | 1065 bool ok = ObjectStoreMetaDataKey::Decode(&slice, &meta_data_key); |
| 1046 DCHECK(ok); | 1066 DCHECK(ok); |
| 1047 if (meta_data_key.MetaDataType() != ObjectStoreMetaDataKey::NAME) { | 1067 if (meta_data_key.MetaDataType() != ObjectStoreMetaDataKey::NAME) { |
| 1048 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); | 1068 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); |
| 1049 // Possible stale metadata, but don't fail the load. | 1069 // Possible stale metadata, but don't fail the load. |
| 1050 it->Next(); | 1070 s = it->Next(); |
| 1071 if (!s.ok()) |
| 1072 break; |
| 1051 continue; | 1073 continue; |
| 1052 } | 1074 } |
| 1053 | 1075 |
| 1054 int64 object_store_id = meta_data_key.ObjectStoreId(); | 1076 int64 object_store_id = meta_data_key.ObjectStoreId(); |
| 1055 | 1077 |
| 1056 // TODO(jsbell): Do this by direct key lookup rather than iteration, to | 1078 // TODO(jsbell): Do this by direct key lookup rather than iteration, to |
| 1057 // simplify. | 1079 // simplify. |
| 1058 base::string16 object_store_name; | 1080 base::string16 object_store_name; |
| 1059 { | 1081 { |
| 1060 StringPiece slice(it->Value()); | 1082 StringPiece slice(it->Value()); |
| 1061 if (!DecodeString(&slice, &object_store_name) || !slice.empty()) | 1083 if (!DecodeString(&slice, &object_store_name) || !slice.empty()) |
| 1062 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); | 1084 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); |
| 1063 } | 1085 } |
| 1064 | 1086 |
| 1065 it->Next(); | 1087 s = it->Next(); |
| 1088 if (!s.ok()) |
| 1089 break; |
| 1066 if (!CheckObjectStoreAndMetaDataType(it.get(), | 1090 if (!CheckObjectStoreAndMetaDataType(it.get(), |
| 1067 stop_key, | 1091 stop_key, |
| 1068 object_store_id, | 1092 object_store_id, |
| 1069 ObjectStoreMetaDataKey::KEY_PATH)) { | 1093 ObjectStoreMetaDataKey::KEY_PATH)) { |
| 1070 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); | 1094 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); |
| 1071 break; | 1095 break; |
| 1072 } | 1096 } |
| 1073 IndexedDBKeyPath key_path; | 1097 IndexedDBKeyPath key_path; |
| 1074 { | 1098 { |
| 1075 StringPiece slice(it->Value()); | 1099 StringPiece slice(it->Value()); |
| 1076 if (!DecodeIDBKeyPath(&slice, &key_path) || !slice.empty()) | 1100 if (!DecodeIDBKeyPath(&slice, &key_path) || !slice.empty()) |
| 1077 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); | 1101 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); |
| 1078 } | 1102 } |
| 1079 | 1103 |
| 1080 it->Next(); | 1104 s = it->Next(); |
| 1105 if (!s.ok()) |
| 1106 break; |
| 1081 if (!CheckObjectStoreAndMetaDataType( | 1107 if (!CheckObjectStoreAndMetaDataType( |
| 1082 it.get(), | 1108 it.get(), |
| 1083 stop_key, | 1109 stop_key, |
| 1084 object_store_id, | 1110 object_store_id, |
| 1085 ObjectStoreMetaDataKey::AUTO_INCREMENT)) { | 1111 ObjectStoreMetaDataKey::AUTO_INCREMENT)) { |
| 1086 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); | 1112 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); |
| 1087 break; | 1113 break; |
| 1088 } | 1114 } |
| 1089 bool auto_increment; | 1115 bool auto_increment; |
| 1090 { | 1116 { |
| 1091 StringPiece slice(it->Value()); | 1117 StringPiece slice(it->Value()); |
| 1092 if (!DecodeBool(&slice, &auto_increment) || !slice.empty()) | 1118 if (!DecodeBool(&slice, &auto_increment) || !slice.empty()) |
| 1093 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); | 1119 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); |
| 1094 } | 1120 } |
| 1095 | 1121 |
| 1096 it->Next(); // Is evicatble. | 1122 s = it->Next(); // Is evicatble. |
| 1123 if (!s.ok()) |
| 1124 break; |
| 1097 if (!CheckObjectStoreAndMetaDataType(it.get(), | 1125 if (!CheckObjectStoreAndMetaDataType(it.get(), |
| 1098 stop_key, | 1126 stop_key, |
| 1099 object_store_id, | 1127 object_store_id, |
| 1100 ObjectStoreMetaDataKey::EVICTABLE)) { | 1128 ObjectStoreMetaDataKey::EVICTABLE)) { |
| 1101 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); | 1129 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); |
| 1102 break; | 1130 break; |
| 1103 } | 1131 } |
| 1104 | 1132 |
| 1105 it->Next(); // Last version. | 1133 s = it->Next(); // Last version. |
| 1134 if (!s.ok()) |
| 1135 break; |
| 1106 if (!CheckObjectStoreAndMetaDataType( | 1136 if (!CheckObjectStoreAndMetaDataType( |
| 1107 it.get(), | 1137 it.get(), |
| 1108 stop_key, | 1138 stop_key, |
| 1109 object_store_id, | 1139 object_store_id, |
| 1110 ObjectStoreMetaDataKey::LAST_VERSION)) { | 1140 ObjectStoreMetaDataKey::LAST_VERSION)) { |
| 1111 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); | 1141 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); |
| 1112 break; | 1142 break; |
| 1113 } | 1143 } |
| 1114 | 1144 |
| 1115 it->Next(); // Maximum index id allocated. | 1145 s = it->Next(); // Maximum index id allocated. |
| 1146 if (!s.ok()) |
| 1147 break; |
| 1116 if (!CheckObjectStoreAndMetaDataType( | 1148 if (!CheckObjectStoreAndMetaDataType( |
| 1117 it.get(), | 1149 it.get(), |
| 1118 stop_key, | 1150 stop_key, |
| 1119 object_store_id, | 1151 object_store_id, |
| 1120 ObjectStoreMetaDataKey::MAX_INDEX_ID)) { | 1152 ObjectStoreMetaDataKey::MAX_INDEX_ID)) { |
| 1121 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); | 1153 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); |
| 1122 break; | 1154 break; |
| 1123 } | 1155 } |
| 1124 int64 max_index_id; | 1156 int64 max_index_id; |
| 1125 { | 1157 { |
| 1126 StringPiece slice(it->Value()); | 1158 StringPiece slice(it->Value()); |
| 1127 if (!DecodeInt(&slice, &max_index_id) || !slice.empty()) | 1159 if (!DecodeInt(&slice, &max_index_id) || !slice.empty()) |
| 1128 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); | 1160 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); |
| 1129 } | 1161 } |
| 1130 | 1162 |
| 1131 it->Next(); // [optional] has key path (is not null) | 1163 s = it->Next(); // [optional] has key path (is not null) |
| 1164 if (!s.ok()) |
| 1165 break; |
| 1132 if (CheckObjectStoreAndMetaDataType(it.get(), | 1166 if (CheckObjectStoreAndMetaDataType(it.get(), |
| 1133 stop_key, | 1167 stop_key, |
| 1134 object_store_id, | 1168 object_store_id, |
| 1135 ObjectStoreMetaDataKey::HAS_KEY_PATH)) { | 1169 ObjectStoreMetaDataKey::HAS_KEY_PATH)) { |
| 1136 bool has_key_path; | 1170 bool has_key_path; |
| 1137 { | 1171 { |
| 1138 StringPiece slice(it->Value()); | 1172 StringPiece slice(it->Value()); |
| 1139 if (!DecodeBool(&slice, &has_key_path)) | 1173 if (!DecodeBool(&slice, &has_key_path)) |
| 1140 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); | 1174 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); |
| 1141 } | 1175 } |
| 1142 // This check accounts for two layers of legacy coding: | 1176 // This check accounts for two layers of legacy coding: |
| 1143 // (1) Initially, has_key_path was added to distinguish null vs. string. | 1177 // (1) Initially, has_key_path was added to distinguish null vs. string. |
| 1144 // (2) Later, null vs. string vs. array was stored in the key_path itself. | 1178 // (2) Later, null vs. string vs. array was stored in the key_path itself. |
| 1145 // So this check is only relevant for string-type key_paths. | 1179 // So this check is only relevant for string-type key_paths. |
| 1146 if (!has_key_path && | 1180 if (!has_key_path && |
| 1147 (key_path.type() == blink::WebIDBKeyPathTypeString && | 1181 (key_path.type() == blink::WebIDBKeyPathTypeString && |
| 1148 !key_path.string().empty())) { | 1182 !key_path.string().empty())) { |
| 1149 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); | 1183 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); |
| 1150 break; | 1184 break; |
| 1151 } | 1185 } |
| 1152 if (!has_key_path) | 1186 if (!has_key_path) |
| 1153 key_path = IndexedDBKeyPath(); | 1187 key_path = IndexedDBKeyPath(); |
| 1154 it->Next(); | 1188 s = it->Next(); |
| 1189 if (!s.ok()) |
| 1190 break; |
| 1155 } | 1191 } |
| 1156 | 1192 |
| 1157 int64 key_generator_current_number = -1; | 1193 int64 key_generator_current_number = -1; |
| 1158 if (CheckObjectStoreAndMetaDataType( | 1194 if (CheckObjectStoreAndMetaDataType( |
| 1159 it.get(), | 1195 it.get(), |
| 1160 stop_key, | 1196 stop_key, |
| 1161 object_store_id, | 1197 object_store_id, |
| 1162 ObjectStoreMetaDataKey::KEY_GENERATOR_CURRENT_NUMBER)) { | 1198 ObjectStoreMetaDataKey::KEY_GENERATOR_CURRENT_NUMBER)) { |
| 1163 StringPiece slice(it->Value()); | 1199 StringPiece slice(it->Value()); |
| 1164 if (!DecodeInt(&slice, &key_generator_current_number) || !slice.empty()) | 1200 if (!DecodeInt(&slice, &key_generator_current_number) || !slice.empty()) |
| 1165 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); | 1201 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); |
| 1166 | 1202 |
| 1167 // TODO(jsbell): Return key_generator_current_number, cache in | 1203 // TODO(jsbell): Return key_generator_current_number, cache in |
| 1168 // object store, and write lazily to backing store. For now, | 1204 // object store, and write lazily to backing store. For now, |
| 1169 // just assert that if it was written it was valid. | 1205 // just assert that if it was written it was valid. |
| 1170 DCHECK_GE(key_generator_current_number, kKeyGeneratorInitialNumber); | 1206 DCHECK_GE(key_generator_current_number, kKeyGeneratorInitialNumber); |
| 1171 it->Next(); | 1207 s = it->Next(); |
| 1208 if (!s.ok()) |
| 1209 break; |
| 1172 } | 1210 } |
| 1173 | 1211 |
| 1174 IndexedDBObjectStoreMetadata metadata(object_store_name, | 1212 IndexedDBObjectStoreMetadata metadata(object_store_name, |
| 1175 object_store_id, | 1213 object_store_id, |
| 1176 key_path, | 1214 key_path, |
| 1177 auto_increment, | 1215 auto_increment, |
| 1178 max_index_id); | 1216 max_index_id); |
| 1179 leveldb::Status s = | 1217 s = GetIndexes(database_id, object_store_id, &metadata.indexes); |
| 1180 GetIndexes(database_id, object_store_id, &metadata.indexes); | |
| 1181 if (!s.ok()) | 1218 if (!s.ok()) |
| 1182 return s; | 1219 break; |
| 1183 (*object_stores)[object_store_id] = metadata; | 1220 (*object_stores)[object_store_id] = metadata; |
| 1184 } | 1221 } |
| 1185 return leveldb::Status::OK(); | 1222 |
| 1223 if (!s.ok()) |
| 1224 INTERNAL_READ_ERROR_UNTESTED(GET_OBJECT_STORES); |
| 1225 |
| 1226 return s; |
| 1186 } | 1227 } |
| 1187 | 1228 |
| 1188 WARN_UNUSED_RESULT static leveldb::Status SetMaxObjectStoreId( | 1229 WARN_UNUSED_RESULT static leveldb::Status SetMaxObjectStoreId( |
| 1189 LevelDBTransaction* transaction, | 1230 LevelDBTransaction* transaction, |
| 1190 int64 database_id, | 1231 int64 database_id, |
| 1191 int64 object_store_id) { | 1232 int64 object_store_id) { |
| 1192 const std::string max_object_store_id_key = DatabaseMetaDataKey::Encode( | 1233 const std::string max_object_store_id_key = DatabaseMetaDataKey::Encode( |
| 1193 database_id, DatabaseMetaDataKey::MAX_OBJECT_STORE_ID); | 1234 database_id, DatabaseMetaDataKey::MAX_OBJECT_STORE_ID); |
| 1194 int64 max_object_store_id = -1; | 1235 int64 max_object_store_id = -1; |
| 1195 leveldb::Status s = GetMaxObjectStoreId( | 1236 leveldb::Status s = GetMaxObjectStoreId( |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1279 &found); | 1320 &found); |
| 1280 if (!s.ok()) { | 1321 if (!s.ok()) { |
| 1281 INTERNAL_READ_ERROR_UNTESTED(DELETE_OBJECT_STORE); | 1322 INTERNAL_READ_ERROR_UNTESTED(DELETE_OBJECT_STORE); |
| 1282 return s; | 1323 return s; |
| 1283 } | 1324 } |
| 1284 if (!found) { | 1325 if (!found) { |
| 1285 INTERNAL_CONSISTENCY_ERROR_UNTESTED(DELETE_OBJECT_STORE); | 1326 INTERNAL_CONSISTENCY_ERROR_UNTESTED(DELETE_OBJECT_STORE); |
| 1286 return InternalInconsistencyStatus(); | 1327 return InternalInconsistencyStatus(); |
| 1287 } | 1328 } |
| 1288 | 1329 |
| 1289 DeleteRange( | 1330 s = DeleteRange( |
| 1290 leveldb_transaction, | 1331 leveldb_transaction, |
| 1291 ObjectStoreMetaDataKey::Encode(database_id, object_store_id, 0), | 1332 ObjectStoreMetaDataKey::Encode(database_id, object_store_id, 0), |
| 1292 ObjectStoreMetaDataKey::EncodeMaxKey(database_id, object_store_id)); | 1333 ObjectStoreMetaDataKey::EncodeMaxKey(database_id, object_store_id)); |
| 1293 | 1334 |
| 1294 leveldb_transaction->Remove( | 1335 if (s.ok()) { |
| 1295 ObjectStoreNamesKey::Encode(database_id, object_store_name)); | 1336 leveldb_transaction->Remove( |
| 1337 ObjectStoreNamesKey::Encode(database_id, object_store_name)); |
| 1296 | 1338 |
| 1297 DeleteRange(leveldb_transaction, | 1339 s = DeleteRange( |
| 1298 IndexFreeListKey::Encode(database_id, object_store_id, 0), | 1340 leveldb_transaction, |
| 1299 IndexFreeListKey::EncodeMaxKey(database_id, object_store_id)); | 1341 IndexFreeListKey::Encode(database_id, object_store_id, 0), |
| 1300 DeleteRange(leveldb_transaction, | 1342 IndexFreeListKey::EncodeMaxKey(database_id, object_store_id)); |
| 1301 IndexMetaDataKey::Encode(database_id, object_store_id, 0, 0), | 1343 } |
| 1302 IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id)); | 1344 |
| 1345 if (s.ok()) { |
| 1346 s = DeleteRange( |
| 1347 leveldb_transaction, |
| 1348 IndexMetaDataKey::Encode(database_id, object_store_id, 0, 0), |
| 1349 IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id)); |
| 1350 } |
| 1351 |
| 1352 if (!s.ok()) { |
| 1353 INTERNAL_WRITE_ERROR_UNTESTED(DELETE_OBJECT_STORE); |
| 1354 return s; |
| 1355 } |
| 1303 | 1356 |
| 1304 return ClearObjectStore(transaction, database_id, object_store_id); | 1357 return ClearObjectStore(transaction, database_id, object_store_id); |
| 1305 } | 1358 } |
| 1306 | 1359 |
| 1307 leveldb::Status IndexedDBBackingStore::GetRecord( | 1360 leveldb::Status IndexedDBBackingStore::GetRecord( |
| 1308 IndexedDBBackingStore::Transaction* transaction, | 1361 IndexedDBBackingStore::Transaction* transaction, |
| 1309 int64 database_id, | 1362 int64 database_id, |
| 1310 int64 object_store_id, | 1363 int64 object_store_id, |
| 1311 const IndexedDBKey& key, | 1364 const IndexedDBKey& key, |
| 1312 IndexedDBValue* record) { | 1365 IndexedDBValue* record) { |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1422 int64 database_id, | 1475 int64 database_id, |
| 1423 int64 object_store_id) { | 1476 int64 object_store_id) { |
| 1424 IDB_TRACE("IndexedDBBackingStore::ClearObjectStore"); | 1477 IDB_TRACE("IndexedDBBackingStore::ClearObjectStore"); |
| 1425 if (!KeyPrefix::ValidIds(database_id, object_store_id)) | 1478 if (!KeyPrefix::ValidIds(database_id, object_store_id)) |
| 1426 return InvalidDBKeyStatus(); | 1479 return InvalidDBKeyStatus(); |
| 1427 const std::string start_key = | 1480 const std::string start_key = |
| 1428 KeyPrefix(database_id, object_store_id).Encode(); | 1481 KeyPrefix(database_id, object_store_id).Encode(); |
| 1429 const std::string stop_key = | 1482 const std::string stop_key = |
| 1430 KeyPrefix(database_id, object_store_id + 1).Encode(); | 1483 KeyPrefix(database_id, object_store_id + 1).Encode(); |
| 1431 | 1484 |
| 1432 DeleteRange(transaction->transaction(), start_key, stop_key); | 1485 leveldb::Status s = |
| 1433 return leveldb::Status::OK(); | 1486 DeleteRange(transaction->transaction(), start_key, stop_key); |
| 1487 if (!s.ok()) |
| 1488 INTERNAL_WRITE_ERROR_UNTESTED(CLEAR_OBJECT_STORE); |
| 1489 return s; |
| 1434 } | 1490 } |
| 1435 | 1491 |
| 1436 leveldb::Status IndexedDBBackingStore::DeleteRecord( | 1492 leveldb::Status IndexedDBBackingStore::DeleteRecord( |
| 1437 IndexedDBBackingStore::Transaction* transaction, | 1493 IndexedDBBackingStore::Transaction* transaction, |
| 1438 int64 database_id, | 1494 int64 database_id, |
| 1439 int64 object_store_id, | 1495 int64 object_store_id, |
| 1440 const RecordIdentifier& record_identifier) { | 1496 const RecordIdentifier& record_identifier) { |
| 1441 IDB_TRACE("IndexedDBBackingStore::DeleteRecord"); | 1497 IDB_TRACE("IndexedDBBackingStore::DeleteRecord"); |
| 1442 if (!KeyPrefix::ValidIds(database_id, object_store_id)) | 1498 if (!KeyPrefix::ValidIds(database_id, object_store_id)) |
| 1443 return InvalidDBKeyStatus(); | 1499 return InvalidDBKeyStatus(); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1493 // key generator state must be preserved. | 1549 // key generator state must be preserved. |
| 1494 // TODO(jsbell): Fix this for all stores on database open? | 1550 // TODO(jsbell): Fix this for all stores on database open? |
| 1495 const std::string start_key = | 1551 const std::string start_key = |
| 1496 ObjectStoreDataKey::Encode(database_id, object_store_id, MinIDBKey()); | 1552 ObjectStoreDataKey::Encode(database_id, object_store_id, MinIDBKey()); |
| 1497 const std::string stop_key = | 1553 const std::string stop_key = |
| 1498 ObjectStoreDataKey::Encode(database_id, object_store_id, MaxIDBKey()); | 1554 ObjectStoreDataKey::Encode(database_id, object_store_id, MaxIDBKey()); |
| 1499 | 1555 |
| 1500 scoped_ptr<LevelDBIterator> it = leveldb_transaction->CreateIterator(); | 1556 scoped_ptr<LevelDBIterator> it = leveldb_transaction->CreateIterator(); |
| 1501 int64 max_numeric_key = 0; | 1557 int64 max_numeric_key = 0; |
| 1502 | 1558 |
| 1503 for (it->Seek(start_key); | 1559 for (s = it->Seek(start_key); |
| 1504 it->IsValid() && CompareKeys(it->Key(), stop_key) < 0; | 1560 s.ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0; |
| 1505 it->Next()) { | 1561 s = it->Next()) { |
| 1506 StringPiece slice(it->Key()); | 1562 StringPiece slice(it->Key()); |
| 1507 ObjectStoreDataKey data_key; | 1563 ObjectStoreDataKey data_key; |
| 1508 if (!ObjectStoreDataKey::Decode(&slice, &data_key)) { | 1564 if (!ObjectStoreDataKey::Decode(&slice, &data_key)) { |
| 1509 INTERNAL_READ_ERROR_UNTESTED(GET_KEY_GENERATOR_CURRENT_NUMBER); | 1565 INTERNAL_READ_ERROR_UNTESTED(GET_KEY_GENERATOR_CURRENT_NUMBER); |
| 1510 return InternalInconsistencyStatus(); | 1566 return InternalInconsistencyStatus(); |
| 1511 } | 1567 } |
| 1512 scoped_ptr<IndexedDBKey> user_key = data_key.user_key(); | 1568 scoped_ptr<IndexedDBKey> user_key = data_key.user_key(); |
| 1513 if (user_key->type() == blink::WebIDBKeyTypeNumber) { | 1569 if (user_key->type() == blink::WebIDBKeyTypeNumber) { |
| 1514 int64 n = static_cast<int64>(user_key->number()); | 1570 int64 n = static_cast<int64>(user_key->number()); |
| 1515 if (n > max_numeric_key) | 1571 if (n > max_numeric_key) |
| 1516 max_numeric_key = n; | 1572 max_numeric_key = n; |
| 1517 } | 1573 } |
| 1518 } | 1574 } |
| 1519 | 1575 |
| 1520 *key_generator_current_number = max_numeric_key + 1; | 1576 if (s.ok()) |
| 1577 *key_generator_current_number = max_numeric_key + 1; |
| 1578 else |
| 1579 INTERNAL_READ_ERROR_UNTESTED(GET_KEY_GENERATOR_CURRENT_NUMBER); |
| 1580 |
| 1521 return s; | 1581 return s; |
| 1522 } | 1582 } |
| 1523 | 1583 |
| 1524 leveldb::Status IndexedDBBackingStore::MaybeUpdateKeyGeneratorCurrentNumber( | 1584 leveldb::Status IndexedDBBackingStore::MaybeUpdateKeyGeneratorCurrentNumber( |
| 1525 IndexedDBBackingStore::Transaction* transaction, | 1585 IndexedDBBackingStore::Transaction* transaction, |
| 1526 int64 database_id, | 1586 int64 database_id, |
| 1527 int64 object_store_id, | 1587 int64 object_store_id, |
| 1528 int64 new_number, | 1588 int64 new_number, |
| 1529 bool check_current) { | 1589 bool check_current) { |
| 1530 if (!KeyPrefix::ValidIds(database_id, object_store_id)) | 1590 if (!KeyPrefix::ValidIds(database_id, object_store_id)) |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1617 if (!KeyPrefix::ValidIds(database_id, object_store_id)) | 1677 if (!KeyPrefix::ValidIds(database_id, object_store_id)) |
| 1618 return InvalidDBKeyStatus(); | 1678 return InvalidDBKeyStatus(); |
| 1619 const std::string start_key = | 1679 const std::string start_key = |
| 1620 IndexMetaDataKey::Encode(database_id, object_store_id, 0, 0); | 1680 IndexMetaDataKey::Encode(database_id, object_store_id, 0, 0); |
| 1621 const std::string stop_key = | 1681 const std::string stop_key = |
| 1622 IndexMetaDataKey::Encode(database_id, object_store_id + 1, 0, 0); | 1682 IndexMetaDataKey::Encode(database_id, object_store_id + 1, 0, 0); |
| 1623 | 1683 |
| 1624 DCHECK(indexes->empty()); | 1684 DCHECK(indexes->empty()); |
| 1625 | 1685 |
| 1626 scoped_ptr<LevelDBIterator> it = db_->CreateIterator(); | 1686 scoped_ptr<LevelDBIterator> it = db_->CreateIterator(); |
| 1627 it->Seek(start_key); | 1687 leveldb::Status s = it->Seek(start_key); |
| 1628 while (it->IsValid() && CompareKeys(it->Key(), stop_key) < 0) { | 1688 while (s.ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0) { |
| 1629 StringPiece slice(it->Key()); | 1689 StringPiece slice(it->Key()); |
| 1630 IndexMetaDataKey meta_data_key; | 1690 IndexMetaDataKey meta_data_key; |
| 1631 bool ok = IndexMetaDataKey::Decode(&slice, &meta_data_key); | 1691 bool ok = IndexMetaDataKey::Decode(&slice, &meta_data_key); |
| 1632 DCHECK(ok); | 1692 DCHECK(ok); |
| 1633 if (meta_data_key.meta_data_type() != IndexMetaDataKey::NAME) { | 1693 if (meta_data_key.meta_data_type() != IndexMetaDataKey::NAME) { |
| 1634 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES); | 1694 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES); |
| 1635 // Possible stale metadata due to http://webkit.org/b/85557 but don't fail | 1695 // Possible stale metadata due to http://webkit.org/b/85557 but don't fail |
| 1636 // the load. | 1696 // the load. |
| 1637 it->Next(); | 1697 s = it->Next(); |
| 1698 if (!s.ok()) |
| 1699 break; |
| 1638 continue; | 1700 continue; |
| 1639 } | 1701 } |
| 1640 | 1702 |
| 1641 // TODO(jsbell): Do this by direct key lookup rather than iteration, to | 1703 // TODO(jsbell): Do this by direct key lookup rather than iteration, to |
| 1642 // simplify. | 1704 // simplify. |
| 1643 int64 index_id = meta_data_key.IndexId(); | 1705 int64 index_id = meta_data_key.IndexId(); |
| 1644 base::string16 index_name; | 1706 base::string16 index_name; |
| 1645 { | 1707 { |
| 1646 StringPiece slice(it->Value()); | 1708 StringPiece slice(it->Value()); |
| 1647 if (!DecodeString(&slice, &index_name) || !slice.empty()) | 1709 if (!DecodeString(&slice, &index_name) || !slice.empty()) |
| 1648 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES); | 1710 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES); |
| 1649 } | 1711 } |
| 1650 | 1712 |
| 1651 it->Next(); // unique flag | 1713 s = it->Next(); // unique flag |
| 1714 if (!s.ok()) |
| 1715 break; |
| 1652 if (!CheckIndexAndMetaDataKey( | 1716 if (!CheckIndexAndMetaDataKey( |
| 1653 it.get(), stop_key, index_id, IndexMetaDataKey::UNIQUE)) { | 1717 it.get(), stop_key, index_id, IndexMetaDataKey::UNIQUE)) { |
| 1654 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES); | 1718 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES); |
| 1655 break; | 1719 break; |
| 1656 } | 1720 } |
| 1657 bool index_unique; | 1721 bool index_unique; |
| 1658 { | 1722 { |
| 1659 StringPiece slice(it->Value()); | 1723 StringPiece slice(it->Value()); |
| 1660 if (!DecodeBool(&slice, &index_unique) || !slice.empty()) | 1724 if (!DecodeBool(&slice, &index_unique) || !slice.empty()) |
| 1661 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES); | 1725 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES); |
| 1662 } | 1726 } |
| 1663 | 1727 |
| 1664 it->Next(); // key_path | 1728 s = it->Next(); // key_path |
| 1729 if (!s.ok()) |
| 1730 break; |
| 1665 if (!CheckIndexAndMetaDataKey( | 1731 if (!CheckIndexAndMetaDataKey( |
| 1666 it.get(), stop_key, index_id, IndexMetaDataKey::KEY_PATH)) { | 1732 it.get(), stop_key, index_id, IndexMetaDataKey::KEY_PATH)) { |
| 1667 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES); | 1733 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES); |
| 1668 break; | 1734 break; |
| 1669 } | 1735 } |
| 1670 IndexedDBKeyPath key_path; | 1736 IndexedDBKeyPath key_path; |
| 1671 { | 1737 { |
| 1672 StringPiece slice(it->Value()); | 1738 StringPiece slice(it->Value()); |
| 1673 if (!DecodeIDBKeyPath(&slice, &key_path) || !slice.empty()) | 1739 if (!DecodeIDBKeyPath(&slice, &key_path) || !slice.empty()) |
| 1674 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES); | 1740 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES); |
| 1675 } | 1741 } |
| 1676 | 1742 |
| 1677 it->Next(); // [optional] multi_entry flag | 1743 s = it->Next(); // [optional] multi_entry flag |
| 1744 if (!s.ok()) |
| 1745 break; |
| 1678 bool index_multi_entry = false; | 1746 bool index_multi_entry = false; |
| 1679 if (CheckIndexAndMetaDataKey( | 1747 if (CheckIndexAndMetaDataKey( |
| 1680 it.get(), stop_key, index_id, IndexMetaDataKey::MULTI_ENTRY)) { | 1748 it.get(), stop_key, index_id, IndexMetaDataKey::MULTI_ENTRY)) { |
| 1681 StringPiece slice(it->Value()); | 1749 StringPiece slice(it->Value()); |
| 1682 if (!DecodeBool(&slice, &index_multi_entry) || !slice.empty()) | 1750 if (!DecodeBool(&slice, &index_multi_entry) || !slice.empty()) |
| 1683 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES); | 1751 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES); |
| 1684 | 1752 |
| 1685 it->Next(); | 1753 s = it->Next(); |
| 1754 if (!s.ok()) |
| 1755 break; |
| 1686 } | 1756 } |
| 1687 | 1757 |
| 1688 (*indexes)[index_id] = IndexedDBIndexMetadata( | 1758 (*indexes)[index_id] = IndexedDBIndexMetadata( |
| 1689 index_name, index_id, key_path, index_unique, index_multi_entry); | 1759 index_name, index_id, key_path, index_unique, index_multi_entry); |
| 1690 } | 1760 } |
| 1691 return leveldb::Status::OK(); | 1761 |
| 1762 if (!s.ok()) |
| 1763 INTERNAL_READ_ERROR_UNTESTED(GET_INDEXES); |
| 1764 |
| 1765 return s; |
| 1692 } | 1766 } |
| 1693 | 1767 |
| 1694 WARN_UNUSED_RESULT static leveldb::Status SetMaxIndexId( | 1768 WARN_UNUSED_RESULT static leveldb::Status SetMaxIndexId( |
| 1695 LevelDBTransaction* transaction, | 1769 LevelDBTransaction* transaction, |
| 1696 int64 database_id, | 1770 int64 database_id, |
| 1697 int64 object_store_id, | 1771 int64 object_store_id, |
| 1698 int64 index_id) { | 1772 int64 index_id) { |
| 1699 int64 max_index_id = -1; | 1773 int64 max_index_id = -1; |
| 1700 const std::string max_index_id_key = ObjectStoreMetaDataKey::Encode( | 1774 const std::string max_index_id_key = ObjectStoreMetaDataKey::Encode( |
| 1701 database_id, object_store_id, ObjectStoreMetaDataKey::MAX_INDEX_ID); | 1775 database_id, object_store_id, ObjectStoreMetaDataKey::MAX_INDEX_ID); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1760 int64 index_id) { | 1834 int64 index_id) { |
| 1761 IDB_TRACE("IndexedDBBackingStore::DeleteIndex"); | 1835 IDB_TRACE("IndexedDBBackingStore::DeleteIndex"); |
| 1762 if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id)) | 1836 if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id)) |
| 1763 return InvalidDBKeyStatus(); | 1837 return InvalidDBKeyStatus(); |
| 1764 LevelDBTransaction* leveldb_transaction = transaction->transaction(); | 1838 LevelDBTransaction* leveldb_transaction = transaction->transaction(); |
| 1765 | 1839 |
| 1766 const std::string index_meta_data_start = | 1840 const std::string index_meta_data_start = |
| 1767 IndexMetaDataKey::Encode(database_id, object_store_id, index_id, 0); | 1841 IndexMetaDataKey::Encode(database_id, object_store_id, index_id, 0); |
| 1768 const std::string index_meta_data_end = | 1842 const std::string index_meta_data_end = |
| 1769 IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id, index_id); | 1843 IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id, index_id); |
| 1770 DeleteRange(leveldb_transaction, index_meta_data_start, index_meta_data_end); | 1844 leveldb::Status s = DeleteRange( |
| 1845 leveldb_transaction, index_meta_data_start, index_meta_data_end); |
| 1771 | 1846 |
| 1772 const std::string index_data_start = | 1847 if (s.ok()) { |
| 1773 IndexDataKey::EncodeMinKey(database_id, object_store_id, index_id); | 1848 const std::string index_data_start = |
| 1774 const std::string index_data_end = | 1849 IndexDataKey::EncodeMinKey(database_id, object_store_id, index_id); |
| 1775 IndexDataKey::EncodeMaxKey(database_id, object_store_id, index_id); | 1850 const std::string index_data_end = |
| 1776 DeleteRange(leveldb_transaction, index_data_start, index_data_end); | 1851 IndexDataKey::EncodeMaxKey(database_id, object_store_id, index_id); |
| 1777 return leveldb::Status::OK(); | 1852 s = DeleteRange(leveldb_transaction, index_data_start, index_data_end); |
| 1853 } |
| 1854 |
| 1855 if (!s.ok()) |
| 1856 INTERNAL_WRITE_ERROR_UNTESTED(DELETE_INDEX); |
| 1857 |
| 1858 return s; |
| 1778 } | 1859 } |
| 1779 | 1860 |
| 1780 leveldb::Status IndexedDBBackingStore::PutIndexDataForRecord( | 1861 leveldb::Status IndexedDBBackingStore::PutIndexDataForRecord( |
| 1781 IndexedDBBackingStore::Transaction* transaction, | 1862 IndexedDBBackingStore::Transaction* transaction, |
| 1782 int64 database_id, | 1863 int64 database_id, |
| 1783 int64 object_store_id, | 1864 int64 object_store_id, |
| 1784 int64 index_id, | 1865 int64 index_id, |
| 1785 const IndexedDBKey& key, | 1866 const IndexedDBKey& key, |
| 1786 const RecordIdentifier& record_identifier) { | 1867 const RecordIdentifier& record_identifier) { |
| 1787 IDB_TRACE("IndexedDBBackingStore::PutIndexDataForRecord"); | 1868 IDB_TRACE("IndexedDBBackingStore::PutIndexDataForRecord"); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1803 std::string data; | 1884 std::string data; |
| 1804 EncodeVarInt(record_identifier.version(), &data); | 1885 EncodeVarInt(record_identifier.version(), &data); |
| 1805 data.append(record_identifier.primary_key()); | 1886 data.append(record_identifier.primary_key()); |
| 1806 | 1887 |
| 1807 transaction->transaction()->Put(index_data_key, &data); | 1888 transaction->transaction()->Put(index_data_key, &data); |
| 1808 return leveldb::Status::OK(); | 1889 return leveldb::Status::OK(); |
| 1809 } | 1890 } |
| 1810 | 1891 |
| 1811 static bool FindGreatestKeyLessThanOrEqual(LevelDBTransaction* transaction, | 1892 static bool FindGreatestKeyLessThanOrEqual(LevelDBTransaction* transaction, |
| 1812 const std::string& target, | 1893 const std::string& target, |
| 1813 std::string* found_key) { | 1894 std::string* found_key, |
| 1895 leveldb::Status& s) { |
| 1814 scoped_ptr<LevelDBIterator> it = transaction->CreateIterator(); | 1896 scoped_ptr<LevelDBIterator> it = transaction->CreateIterator(); |
| 1815 it->Seek(target); | 1897 s = it->Seek(target); |
| 1898 if (!s.ok()) |
| 1899 return false; |
| 1816 | 1900 |
| 1817 if (!it->IsValid()) { | 1901 if (!it->IsValid()) { |
| 1818 it->SeekToLast(); | 1902 s = it->SeekToLast(); |
| 1819 if (!it->IsValid()) | 1903 if (!s.ok() || !it->IsValid()) |
| 1820 return false; | 1904 return false; |
| 1821 } | 1905 } |
| 1822 | 1906 |
| 1823 while (CompareIndexKeys(it->Key(), target) > 0) { | 1907 while (CompareIndexKeys(it->Key(), target) > 0) { |
| 1824 it->Prev(); | 1908 s = it->Prev(); |
| 1825 if (!it->IsValid()) | 1909 if (!s.ok() || !it->IsValid()) |
| 1826 return false; | 1910 return false; |
| 1827 } | 1911 } |
| 1828 | 1912 |
| 1829 do { | 1913 do { |
| 1830 *found_key = it->Key().as_string(); | 1914 *found_key = it->Key().as_string(); |
| 1831 | 1915 |
| 1832 // There can be several index keys that compare equal. We want the last one. | 1916 // There can be several index keys that compare equal. We want the last one. |
| 1833 it->Next(); | 1917 s = it->Next(); |
| 1834 } while (it->IsValid() && !CompareIndexKeys(it->Key(), target)); | 1918 } while (s.ok() && it->IsValid() && !CompareIndexKeys(it->Key(), target)); |
| 1835 | 1919 |
| 1836 return true; | 1920 return true; |
| 1837 } | 1921 } |
| 1838 | 1922 |
| 1839 static leveldb::Status VersionExists(LevelDBTransaction* transaction, | 1923 static leveldb::Status VersionExists(LevelDBTransaction* transaction, |
| 1840 int64 database_id, | 1924 int64 database_id, |
| 1841 int64 object_store_id, | 1925 int64 object_store_id, |
| 1842 int64 version, | 1926 int64 version, |
| 1843 const std::string& encoded_primary_key, | 1927 const std::string& encoded_primary_key, |
| 1844 bool* exists) { | 1928 bool* exists) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1873 IDB_TRACE("IndexedDBBackingStore::FindKeyInIndex"); | 1957 IDB_TRACE("IndexedDBBackingStore::FindKeyInIndex"); |
| 1874 DCHECK(KeyPrefix::ValidIds(database_id, object_store_id, index_id)); | 1958 DCHECK(KeyPrefix::ValidIds(database_id, object_store_id, index_id)); |
| 1875 | 1959 |
| 1876 DCHECK(found_encoded_primary_key->empty()); | 1960 DCHECK(found_encoded_primary_key->empty()); |
| 1877 *found = false; | 1961 *found = false; |
| 1878 | 1962 |
| 1879 LevelDBTransaction* leveldb_transaction = transaction->transaction(); | 1963 LevelDBTransaction* leveldb_transaction = transaction->transaction(); |
| 1880 const std::string leveldb_key = | 1964 const std::string leveldb_key = |
| 1881 IndexDataKey::Encode(database_id, object_store_id, index_id, key); | 1965 IndexDataKey::Encode(database_id, object_store_id, index_id, key); |
| 1882 scoped_ptr<LevelDBIterator> it = leveldb_transaction->CreateIterator(); | 1966 scoped_ptr<LevelDBIterator> it = leveldb_transaction->CreateIterator(); |
| 1883 it->Seek(leveldb_key); | 1967 leveldb::Status s = it->Seek(leveldb_key); |
| 1968 if (!s.ok()) { |
| 1969 INTERNAL_READ_ERROR_UNTESTED(FIND_KEY_IN_INDEX); |
| 1970 return s; |
| 1971 } |
| 1884 | 1972 |
| 1885 for (;;) { | 1973 for (;;) { |
| 1886 if (!it->IsValid()) | 1974 if (!it->IsValid()) |
| 1887 return leveldb::Status::OK(); | 1975 return leveldb::Status::OK(); |
| 1888 if (CompareIndexKeys(it->Key(), leveldb_key) > 0) | 1976 if (CompareIndexKeys(it->Key(), leveldb_key) > 0) |
| 1889 return leveldb::Status::OK(); | 1977 return leveldb::Status::OK(); |
| 1890 | 1978 |
| 1891 StringPiece slice(it->Value()); | 1979 StringPiece slice(it->Value()); |
| 1892 | 1980 |
| 1893 int64 version; | 1981 int64 version; |
| 1894 if (!DecodeVarInt(&slice, &version)) { | 1982 if (!DecodeVarInt(&slice, &version)) { |
| 1895 INTERNAL_READ_ERROR_UNTESTED(FIND_KEY_IN_INDEX); | 1983 INTERNAL_READ_ERROR_UNTESTED(FIND_KEY_IN_INDEX); |
| 1896 return InternalInconsistencyStatus(); | 1984 return InternalInconsistencyStatus(); |
| 1897 } | 1985 } |
| 1898 *found_encoded_primary_key = slice.as_string(); | 1986 *found_encoded_primary_key = slice.as_string(); |
| 1899 | 1987 |
| 1900 bool exists = false; | 1988 bool exists = false; |
| 1901 leveldb::Status s = VersionExists(leveldb_transaction, | 1989 s = VersionExists(leveldb_transaction, |
| 1902 database_id, | 1990 database_id, |
| 1903 object_store_id, | 1991 object_store_id, |
| 1904 version, | 1992 version, |
| 1905 *found_encoded_primary_key, | 1993 *found_encoded_primary_key, |
| 1906 &exists); | 1994 &exists); |
| 1907 if (!s.ok()) | 1995 if (!s.ok()) |
| 1908 return s; | 1996 return s; |
| 1909 if (!exists) { | 1997 if (!exists) { |
| 1910 // Delete stale index data entry and continue. | 1998 // Delete stale index data entry and continue. |
| 1911 leveldb_transaction->Remove(it->Key()); | 1999 leveldb_transaction->Remove(it->Key()); |
| 1912 it->Next(); | 2000 s = it->Next(); |
| 1913 continue; | 2001 continue; |
| 1914 } | 2002 } |
| 1915 *found = true; | 2003 *found = true; |
| 1916 return s; | 2004 return s; |
| 1917 } | 2005 } |
| 1918 } | 2006 } |
| 1919 | 2007 |
| 1920 leveldb::Status IndexedDBBackingStore::GetPrimaryKeyViaIndex( | 2008 leveldb::Status IndexedDBBackingStore::GetPrimaryKeyViaIndex( |
| 1921 IndexedDBBackingStore::Transaction* transaction, | 2009 IndexedDBBackingStore::Transaction* transaction, |
| 1922 int64 database_id, | 2010 int64 database_id, |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2001 | 2089 |
| 2002 IndexedDBBackingStore::Cursor::Cursor( | 2090 IndexedDBBackingStore::Cursor::Cursor( |
| 2003 const IndexedDBBackingStore::Cursor* other) | 2091 const IndexedDBBackingStore::Cursor* other) |
| 2004 : transaction_(other->transaction_), | 2092 : transaction_(other->transaction_), |
| 2005 cursor_options_(other->cursor_options_), | 2093 cursor_options_(other->cursor_options_), |
| 2006 current_key_(new IndexedDBKey(*other->current_key_)) { | 2094 current_key_(new IndexedDBKey(*other->current_key_)) { |
| 2007 if (other->iterator_) { | 2095 if (other->iterator_) { |
| 2008 iterator_ = transaction_->CreateIterator(); | 2096 iterator_ = transaction_->CreateIterator(); |
| 2009 | 2097 |
| 2010 if (other->iterator_->IsValid()) { | 2098 if (other->iterator_->IsValid()) { |
| 2011 iterator_->Seek(other->iterator_->Key()); | 2099 leveldb::Status s = iterator_->Seek(other->iterator_->Key()); |
| 2100 // TODO(cmumford): Handle this error (crbug.com/363397) |
| 2012 DCHECK(iterator_->IsValid()); | 2101 DCHECK(iterator_->IsValid()); |
| 2013 } | 2102 } |
| 2014 } | 2103 } |
| 2015 } | 2104 } |
| 2016 | 2105 |
| 2017 IndexedDBBackingStore::Cursor::Cursor(LevelDBTransaction* transaction, | 2106 IndexedDBBackingStore::Cursor::Cursor(LevelDBTransaction* transaction, |
| 2018 const CursorOptions& cursor_options) | 2107 const CursorOptions& cursor_options) |
| 2019 : transaction_(transaction), cursor_options_(cursor_options) {} | 2108 : transaction_(transaction), cursor_options_(cursor_options) {} |
| 2020 IndexedDBBackingStore::Cursor::~Cursor() {} | 2109 IndexedDBBackingStore::Cursor::~Cursor() {} |
| 2021 | 2110 |
| 2022 bool IndexedDBBackingStore::Cursor::FirstSeek() { | 2111 bool IndexedDBBackingStore::Cursor::FirstSeek(leveldb::Status* s) { |
| 2023 iterator_ = transaction_->CreateIterator(); | 2112 iterator_ = transaction_->CreateIterator(); |
| 2024 if (cursor_options_.forward) | 2113 if (cursor_options_.forward) |
| 2025 iterator_->Seek(cursor_options_.low_key); | 2114 *s = iterator_->Seek(cursor_options_.low_key); |
| 2026 else | 2115 else |
| 2027 iterator_->Seek(cursor_options_.high_key); | 2116 *s = iterator_->Seek(cursor_options_.high_key); |
| 2117 if (!s->ok()) |
| 2118 return false; |
| 2028 | 2119 |
| 2029 return Continue(0, READY); | 2120 return Continue(0, READY, s); |
| 2030 } | 2121 } |
| 2031 | 2122 |
| 2032 bool IndexedDBBackingStore::Cursor::Advance(uint32 count) { | 2123 bool IndexedDBBackingStore::Cursor::Advance(uint32 count, leveldb::Status* s) { |
| 2124 *s = leveldb::Status::OK(); |
| 2033 while (count--) { | 2125 while (count--) { |
| 2034 if (!Continue()) | 2126 if (!Continue(s)) |
| 2035 return false; | 2127 return false; |
| 2036 } | 2128 } |
| 2037 return true; | 2129 return true; |
| 2038 } | 2130 } |
| 2039 | 2131 |
| 2040 bool IndexedDBBackingStore::Cursor::Continue(const IndexedDBKey* key, | 2132 bool IndexedDBBackingStore::Cursor::Continue(const IndexedDBKey* key, |
| 2041 const IndexedDBKey* primary_key, | 2133 const IndexedDBKey* primary_key, |
| 2042 IteratorState next_state) { | 2134 IteratorState next_state, |
| 2135 leveldb::Status* s) { |
| 2043 DCHECK(!key || key->IsValid()); | 2136 DCHECK(!key || key->IsValid()); |
| 2044 DCHECK(!primary_key || primary_key->IsValid()); | 2137 DCHECK(!primary_key || primary_key->IsValid()); |
| 2138 *s = leveldb::Status::OK(); |
| 2045 | 2139 |
| 2046 // TODO(alecflett): avoid a copy here? | 2140 // TODO(alecflett): avoid a copy here? |
| 2047 IndexedDBKey previous_key = current_key_ ? *current_key_ : IndexedDBKey(); | 2141 IndexedDBKey previous_key = current_key_ ? *current_key_ : IndexedDBKey(); |
| 2048 | 2142 |
| 2049 bool first_iteration = true; | 2143 bool first_iteration = true; |
| 2050 | 2144 |
| 2051 // When iterating with PrevNoDuplicate, spec requires that the | 2145 // When iterating with PrevNoDuplicate, spec requires that the |
| 2052 // value we yield for each key is the first duplicate in forwards | 2146 // value we yield for each key is the first duplicate in forwards |
| 2053 // order. | 2147 // order. |
| 2054 IndexedDBKey last_duplicate_key; | 2148 IndexedDBKey last_duplicate_key; |
| 2055 | 2149 |
| 2056 bool forward = cursor_options_.forward; | 2150 bool forward = cursor_options_.forward; |
| 2057 | 2151 |
| 2058 for (;;) { | 2152 for (;;) { |
| 2059 if (next_state == SEEK) { | 2153 if (next_state == SEEK) { |
| 2060 // TODO(jsbell): Optimize seeking for reverse cursors as well. | 2154 // TODO(jsbell): Optimize seeking for reverse cursors as well. |
| 2061 if (first_iteration && key && forward) { | 2155 if (first_iteration && key && forward) { |
| 2062 std::string leveldb_key; | 2156 std::string leveldb_key; |
| 2063 if (primary_key) { | 2157 if (primary_key) { |
| 2064 leveldb_key = EncodeKey(*key, *primary_key); | 2158 leveldb_key = EncodeKey(*key, *primary_key); |
| 2065 } else { | 2159 } else { |
| 2066 leveldb_key = EncodeKey(*key); | 2160 leveldb_key = EncodeKey(*key); |
| 2067 } | 2161 } |
| 2068 iterator_->Seek(leveldb_key); | 2162 *s = iterator_->Seek(leveldb_key); |
| 2069 first_iteration = false; | 2163 first_iteration = false; |
| 2070 } else if (forward) { | 2164 } else if (forward) { |
| 2071 iterator_->Next(); | 2165 *s = iterator_->Next(); |
| 2072 } else { | 2166 } else { |
| 2073 iterator_->Prev(); | 2167 *s = iterator_->Prev(); |
| 2074 } | 2168 } |
| 2169 if (!s->ok()) |
| 2170 return false; |
| 2075 } else { | 2171 } else { |
| 2076 next_state = SEEK; // for subsequent iterations | 2172 next_state = SEEK; // for subsequent iterations |
| 2077 } | 2173 } |
| 2078 | 2174 |
| 2079 if (!iterator_->IsValid()) { | 2175 if (!iterator_->IsValid()) { |
| 2080 if (!forward && last_duplicate_key.IsValid()) { | 2176 if (!forward && last_duplicate_key.IsValid()) { |
| 2081 // We need to walk forward because we hit the end of | 2177 // We need to walk forward because we hit the end of |
| 2082 // the data. | 2178 // the data. |
| 2083 forward = true; | 2179 forward = true; |
| 2084 continue; | 2180 continue; |
| (...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2546 if (!lower_bound) { | 2642 if (!lower_bound) { |
| 2547 cursor_options->low_key = | 2643 cursor_options->low_key = |
| 2548 ObjectStoreDataKey::Encode(database_id, object_store_id, MinIDBKey()); | 2644 ObjectStoreDataKey::Encode(database_id, object_store_id, MinIDBKey()); |
| 2549 cursor_options->low_open = true; // Not included. | 2645 cursor_options->low_open = true; // Not included. |
| 2550 } else { | 2646 } else { |
| 2551 cursor_options->low_key = | 2647 cursor_options->low_key = |
| 2552 ObjectStoreDataKey::Encode(database_id, object_store_id, range.lower()); | 2648 ObjectStoreDataKey::Encode(database_id, object_store_id, range.lower()); |
| 2553 cursor_options->low_open = range.lowerOpen(); | 2649 cursor_options->low_open = range.lowerOpen(); |
| 2554 } | 2650 } |
| 2555 | 2651 |
| 2652 leveldb::Status s; |
| 2653 |
| 2556 if (!upper_bound) { | 2654 if (!upper_bound) { |
| 2557 cursor_options->high_key = | 2655 cursor_options->high_key = |
| 2558 ObjectStoreDataKey::Encode(database_id, object_store_id, MaxIDBKey()); | 2656 ObjectStoreDataKey::Encode(database_id, object_store_id, MaxIDBKey()); |
| 2559 | 2657 |
| 2560 if (cursor_options->forward) { | 2658 if (cursor_options->forward) { |
| 2561 cursor_options->high_open = true; // Not included. | 2659 cursor_options->high_open = true; // Not included. |
| 2562 } else { | 2660 } else { |
| 2563 // We need a key that exists. | 2661 // We need a key that exists. |
| 2662 // TODO(cmumford): Handle this error (crbug.com/363397) |
| 2564 if (!FindGreatestKeyLessThanOrEqual(transaction, | 2663 if (!FindGreatestKeyLessThanOrEqual(transaction, |
| 2565 cursor_options->high_key, | 2664 cursor_options->high_key, |
| 2566 &cursor_options->high_key)) | 2665 &cursor_options->high_key, |
| 2666 s)) |
| 2567 return false; | 2667 return false; |
| 2568 cursor_options->high_open = false; | 2668 cursor_options->high_open = false; |
| 2569 } | 2669 } |
| 2570 } else { | 2670 } else { |
| 2571 cursor_options->high_key = | 2671 cursor_options->high_key = |
| 2572 ObjectStoreDataKey::Encode(database_id, object_store_id, range.upper()); | 2672 ObjectStoreDataKey::Encode(database_id, object_store_id, range.upper()); |
| 2573 cursor_options->high_open = range.upperOpen(); | 2673 cursor_options->high_open = range.upperOpen(); |
| 2574 | 2674 |
| 2575 if (!cursor_options->forward) { | 2675 if (!cursor_options->forward) { |
| 2576 // For reverse cursors, we need a key that exists. | 2676 // For reverse cursors, we need a key that exists. |
| 2577 std::string found_high_key; | 2677 std::string found_high_key; |
| 2678 // TODO(cmumford): Handle this error (crbug.com/363397) |
| 2578 if (!FindGreatestKeyLessThanOrEqual( | 2679 if (!FindGreatestKeyLessThanOrEqual( |
| 2579 transaction, cursor_options->high_key, &found_high_key)) | 2680 transaction, cursor_options->high_key, &found_high_key, s)) |
| 2580 return false; | 2681 return false; |
| 2581 | 2682 |
| 2582 // If the target key should not be included, but we end up with a smaller | 2683 // If the target key should not be included, but we end up with a smaller |
| 2583 // key, we should include that. | 2684 // key, we should include that. |
| 2584 if (cursor_options->high_open && | 2685 if (cursor_options->high_open && |
| 2585 CompareIndexKeys(found_high_key, cursor_options->high_key) < 0) | 2686 CompareIndexKeys(found_high_key, cursor_options->high_key) < 0) |
| 2586 cursor_options->high_open = false; | 2687 cursor_options->high_open = false; |
| 2587 | 2688 |
| 2588 cursor_options->high_key = found_high_key; | 2689 cursor_options->high_key = found_high_key; |
| 2589 } | 2690 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2619 if (!lower_bound) { | 2720 if (!lower_bound) { |
| 2620 cursor_options->low_key = | 2721 cursor_options->low_key = |
| 2621 IndexDataKey::EncodeMinKey(database_id, object_store_id, index_id); | 2722 IndexDataKey::EncodeMinKey(database_id, object_store_id, index_id); |
| 2622 cursor_options->low_open = false; // Included. | 2723 cursor_options->low_open = false; // Included. |
| 2623 } else { | 2724 } else { |
| 2624 cursor_options->low_key = IndexDataKey::Encode( | 2725 cursor_options->low_key = IndexDataKey::Encode( |
| 2625 database_id, object_store_id, index_id, range.lower()); | 2726 database_id, object_store_id, index_id, range.lower()); |
| 2626 cursor_options->low_open = range.lowerOpen(); | 2727 cursor_options->low_open = range.lowerOpen(); |
| 2627 } | 2728 } |
| 2628 | 2729 |
| 2730 leveldb::Status s; |
| 2731 |
| 2629 if (!upper_bound) { | 2732 if (!upper_bound) { |
| 2630 cursor_options->high_key = | 2733 cursor_options->high_key = |
| 2631 IndexDataKey::EncodeMaxKey(database_id, object_store_id, index_id); | 2734 IndexDataKey::EncodeMaxKey(database_id, object_store_id, index_id); |
| 2632 cursor_options->high_open = false; // Included. | 2735 cursor_options->high_open = false; // Included. |
| 2633 | 2736 |
| 2634 if (!cursor_options->forward) { // We need a key that exists. | 2737 if (!cursor_options->forward) { // We need a key that exists. |
| 2635 if (!FindGreatestKeyLessThanOrEqual(transaction, | 2738 if (!FindGreatestKeyLessThanOrEqual(transaction, |
| 2636 cursor_options->high_key, | 2739 cursor_options->high_key, |
| 2637 &cursor_options->high_key)) | 2740 &cursor_options->high_key, |
| 2741 s)) |
| 2638 return false; | 2742 return false; |
| 2639 cursor_options->high_open = false; | 2743 cursor_options->high_open = false; |
| 2640 } | 2744 } |
| 2641 } else { | 2745 } else { |
| 2642 cursor_options->high_key = IndexDataKey::Encode( | 2746 cursor_options->high_key = IndexDataKey::Encode( |
| 2643 database_id, object_store_id, index_id, range.upper()); | 2747 database_id, object_store_id, index_id, range.upper()); |
| 2644 cursor_options->high_open = range.upperOpen(); | 2748 cursor_options->high_open = range.upperOpen(); |
| 2645 | 2749 |
| 2646 std::string found_high_key; | 2750 std::string found_high_key; |
| 2647 // Seek to the *last* key in the set of non-unique keys | 2751 // Seek to the *last* key in the set of non-unique keys |
| 2752 // TODO(cmumford): Handle this error (crbug.com/363397) |
| 2648 if (!FindGreatestKeyLessThanOrEqual( | 2753 if (!FindGreatestKeyLessThanOrEqual( |
| 2649 transaction, cursor_options->high_key, &found_high_key)) | 2754 transaction, cursor_options->high_key, &found_high_key, s)) |
| 2650 return false; | 2755 return false; |
| 2651 | 2756 |
| 2652 // If the target key should not be included, but we end up with a smaller | 2757 // If the target key should not be included, but we end up with a smaller |
| 2653 // key, we should include that. | 2758 // key, we should include that. |
| 2654 if (cursor_options->high_open && | 2759 if (cursor_options->high_open && |
| 2655 CompareIndexKeys(found_high_key, cursor_options->high_key) < 0) | 2760 CompareIndexKeys(found_high_key, cursor_options->high_key) < 0) |
| 2656 cursor_options->high_open = false; | 2761 cursor_options->high_open = false; |
| 2657 | 2762 |
| 2658 cursor_options->high_key = found_high_key; | 2763 cursor_options->high_key = found_high_key; |
| 2659 } | 2764 } |
| 2660 | 2765 |
| 2661 return true; | 2766 return true; |
| 2662 } | 2767 } |
| 2663 | 2768 |
| 2664 scoped_ptr<IndexedDBBackingStore::Cursor> | 2769 scoped_ptr<IndexedDBBackingStore::Cursor> |
| 2665 IndexedDBBackingStore::OpenObjectStoreCursor( | 2770 IndexedDBBackingStore::OpenObjectStoreCursor( |
| 2666 IndexedDBBackingStore::Transaction* transaction, | 2771 IndexedDBBackingStore::Transaction* transaction, |
| 2667 int64 database_id, | 2772 int64 database_id, |
| 2668 int64 object_store_id, | 2773 int64 object_store_id, |
| 2669 const IndexedDBKeyRange& range, | 2774 const IndexedDBKeyRange& range, |
| 2670 indexed_db::CursorDirection direction) { | 2775 indexed_db::CursorDirection direction, |
| 2776 leveldb::Status* s) { |
| 2671 IDB_TRACE("IndexedDBBackingStore::OpenObjectStoreCursor"); | 2777 IDB_TRACE("IndexedDBBackingStore::OpenObjectStoreCursor"); |
| 2778 *s = leveldb::Status::OK(); |
| 2672 LevelDBTransaction* leveldb_transaction = transaction->transaction(); | 2779 LevelDBTransaction* leveldb_transaction = transaction->transaction(); |
| 2673 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; | 2780 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; |
| 2674 if (!ObjectStoreCursorOptions(leveldb_transaction, | 2781 if (!ObjectStoreCursorOptions(leveldb_transaction, |
| 2675 database_id, | 2782 database_id, |
| 2676 object_store_id, | 2783 object_store_id, |
| 2677 range, | 2784 range, |
| 2678 direction, | 2785 direction, |
| 2679 &cursor_options)) | 2786 &cursor_options)) |
| 2680 return scoped_ptr<IndexedDBBackingStore::Cursor>(); | 2787 return scoped_ptr<IndexedDBBackingStore::Cursor>(); |
| 2681 scoped_ptr<ObjectStoreCursorImpl> cursor( | 2788 scoped_ptr<ObjectStoreCursorImpl> cursor( |
| 2682 new ObjectStoreCursorImpl(leveldb_transaction, cursor_options)); | 2789 new ObjectStoreCursorImpl(leveldb_transaction, cursor_options)); |
| 2683 if (!cursor->FirstSeek()) | 2790 if (!cursor->FirstSeek(s)) |
| 2684 return scoped_ptr<IndexedDBBackingStore::Cursor>(); | 2791 return scoped_ptr<IndexedDBBackingStore::Cursor>(); |
| 2685 | 2792 |
| 2686 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); | 2793 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); |
| 2687 } | 2794 } |
| 2688 | 2795 |
| 2689 scoped_ptr<IndexedDBBackingStore::Cursor> | 2796 scoped_ptr<IndexedDBBackingStore::Cursor> |
| 2690 IndexedDBBackingStore::OpenObjectStoreKeyCursor( | 2797 IndexedDBBackingStore::OpenObjectStoreKeyCursor( |
| 2691 IndexedDBBackingStore::Transaction* transaction, | 2798 IndexedDBBackingStore::Transaction* transaction, |
| 2692 int64 database_id, | 2799 int64 database_id, |
| 2693 int64 object_store_id, | 2800 int64 object_store_id, |
| 2694 const IndexedDBKeyRange& range, | 2801 const IndexedDBKeyRange& range, |
| 2695 indexed_db::CursorDirection direction) { | 2802 indexed_db::CursorDirection direction, |
| 2803 leveldb::Status* s) { |
| 2696 IDB_TRACE("IndexedDBBackingStore::OpenObjectStoreKeyCursor"); | 2804 IDB_TRACE("IndexedDBBackingStore::OpenObjectStoreKeyCursor"); |
| 2805 *s = leveldb::Status::OK(); |
| 2697 LevelDBTransaction* leveldb_transaction = transaction->transaction(); | 2806 LevelDBTransaction* leveldb_transaction = transaction->transaction(); |
| 2698 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; | 2807 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; |
| 2699 if (!ObjectStoreCursorOptions(leveldb_transaction, | 2808 if (!ObjectStoreCursorOptions(leveldb_transaction, |
| 2700 database_id, | 2809 database_id, |
| 2701 object_store_id, | 2810 object_store_id, |
| 2702 range, | 2811 range, |
| 2703 direction, | 2812 direction, |
| 2704 &cursor_options)) | 2813 &cursor_options)) |
| 2705 return scoped_ptr<IndexedDBBackingStore::Cursor>(); | 2814 return scoped_ptr<IndexedDBBackingStore::Cursor>(); |
| 2706 scoped_ptr<ObjectStoreKeyCursorImpl> cursor( | 2815 scoped_ptr<ObjectStoreKeyCursorImpl> cursor( |
| 2707 new ObjectStoreKeyCursorImpl(leveldb_transaction, cursor_options)); | 2816 new ObjectStoreKeyCursorImpl(leveldb_transaction, cursor_options)); |
| 2708 if (!cursor->FirstSeek()) | 2817 if (!cursor->FirstSeek(s)) |
| 2709 return scoped_ptr<IndexedDBBackingStore::Cursor>(); | 2818 return scoped_ptr<IndexedDBBackingStore::Cursor>(); |
| 2710 | 2819 |
| 2711 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); | 2820 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); |
| 2712 } | 2821 } |
| 2713 | 2822 |
| 2714 scoped_ptr<IndexedDBBackingStore::Cursor> | 2823 scoped_ptr<IndexedDBBackingStore::Cursor> |
| 2715 IndexedDBBackingStore::OpenIndexKeyCursor( | 2824 IndexedDBBackingStore::OpenIndexKeyCursor( |
| 2716 IndexedDBBackingStore::Transaction* transaction, | 2825 IndexedDBBackingStore::Transaction* transaction, |
| 2717 int64 database_id, | 2826 int64 database_id, |
| 2718 int64 object_store_id, | 2827 int64 object_store_id, |
| 2719 int64 index_id, | 2828 int64 index_id, |
| 2720 const IndexedDBKeyRange& range, | 2829 const IndexedDBKeyRange& range, |
| 2721 indexed_db::CursorDirection direction) { | 2830 indexed_db::CursorDirection direction, |
| 2831 leveldb::Status* s) { |
| 2722 IDB_TRACE("IndexedDBBackingStore::OpenIndexKeyCursor"); | 2832 IDB_TRACE("IndexedDBBackingStore::OpenIndexKeyCursor"); |
| 2833 *s = leveldb::Status::OK(); |
| 2723 LevelDBTransaction* leveldb_transaction = transaction->transaction(); | 2834 LevelDBTransaction* leveldb_transaction = transaction->transaction(); |
| 2724 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; | 2835 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; |
| 2725 if (!IndexCursorOptions(leveldb_transaction, | 2836 if (!IndexCursorOptions(leveldb_transaction, |
| 2726 database_id, | 2837 database_id, |
| 2727 object_store_id, | 2838 object_store_id, |
| 2728 index_id, | 2839 index_id, |
| 2729 range, | 2840 range, |
| 2730 direction, | 2841 direction, |
| 2731 &cursor_options)) | 2842 &cursor_options)) |
| 2732 return scoped_ptr<IndexedDBBackingStore::Cursor>(); | 2843 return scoped_ptr<IndexedDBBackingStore::Cursor>(); |
| 2733 scoped_ptr<IndexKeyCursorImpl> cursor( | 2844 scoped_ptr<IndexKeyCursorImpl> cursor( |
| 2734 new IndexKeyCursorImpl(leveldb_transaction, cursor_options)); | 2845 new IndexKeyCursorImpl(leveldb_transaction, cursor_options)); |
| 2735 if (!cursor->FirstSeek()) | 2846 if (!cursor->FirstSeek(s)) |
| 2736 return scoped_ptr<IndexedDBBackingStore::Cursor>(); | 2847 return scoped_ptr<IndexedDBBackingStore::Cursor>(); |
| 2737 | 2848 |
| 2738 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); | 2849 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); |
| 2739 } | 2850 } |
| 2740 | 2851 |
| 2741 scoped_ptr<IndexedDBBackingStore::Cursor> | 2852 scoped_ptr<IndexedDBBackingStore::Cursor> |
| 2742 IndexedDBBackingStore::OpenIndexCursor( | 2853 IndexedDBBackingStore::OpenIndexCursor( |
| 2743 IndexedDBBackingStore::Transaction* transaction, | 2854 IndexedDBBackingStore::Transaction* transaction, |
| 2744 int64 database_id, | 2855 int64 database_id, |
| 2745 int64 object_store_id, | 2856 int64 object_store_id, |
| 2746 int64 index_id, | 2857 int64 index_id, |
| 2747 const IndexedDBKeyRange& range, | 2858 const IndexedDBKeyRange& range, |
| 2748 indexed_db::CursorDirection direction) { | 2859 indexed_db::CursorDirection direction, |
| 2860 leveldb::Status* s) { |
| 2749 IDB_TRACE("IndexedDBBackingStore::OpenIndexCursor"); | 2861 IDB_TRACE("IndexedDBBackingStore::OpenIndexCursor"); |
| 2750 LevelDBTransaction* leveldb_transaction = transaction->transaction(); | 2862 LevelDBTransaction* leveldb_transaction = transaction->transaction(); |
| 2751 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; | 2863 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; |
| 2752 if (!IndexCursorOptions(leveldb_transaction, | 2864 if (!IndexCursorOptions(leveldb_transaction, |
| 2753 database_id, | 2865 database_id, |
| 2754 object_store_id, | 2866 object_store_id, |
| 2755 index_id, | 2867 index_id, |
| 2756 range, | 2868 range, |
| 2757 direction, | 2869 direction, |
| 2758 &cursor_options)) | 2870 &cursor_options)) |
| 2759 return scoped_ptr<IndexedDBBackingStore::Cursor>(); | 2871 return scoped_ptr<IndexedDBBackingStore::Cursor>(); |
| 2760 scoped_ptr<IndexCursorImpl> cursor( | 2872 scoped_ptr<IndexCursorImpl> cursor( |
| 2761 new IndexCursorImpl(leveldb_transaction, cursor_options)); | 2873 new IndexCursorImpl(leveldb_transaction, cursor_options)); |
| 2762 if (!cursor->FirstSeek()) | 2874 if (!cursor->FirstSeek(s)) |
| 2763 return scoped_ptr<IndexedDBBackingStore::Cursor>(); | 2875 return scoped_ptr<IndexedDBBackingStore::Cursor>(); |
| 2764 | 2876 |
| 2765 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); | 2877 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); |
| 2766 } | 2878 } |
| 2767 | 2879 |
| 2768 IndexedDBBackingStore::Transaction::Transaction( | 2880 IndexedDBBackingStore::Transaction::Transaction( |
| 2769 IndexedDBBackingStore* backing_store) | 2881 IndexedDBBackingStore* backing_store) |
| 2770 : backing_store_(backing_store) {} | 2882 : backing_store_(backing_store) {} |
| 2771 | 2883 |
| 2772 IndexedDBBackingStore::Transaction::~Transaction() {} | 2884 IndexedDBBackingStore::Transaction::~Transaction() {} |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2788 } | 2900 } |
| 2789 | 2901 |
| 2790 void IndexedDBBackingStore::Transaction::Rollback() { | 2902 void IndexedDBBackingStore::Transaction::Rollback() { |
| 2791 IDB_TRACE("IndexedDBBackingStore::Transaction::Rollback"); | 2903 IDB_TRACE("IndexedDBBackingStore::Transaction::Rollback"); |
| 2792 DCHECK(transaction_.get()); | 2904 DCHECK(transaction_.get()); |
| 2793 transaction_->Rollback(); | 2905 transaction_->Rollback(); |
| 2794 transaction_ = NULL; | 2906 transaction_ = NULL; |
| 2795 } | 2907 } |
| 2796 | 2908 |
| 2797 } // namespace content | 2909 } // namespace content |
| OLD | NEW |