| 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 <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
| 12 #include "base/strings/string_piece.h" |
| 12 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
| 13 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" | 14 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" |
| 14 #include "content/browser/indexed_db/indexed_db_metadata.h" | 15 #include "content/browser/indexed_db/indexed_db_metadata.h" |
| 15 #include "content/browser/indexed_db/indexed_db_tracing.h" | 16 #include "content/browser/indexed_db/indexed_db_tracing.h" |
| 16 #include "content/browser/indexed_db/leveldb/leveldb_comparator.h" | 17 #include "content/browser/indexed_db/leveldb/leveldb_comparator.h" |
| 17 #include "content/browser/indexed_db/leveldb/leveldb_database.h" | 18 #include "content/browser/indexed_db/leveldb/leveldb_database.h" |
| 18 #include "content/browser/indexed_db/leveldb/leveldb_iterator.h" | 19 #include "content/browser/indexed_db/leveldb/leveldb_iterator.h" |
| 19 #include "content/browser/indexed_db/leveldb/leveldb_slice.h" | 20 #include "content/browser/indexed_db/leveldb/leveldb_slice.h" |
| 20 #include "content/browser/indexed_db/leveldb/leveldb_transaction.h" | 21 #include "content/browser/indexed_db/leveldb/leveldb_transaction.h" |
| 21 #include "content/common/indexed_db/indexed_db_key.h" | 22 #include "content/common/indexed_db/indexed_db_key.h" |
| 22 #include "content/common/indexed_db/indexed_db_key_path.h" | 23 #include "content/common/indexed_db/indexed_db_key_path.h" |
| 23 #include "content/common/indexed_db/indexed_db_key_range.h" | 24 #include "content/common/indexed_db/indexed_db_key_range.h" |
| 24 #include "third_party/WebKit/public/platform/WebIDBKey.h" | 25 #include "third_party/WebKit/public/platform/WebIDBKey.h" |
| 25 #include "third_party/WebKit/public/platform/WebIDBKeyPath.h" | 26 #include "third_party/WebKit/public/platform/WebIDBKeyPath.h" |
| 26 | 27 |
| 28 using base::StringPiece; |
| 29 |
| 27 // TODO(jsbell): Make blink push the version during the open() call. | 30 // TODO(jsbell): Make blink push the version during the open() call. |
| 28 static const uint32 kWireVersion = 2; | 31 static const uint32 kWireVersion = 2; |
| 29 | 32 |
| 30 namespace content { | 33 namespace content { |
| 31 | 34 |
| 32 static const int64 kKeyGeneratorInitialNumber = | 35 static const int64 kKeyGeneratorInitialNumber = |
| 33 1; // From the IndexedDB specification. | 36 1; // From the IndexedDB specification. |
| 34 | 37 |
| 35 enum IndexedDBBackingStoreErrorSource { | 38 enum IndexedDBBackingStoreErrorSource { |
| 36 // 0 - 2 are no longer used. | 39 // 0 - 2 are no longer used. |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 std::vector<char> buffer; | 93 std::vector<char> buffer; |
| 91 EncodeBool(value, &buffer); | 94 EncodeBool(value, &buffer); |
| 92 transaction->Put(key, buffer); | 95 transaction->Put(key, buffer); |
| 93 } | 96 } |
| 94 | 97 |
| 95 template <typename DBOrTransaction> | 98 template <typename DBOrTransaction> |
| 96 static bool GetInt(DBOrTransaction* db, | 99 static bool GetInt(DBOrTransaction* db, |
| 97 const LevelDBSlice& key, | 100 const LevelDBSlice& key, |
| 98 int64& found_int, | 101 int64& found_int, |
| 99 bool& found) { | 102 bool& found) { |
| 100 std::vector<char> result; | 103 std::string result; |
| 101 bool ok = db->Get(key, result, found); | 104 bool ok = db->Get(key, &result, found); |
| 102 if (!ok) | 105 if (!ok) |
| 103 return false; | 106 return false; |
| 104 if (!found) | 107 if (!found) |
| 105 return true; | 108 return true; |
| 106 | 109 StringPiece slice(result); |
| 107 found_int = DecodeInt(result.begin(), result.end()); | 110 return DecodeInt(&slice, &found_int) && slice.empty(); |
| 108 return true; | |
| 109 } | 111 } |
| 110 | 112 |
| 111 static void PutInt(LevelDBTransaction* transaction, | 113 static void PutInt(LevelDBTransaction* transaction, |
| 112 const LevelDBSlice& key, | 114 const LevelDBSlice& key, |
| 113 int64 value) { | 115 int64 value) { |
| 114 DCHECK_GE(value, 0); | 116 DCHECK_GE(value, 0); |
| 115 std::vector<char> buffer; | 117 std::vector<char> buffer; |
| 116 EncodeInt(value, &buffer); | 118 EncodeInt(value, &buffer); |
| 117 transaction->Put(key, buffer); | 119 transaction->Put(key, buffer); |
| 118 } | 120 } |
| 119 | 121 |
| 120 template <typename DBOrTransaction> | 122 template <typename DBOrTransaction> |
| 121 WARN_UNUSED_RESULT static bool GetVarInt(DBOrTransaction* db, | 123 WARN_UNUSED_RESULT static bool GetVarInt(DBOrTransaction* db, |
| 122 const LevelDBSlice& key, | 124 const LevelDBSlice& key, |
| 123 int64& found_int, | 125 int64& found_int, |
| 124 bool& found) { | 126 bool& found) { |
| 125 std::vector<char> result; | 127 std::string result; |
| 126 bool ok = db->Get(key, result, found); | 128 bool ok = db->Get(key, &result, found); |
| 127 if (!ok) | 129 if (!ok) |
| 128 return false; | 130 return false; |
| 129 if (!found) | 131 if (!found) |
| 130 return true; | 132 return true; |
| 131 if (!result.size()) | 133 StringPiece slice(result); |
| 132 return false; | 134 return DecodeVarInt(&slice, &found_int) && slice.empty(); |
| 133 | |
| 134 found = DecodeVarInt(&*result.begin(), &*result.rbegin() + 1, found_int) == | |
| 135 &*result.rbegin() + 1; | |
| 136 return true; | |
| 137 } | 135 } |
| 138 | 136 |
| 139 static void PutVarInt(LevelDBTransaction* transaction, | 137 static void PutVarInt(LevelDBTransaction* transaction, |
| 140 const LevelDBSlice& key, | 138 const LevelDBSlice& key, |
| 141 int64 value) { | 139 int64 value) { |
| 142 std::vector<char> buffer; | 140 std::vector<char> buffer; |
| 143 EncodeVarInt(value, &buffer); | 141 EncodeVarInt(value, &buffer); |
| 144 transaction->Put(key, buffer); | 142 transaction->Put(key, buffer); |
| 145 } | 143 } |
| 146 | 144 |
| 147 template <typename DBOrTransaction> | 145 template <typename DBOrTransaction> |
| 148 WARN_UNUSED_RESULT static bool GetString(DBOrTransaction* db, | 146 WARN_UNUSED_RESULT static bool GetString(DBOrTransaction* db, |
| 149 const LevelDBSlice& key, | 147 const LevelDBSlice& key, |
| 150 string16& found_string, | 148 string16& found_string, |
| 151 bool& found) { | 149 bool& found) { |
| 152 std::vector<char> result; | 150 std::string result; |
| 153 found = false; | 151 found = false; |
| 154 bool ok = db->Get(key, result, found); | 152 bool ok = db->Get(key, &result, found); |
| 155 if (!ok) | 153 if (!ok) |
| 156 return false; | 154 return false; |
| 157 if (!found) | 155 if (!found) |
| 158 return true; | 156 return true; |
| 159 if (!result.size()) { | 157 StringPiece slice(result); |
| 160 found_string.clear(); | 158 return DecodeString(&slice, &found_string) && slice.empty(); |
| 161 return true; | |
| 162 } | |
| 163 | |
| 164 found_string = DecodeString(&*result.begin(), &*result.rbegin() + 1); | |
| 165 return true; | |
| 166 } | 159 } |
| 167 | 160 |
| 168 static void PutString(LevelDBTransaction* transaction, | 161 static void PutString(LevelDBTransaction* transaction, |
| 169 const LevelDBSlice& key, | 162 const LevelDBSlice& key, |
| 170 const string16& value) { | 163 const string16& value) { |
| 171 std::vector<char> buffer; | 164 std::vector<char> buffer; |
| 172 EncodeString(value, &buffer); | 165 EncodeString(value, &buffer); |
| 173 transaction->Put(key, buffer); | 166 transaction->Put(key, buffer); |
| 174 } | 167 } |
| 175 | 168 |
| (...skipping 688 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 864 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); | 857 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); |
| 865 // Possible stale metadata, but don't fail the load. | 858 // Possible stale metadata, but don't fail the load. |
| 866 it->Next(); | 859 it->Next(); |
| 867 continue; | 860 continue; |
| 868 } | 861 } |
| 869 | 862 |
| 870 int64 object_store_id = meta_data_key.ObjectStoreId(); | 863 int64 object_store_id = meta_data_key.ObjectStoreId(); |
| 871 | 864 |
| 872 // TODO(jsbell): Do this by direct key lookup rather than iteration, to | 865 // TODO(jsbell): Do this by direct key lookup rather than iteration, to |
| 873 // simplify. | 866 // simplify. |
| 874 string16 object_store_name = | 867 string16 object_store_name; |
| 875 DecodeString(it->Value().begin(), it->Value().end()); | 868 { |
| 869 StringPiece slice(it->Value().AsStringPiece()); |
| 870 if (!DecodeString(&slice, &object_store_name) || !slice.empty()) |
| 871 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); |
| 872 } |
| 876 | 873 |
| 877 it->Next(); | 874 it->Next(); |
| 878 if (!CheckObjectStoreAndMetaDataType(it.get(), | 875 if (!CheckObjectStoreAndMetaDataType(it.get(), |
| 879 stop_key, | 876 stop_key, |
| 880 object_store_id, | 877 object_store_id, |
| 881 ObjectStoreMetaDataKey::KEY_PATH)) { | 878 ObjectStoreMetaDataKey::KEY_PATH)) { |
| 882 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); | 879 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); |
| 883 break; | 880 break; |
| 884 } | 881 } |
| 885 IndexedDBKeyPath key_path = | 882 IndexedDBKeyPath key_path; |
| 886 DecodeIDBKeyPath(it->Value().begin(), it->Value().end()); | 883 { |
| 884 StringPiece slice(it->Value().AsStringPiece()); |
| 885 if (!DecodeIDBKeyPath(&slice, &key_path) || !slice.empty()) |
| 886 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); |
| 887 } |
| 887 | 888 |
| 888 it->Next(); | 889 it->Next(); |
| 889 if (!CheckObjectStoreAndMetaDataType( | 890 if (!CheckObjectStoreAndMetaDataType( |
| 890 it.get(), | 891 it.get(), |
| 891 stop_key, | 892 stop_key, |
| 892 object_store_id, | 893 object_store_id, |
| 893 ObjectStoreMetaDataKey::AUTO_INCREMENT)) { | 894 ObjectStoreMetaDataKey::AUTO_INCREMENT)) { |
| 894 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); | 895 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); |
| 895 break; | 896 break; |
| 896 } | 897 } |
| 897 bool auto_increment = DecodeBool(it->Value().begin(), it->Value().end()); | 898 bool auto_increment; |
| 899 { |
| 900 StringPiece slice(it->Value().AsStringPiece()); |
| 901 if (!DecodeBool(&slice, &auto_increment) || !slice.empty()) |
| 902 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); |
| 903 } |
| 898 | 904 |
| 899 it->Next(); // Is evicatble. | 905 it->Next(); // Is evicatble. |
| 900 if (!CheckObjectStoreAndMetaDataType(it.get(), | 906 if (!CheckObjectStoreAndMetaDataType(it.get(), |
| 901 stop_key, | 907 stop_key, |
| 902 object_store_id, | 908 object_store_id, |
| 903 ObjectStoreMetaDataKey::EVICTABLE)) { | 909 ObjectStoreMetaDataKey::EVICTABLE)) { |
| 904 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); | 910 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); |
| 905 break; | 911 break; |
| 906 } | 912 } |
| 907 | 913 |
| 908 it->Next(); // Last version. | 914 it->Next(); // Last version. |
| 909 if (!CheckObjectStoreAndMetaDataType( | 915 if (!CheckObjectStoreAndMetaDataType( |
| 910 it.get(), | 916 it.get(), |
| 911 stop_key, | 917 stop_key, |
| 912 object_store_id, | 918 object_store_id, |
| 913 ObjectStoreMetaDataKey::LAST_VERSION)) { | 919 ObjectStoreMetaDataKey::LAST_VERSION)) { |
| 914 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); | 920 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); |
| 915 break; | 921 break; |
| 916 } | 922 } |
| 917 | 923 |
| 918 it->Next(); // Maximum index id allocated. | 924 it->Next(); // Maximum index id allocated. |
| 919 if (!CheckObjectStoreAndMetaDataType( | 925 if (!CheckObjectStoreAndMetaDataType( |
| 920 it.get(), | 926 it.get(), |
| 921 stop_key, | 927 stop_key, |
| 922 object_store_id, | 928 object_store_id, |
| 923 ObjectStoreMetaDataKey::MAX_INDEX_ID)) { | 929 ObjectStoreMetaDataKey::MAX_INDEX_ID)) { |
| 924 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); | 930 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); |
| 925 break; | 931 break; |
| 926 } | 932 } |
| 927 int64 max_index_id = DecodeInt(it->Value().begin(), it->Value().end()); | 933 int64 max_index_id; |
| 934 { |
| 935 StringPiece slice(it->Value().AsStringPiece()); |
| 936 if (!DecodeInt(&slice, &max_index_id) || !slice.empty()) |
| 937 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); |
| 938 } |
| 928 | 939 |
| 929 it->Next(); // [optional] has key path (is not null) | 940 it->Next(); // [optional] has key path (is not null) |
| 930 if (CheckObjectStoreAndMetaDataType(it.get(), | 941 if (CheckObjectStoreAndMetaDataType(it.get(), |
| 931 stop_key, | 942 stop_key, |
| 932 object_store_id, | 943 object_store_id, |
| 933 ObjectStoreMetaDataKey::HAS_KEY_PATH)) { | 944 ObjectStoreMetaDataKey::HAS_KEY_PATH)) { |
| 934 bool has_key_path = DecodeBool(it->Value().begin(), it->Value().end()); | 945 bool has_key_path; |
| 946 { |
| 947 StringPiece slice(it->Value().AsStringPiece()); |
| 948 if (!DecodeBool(&slice, &has_key_path)) |
| 949 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); |
| 950 } |
| 935 // This check accounts for two layers of legacy coding: | 951 // This check accounts for two layers of legacy coding: |
| 936 // (1) Initially, has_key_path was added to distinguish null vs. string. | 952 // (1) Initially, has_key_path was added to distinguish null vs. string. |
| 937 // (2) Later, null vs. string vs. array was stored in the key_path itself. | 953 // (2) Later, null vs. string vs. array was stored in the key_path itself. |
| 938 // So this check is only relevant for string-type key_paths. | 954 // So this check is only relevant for string-type key_paths. |
| 939 if (!has_key_path && | 955 if (!has_key_path && |
| 940 (key_path.type() == WebKit::WebIDBKeyPath::StringType && | 956 (key_path.type() == WebKit::WebIDBKeyPath::StringType && |
| 941 !key_path.string().empty())) { | 957 !key_path.string().empty())) { |
| 942 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); | 958 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); |
| 943 break; | 959 break; |
| 944 } | 960 } |
| 945 if (!has_key_path) | 961 if (!has_key_path) |
| 946 key_path = IndexedDBKeyPath(); | 962 key_path = IndexedDBKeyPath(); |
| 947 it->Next(); | 963 it->Next(); |
| 948 } | 964 } |
| 949 | 965 |
| 950 int64 key_generator_current_number = -1; | 966 int64 key_generator_current_number = -1; |
| 951 if (CheckObjectStoreAndMetaDataType( | 967 if (CheckObjectStoreAndMetaDataType( |
| 952 it.get(), | 968 it.get(), |
| 953 stop_key, | 969 stop_key, |
| 954 object_store_id, | 970 object_store_id, |
| 955 ObjectStoreMetaDataKey::KEY_GENERATOR_CURRENT_NUMBER)) { | 971 ObjectStoreMetaDataKey::KEY_GENERATOR_CURRENT_NUMBER)) { |
| 956 key_generator_current_number = | 972 StringPiece slice(it->Value().AsStringPiece()); |
| 957 DecodeInt(it->Value().begin(), it->Value().end()); | 973 if (!DecodeInt(&slice, &key_generator_current_number) || !slice.empty()) |
| 974 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); |
| 975 |
| 958 // TODO(jsbell): Return key_generator_current_number, cache in | 976 // TODO(jsbell): Return key_generator_current_number, cache in |
| 959 // object store, and write lazily to backing store. For now, | 977 // object store, and write lazily to backing store. For now, |
| 960 // just assert that if it was written it was valid. | 978 // just assert that if it was written it was valid. |
| 961 DCHECK_GE(key_generator_current_number, kKeyGeneratorInitialNumber); | 979 DCHECK_GE(key_generator_current_number, kKeyGeneratorInitialNumber); |
| 962 it->Next(); | 980 it->Next(); |
| 963 } | 981 } |
| 964 | 982 |
| 965 IndexedDBObjectStoreMetadata metadata(object_store_name, | 983 IndexedDBObjectStoreMetadata metadata(object_store_name, |
| 966 object_store_id, | 984 object_store_id, |
| 967 key_path, | 985 key_path, |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1100 const IndexedDBKey& key, | 1118 const IndexedDBKey& key, |
| 1101 std::vector<char>& record) { | 1119 std::vector<char>& record) { |
| 1102 IDB_TRACE("IndexedDBBackingStore::get_record"); | 1120 IDB_TRACE("IndexedDBBackingStore::get_record"); |
| 1103 if (!KeyPrefix::ValidIds(database_id, object_store_id)) | 1121 if (!KeyPrefix::ValidIds(database_id, object_store_id)) |
| 1104 return false; | 1122 return false; |
| 1105 LevelDBTransaction* leveldb_transaction = | 1123 LevelDBTransaction* leveldb_transaction = |
| 1106 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction); | 1124 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction); |
| 1107 | 1125 |
| 1108 const std::vector<char> leveldb_key = | 1126 const std::vector<char> leveldb_key = |
| 1109 ObjectStoreDataKey::Encode(database_id, object_store_id, key); | 1127 ObjectStoreDataKey::Encode(database_id, object_store_id, key); |
| 1110 std::vector<char> data; | 1128 std::string data; |
| 1111 | 1129 |
| 1112 record.clear(); | 1130 record.clear(); |
| 1113 | 1131 |
| 1114 bool found = false; | 1132 bool found = false; |
| 1115 bool ok = leveldb_transaction->Get(LevelDBSlice(leveldb_key), data, found); | 1133 bool ok = leveldb_transaction->Get(LevelDBSlice(leveldb_key), &data, found); |
| 1116 if (!ok) { | 1134 if (!ok) { |
| 1117 INTERNAL_READ_ERROR(GET_RECORD); | 1135 INTERNAL_READ_ERROR(GET_RECORD); |
| 1118 return false; | 1136 return false; |
| 1119 } | 1137 } |
| 1120 if (!found) | 1138 if (!found) |
| 1121 return true; | 1139 return true; |
| 1122 if (!data.size()) { | 1140 if (data.empty()) { |
| 1123 INTERNAL_READ_ERROR(GET_RECORD); | 1141 INTERNAL_READ_ERROR(GET_RECORD); |
| 1124 return false; | 1142 return false; |
| 1125 } | 1143 } |
| 1126 | 1144 |
| 1127 int64 version; | 1145 int64 version; |
| 1128 const char* p = DecodeVarInt(&*data.begin(), &*data.rbegin() + 1, version); | 1146 StringPiece slice(data); |
| 1129 if (!p) { | 1147 if (!DecodeVarInt(&slice, &version)) { |
| 1130 INTERNAL_READ_ERROR(GET_RECORD); | 1148 INTERNAL_READ_ERROR(GET_RECORD); |
| 1131 return false; | 1149 return false; |
| 1132 } | 1150 } |
| 1133 | 1151 |
| 1134 record.insert(record.end(), p, static_cast<const char*>(&*data.rbegin()) + 1); | 1152 record.insert(record.end(), slice.begin(), slice.end()); |
| 1135 return true; | 1153 return true; |
| 1136 } | 1154 } |
| 1137 | 1155 |
| 1138 WARN_UNUSED_RESULT static bool GetNewVersionNumber( | 1156 WARN_UNUSED_RESULT static bool GetNewVersionNumber( |
| 1139 LevelDBTransaction* transaction, | 1157 LevelDBTransaction* transaction, |
| 1140 int64 database_id, | 1158 int64 database_id, |
| 1141 int64 object_store_id, | 1159 int64 object_store_id, |
| 1142 int64& new_version_number) { | 1160 int64& new_version_number) { |
| 1143 const std::vector<char> last_version_key = ObjectStoreMetaDataKey::Encode( | 1161 const std::vector<char> last_version_key = ObjectStoreMetaDataKey::Encode( |
| 1144 database_id, object_store_id, ObjectStoreMetaDataKey::LAST_VERSION); | 1162 database_id, object_store_id, ObjectStoreMetaDataKey::LAST_VERSION); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1196 v.insert(v.end(), value.begin(), value.end()); | 1214 v.insert(v.end(), value.begin(), value.end()); |
| 1197 | 1215 |
| 1198 leveldb_transaction->Put(LevelDBSlice(object_storedata_key), v); | 1216 leveldb_transaction->Put(LevelDBSlice(object_storedata_key), v); |
| 1199 | 1217 |
| 1200 const std::vector<char> exists_entry_key = | 1218 const std::vector<char> exists_entry_key = |
| 1201 ExistsEntryKey::Encode(database_id, object_store_id, key); | 1219 ExistsEntryKey::Encode(database_id, object_store_id, key); |
| 1202 std::vector<char> version_encoded; | 1220 std::vector<char> version_encoded; |
| 1203 EncodeInt(version, &version_encoded); | 1221 EncodeInt(version, &version_encoded); |
| 1204 leveldb_transaction->Put(LevelDBSlice(exists_entry_key), version_encoded); | 1222 leveldb_transaction->Put(LevelDBSlice(exists_entry_key), version_encoded); |
| 1205 | 1223 |
| 1206 record_identifier->Reset(EncodeIDBKey(key), version); | 1224 std::vector<char> key_encoded; |
| 1225 EncodeIDBKey(key, &key_encoded); |
| 1226 record_identifier->Reset(key_encoded, version); |
| 1207 return true; | 1227 return true; |
| 1208 } | 1228 } |
| 1209 | 1229 |
| 1210 bool IndexedDBBackingStore::ClearObjectStore( | 1230 bool IndexedDBBackingStore::ClearObjectStore( |
| 1211 IndexedDBBackingStore::Transaction* transaction, | 1231 IndexedDBBackingStore::Transaction* transaction, |
| 1212 int64 database_id, | 1232 int64 database_id, |
| 1213 int64 object_store_id) { | 1233 int64 object_store_id) { |
| 1214 IDB_TRACE("IndexedDBBackingStore::clear_object_store"); | 1234 IDB_TRACE("IndexedDBBackingStore::clear_object_store"); |
| 1215 if (!KeyPrefix::ValidIds(database_id, object_store_id)) | 1235 if (!KeyPrefix::ValidIds(database_id, object_store_id)) |
| 1216 return false; | 1236 return false; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1256 LevelDBTransaction* leveldb_transaction = | 1276 LevelDBTransaction* leveldb_transaction = |
| 1257 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction); | 1277 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction); |
| 1258 | 1278 |
| 1259 const std::vector<char> key_generator_current_number_key = | 1279 const std::vector<char> key_generator_current_number_key = |
| 1260 ObjectStoreMetaDataKey::Encode( | 1280 ObjectStoreMetaDataKey::Encode( |
| 1261 database_id, | 1281 database_id, |
| 1262 object_store_id, | 1282 object_store_id, |
| 1263 ObjectStoreMetaDataKey::KEY_GENERATOR_CURRENT_NUMBER); | 1283 ObjectStoreMetaDataKey::KEY_GENERATOR_CURRENT_NUMBER); |
| 1264 | 1284 |
| 1265 key_generator_current_number = -1; | 1285 key_generator_current_number = -1; |
| 1266 std::vector<char> data; | 1286 std::string data; |
| 1267 | 1287 |
| 1268 bool found = false; | 1288 bool found = false; |
| 1269 bool ok = leveldb_transaction->Get( | 1289 bool ok = leveldb_transaction->Get( |
| 1270 LevelDBSlice(key_generator_current_number_key), data, found); | 1290 LevelDBSlice(key_generator_current_number_key), &data, found); |
| 1271 if (!ok) { | 1291 if (!ok) { |
| 1272 INTERNAL_READ_ERROR(GET_KEY_GENERATOR_CURRENT_NUMBER); | 1292 INTERNAL_READ_ERROR(GET_KEY_GENERATOR_CURRENT_NUMBER); |
| 1273 return false; | 1293 return false; |
| 1274 } | 1294 } |
| 1275 if (found) { | 1295 if (found && !data.empty()) { |
| 1276 key_generator_current_number = DecodeInt(data.begin(), data.end()); | 1296 StringPiece slice(data); |
| 1277 } else { | 1297 if (!DecodeInt(&slice, &key_generator_current_number) || !slice.empty()) { |
| 1278 // Previously, the key generator state was not stored explicitly | 1298 INTERNAL_READ_ERROR(GET_KEY_GENERATOR_CURRENT_NUMBER); |
| 1279 // but derived from the maximum numeric key present in existing | 1299 return false; |
| 1280 // data. This violates the spec as the data may be cleared but the | |
| 1281 // key generator state must be preserved. | |
| 1282 // TODO(jsbell): Fix this for all stores on database open? | |
| 1283 const std::vector<char> start_key = | |
| 1284 ObjectStoreDataKey::Encode(database_id, object_store_id, MinIDBKey()); | |
| 1285 const std::vector<char> stop_key = | |
| 1286 ObjectStoreDataKey::Encode(database_id, object_store_id, MaxIDBKey()); | |
| 1287 | |
| 1288 scoped_ptr<LevelDBIterator> it = leveldb_transaction->CreateIterator(); | |
| 1289 int64 max_numeric_key = 0; | |
| 1290 | |
| 1291 for (it->Seek(LevelDBSlice(start_key)); | |
| 1292 it->IsValid() && CompareKeys(it->Key(), LevelDBSlice(stop_key)) < 0; | |
| 1293 it->Next()) { | |
| 1294 const char* p = it->Key().begin(); | |
| 1295 const char* limit = it->Key().end(); | |
| 1296 | |
| 1297 ObjectStoreDataKey data_key; | |
| 1298 p = ObjectStoreDataKey::Decode(p, limit, &data_key); | |
| 1299 DCHECK(p); | |
| 1300 | |
| 1301 scoped_ptr<IndexedDBKey> user_key = data_key.user_key(); | |
| 1302 if (user_key->type() == WebKit::WebIDBKey::NumberType) { | |
| 1303 int64 n = static_cast<int64>(user_key->number()); | |
| 1304 if (n > max_numeric_key) | |
| 1305 max_numeric_key = n; | |
| 1306 } | |
| 1307 } | 1300 } |
| 1308 | 1301 return true; |
| 1309 key_generator_current_number = max_numeric_key + 1; | |
| 1310 } | 1302 } |
| 1311 | 1303 |
| 1304 // Previously, the key generator state was not stored explicitly |
| 1305 // but derived from the maximum numeric key present in existing |
| 1306 // data. This violates the spec as the data may be cleared but the |
| 1307 // key generator state must be preserved. |
| 1308 // TODO(jsbell): Fix this for all stores on database open? |
| 1309 const std::vector<char> start_key = |
| 1310 ObjectStoreDataKey::Encode(database_id, object_store_id, MinIDBKey()); |
| 1311 const std::vector<char> stop_key = |
| 1312 ObjectStoreDataKey::Encode(database_id, object_store_id, MaxIDBKey()); |
| 1313 |
| 1314 scoped_ptr<LevelDBIterator> it = leveldb_transaction->CreateIterator(); |
| 1315 int64 max_numeric_key = 0; |
| 1316 |
| 1317 for (it->Seek(LevelDBSlice(start_key)); |
| 1318 it->IsValid() && CompareKeys(it->Key(), LevelDBSlice(stop_key)) < 0; |
| 1319 it->Next()) { |
| 1320 const char* p = it->Key().begin(); |
| 1321 const char* limit = it->Key().end(); |
| 1322 |
| 1323 ObjectStoreDataKey data_key; |
| 1324 p = ObjectStoreDataKey::Decode(p, limit, &data_key); |
| 1325 DCHECK(p); |
| 1326 |
| 1327 scoped_ptr<IndexedDBKey> user_key = data_key.user_key(); |
| 1328 if (user_key->type() == WebKit::WebIDBKey::NumberType) { |
| 1329 int64 n = static_cast<int64>(user_key->number()); |
| 1330 if (n > max_numeric_key) |
| 1331 max_numeric_key = n; |
| 1332 } |
| 1333 } |
| 1334 |
| 1335 key_generator_current_number = max_numeric_key + 1; |
| 1312 return true; | 1336 return true; |
| 1313 } | 1337 } |
| 1314 | 1338 |
| 1315 bool IndexedDBBackingStore::MaybeUpdateKeyGeneratorCurrentNumber( | 1339 bool IndexedDBBackingStore::MaybeUpdateKeyGeneratorCurrentNumber( |
| 1316 IndexedDBBackingStore::Transaction* transaction, | 1340 IndexedDBBackingStore::Transaction* transaction, |
| 1317 int64 database_id, | 1341 int64 database_id, |
| 1318 int64 object_store_id, | 1342 int64 object_store_id, |
| 1319 int64 new_number, | 1343 int64 new_number, |
| 1320 bool check_current) { | 1344 bool check_current) { |
| 1321 if (!KeyPrefix::ValidIds(database_id, object_store_id)) | 1345 if (!KeyPrefix::ValidIds(database_id, object_store_id)) |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1352 RecordIdentifier* found_record_identifier, | 1376 RecordIdentifier* found_record_identifier, |
| 1353 bool& found) { | 1377 bool& found) { |
| 1354 IDB_TRACE("IndexedDBBackingStore::key_exists_in_object_store"); | 1378 IDB_TRACE("IndexedDBBackingStore::key_exists_in_object_store"); |
| 1355 if (!KeyPrefix::ValidIds(database_id, object_store_id)) | 1379 if (!KeyPrefix::ValidIds(database_id, object_store_id)) |
| 1356 return false; | 1380 return false; |
| 1357 found = false; | 1381 found = false; |
| 1358 LevelDBTransaction* leveldb_transaction = | 1382 LevelDBTransaction* leveldb_transaction = |
| 1359 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction); | 1383 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction); |
| 1360 const std::vector<char> leveldb_key = | 1384 const std::vector<char> leveldb_key = |
| 1361 ObjectStoreDataKey::Encode(database_id, object_store_id, key); | 1385 ObjectStoreDataKey::Encode(database_id, object_store_id, key); |
| 1362 std::vector<char> data; | 1386 std::string data; |
| 1363 | 1387 |
| 1364 bool ok = leveldb_transaction->Get(LevelDBSlice(leveldb_key), data, found); | 1388 bool ok = leveldb_transaction->Get(LevelDBSlice(leveldb_key), &data, found); |
| 1365 if (!ok) { | 1389 if (!ok) { |
| 1366 INTERNAL_READ_ERROR(KEY_EXISTS_IN_OBJECT_STORE); | 1390 INTERNAL_READ_ERROR(KEY_EXISTS_IN_OBJECT_STORE); |
| 1367 return false; | 1391 return false; |
| 1368 } | 1392 } |
| 1369 if (!found) | 1393 if (!found) |
| 1370 return true; | 1394 return true; |
| 1371 if (!data.size()) { | 1395 if (!data.size()) { |
| 1372 INTERNAL_READ_ERROR(KEY_EXISTS_IN_OBJECT_STORE); | 1396 INTERNAL_READ_ERROR(KEY_EXISTS_IN_OBJECT_STORE); |
| 1373 return false; | 1397 return false; |
| 1374 } | 1398 } |
| 1375 | 1399 |
| 1376 int64 version; | 1400 int64 version; |
| 1377 if (DecodeVarInt(&*data.begin(), &*data.rbegin() + 1, version) == 0) | 1401 StringPiece slice(data); |
| 1402 if (!DecodeVarInt(&slice, &version)) |
| 1378 return false; | 1403 return false; |
| 1379 | 1404 |
| 1380 found_record_identifier->Reset(EncodeIDBKey(key), version); | 1405 std::vector<char> encoded_key; |
| 1406 EncodeIDBKey(key, &encoded_key); |
| 1407 found_record_identifier->Reset(encoded_key, version); |
| 1381 return true; | 1408 return true; |
| 1382 } | 1409 } |
| 1383 | 1410 |
| 1384 static bool CheckIndexAndMetaDataKey(const LevelDBIterator* it, | 1411 static bool CheckIndexAndMetaDataKey(const LevelDBIterator* it, |
| 1385 const std::vector<char>& stop_key, | 1412 const std::vector<char>& stop_key, |
| 1386 int64 index_id, | 1413 int64 index_id, |
| 1387 unsigned char meta_data_type) { | 1414 unsigned char meta_data_type) { |
| 1388 if (!it->IsValid() || CompareKeys(it->Key(), LevelDBSlice(stop_key)) >= 0) | 1415 if (!it->IsValid() || CompareKeys(it->Key(), LevelDBSlice(stop_key)) >= 0) |
| 1389 return false; | 1416 return false; |
| 1390 | 1417 |
| 1391 IndexMetaDataKey meta_data_key; | 1418 IndexMetaDataKey meta_data_key; |
| 1392 const char* p = IndexMetaDataKey::Decode( | 1419 const char* p = IndexMetaDataKey::Decode( |
| 1393 it->Key().begin(), it->Key().end(), &meta_data_key); | 1420 it->Key().begin(), it->Key().end(), &meta_data_key); |
| 1394 DCHECK(p); | 1421 DCHECK(p); |
| 1395 if (meta_data_key.IndexId() != index_id) | 1422 if (meta_data_key.IndexId() != index_id) |
| 1396 return false; | 1423 return false; |
| 1397 if (meta_data_key.meta_data_type() != meta_data_type) | 1424 if (meta_data_key.meta_data_type() != meta_data_type) |
| 1398 return false; | 1425 return false; |
| 1399 return true; | 1426 return true; |
| 1400 } | 1427 } |
| 1401 | 1428 |
| 1402 // TODO(jsbell): This should do some error handling rather than plowing ahead | 1429 // TODO(jsbell): This should do some error handling rather than plowing ahead |
| 1403 // when bad | 1430 // when bad data is encountered. |
| 1404 // data is encountered. | |
| 1405 bool IndexedDBBackingStore::GetIndexes( | 1431 bool IndexedDBBackingStore::GetIndexes( |
| 1406 int64 database_id, | 1432 int64 database_id, |
| 1407 int64 object_store_id, | 1433 int64 object_store_id, |
| 1408 IndexedDBObjectStoreMetadata::IndexMap* indexes) { | 1434 IndexedDBObjectStoreMetadata::IndexMap* indexes) { |
| 1409 IDB_TRACE("IndexedDBBackingStore::get_indexes"); | 1435 IDB_TRACE("IndexedDBBackingStore::get_indexes"); |
| 1410 if (!KeyPrefix::ValidIds(database_id, object_store_id)) | 1436 if (!KeyPrefix::ValidIds(database_id, object_store_id)) |
| 1411 return false; | 1437 return false; |
| 1412 const std::vector<char> start_key = | 1438 const std::vector<char> start_key = |
| 1413 IndexMetaDataKey::Encode(database_id, object_store_id, 0, 0); | 1439 IndexMetaDataKey::Encode(database_id, object_store_id, 0, 0); |
| 1414 const std::vector<char> stop_key = | 1440 const std::vector<char> stop_key = |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1430 INTERNAL_CONSISTENCY_ERROR(GET_INDEXES); | 1456 INTERNAL_CONSISTENCY_ERROR(GET_INDEXES); |
| 1431 // Possible stale metadata due to http://webkit.org/b/85557 but don't fail | 1457 // Possible stale metadata due to http://webkit.org/b/85557 but don't fail |
| 1432 // the load. | 1458 // the load. |
| 1433 it->Next(); | 1459 it->Next(); |
| 1434 continue; | 1460 continue; |
| 1435 } | 1461 } |
| 1436 | 1462 |
| 1437 // TODO(jsbell): Do this by direct key lookup rather than iteration, to | 1463 // TODO(jsbell): Do this by direct key lookup rather than iteration, to |
| 1438 // simplify. | 1464 // simplify. |
| 1439 int64 index_id = meta_data_key.IndexId(); | 1465 int64 index_id = meta_data_key.IndexId(); |
| 1440 string16 index_name = DecodeString(it->Value().begin(), it->Value().end()); | 1466 string16 index_name; |
| 1467 { |
| 1468 StringPiece slice(it->Value().AsStringPiece()); |
| 1469 if (!DecodeString(&slice, &index_name) || !slice.empty()) |
| 1470 INTERNAL_CONSISTENCY_ERROR(GET_INDEXES); |
| 1471 } |
| 1441 | 1472 |
| 1442 it->Next(); // unique flag | 1473 it->Next(); // unique flag |
| 1443 if (!CheckIndexAndMetaDataKey( | 1474 if (!CheckIndexAndMetaDataKey( |
| 1444 it.get(), stop_key, index_id, IndexMetaDataKey::UNIQUE)) { | 1475 it.get(), stop_key, index_id, IndexMetaDataKey::UNIQUE)) { |
| 1445 INTERNAL_CONSISTENCY_ERROR(GET_INDEXES); | 1476 INTERNAL_CONSISTENCY_ERROR(GET_INDEXES); |
| 1446 break; | 1477 break; |
| 1447 } | 1478 } |
| 1448 bool index_unique = DecodeBool(it->Value().begin(), it->Value().end()); | 1479 bool index_unique; |
| 1480 { |
| 1481 StringPiece slice(it->Value().AsStringPiece()); |
| 1482 if (!DecodeBool(&slice, &index_unique) || !slice.empty()) |
| 1483 INTERNAL_CONSISTENCY_ERROR(GET_INDEXES); |
| 1484 } |
| 1449 | 1485 |
| 1450 it->Next(); // key_path | 1486 it->Next(); // key_path |
| 1451 if (!CheckIndexAndMetaDataKey( | 1487 if (!CheckIndexAndMetaDataKey( |
| 1452 it.get(), stop_key, index_id, IndexMetaDataKey::KEY_PATH)) { | 1488 it.get(), stop_key, index_id, IndexMetaDataKey::KEY_PATH)) { |
| 1453 INTERNAL_CONSISTENCY_ERROR(GET_INDEXES); | 1489 INTERNAL_CONSISTENCY_ERROR(GET_INDEXES); |
| 1454 break; | 1490 break; |
| 1455 } | 1491 } |
| 1456 IndexedDBKeyPath key_path = | 1492 IndexedDBKeyPath key_path; |
| 1457 DecodeIDBKeyPath(it->Value().begin(), it->Value().end()); | 1493 { |
| 1494 StringPiece slice(it->Value().AsStringPiece()); |
| 1495 if (!DecodeIDBKeyPath(&slice, &key_path) || !slice.empty()) |
| 1496 INTERNAL_CONSISTENCY_ERROR(GET_INDEXES); |
| 1497 } |
| 1458 | 1498 |
| 1459 it->Next(); // [optional] multi_entry flag | 1499 it->Next(); // [optional] multi_entry flag |
| 1460 bool index_multi_entry = false; | 1500 bool index_multi_entry = false; |
| 1461 if (CheckIndexAndMetaDataKey( | 1501 if (CheckIndexAndMetaDataKey( |
| 1462 it.get(), stop_key, index_id, IndexMetaDataKey::MULTI_ENTRY)) { | 1502 it.get(), stop_key, index_id, IndexMetaDataKey::MULTI_ENTRY)) { |
| 1463 index_multi_entry = DecodeBool(it->Value().begin(), it->Value().end()); | 1503 StringPiece slice(it->Value().AsStringPiece()); |
| 1504 if (!DecodeBool(&slice, &index_multi_entry) || !slice.empty()) |
| 1505 INTERNAL_CONSISTENCY_ERROR(GET_INDEXES); |
| 1506 |
| 1464 it->Next(); | 1507 it->Next(); |
| 1465 } | 1508 } |
| 1466 | 1509 |
| 1467 (*indexes)[index_id] = IndexedDBIndexMetadata( | 1510 (*indexes)[index_id] = IndexedDBIndexMetadata( |
| 1468 index_name, index_id, key_path, index_unique, index_multi_entry); | 1511 index_name, index_id, key_path, index_unique, index_multi_entry); |
| 1469 } | 1512 } |
| 1470 return true; | 1513 return true; |
| 1471 } | 1514 } |
| 1472 | 1515 |
| 1473 WARN_UNUSED_RESULT static bool SetMaxIndexId(LevelDBTransaction* transaction, | 1516 WARN_UNUSED_RESULT static bool SetMaxIndexId(LevelDBTransaction* transaction, |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1562 int64 index_id, | 1605 int64 index_id, |
| 1563 const IndexedDBKey& key, | 1606 const IndexedDBKey& key, |
| 1564 const RecordIdentifier& record_identifier) { | 1607 const RecordIdentifier& record_identifier) { |
| 1565 IDB_TRACE("IndexedDBBackingStore::put_index_data_for_record"); | 1608 IDB_TRACE("IndexedDBBackingStore::put_index_data_for_record"); |
| 1566 DCHECK(key.IsValid()); | 1609 DCHECK(key.IsValid()); |
| 1567 if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id)) | 1610 if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id)) |
| 1568 return false; | 1611 return false; |
| 1569 | 1612 |
| 1570 LevelDBTransaction* leveldb_transaction = | 1613 LevelDBTransaction* leveldb_transaction = |
| 1571 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction); | 1614 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction); |
| 1615 |
| 1616 std::vector<char> encoded_key; |
| 1617 EncodeIDBKey(key, &encoded_key); |
| 1618 |
| 1572 const std::vector<char> index_data_key = | 1619 const std::vector<char> index_data_key = |
| 1573 IndexDataKey::Encode(database_id, | 1620 IndexDataKey::Encode(database_id, |
| 1574 object_store_id, | 1621 object_store_id, |
| 1575 index_id, | 1622 index_id, |
| 1576 EncodeIDBKey(key), | 1623 encoded_key, |
| 1577 record_identifier.primary_key()); | 1624 record_identifier.primary_key()); |
| 1578 | 1625 |
| 1579 std::vector<char> data; | 1626 std::vector<char> data; |
| 1580 EncodeVarInt(record_identifier.version(), &data); | 1627 EncodeVarInt(record_identifier.version(), &data); |
| 1581 const std::vector<char>& primary_key = record_identifier.primary_key(); | 1628 const std::vector<char>& primary_key = record_identifier.primary_key(); |
| 1582 data.insert(data.end(), primary_key.begin(), primary_key.end()); | 1629 data.insert(data.end(), primary_key.begin(), primary_key.end()); |
| 1583 | 1630 |
| 1584 leveldb_transaction->Put(LevelDBSlice(index_data_key), data); | 1631 leveldb_transaction->Put(LevelDBSlice(index_data_key), data); |
| 1585 return true; | 1632 return true; |
| 1586 } | 1633 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1614 } | 1661 } |
| 1615 | 1662 |
| 1616 static bool VersionExists(LevelDBTransaction* transaction, | 1663 static bool VersionExists(LevelDBTransaction* transaction, |
| 1617 int64 database_id, | 1664 int64 database_id, |
| 1618 int64 object_store_id, | 1665 int64 object_store_id, |
| 1619 int64 version, | 1666 int64 version, |
| 1620 const std::vector<char>& encoded_primary_key, | 1667 const std::vector<char>& encoded_primary_key, |
| 1621 bool& exists) { | 1668 bool& exists) { |
| 1622 const std::vector<char> key = | 1669 const std::vector<char> key = |
| 1623 ExistsEntryKey::Encode(database_id, object_store_id, encoded_primary_key); | 1670 ExistsEntryKey::Encode(database_id, object_store_id, encoded_primary_key); |
| 1624 std::vector<char> data; | 1671 std::string data; |
| 1625 | 1672 |
| 1626 bool ok = transaction->Get(LevelDBSlice(key), data, exists); | 1673 bool ok = transaction->Get(LevelDBSlice(key), &data, exists); |
| 1627 if (!ok) { | 1674 if (!ok) { |
| 1628 INTERNAL_READ_ERROR(VERSION_EXISTS); | 1675 INTERNAL_READ_ERROR(VERSION_EXISTS); |
| 1629 return false; | 1676 return false; |
| 1630 } | 1677 } |
| 1631 if (!exists) | 1678 if (!exists) |
| 1632 return true; | 1679 return true; |
| 1633 | 1680 |
| 1634 exists = (DecodeInt(data.begin(), data.end()) == version); | 1681 StringPiece slice(data); |
| 1682 int64 decoded; |
| 1683 if (!DecodeInt(&slice, &decoded) || !slice.empty()) |
| 1684 return false; |
| 1685 exists = (decoded == version); |
| 1635 return true; | 1686 return true; |
| 1636 } | 1687 } |
| 1637 | 1688 |
| 1638 bool IndexedDBBackingStore::FindKeyInIndex( | 1689 bool IndexedDBBackingStore::FindKeyInIndex( |
| 1639 IndexedDBBackingStore::Transaction* transaction, | 1690 IndexedDBBackingStore::Transaction* transaction, |
| 1640 int64 database_id, | 1691 int64 database_id, |
| 1641 int64 object_store_id, | 1692 int64 object_store_id, |
| 1642 int64 index_id, | 1693 int64 index_id, |
| 1643 const IndexedDBKey& key, | 1694 const IndexedDBKey& key, |
| 1644 std::vector<char>& found_encoded_primary_key, | 1695 std::vector<char>& found_encoded_primary_key, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1655 IndexDataKey::Encode(database_id, object_store_id, index_id, key); | 1706 IndexDataKey::Encode(database_id, object_store_id, index_id, key); |
| 1656 scoped_ptr<LevelDBIterator> it = leveldb_transaction->CreateIterator(); | 1707 scoped_ptr<LevelDBIterator> it = leveldb_transaction->CreateIterator(); |
| 1657 it->Seek(LevelDBSlice(leveldb_key)); | 1708 it->Seek(LevelDBSlice(leveldb_key)); |
| 1658 | 1709 |
| 1659 for (;;) { | 1710 for (;;) { |
| 1660 if (!it->IsValid()) | 1711 if (!it->IsValid()) |
| 1661 return true; | 1712 return true; |
| 1662 if (CompareIndexKeys(it->Key(), LevelDBSlice(leveldb_key)) > 0) | 1713 if (CompareIndexKeys(it->Key(), LevelDBSlice(leveldb_key)) > 0) |
| 1663 return true; | 1714 return true; |
| 1664 | 1715 |
| 1716 StringPiece slice(it->Value().AsStringPiece()); |
| 1717 |
| 1665 int64 version; | 1718 int64 version; |
| 1666 const char* p = | 1719 if (!DecodeVarInt(&slice, &version)) { |
| 1667 DecodeVarInt(it->Value().begin(), it->Value().end(), version); | |
| 1668 if (!p) { | |
| 1669 INTERNAL_READ_ERROR(FIND_KEY_IN_INDEX); | 1720 INTERNAL_READ_ERROR(FIND_KEY_IN_INDEX); |
| 1670 return false; | 1721 return false; |
| 1671 } | 1722 } |
| 1672 found_encoded_primary_key.insert( | 1723 found_encoded_primary_key.insert( |
| 1673 found_encoded_primary_key.end(), p, it->Value().end()); | 1724 found_encoded_primary_key.end(), slice.begin(), slice.end()); |
| 1674 | 1725 |
| 1675 bool exists = false; | 1726 bool exists = false; |
| 1676 bool ok = VersionExists(leveldb_transaction, | 1727 bool ok = VersionExists(leveldb_transaction, |
| 1677 database_id, | 1728 database_id, |
| 1678 object_store_id, | 1729 object_store_id, |
| 1679 version, | 1730 version, |
| 1680 found_encoded_primary_key, | 1731 found_encoded_primary_key, |
| 1681 exists); | 1732 exists); |
| 1682 if (!ok) | 1733 if (!ok) |
| 1683 return false; | 1734 return false; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1716 INTERNAL_READ_ERROR(GET_PRIMARY_KEY_VIA_INDEX); | 1767 INTERNAL_READ_ERROR(GET_PRIMARY_KEY_VIA_INDEX); |
| 1717 return false; | 1768 return false; |
| 1718 } | 1769 } |
| 1719 if (!found) | 1770 if (!found) |
| 1720 return true; | 1771 return true; |
| 1721 if (!found_encoded_primary_key.size()) { | 1772 if (!found_encoded_primary_key.size()) { |
| 1722 INTERNAL_READ_ERROR(GET_PRIMARY_KEY_VIA_INDEX); | 1773 INTERNAL_READ_ERROR(GET_PRIMARY_KEY_VIA_INDEX); |
| 1723 return false; | 1774 return false; |
| 1724 } | 1775 } |
| 1725 | 1776 |
| 1726 DecodeIDBKey(&*found_encoded_primary_key.begin(), | 1777 StringPiece slice(&*found_encoded_primary_key.begin(), |
| 1727 &*found_encoded_primary_key.rbegin() + 1, | 1778 found_encoded_primary_key.size()); |
| 1728 primary_key); | 1779 return DecodeIDBKey(&slice, primary_key) && slice.empty(); |
| 1729 return true; | |
| 1730 } | 1780 } |
| 1731 | 1781 |
| 1732 bool IndexedDBBackingStore::KeyExistsInIndex( | 1782 bool IndexedDBBackingStore::KeyExistsInIndex( |
| 1733 IndexedDBBackingStore::Transaction* transaction, | 1783 IndexedDBBackingStore::Transaction* transaction, |
| 1734 int64 database_id, | 1784 int64 database_id, |
| 1735 int64 object_store_id, | 1785 int64 object_store_id, |
| 1736 int64 index_id, | 1786 int64 index_id, |
| 1737 const IndexedDBKey& index_key, | 1787 const IndexedDBKey& index_key, |
| 1738 scoped_ptr<IndexedDBKey>* found_primary_key, | 1788 scoped_ptr<IndexedDBKey>* found_primary_key, |
| 1739 bool& exists) { | 1789 bool& exists) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1754 INTERNAL_READ_ERROR(KEY_EXISTS_IN_INDEX); | 1804 INTERNAL_READ_ERROR(KEY_EXISTS_IN_INDEX); |
| 1755 return false; | 1805 return false; |
| 1756 } | 1806 } |
| 1757 if (!exists) | 1807 if (!exists) |
| 1758 return true; | 1808 return true; |
| 1759 if (!found_encoded_primary_key.size()) { | 1809 if (!found_encoded_primary_key.size()) { |
| 1760 INTERNAL_READ_ERROR(KEY_EXISTS_IN_INDEX); | 1810 INTERNAL_READ_ERROR(KEY_EXISTS_IN_INDEX); |
| 1761 return false; | 1811 return false; |
| 1762 } | 1812 } |
| 1763 | 1813 |
| 1764 DecodeIDBKey(&*found_encoded_primary_key.begin(), | 1814 StringPiece slice(&*found_encoded_primary_key.begin(), |
| 1765 &*found_encoded_primary_key.rbegin() + 1, | 1815 found_encoded_primary_key.size()); |
| 1766 found_primary_key); | 1816 return DecodeIDBKey(&slice, found_primary_key) && slice.empty(); |
| 1767 return true; | |
| 1768 } | 1817 } |
| 1769 | 1818 |
| 1770 IndexedDBBackingStore::Cursor::Cursor( | 1819 IndexedDBBackingStore::Cursor::Cursor( |
| 1771 const IndexedDBBackingStore::Cursor* other) | 1820 const IndexedDBBackingStore::Cursor* other) |
| 1772 : transaction_(other->transaction_), | 1821 : transaction_(other->transaction_), |
| 1773 cursor_options_(other->cursor_options_), | 1822 cursor_options_(other->cursor_options_), |
| 1774 current_key_(new IndexedDBKey(*other->current_key_)) { | 1823 current_key_(new IndexedDBKey(*other->current_key_)) { |
| 1775 if (other->iterator_) { | 1824 if (other->iterator_) { |
| 1776 iterator_ = transaction_->CreateIterator(); | 1825 iterator_ = transaction_->CreateIterator(); |
| 1777 | 1826 |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1986 key_position = ObjectStoreDataKey::Decode( | 2035 key_position = ObjectStoreDataKey::Decode( |
| 1987 key_position, key_limit, &object_store_data_key); | 2036 key_position, key_limit, &object_store_data_key); |
| 1988 if (!key_position) { | 2037 if (!key_position) { |
| 1989 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); | 2038 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); |
| 1990 return false; | 2039 return false; |
| 1991 } | 2040 } |
| 1992 | 2041 |
| 1993 current_key_ = object_store_data_key.user_key(); | 2042 current_key_ = object_store_data_key.user_key(); |
| 1994 | 2043 |
| 1995 int64 version; | 2044 int64 version; |
| 1996 const char* value_position = DecodeVarInt( | 2045 StringPiece slice(iterator_->Value().AsStringPiece()); |
| 1997 iterator_->Value().begin(), iterator_->Value().end(), version); | 2046 if (!DecodeVarInt(&slice, &version)) { |
| 1998 if (!value_position) { | |
| 1999 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); | 2047 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); |
| 2000 return false; | 2048 return false; |
| 2001 } | 2049 } |
| 2002 | 2050 |
| 2003 // TODO(jsbell): This re-encodes what was just decoded; try and optimize. | 2051 // TODO(jsbell): This re-encodes what was just decoded; try and optimize. |
| 2004 record_identifier_.Reset(EncodeIDBKey(*current_key_), version); | 2052 std::vector<char> encoded_key; |
| 2053 EncodeIDBKey(*current_key_, &encoded_key); |
| 2054 record_identifier_.Reset(encoded_key, version); |
| 2005 | 2055 |
| 2006 return true; | 2056 return true; |
| 2007 } | 2057 } |
| 2008 | 2058 |
| 2009 class ObjectStoreCursorImpl : public IndexedDBBackingStore::Cursor { | 2059 class ObjectStoreCursorImpl : public IndexedDBBackingStore::Cursor { |
| 2010 public: | 2060 public: |
| 2011 ObjectStoreCursorImpl( | 2061 ObjectStoreCursorImpl( |
| 2012 LevelDBTransaction* transaction, | 2062 LevelDBTransaction* transaction, |
| 2013 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options) | 2063 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options) |
| 2014 : IndexedDBBackingStore::Cursor(transaction, cursor_options) {} | 2064 : IndexedDBBackingStore::Cursor(transaction, cursor_options) {} |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2041 key_position = ObjectStoreDataKey::Decode( | 2091 key_position = ObjectStoreDataKey::Decode( |
| 2042 key_position, key_limit, &object_store_data_key); | 2092 key_position, key_limit, &object_store_data_key); |
| 2043 if (!key_position) { | 2093 if (!key_position) { |
| 2044 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); | 2094 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); |
| 2045 return false; | 2095 return false; |
| 2046 } | 2096 } |
| 2047 | 2097 |
| 2048 current_key_ = object_store_data_key.user_key(); | 2098 current_key_ = object_store_data_key.user_key(); |
| 2049 | 2099 |
| 2050 int64 version; | 2100 int64 version; |
| 2051 const char* value_position = DecodeVarInt( | 2101 StringPiece slice(iterator_->Value().AsStringPiece()); |
| 2052 iterator_->Value().begin(), iterator_->Value().end(), version); | 2102 if (!DecodeVarInt(&slice, &version)) { |
| 2053 if (!value_position) { | |
| 2054 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); | 2103 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); |
| 2055 return false; | 2104 return false; |
| 2056 } | 2105 } |
| 2057 | 2106 |
| 2058 // TODO(jsbell): This re-encodes what was just decoded; try and optimize. | 2107 // TODO(jsbell): This re-encodes what was just decoded; try and optimize. |
| 2059 record_identifier_.Reset(EncodeIDBKey(*current_key_), version); | 2108 std::vector<char> encoded_key; |
| 2109 EncodeIDBKey(*current_key_, &encoded_key); |
| 2110 record_identifier_.Reset(encoded_key, version); |
| 2060 | 2111 |
| 2061 std::vector<char> value; | 2112 std::vector<char> value; |
| 2062 value.insert(value.end(), value_position, iterator_->Value().end()); | 2113 value.insert(value.end(), slice.begin(), slice.end()); |
| 2063 current_value_.swap(value); | 2114 current_value_.swap(value); |
| 2064 return true; | 2115 return true; |
| 2065 } | 2116 } |
| 2066 | 2117 |
| 2067 class IndexKeyCursorImpl : public IndexedDBBackingStore::Cursor { | 2118 class IndexKeyCursorImpl : public IndexedDBBackingStore::Cursor { |
| 2068 public: | 2119 public: |
| 2069 IndexKeyCursorImpl( | 2120 IndexKeyCursorImpl( |
| 2070 LevelDBTransaction* transaction, | 2121 LevelDBTransaction* transaction, |
| 2071 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options) | 2122 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options) |
| 2072 : IndexedDBBackingStore::Cursor(transaction, cursor_options) {} | 2123 : IndexedDBBackingStore::Cursor(transaction, cursor_options) {} |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2107 bool IndexKeyCursorImpl::LoadCurrentRow() { | 2158 bool IndexKeyCursorImpl::LoadCurrentRow() { |
| 2108 const char* key_position = iterator_->Key().begin(); | 2159 const char* key_position = iterator_->Key().begin(); |
| 2109 const char* key_limit = iterator_->Key().end(); | 2160 const char* key_limit = iterator_->Key().end(); |
| 2110 | 2161 |
| 2111 IndexDataKey index_data_key; | 2162 IndexDataKey index_data_key; |
| 2112 key_position = IndexDataKey::Decode(key_position, key_limit, &index_data_key); | 2163 key_position = IndexDataKey::Decode(key_position, key_limit, &index_data_key); |
| 2113 | 2164 |
| 2114 current_key_ = index_data_key.user_key(); | 2165 current_key_ = index_data_key.user_key(); |
| 2115 DCHECK(current_key_); | 2166 DCHECK(current_key_); |
| 2116 | 2167 |
| 2168 StringPiece slice(iterator_->Value().AsStringPiece()); |
| 2117 int64 index_data_version; | 2169 int64 index_data_version; |
| 2118 const char* value_position = DecodeVarInt( | 2170 if (!DecodeVarInt(&slice, &index_data_version)) { |
| 2119 iterator_->Value().begin(), iterator_->Value().end(), index_data_version); | |
| 2120 if (!value_position) { | |
| 2121 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); | 2171 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); |
| 2122 return false; | 2172 return false; |
| 2123 } | 2173 } |
| 2124 | 2174 |
| 2125 value_position = | 2175 if (!DecodeIDBKey(&slice, &primary_key_) || !slice.empty()) { |
| 2126 DecodeIDBKey(value_position, iterator_->Value().end(), &primary_key_); | |
| 2127 if (!value_position) { | |
| 2128 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); | 2176 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); |
| 2129 return false; | 2177 return false; |
| 2130 } | 2178 } |
| 2131 | 2179 |
| 2132 std::vector<char> primary_leveldb_key = | 2180 std::vector<char> primary_leveldb_key = |
| 2133 ObjectStoreDataKey::Encode(index_data_key.DatabaseId(), | 2181 ObjectStoreDataKey::Encode(index_data_key.DatabaseId(), |
| 2134 index_data_key.ObjectStoreId(), | 2182 index_data_key.ObjectStoreId(), |
| 2135 *primary_key_); | 2183 *primary_key_); |
| 2136 | 2184 |
| 2137 std::vector<char> result; | 2185 std::string result; |
| 2138 bool found = false; | 2186 bool found = false; |
| 2139 bool ok = transaction_->Get(LevelDBSlice(primary_leveldb_key), result, found); | 2187 bool ok = |
| 2188 transaction_->Get(LevelDBSlice(primary_leveldb_key), &result, found); |
| 2140 if (!ok) { | 2189 if (!ok) { |
| 2141 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); | 2190 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); |
| 2142 return false; | 2191 return false; |
| 2143 } | 2192 } |
| 2144 if (!found) { | 2193 if (!found) { |
| 2145 transaction_->Remove(iterator_->Key()); | 2194 transaction_->Remove(iterator_->Key()); |
| 2146 return false; | 2195 return false; |
| 2147 } | 2196 } |
| 2148 if (!result.size()) { | 2197 if (!result.size()) { |
| 2149 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); | 2198 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); |
| 2150 return false; | 2199 return false; |
| 2151 } | 2200 } |
| 2152 | 2201 |
| 2153 int64 object_store_data_version; | 2202 int64 object_store_data_version; |
| 2154 const char* t = DecodeVarInt( | 2203 slice = StringPiece(result); |
| 2155 &*result.begin(), &*result.rbegin() + 1, object_store_data_version); | 2204 if (!DecodeVarInt(&slice, &object_store_data_version)) { |
| 2156 if (!t) { | |
| 2157 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); | 2205 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); |
| 2158 return false; | 2206 return false; |
| 2159 } | 2207 } |
| 2160 | 2208 |
| 2161 if (object_store_data_version != index_data_version) { | 2209 if (object_store_data_version != index_data_version) { |
| 2162 transaction_->Remove(iterator_->Key()); | 2210 transaction_->Remove(iterator_->Key()); |
| 2163 return false; | 2211 return false; |
| 2164 } | 2212 } |
| 2165 | 2213 |
| 2166 return true; | 2214 return true; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2210 bool IndexCursorImpl::LoadCurrentRow() { | 2258 bool IndexCursorImpl::LoadCurrentRow() { |
| 2211 const char* key_position = iterator_->Key().begin(); | 2259 const char* key_position = iterator_->Key().begin(); |
| 2212 const char* key_limit = iterator_->Key().end(); | 2260 const char* key_limit = iterator_->Key().end(); |
| 2213 | 2261 |
| 2214 IndexDataKey index_data_key; | 2262 IndexDataKey index_data_key; |
| 2215 key_position = IndexDataKey::Decode(key_position, key_limit, &index_data_key); | 2263 key_position = IndexDataKey::Decode(key_position, key_limit, &index_data_key); |
| 2216 | 2264 |
| 2217 current_key_ = index_data_key.user_key(); | 2265 current_key_ = index_data_key.user_key(); |
| 2218 DCHECK(current_key_); | 2266 DCHECK(current_key_); |
| 2219 | 2267 |
| 2220 const char* value_position = iterator_->Value().begin(); | 2268 StringPiece slice(iterator_->Value().AsStringPiece()); |
| 2221 const char* value_limit = iterator_->Value().end(); | |
| 2222 | |
| 2223 int64 index_data_version; | 2269 int64 index_data_version; |
| 2224 value_position = | 2270 if (!DecodeVarInt(&slice, &index_data_version)) { |
| 2225 DecodeVarInt(value_position, value_limit, index_data_version); | |
| 2226 if (!value_position) { | |
| 2227 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); | 2271 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); |
| 2228 return false; | 2272 return false; |
| 2229 } | 2273 } |
| 2230 value_position = DecodeIDBKey(value_position, value_limit, &primary_key_); | 2274 if (!DecodeIDBKey(&slice, &primary_key_)) { |
| 2231 if (!value_position) { | |
| 2232 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); | 2275 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); |
| 2233 return false; | 2276 return false; |
| 2234 } | 2277 } |
| 2235 | 2278 |
| 2236 primary_leveldb_key_ = | 2279 primary_leveldb_key_ = |
| 2237 ObjectStoreDataKey::Encode(index_data_key.DatabaseId(), | 2280 ObjectStoreDataKey::Encode(index_data_key.DatabaseId(), |
| 2238 index_data_key.ObjectStoreId(), | 2281 index_data_key.ObjectStoreId(), |
| 2239 *primary_key_); | 2282 *primary_key_); |
| 2240 | 2283 |
| 2241 std::vector<char> result; | 2284 std::string result; |
| 2242 bool found = false; | 2285 bool found = false; |
| 2243 bool ok = | 2286 bool ok = |
| 2244 transaction_->Get(LevelDBSlice(primary_leveldb_key_), result, found); | 2287 transaction_->Get(LevelDBSlice(primary_leveldb_key_), &result, found); |
| 2245 if (!ok) { | 2288 if (!ok) { |
| 2246 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); | 2289 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); |
| 2247 return false; | 2290 return false; |
| 2248 } | 2291 } |
| 2249 if (!found) { | 2292 if (!found) { |
| 2250 transaction_->Remove(iterator_->Key()); | 2293 transaction_->Remove(iterator_->Key()); |
| 2251 return false; | 2294 return false; |
| 2252 } | 2295 } |
| 2253 if (!result.size()) { | 2296 if (!result.size()) { |
| 2254 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); | 2297 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); |
| 2255 return false; | 2298 return false; |
| 2256 } | 2299 } |
| 2257 | 2300 |
| 2258 int64 object_store_data_version; | 2301 int64 object_store_data_version; |
| 2259 value_position = DecodeVarInt( | 2302 slice = StringPiece(result); |
| 2260 &*result.begin(), &*result.rbegin() + 1, object_store_data_version); | 2303 if (!DecodeVarInt(&slice, &object_store_data_version)) { |
| 2261 if (!value_position) { | |
| 2262 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); | 2304 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); |
| 2263 return false; | 2305 return false; |
| 2264 } | 2306 } |
| 2265 | 2307 |
| 2266 if (object_store_data_version != index_data_version) { | 2308 if (object_store_data_version != index_data_version) { |
| 2267 transaction_->Remove(iterator_->Key()); | 2309 transaction_->Remove(iterator_->Key()); |
| 2268 return false; | 2310 return false; |
| 2269 } | 2311 } |
| 2270 | 2312 |
| 2271 // TODO(jsbell): Make value_position an iterator. | 2313 current_value_.clear(); |
| 2272 std::vector<char> value; | 2314 current_value_.insert(current_value_.end(), slice.begin(), slice.end()); |
| 2273 value.insert(value.end(), | |
| 2274 value_position, | |
| 2275 static_cast<const char*>(&*result.rbegin()) + 1); | |
| 2276 current_value_.swap(value); | |
| 2277 return true; | 2315 return true; |
| 2278 } | 2316 } |
| 2279 | 2317 |
| 2280 bool ObjectStoreCursorOptions( | 2318 bool ObjectStoreCursorOptions( |
| 2281 LevelDBTransaction* transaction, | 2319 LevelDBTransaction* transaction, |
| 2282 int64 database_id, | 2320 int64 database_id, |
| 2283 int64 object_store_id, | 2321 int64 object_store_id, |
| 2284 const IndexedDBKeyRange& range, | 2322 const IndexedDBKeyRange& range, |
| 2285 indexed_db::CursorDirection direction, | 2323 indexed_db::CursorDirection direction, |
| 2286 IndexedDBBackingStore::Cursor::CursorOptions& cursor_options) { | 2324 IndexedDBBackingStore::Cursor::CursorOptions& cursor_options) { |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2546 } | 2584 } |
| 2547 | 2585 |
| 2548 void IndexedDBBackingStore::Transaction::Rollback() { | 2586 void IndexedDBBackingStore::Transaction::Rollback() { |
| 2549 IDB_TRACE("IndexedDBBackingStore::Transaction::rollback"); | 2587 IDB_TRACE("IndexedDBBackingStore::Transaction::rollback"); |
| 2550 DCHECK(transaction_); | 2588 DCHECK(transaction_); |
| 2551 transaction_->Rollback(); | 2589 transaction_->Rollback(); |
| 2552 transaction_ = NULL; | 2590 transaction_ = NULL; |
| 2553 } | 2591 } |
| 2554 | 2592 |
| 2555 } // namespace content | 2593 } // namespace content |
| OLD | NEW |