Changeset 84149 in webkit
- Timestamp:
- Apr 18, 2011 9:13:25 AM (13 years ago)
- Location:
- trunk
- Files:
-
- 7 added
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/ChangeLog
r84130 r84149 1 2011-04-18 Hans Wennborg <hans@chromium.org> 2 3 Reviewed by Steve Block. 4 5 LevelDB backend for IndexedDB 6 https://bugs.webkit.org/show_bug.cgi?id=57372 7 8 Add LevelDB wrappers to Android.mk. 9 10 * Source/Android.mk: 11 1 12 2011-04-18 Patrick Gansterer <paroga@webkit.org> 2 13 -
trunk/Source/Android.mk
r78107 r84149 117 117 $(LOCAL_PATH)/WebCore/platform/graphics/transforms \ 118 118 $(LOCAL_PATH)/WebCore/platform/image-decoders \ 119 $(LOCAL_PATH)/WebCore/platform/leveldb \ 119 120 $(LOCAL_PATH)/WebCore/platform/mock \ 120 121 $(LOCAL_PATH)/WebCore/platform/network \ -
trunk/Source/WebCore/Android.mk
r84039 r84149 604 604 platform/image-decoders/gif/GIFImageDecoder.cpp \ 605 605 platform/image-decoders/gif/GIFImageReader.cpp \ 606 \ 607 platform/leveldb/LevelDBDatabase.cpp \ 608 platform/leveldb/LevelDBIterator.cpp \ 606 609 \ 607 610 platform/mock/DeviceOrientationClientMock.cpp \ -
trunk/Source/WebCore/CMakeLists.txt
r84125 r84149 39 39 "${WEBCORE_DIR}/platform/image-decoders/png" 40 40 "${WEBCORE_DIR}/platform/image-decoders/webp" 41 "${WEBCORE_DIR}/platform/leveldb" 41 42 "${WEBCORE_DIR}/platform/mock" 42 43 "${WEBCORE_DIR}/platform/network" … … 1447 1448 dom/DataTransferItem.cpp 1448 1449 dom/StringCallback.cpp 1450 ) 1451 ENDIF () 1452 1453 IF (ENABLE_LEVELDB) 1454 LIST(APPEND WebCore_SOURCES 1455 platform/leveldb/LevelDBDatabase.cpp 1456 platform/leveldb/LevelDBIterator.cpp 1449 1457 ) 1450 1458 ENDIF () -
trunk/Source/WebCore/ChangeLog
r84148 r84149 1 2011-04-18 Hans Wennborg <hans@chromium.org> 2 3 Reviewed by Steve Block. 4 5 LevelDB backend for IndexedDB 6 https://bugs.webkit.org/show_bug.cgi?id=57372 7 8 Only available behind a run-time flag. Covered by existing layout 9 tests. 10 11 * Android.mk: 12 * CMakeLists.txt: 13 * GNUmakefile.am: 14 * GNUmakefile.list.am: 15 * WebCore.gyp/WebCore.gyp: 16 * WebCore.gypi: 17 * WebCore.pri: 18 * WebCore.pro: 19 * WebCore.xcodeproj/project.pbxproj: 20 * platform/leveldb/LevelDBComparator.h: Added. 21 (WebCore::LevelDBComparator::~LevelDBComparator): 22 * platform/leveldb/LevelDBDatabase.cpp: Added. 23 (WebCore::makeSlice): 24 (WebCore::makeLevelDBSlice): 25 (WebCore::makeVector): 26 (WebCore::LevelDBDatabase::LevelDBDatabase): 27 (WebCore::LevelDBDatabase::~LevelDBDatabase): 28 (WebCore::LevelDBDatabase::open): 29 (WebCore::LevelDBDatabase::put): 30 (WebCore::LevelDBDatabase::remove): 31 (WebCore::LevelDBDatabase::get): 32 (WebCore::LevelDBDatabase::newIterator): 33 * platform/leveldb/LevelDBDatabase.h: Added. 34 * platform/leveldb/LevelDBIterator.cpp: Added. 35 (WebCore::LevelDBIterator::~LevelDBIterator): 36 (WebCore::LevelDBIterator::LevelDBIterator): 37 (WebCore::makeSlice): 38 (WebCore::makeLevelDBSlice): 39 (WebCore::LevelDBIterator::isValid): 40 (WebCore::LevelDBIterator::seekToLast): 41 (WebCore::LevelDBIterator::seek): 42 (WebCore::LevelDBIterator::next): 43 (WebCore::LevelDBIterator::prev): 44 (WebCore::LevelDBIterator::key): 45 (WebCore::LevelDBIterator::value): 46 * platform/leveldb/LevelDBIterator.h: Added. 47 * platform/leveldb/LevelDBSlice.h: Added. 48 (WebCore::LevelDBSlice::LevelDBSlice): 49 (WebCore::LevelDBSlice::~LevelDBSlice): 50 (WebCore::LevelDBSlice::begin): 51 (WebCore::LevelDBSlice::end): 52 * storage/IDBLevelDBBackingStore.cpp: 53 (WebCore::encodeByte): 54 (WebCore::maxIDBKey): 55 (WebCore::minIDBKey): 56 (WebCore::encodeInt): 57 (WebCore::decodeInt): 58 (WebCore::encodeVarInt): 59 (WebCore::decodeVarInt): 60 (WebCore::encodeString): 61 (WebCore::decodeString): 62 (WebCore::encodeStringWithLength): 63 (WebCore::decodeStringWithLength): 64 (WebCore::encodeDouble): 65 (WebCore::decodeDouble): 66 (WebCore::encodeIDBKey): 67 (WebCore::decodeIDBKey): 68 (WebCore::extractEncodedIDBKey): 69 (WebCore::compareEncodedIDBKeys): 70 (WebCore::getInt): 71 (WebCore::putInt): 72 (WebCore::getString): 73 (WebCore::putString): 74 (WebCore::KeyPrefix::SchemaVersionKey::encode): 75 (WebCore::KeyPrefix::MaxDatabaseIdKey::encode): 76 (WebCore::KeyPrefix::DatabaseFreeListKey::DatabaseFreeListKey): 77 (WebCore::KeyPrefix::DatabaseFreeListKey::decode): 78 (WebCore::KeyPrefix::DatabaseFreeListKey::encode): 79 (WebCore::KeyPrefix::DatabaseFreeListKey::databaseId): 80 (WebCore::KeyPrefix::DatabaseFreeListKey::compare): 81 (WebCore::KeyPrefix::DatabaseNameKey::decode): 82 (WebCore::KeyPrefix::DatabaseNameKey::encode): 83 (WebCore::KeyPrefix::DatabaseNameKey::origin): 84 (WebCore::KeyPrefix::DatabaseNameKey::databaseName): 85 (WebCore::KeyPrefix::DatabaseNameKey::compare): 86 (WebCore::KeyPrefix::DatabaseMetaDataKey::encode): 87 (WebCore::KeyPrefix::ObjectStoreMetaDataKey::ObjectStoreMetaDataKey): 88 (WebCore::KeyPrefix::ObjectStoreMetaDataKey::decode): 89 (WebCore::KeyPrefix::ObjectStoreMetaDataKey::encode): 90 (WebCore::KeyPrefix::ObjectStoreMetaDataKey::objectStoreId): 91 (WebCore::KeyPrefix::ObjectStoreMetaDataKey::metaDataType): 92 (WebCore::KeyPrefix::ObjectStoreMetaDataKey::compare): 93 (WebCore::KeyPrefix::IndexMetaDataKey::IndexMetaDataKey): 94 (WebCore::KeyPrefix::IndexMetaDataKey::decode): 95 (WebCore::KeyPrefix::IndexMetaDataKey::encode): 96 (WebCore::KeyPrefix::IndexMetaDataKey::compare): 97 (WebCore::KeyPrefix::IndexMetaDataKey::indexId): 98 (WebCore::KeyPrefix::IndexMetaDataKey::metaDataType): 99 (WebCore::KeyPrefix::ObjectStoreFreeListKey::ObjectStoreFreeListKey): 100 (WebCore::KeyPrefix::ObjectStoreFreeListKey::decode): 101 (WebCore::KeyPrefix::ObjectStoreFreeListKey::encode): 102 (WebCore::KeyPrefix::ObjectStoreFreeListKey::objectStoreId): 103 (WebCore::KeyPrefix::ObjectStoreFreeListKey::compare): 104 (WebCore::KeyPrefix::IndexFreeListKey::IndexFreeListKey): 105 (WebCore::KeyPrefix::IndexFreeListKey::decode): 106 (WebCore::KeyPrefix::IndexFreeListKey::encode): 107 (WebCore::KeyPrefix::IndexFreeListKey::compare): 108 (WebCore::KeyPrefix::IndexFreeListKey::objectStoreId): 109 (WebCore::KeyPrefix::IndexFreeListKey::indexId): 110 (WebCore::KeyPrefix::ObjectStoreNamesKey::decode): 111 (WebCore::KeyPrefix::ObjectStoreNamesKey::encode): 112 (WebCore::KeyPrefix::ObjectStoreNamesKey::compare): 113 (WebCore::KeyPrefix::ObjectStoreNamesKey::objectStoreName): 114 (WebCore::KeyPrefix::IndexNamesKey::IndexNamesKey): 115 (WebCore::KeyPrefix::IndexNamesKey::decode): 116 (WebCore::KeyPrefix::IndexNamesKey::encode): 117 (WebCore::KeyPrefix::IndexNamesKey::compare): 118 (WebCore::KeyPrefix::IndexNamesKey::indexName): 119 (WebCore::KeyPrefix::ObjectStoreDataKey::decode): 120 (WebCore::KeyPrefix::ObjectStoreDataKey::encode): 121 (WebCore::KeyPrefix::ObjectStoreDataKey::compare): 122 (WebCore::KeyPrefix::ObjectStoreDataKey::userKey): 123 (WebCore::KeyPrefix::ExistsEntryKey::decode): 124 (WebCore::KeyPrefix::ExistsEntryKey::encode): 125 (WebCore::KeyPrefix::ExistsEntryKey::compare): 126 (WebCore::KeyPrefix::ExistsEntryKey::userKey): 127 (WebCore::KeyPrefix::IndexDataKey::IndexDataKey): 128 (WebCore::KeyPrefix::IndexDataKey::decode): 129 (WebCore::KeyPrefix::IndexDataKey::encode): 130 (WebCore::KeyPrefix::IndexDataKey::encodeMaxKey): 131 (WebCore::KeyPrefix::IndexDataKey::compare): 132 (WebCore::KeyPrefix::IndexDataKey::databaseId): 133 (WebCore::KeyPrefix::IndexDataKey::objectStoreId): 134 (WebCore::KeyPrefix::IndexDataKey::indexId): 135 (WebCore::KeyPrefix::IndexDataKey::userKey): 136 (WebCore::KeyPrefix::realCompare): 137 (WebCore::KeyPrefix::compareKeys): 138 (WebCore::KeyPrefix::compareIndexKeys): 139 (WebCore::KeyPrefix::Comparator::compare): 140 (WebCore::KeyPrefix::Comparator::name): 141 (WebCore::setUpMetadata): 142 (WebCore::IDBLevelDBBackingStore::IDBLevelDBBackingStore): 143 (WebCore::IDBLevelDBBackingStore::open): 144 (WebCore::IDBLevelDBBackingStore::extractIDBDatabaseMetaData): 145 (WebCore::getNewDatabaseId): 146 (WebCore::IDBLevelDBBackingStore::setIDBDatabaseMetaData): 147 (WebCore::IDBLevelDBBackingStore::getObjectStores): 148 (WebCore::getNewObjectStoreId): 149 (WebCore::IDBLevelDBBackingStore::createObjectStore): 150 (WebCore::deleteRange): 151 (WebCore::IDBLevelDBBackingStore::deleteObjectStore): 152 (WebCore::IDBLevelDBBackingStore::getObjectStoreRecord): 153 (WebCore::getNewVersionNumber): 154 (WebCore::IDBLevelDBBackingStore::putObjectStoreRecord): 155 (WebCore::IDBLevelDBBackingStore::clearObjectStore): 156 (WebCore::IDBLevelDBBackingStore::createInvalidRecordIdentifier): 157 (WebCore::IDBLevelDBBackingStore::deleteObjectStoreRecord): 158 (WebCore::IDBLevelDBBackingStore::nextAutoIncrementNumber): 159 (WebCore::IDBLevelDBBackingStore::keyExistsInObjectStore): 160 (WebCore::IDBLevelDBBackingStore::forEachObjectStoreRecord): 161 (WebCore::IDBLevelDBBackingStore::getIndexes): 162 (WebCore::getNewIndexId): 163 (WebCore::IDBLevelDBBackingStore::createIndex): 164 (WebCore::IDBLevelDBBackingStore::deleteIndex): 165 (WebCore::IDBLevelDBBackingStore::putIndexDataForRecord): 166 (WebCore::findGreatestKeyLessThan): 167 (WebCore::IDBLevelDBBackingStore::deleteIndexDataForRecord): 168 (WebCore::IDBLevelDBBackingStore::getObjectViaIndex): 169 (WebCore::versionExists): 170 (WebCore::IDBLevelDBBackingStore::getPrimaryKeyViaIndex): 171 (WebCore::IDBLevelDBBackingStore::keyExistsInIndex): 172 (WebCore::findLastIndexKeyEqualTo): 173 (WebCore::IDBLevelDBBackingStore::openObjectStoreCursor): 174 (WebCore::IDBLevelDBBackingStore::openIndexKeyCursor): 175 (WebCore::IDBLevelDBBackingStore::openIndexCursor): 176 (WebCore::IDBLevelDBBackingStore::createTransaction): 177 * storage/IDBLevelDBBackingStore.h: 178 1 179 2011-04-18 Pavel Feldman <pfeldman@google.com> 2 180 -
trunk/Source/WebCore/GNUmakefile.am
r84053 r84149 57 57 -I$(srcdir)/Source/WebCore/platform/image-decoders/webp \ 58 58 -I$(srcdir)/Source/WebCore/platform/image-decoders/png \ 59 -I$(srcdir)/Source/WebCore/platform/leveldb \ 59 60 -I$(srcdir)/Source/WebCore/platform/mock \ 60 61 -I$(srcdir)/Source/WebCore/platform/network \ -
trunk/Source/WebCore/GNUmakefile.list.am
r84125 r84149 2509 2509 Source/WebCore/platform/Length.h \ 2510 2510 Source/WebCore/platform/LengthSize.h \ 2511 Source/WebCore/platform/leveldb/LevelDBComparator.h \ 2512 Source/WebCore/platform/leveldb/LevelDBDatabase.cpp \ 2513 Source/WebCore/platform/leveldb/LevelDBDatabase.h \ 2514 Source/WebCore/platform/leveldb/LevelDBIterator.cpp \ 2515 Source/WebCore/platform/leveldb/LevelDBIterator.h \ 2516 Source/WebCore/platform/leveldb/LevelDBSlice.h \ 2511 2517 Source/WebCore/platform/LinkHash.cpp \ 2512 2518 Source/WebCore/platform/LinkHash.h \ -
trunk/Source/WebCore/WebCore.gyp/WebCore.gyp
r83893 r84149 185 185 '../platform/image-decoders/webp', 186 186 '../platform/image-encoders/skia', 187 '../platform/leveldb', 187 188 '../platform/mock', 188 189 '../platform/network', -
trunk/Source/WebCore/WebCore.gypi
r84125 r84149 859 859 'platform/graphics/transforms/TransformationMatrix.h', 860 860 'platform/gtk/PasteboardHelper.h', 861 'platform/leveldb/LevelDBComparator.h', 862 'platform/leveldb/LevelDBDatabase.cpp', 863 'platform/leveldb/LevelDBDatabase.h', 864 'platform/leveldb/LevelDBIterator.cpp', 865 'platform/leveldb/LevelDBIterator.h', 866 'platform/leveldb/LevelDBSlice.h', 861 867 'platform/mac/BlockExceptions.h', 862 868 'platform/mac/ClipboardMac.h', -
trunk/Source/WebCore/WebCore.pri
r83835 r84149 98 98 $$SOURCE_DIR/WebCore/platform/graphics/transforms \ 99 99 $$SOURCE_DIR/WebCore/platform/image-decoders \ 100 $$SOURCE_DIR/WebCore/platform/leveldb \ 100 101 $$SOURCE_DIR/WebCore/platform/mock \ 101 102 $$SOURCE_DIR/WebCore/platform/network \ -
trunk/Source/WebCore/WebCore.pro
r84125 r84149 1012 1012 platform/Length.cpp \ 1013 1013 platform/text/LineEnding.cpp \ 1014 platform/leveldb/LevelDBComparator.h \ 1015 platform/leveldb/LevelDBDatabase.cpp \ 1016 platform/leveldb/LevelDBDatabase.h \ 1017 platform/leveldb/LevelDBIterator.cpp \ 1018 platform/leveldb/LevelDBIterator.h \ 1019 platform/leveldb/LevelDBSlice.h \ 1014 1020 platform/LinkHash.cpp \ 1015 1021 platform/Logging.cpp \ -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r84125 r84149 2791 2791 8C6EA61911EF7E0400FD8EE3 /* RuntimeEnabledFeatures.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C6EA61711EF7E0400FD8EE3 /* RuntimeEnabledFeatures.cpp */; }; 2792 2792 8C6EA61A11EF7E0400FD8EE3 /* RuntimeEnabledFeatures.h in Headers */ = {isa = PBXBuildFile; fileRef = 8C6EA61811EF7E0400FD8EE3 /* RuntimeEnabledFeatures.h */; }; 2793 8CADF2A9135C7B36009EF43F /* LevelDBComparator.h in Headers */ = {isa = PBXBuildFile; fileRef = 8CADF2A3135C7B36009EF43F /* LevelDBComparator.h */; }; 2794 8CADF2AA135C7B36009EF43F /* LevelDBDatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CADF2A4135C7B36009EF43F /* LevelDBDatabase.cpp */; }; 2795 8CADF2AB135C7B36009EF43F /* LevelDBDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 8CADF2A5135C7B36009EF43F /* LevelDBDatabase.h */; }; 2796 8CADF2AC135C7B36009EF43F /* LevelDBIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CADF2A6135C7B36009EF43F /* LevelDBIterator.cpp */; }; 2797 8CADF2AD135C7B36009EF43F /* LevelDBIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = 8CADF2A7135C7B36009EF43F /* LevelDBIterator.h */; }; 2798 8CADF2AE135C7B36009EF43F /* LevelDBSlice.h in Headers */ = {isa = PBXBuildFile; fileRef = 8CADF2A8135C7B36009EF43F /* LevelDBSlice.h */; }; 2793 2799 8F67561B1288B17B0047ACA3 /* EventQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 8F6756191288B17B0047ACA3 /* EventQueue.h */; }; 2794 2800 8F67561C1288B17B0047ACA3 /* EventQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8F67561A1288B17B0047ACA3 /* EventQueue.cpp */; }; … … 9350 9356 8C6EA61711EF7E0400FD8EE3 /* RuntimeEnabledFeatures.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RuntimeEnabledFeatures.cpp; path = generic/RuntimeEnabledFeatures.cpp; sourceTree = "<group>"; }; 9351 9357 8C6EA61811EF7E0400FD8EE3 /* RuntimeEnabledFeatures.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RuntimeEnabledFeatures.h; path = generic/RuntimeEnabledFeatures.h; sourceTree = "<group>"; }; 9358 8CADF2A3135C7B36009EF43F /* LevelDBComparator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LevelDBComparator.h; sourceTree = "<group>"; }; 9359 8CADF2A4135C7B36009EF43F /* LevelDBDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LevelDBDatabase.cpp; sourceTree = "<group>"; }; 9360 8CADF2A5135C7B36009EF43F /* LevelDBDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LevelDBDatabase.h; sourceTree = "<group>"; }; 9361 8CADF2A6135C7B36009EF43F /* LevelDBIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LevelDBIterator.cpp; sourceTree = "<group>"; }; 9362 8CADF2A7135C7B36009EF43F /* LevelDBIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LevelDBIterator.h; sourceTree = "<group>"; }; 9363 8CADF2A8135C7B36009EF43F /* LevelDBSlice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LevelDBSlice.h; sourceTree = "<group>"; }; 9352 9364 8F6756191288B17B0047ACA3 /* EventQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventQueue.h; sourceTree = "<group>"; }; 9353 9365 8F67561A1288B17B0047ACA3 /* EventQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EventQueue.cpp; sourceTree = "<group>"; }; … … 15614 15626 sourceTree = "<group>"; 15615 15627 }; 15628 8CADF2A2135C7B36009EF43F /* leveldb */ = { 15629 isa = PBXGroup; 15630 children = ( 15631 8CADF2A3135C7B36009EF43F /* LevelDBComparator.h */, 15632 8CADF2A4135C7B36009EF43F /* LevelDBDatabase.cpp */, 15633 8CADF2A5135C7B36009EF43F /* LevelDBDatabase.h */, 15634 8CADF2A6135C7B36009EF43F /* LevelDBIterator.cpp */, 15635 8CADF2A7135C7B36009EF43F /* LevelDBIterator.h */, 15636 8CADF2A8135C7B36009EF43F /* LevelDBSlice.h */, 15637 ); 15638 path = leveldb; 15639 sourceTree = "<group>"; 15640 }; 15616 15641 93309D86099E64910056E581 /* editing */ = { 15617 15642 isa = PBXGroup; … … 18628 18653 B2A015910AF6CD53006BCE0E /* graphics */, 18629 18654 A59E3C1B11580F340072928E /* iphone */, 18655 8CADF2A2135C7B36009EF43F /* leveldb */, 18630 18656 6582A14809999D6C00BEEB6D /* mac */, 18631 18657 59C77F101054591C00506104 /* mock */, … … 22967 22993 E1BE512E0CF6C512002EA959 /* XSLTUnicodeSort.h in Headers */, 22968 22994 977E2E0F12F0FC9C00C13379 /* XSSFilter.h in Headers */, 22995 8CADF2A9135C7B36009EF43F /* LevelDBComparator.h in Headers */, 22996 8CADF2AB135C7B36009EF43F /* LevelDBDatabase.h in Headers */, 22997 8CADF2AD135C7B36009EF43F /* LevelDBIterator.h in Headers */, 22998 8CADF2AE135C7B36009EF43F /* LevelDBSlice.h in Headers */, 22969 22999 ); 22970 23000 runOnlyForDeploymentPostprocessing = 0; … … 25673 25703 E1BE512D0CF6C512002EA959 /* XSLTUnicodeSort.cpp in Sources */, 25674 25704 977E2E0E12F0FC9C00C13379 /* XSSFilter.cpp in Sources */, 25705 8CADF2AA135C7B36009EF43F /* LevelDBDatabase.cpp in Sources */, 25706 8CADF2AC135C7B36009EF43F /* LevelDBIterator.cpp in Sources */, 25675 25707 ); 25676 25708 runOnlyForDeploymentPostprocessing = 0; -
trunk/Source/WebCore/storage/IDBLevelDBBackingStore.cpp
r83443 r84149 30 30 #if ENABLE(LEVELDB) 31 31 32 #include "Assertions.h" 33 #include "FileSystem.h" 32 34 #include "IDBFactoryBackendImpl.h" 33 #include <leveldb/db.h> 35 #include "IDBKeyRange.h" 36 #include "LevelDBComparator.h" 37 #include "LevelDBDatabase.h" 38 #include "LevelDBIterator.h" 39 #include "LevelDBSlice.h" 40 #include "SecurityOrigin.h" 41 #include <string> 42 43 #ifndef INT64_MAX 44 // FIXME: We shouldn't need to rely on these macros. 45 #define INT64_MAX 0x7fffffffffffffffLL 46 #endif 47 #ifndef INT32_MAX 48 #define INT32_MAX 0x7fffffffL 49 #endif 50 51 // LevelDB stores key/value pairs. Keys and values are strings of bytes, normally of type Vector<char>. 52 // 53 // The keys in the backing store are variable-length tuples with different types 54 // of fields. Each key in the backing store starts with a ternary prefix: (database id, object store id, index id). For each, 0 is reserved for meta-data. 55 // The prefix makes sure that data for a specific database, object store, and index are grouped together. The locality is important for performance: common 56 // operations should only need a minimal number of seek operations. For example, all the meta-data for a database is grouped together so that reading that 57 // meta-data only requires one seek. 58 // 59 // Each key type has a class (in square brackets below) which knows how to encode, decode, and compare that key type. 60 // 61 // Global meta-data have keys with prefix (0,0,0), followed by a type byte: 62 // 63 // <0, 0, 0, 0> => IndexedDB/LevelDB schema version (0 for now) [SchemaVersionKey] 64 // <0, 0, 0, 1> => The maximum database id ever allocated [MaxDatabaseIdKey] 65 // <0, 0, 0, 100, database id> => Existence implies the database id is in the free list [DatabaseFreeListKey] 66 // <0, 0, 0, 201, utf16 origin name, utf16 database name> => Database id [DatabaseNameKey] 67 // 68 // 69 // Database meta-data: 70 // 71 // Again, the prefix is followed by a type byte. 72 // 73 // <database id, 0, 0, 0> => utf16 origin name [DatabaseMetaDataKey] 74 // <database id, 0, 0, 1> => utf16 database name [DatabaseMetaDataKey] 75 // <database id, 0, 0, 2> => utf16 user version data [DatabaseMetaDataKey] 76 // <database id, 0, 0, 3> => maximum object store id ever allocated [DatabaseMetaDataKey] 77 // 78 // 79 // Object store meta-data: 80 // 81 // The prefix is followed by a type byte, then a variable-length integer, and then another variable-length integer (FIXME: this should be a byte). 82 // 83 // <database id, 0, 0, 50, object store id, 0> => utf16 object store name [ObjectStoreMetaDataKey] 84 // <database id, 0, 0, 50, object store id, 1> => utf16 key path [ObjectStoreMetaDataKey] 85 // <database id, 0, 0, 50, object store id, 2> => has auto increment [ObjectStoreMetaDataKey] 86 // <database id, 0, 0, 50, object store id, 3> => is evictable [ObjectStoreMetaDataKey] 87 // <database id, 0, 0, 50, object store id, 4> => last "version" number [ObjectStoreMetaDataKey] 88 // <database id, 0, 0, 50, object store id, 5> => maximum index id ever allocated [ObjectStoreMetaDataKey] 89 // 90 // 91 // Index meta-data: 92 // 93 // The prefix is followed by a type byte, then two variable-length integers, and then another type byte. 94 // 95 // <database id, 0, 0, 100, object store id, index id, 0> => utf16 index name [IndexMetaDataKey] 96 // <database id, 0, 0, 100, object store id, index id, 1> => are index keys unique [IndexMetaDataKey] 97 // <database id, 0, 0, 100, object store id, index id, 2> => utf16 key path [IndexMetaDataKey] 98 // 99 // 100 // Other object store and index meta-data: 101 // 102 // The prefix is followed by a type byte. The object store and index id are variable length integers, the utf16 strings are variable length strings. 103 // 104 // <database id, 0, 0, 150, object store id> => existence implies the object store id is in the free list [ObjectStoreFreeListKey] 105 // <database id, 0, 0, 151, object store id, index id> => existence implies the index id is in the free list [IndexFreeListKey] 106 // <database id, 0, 0, 200, utf16 object store name> => object store id [ObjectStoreNamesKey] 107 // <database id, 0, 0, 201, object store id, utf16 index name> => index id [IndexNamesKey] 108 // 109 // 110 // Object store data: 111 // 112 // The prefix is followed by a type byte. The user key is an encoded IDBKey. 113 // 114 // <database id, object store id, 1, user key> => "version", serialized script value [ObjectStoreDataKey] 115 // 116 // 117 // "Exists" entry: 118 // 119 // The prefix is followed by a type byte. The user key is an encoded IDBKey. 120 // 121 // <database id, object store id, 2, user key> => "version" [ExistsEntryKey] 122 // 123 // 124 // Index data: 125 // 126 // The prefix is followed by a type byte. The user key is an encoded IDBKey. The sequence number is a variable length integer. 127 // 128 // <database id, object store id, index id, user key, sequence number> => "version", user key [IndexDataKey] 129 // 130 // (The sequence number is used to allow two entries with the same user key 131 // in non-unique indexes. The "version" field is used to weed out stale 132 // index data. Whenever new object store data is inserted, it gets a new 133 // "version" number, and new index data is written with this number. When 134 // the index is used for look-ups, entries are validated against the 135 // "exists" entries, and records with old "version" numbers are deleted 136 // when they are encountered in getPrimaryKeyViaIndex, 137 // IndexCursorImpl::loadCurrentRow, and IndexKeyCursorImpl::loadCurrentRow). 138 139 static const unsigned char kIDBKeyNullTypeByte = 0; 140 static const unsigned char kIDBKeyStringTypeByte = 1; 141 static const unsigned char kIDBKeyDateTypeByte = 2; 142 static const unsigned char kIDBKeyNumberTypeByte = 3; 143 static const unsigned char kIDBKeyMinKeyTypeByte = 4; 144 145 static const unsigned char kMinimumIndexId = 30; 146 static const unsigned char kObjectStoreDataIndexId = 1; 147 static const unsigned char kExistsEntryIndexId = 2; 148 149 static const unsigned char kSchemaVersionTypeByte = 0; 150 static const unsigned char kMaxDatabaseIdTypeByte = 1; 151 static const unsigned char kDatabaseFreeListTypeByte = 100; 152 static const unsigned char kDatabaseNameTypeByte = 201; 153 154 static const unsigned char kObjectStoreMetaDataTypeByte = 50; 155 static const unsigned char kIndexMetaDataTypeByte = 100; 156 static const unsigned char kObjectStoreFreeListTypeByte = 150; 157 static const unsigned char kIndexFreeListTypeByte = 151; 158 static const unsigned char kObjectStoreNamesTypeByte = 200; 159 static const unsigned char kIndexNamesKeyTypeByte = 201; 34 160 35 161 namespace WebCore { 36 162 37 IDBLevelDBBackingStore::IDBLevelDBBackingStore(String identifier, IDBFactoryBackendImpl* factory, leveldb::DB* db) 163 static Vector<char> encodeByte(unsigned char c) 164 { 165 Vector<char> v; 166 v.append(c); 167 return v; 168 } 169 170 static Vector<char> maxIDBKey() 171 { 172 return encodeByte(kIDBKeyNullTypeByte); 173 } 174 175 static Vector<char> minIDBKey() 176 { 177 return encodeByte(kIDBKeyMinKeyTypeByte); 178 } 179 180 static Vector<char> encodeInt(int64_t n) 181 { 182 ASSERT(n >= 0); 183 Vector<char> ret; // FIXME: Size this at creation. 184 185 do { 186 unsigned char c = n; 187 ret.append(c); 188 n >>= 8; 189 } while (n); 190 191 return ret; 192 } 193 194 static int64_t decodeInt(const char* begin, const char* end) 195 { 196 ASSERT(begin <= end); 197 int64_t ret = 0; 198 199 while (begin < end) { 200 unsigned char c = *begin++; 201 ret = (ret << 8) | c; 202 } 203 204 return ret; 205 } 206 207 static Vector<char> encodeVarInt(int64_t n) 208 { 209 Vector<char> ret; // FIXME: Size this at creation. 210 211 do { 212 unsigned char c = n & 0x7f; 213 n >>= 7; 214 if (n) 215 c |= 128; 216 ret.append(c); 217 } while (n); 218 219 return ret; 220 } 221 222 static const char* decodeVarInt(const char *p, const char* limit, int64_t& foundInt) 223 { 224 ASSERT(limit >= p); 225 foundInt = 0; 226 227 do { 228 if (p >= limit) 229 return 0; 230 231 foundInt = (foundInt << 7) | (*p & 0x7f); 232 } while (*p++ & 128); 233 return p; 234 } 235 236 static Vector<char> encodeString(const String& s) 237 { 238 Vector<char> ret; // FIXME: Size this at creation. 239 240 for (unsigned i = 0; i < s.length(); ++i) { 241 UChar u = s[i]; 242 unsigned char hi = u >> 8; 243 unsigned char lo = u; 244 ret.append(hi); 245 ret.append(lo); 246 } 247 248 return ret; 249 } 250 251 static String decodeString(const char* p, const char* end) 252 { 253 ASSERT(end >= p); 254 ASSERT(!((end - p) % 2)); 255 256 size_t len = (end - p) / 2; 257 Vector<UChar> vector(len); 258 259 for (size_t i = 0; i < len; ++i) { 260 unsigned char hi = *p++; 261 unsigned char lo = *p++; 262 263 vector[i] = (hi << 8) | lo; 264 } 265 266 return String::adopt(vector); 267 } 268 269 static Vector<char> encodeStringWithLength(const String& s) 270 { 271 Vector<char> ret = encodeVarInt(s.length()); 272 ret.append(encodeString(s)); 273 return ret; 274 } 275 276 static const char* decodeStringWithLength(const char* p, const char* limit, String& foundString) 277 { 278 ASSERT(limit >= p); 279 int64_t len; 280 p = decodeVarInt(p, limit, len); 281 if (!p) 282 return 0; 283 if (p + len * 2 > limit) 284 return 0; 285 286 foundString = decodeString(p, p + len * 2); 287 p += len * 2; 288 return p; 289 } 290 291 static Vector<char> encodeDouble(double x) 292 { 293 // FIXME: It would be nice if we could be byte order independent. 294 const char* p = reinterpret_cast<char*>(&x); 295 Vector<char> v; 296 v.append(p, sizeof(x)); 297 ASSERT(v.size() == sizeof(x)); 298 return v; 299 } 300 301 static const char* decodeDouble(const char* p, const char* limit, double* d) 302 { 303 if (p + sizeof(*d) > limit) 304 return 0; 305 306 char* x = reinterpret_cast<char*>(d); 307 for (size_t i = 0; i < sizeof(*d); ++i) 308 *x++ = *p++; 309 return p; 310 } 311 312 static Vector<char> encodeIDBKey(const IDBKey& key) 313 { 314 Vector<char> ret; 315 316 switch (key.type()) { 317 case IDBKey::NullType: 318 return encodeByte(kIDBKeyNullTypeByte); 319 case IDBKey::StringType: 320 ret = encodeByte(kIDBKeyStringTypeByte); 321 ret.append(encodeStringWithLength(key.string())); 322 return ret; 323 case IDBKey::DateType: 324 ret = encodeByte(kIDBKeyDateTypeByte); 325 ret.append(encodeDouble(key.date())); 326 ASSERT(ret.size() == 9); 327 return ret; 328 case IDBKey::NumberType: 329 ret = encodeByte(kIDBKeyNumberTypeByte); 330 ret.append(encodeDouble(key.number())); 331 ASSERT(ret.size() == 9); 332 return ret; 333 } 334 335 ASSERT_NOT_REACHED(); 336 return Vector<char>(); 337 } 338 339 static const char* decodeIDBKey(const char* p, const char* limit, RefPtr<IDBKey>& foundKey) 340 { 341 ASSERT(limit >= p); 342 if (p >= limit) 343 return 0; 344 345 unsigned char type = *p++; 346 String s; 347 double d; 348 349 switch (type) { 350 case kIDBKeyNullTypeByte: 351 // Null. 352 foundKey = IDBKey::createNull(); 353 return p; 354 case kIDBKeyStringTypeByte: 355 // String. 356 p = decodeStringWithLength(p, limit, s); 357 if (!p) 358 return 0; 359 foundKey = IDBKey::createString(s); 360 return p; 361 case kIDBKeyDateTypeByte: 362 // Date. 363 p = decodeDouble(p, limit, &d); 364 if (!p) 365 return 0; 366 foundKey = IDBKey::createDate(d); 367 return p; 368 case kIDBKeyNumberTypeByte: 369 // Number. 370 p = decodeDouble(p, limit, &d); 371 if (!p) 372 return 0; 373 foundKey = IDBKey::createNumber(d); 374 return p; 375 } 376 377 ASSERT_NOT_REACHED(); 378 return 0; 379 } 380 381 static const char* extractEncodedIDBKey(const char* start, const char* limit, Vector<char>* result) 382 { 383 const char* p = start; 384 if (p >= limit) 385 return 0; 386 387 unsigned char type = *p++; 388 389 int64_t stringLen; 390 391 switch (type) { 392 case kIDBKeyNullTypeByte: 393 case kIDBKeyMinKeyTypeByte: 394 *result = encodeByte(type); 395 return p; 396 case kIDBKeyStringTypeByte: 397 // String. 398 p = decodeVarInt(p, limit, stringLen); 399 if (!p) 400 return 0; 401 if (p + stringLen * 2 > limit) 402 return 0; 403 result->clear(); 404 result->append(start, p - start + stringLen * 2); 405 return p + stringLen * 2; 406 case kIDBKeyDateTypeByte: 407 case kIDBKeyNumberTypeByte: 408 // Date or number. 409 if (p + sizeof(double) > limit) 410 return 0; 411 result->clear(); 412 result->append(start, 1 + sizeof(double)); 413 return p + sizeof(double); 414 } 415 ASSERT_NOT_REACHED(); 416 return 0; 417 } 418 419 static int compareEncodedIDBKeys(const Vector<char>& keyA, const Vector<char>& keyB) 420 { 421 ASSERT(keyA.size() >= 1); 422 ASSERT(keyB.size() >= 1); 423 424 const char* p = keyA.data(); 425 const char* limitA = p + keyA.size(); 426 const char* q = keyB.data(); 427 const char* limitB = q + keyB.size(); 428 429 unsigned char typeA = *p++; 430 unsigned char typeB = *q++; 431 432 String s, t; 433 double d, e; 434 435 if (int x = typeB - typeA) // FIXME: Note the subtleness! 436 return x; 437 438 switch (typeA) { 439 case kIDBKeyNullTypeByte: 440 case kIDBKeyMinKeyTypeByte: 441 // Null type or max type; no payload to compare. 442 return 0; 443 case kIDBKeyStringTypeByte: 444 // String type. 445 p = decodeStringWithLength(p, limitA, s); // FIXME: Compare without actually decoding the String! 446 ASSERT(p); 447 q = decodeStringWithLength(q, limitB, t); 448 ASSERT(q); 449 return codePointCompare(s, t); 450 case kIDBKeyDateTypeByte: 451 case kIDBKeyNumberTypeByte: 452 // Date or number. 453 p = decodeDouble(p, limitA, &d); 454 ASSERT(p); 455 q = decodeDouble(q, limitB, &e); 456 ASSERT(q); 457 if (d < e) 458 return -1; 459 if (d > e) 460 return 1; 461 return 0; 462 } 463 464 ASSERT_NOT_REACHED(); 465 return 0; 466 } 467 468 static bool getInt(LevelDBDatabase* db, const Vector<char>& key, int64_t& foundInt) 469 { 470 Vector<char> result; 471 if (!db->get(key, result)) 472 return false; 473 474 foundInt = decodeInt(result.begin(), result.end()); 475 return true; 476 } 477 478 static bool putInt(LevelDBDatabase* db, const Vector<char>& key, int64_t value) 479 { 480 return db->put(key, encodeInt(value)); 481 } 482 483 static bool getString(LevelDBDatabase* db, const Vector<char>& key, String& foundString) 484 { 485 Vector<char> result; 486 if (!db->get(key, result)) 487 return false; 488 489 foundString = decodeString(result.begin(), result.end()); 490 return true; 491 } 492 493 static bool putString(LevelDBDatabase* db, const Vector<char> key, const String& value) 494 { 495 if (!db->put(key, encodeString(value))) 496 return false; 497 return true; 498 } 499 500 namespace { 501 class KeyPrefix { 502 public: 503 KeyPrefix() 504 : m_databaseId(kInvalidType) 505 , m_objectStoreId(kInvalidType) 506 , m_indexId(kInvalidType) 507 { 508 } 509 510 KeyPrefix(int64_t databaseId, int64_t objectStoreId, int64_t indexId) 511 : m_databaseId(databaseId) 512 , m_objectStoreId(objectStoreId) 513 , m_indexId(indexId) 514 { 515 } 516 517 static const char* decode(const char* start, const char* limit, KeyPrefix* result) 518 { 519 if (start == limit) 520 return 0; 521 522 unsigned char firstByte = *start++; 523 524 int databaseIdBytes = ((firstByte >> 5) & 0x7) + 1; 525 int objectStoreIdBytes = ((firstByte >> 2) & 0x7) + 1; 526 int indexIdBytes = (firstByte & 0x3) + 1; 527 528 if (start + databaseIdBytes + objectStoreIdBytes + indexIdBytes > limit) 529 return 0; 530 531 result->m_databaseId = decodeInt(start, start + databaseIdBytes); 532 start += databaseIdBytes; 533 result->m_objectStoreId = decodeInt(start, start + objectStoreIdBytes); 534 start += objectStoreIdBytes; 535 result->m_indexId = decodeInt(start, start + indexIdBytes); 536 start += indexIdBytes; 537 538 return start; 539 } 540 541 Vector<char> encode() const 542 { 543 ASSERT(m_databaseId != kInvalidId); 544 ASSERT(m_objectStoreId != kInvalidId); 545 ASSERT(m_indexId != kInvalidId); 546 547 Vector<char> databaseIdString = encodeInt(m_databaseId); 548 Vector<char> objectStoreIdString = encodeInt(m_objectStoreId); 549 Vector<char> indexIdString = encodeInt(m_indexId); 550 551 ASSERT(databaseIdString.size() <= 8); 552 ASSERT(objectStoreIdString.size() <= 8); 553 ASSERT(indexIdString.size() <= 4); 554 555 556 unsigned char firstByte = (databaseIdString.size() - 1) << 5 | (objectStoreIdString.size() - 1) << 2 | (indexIdString.size() - 1); 557 Vector<char> ret; 558 ret.append(firstByte); 559 ret.append(databaseIdString); 560 ret.append(objectStoreIdString); 561 ret.append(indexIdString); 562 563 return ret; 564 } 565 566 int compare(const KeyPrefix& other) const 567 { 568 ASSERT(m_databaseId != kInvalidId); 569 ASSERT(m_objectStoreId != kInvalidId); 570 ASSERT(m_indexId != kInvalidId); 571 572 if (m_databaseId != other.m_databaseId) 573 return m_databaseId - other.m_databaseId; 574 if (m_objectStoreId != other.m_objectStoreId) 575 return m_objectStoreId - other.m_objectStoreId; 576 if (m_indexId != other.m_indexId) 577 return m_indexId - other.m_indexId; 578 return 0; 579 } 580 581 enum Type { 582 kGlobalMetaData, 583 kDatabaseMetaData, 584 kObjectStoreData, 585 kExistsEntry, 586 kIndexData, 587 kInvalidType 588 }; 589 590 Type type() const 591 { 592 ASSERT(m_databaseId != kInvalidId); 593 ASSERT(m_objectStoreId != kInvalidId); 594 ASSERT(m_indexId != kInvalidId); 595 596 if (!m_databaseId) 597 return kGlobalMetaData; 598 if (!m_objectStoreId) 599 return kDatabaseMetaData; 600 if (m_indexId == kObjectStoreDataIndexId) 601 return kObjectStoreData; 602 if (m_indexId == kExistsEntryIndexId) 603 return kExistsEntry; 604 if (m_indexId >= kMinimumIndexId) 605 return kIndexData; 606 607 ASSERT_NOT_REACHED(); 608 return kInvalidType; 609 } 610 611 int64_t m_databaseId; 612 int64_t m_objectStoreId; 613 int64_t m_indexId; 614 615 static const int64_t kInvalidId = -1; 616 }; 617 618 class SchemaVersionKey { 619 public: 620 static Vector<char> encode() 621 { 622 KeyPrefix prefix(0, 0, 0); 623 Vector<char> ret = prefix.encode(); 624 ret.append(encodeByte(kSchemaVersionTypeByte)); 625 return ret; 626 } 627 }; 628 629 class MaxDatabaseIdKey { 630 public: 631 static Vector<char> encode() 632 { 633 KeyPrefix prefix(0, 0, 0); 634 Vector<char> ret = prefix.encode(); 635 ret.append(encodeByte(kMaxDatabaseIdTypeByte)); 636 return ret; 637 } 638 }; 639 640 class DatabaseFreeListKey { 641 public: 642 DatabaseFreeListKey() 643 : m_databaseId(-1) 644 { 645 } 646 647 static const char* decode(const char* start, const char* limit, DatabaseFreeListKey* result) 648 { 649 KeyPrefix prefix; 650 const char *p = KeyPrefix::decode(start, limit, &prefix); 651 if (!p) 652 return 0; 653 ASSERT(!prefix.m_databaseId); 654 ASSERT(!prefix.m_objectStoreId); 655 ASSERT(!prefix.m_indexId); 656 if (p == limit) 657 return 0; 658 unsigned char typeByte = *p++; 659 ASSERT_UNUSED(typeByte, typeByte == kDatabaseFreeListTypeByte); 660 if (p == limit) 661 return 0; 662 return decodeVarInt(p, limit, result->m_databaseId); 663 } 664 665 static Vector<char> encode(int64_t databaseId) 666 { 667 KeyPrefix prefix(0, 0, 0); 668 Vector<char> ret = prefix.encode(); 669 ret.append(encodeByte(kDatabaseFreeListTypeByte)); 670 ret.append(encodeVarInt(databaseId)); 671 return ret; 672 } 673 674 int64_t databaseId() const 675 { 676 ASSERT(m_databaseId >= 0); 677 return m_databaseId; 678 } 679 680 int compare(const DatabaseFreeListKey& other) const 681 { 682 ASSERT(m_databaseId >= 0); 683 return m_databaseId - other.m_databaseId; 684 } 685 686 private: 687 int64_t m_databaseId; 688 }; 689 690 class DatabaseNameKey { 691 public: 692 static const char* decode(const char* start, const char* limit, DatabaseNameKey* result) 693 { 694 KeyPrefix prefix; 695 const char* p = KeyPrefix::decode(start, limit, &prefix); 696 if (!p) 697 return p; 698 ASSERT(!prefix.m_databaseId); 699 ASSERT(!prefix.m_objectStoreId); 700 ASSERT(!prefix.m_indexId); 701 if (p == limit) 702 return 0; 703 unsigned char typeByte = *p++; 704 ASSERT_UNUSED(typeByte, typeByte == kDatabaseNameTypeByte); 705 if (p == limit) 706 return 0; 707 p = decodeStringWithLength(p, limit, result->m_origin); 708 if (!p) 709 return 0; 710 return decodeStringWithLength(p, limit, result->m_databaseName); 711 } 712 713 static Vector<char> encode(const String& origin, const String& databaseName) 714 { 715 KeyPrefix prefix(0, 0, 0); 716 Vector<char> ret = prefix.encode(); 717 ret.append(encodeByte(kDatabaseNameTypeByte)); 718 ret.append(encodeStringWithLength(origin)); 719 ret.append(encodeStringWithLength(databaseName)); 720 return ret; 721 } 722 723 String origin() const { return m_origin; } 724 String databaseName() const { return m_databaseName; } 725 726 int compare(const DatabaseNameKey& other) 727 { 728 if (int x = codePointCompare(m_origin, other.m_origin)) 729 return x; 730 return codePointCompare(m_databaseName, other.m_databaseName); 731 } 732 733 private: 734 String m_origin; // FIXME: Store encoded strings, or just pointers. 735 String m_databaseName; 736 }; 737 738 class DatabaseMetaDataKey { 739 public: 740 enum MetaDataType { 741 kOriginName = 0, 742 kDatabaseName = 1, 743 kUserVersion = 2, 744 kMaxObjectStoreId = 3 745 }; 746 747 static Vector<char> encode(int64_t databaseId, MetaDataType metaDataType) 748 { 749 KeyPrefix prefix(databaseId, 0, 0); 750 Vector<char> ret = prefix.encode(); 751 ret.append(encodeByte(metaDataType)); 752 return ret; 753 } 754 }; 755 756 class ObjectStoreMetaDataKey { 757 public: 758 ObjectStoreMetaDataKey() 759 : m_objectStoreId(-1) 760 , m_metaDataType(-1) 761 { 762 } 763 764 static const char* decode(const char* start, const char* limit, ObjectStoreMetaDataKey* result) 765 { 766 KeyPrefix prefix; 767 const char* p = KeyPrefix::decode(start, limit, &prefix); 768 if (!p) 769 return 0; 770 ASSERT(prefix.m_databaseId); 771 ASSERT(!prefix.m_objectStoreId); 772 ASSERT(!prefix.m_indexId); 773 if (p == limit) 774 return 0; 775 unsigned char typeByte = *p++; 776 ASSERT_UNUSED(typeByte, typeByte == kObjectStoreMetaDataTypeByte); 777 if (p == limit) 778 return 0; 779 p = decodeVarInt(p, limit, result->m_objectStoreId); 780 if (!p) 781 return 0; 782 ASSERT(result->m_objectStoreId); 783 if (p == limit) 784 return 0; 785 return decodeVarInt(p, limit, result->m_metaDataType); 786 } 787 788 static Vector<char> encode(int64_t databaseId, int64_t objectStoreId, int64_t metaDataType) 789 { 790 KeyPrefix prefix(databaseId, 0, 0); 791 Vector<char> ret = prefix.encode(); 792 ret.append(encodeByte(kObjectStoreMetaDataTypeByte)); 793 ret.append(encodeVarInt(objectStoreId)); 794 ret.append(encodeVarInt(metaDataType)); 795 return ret; 796 } 797 798 int64_t objectStoreId() const 799 { 800 ASSERT(m_objectStoreId >= 0); 801 return m_objectStoreId; 802 } 803 int64_t metaDataType() const 804 { 805 ASSERT(m_metaDataType >= 0); 806 return m_metaDataType; 807 } 808 809 int compare(const ObjectStoreMetaDataKey& other) 810 { 811 ASSERT(m_objectStoreId >= 0); 812 ASSERT(m_metaDataType >= 0); 813 if (int x = m_objectStoreId - other.m_objectStoreId) 814 return x; // FIXME: Is this cast safe? I.e., will it preserve the sign? 815 return m_metaDataType - other.m_metaDataType; 816 } 817 818 private: 819 int64_t m_objectStoreId; 820 int64_t m_metaDataType; // FIXME: Make this a byte. 821 }; 822 823 class IndexMetaDataKey { 824 public: 825 IndexMetaDataKey() 826 : m_objectStoreId(-1) 827 , m_indexId(-1) 828 , m_metaDataType(0) 829 { 830 } 831 832 static const char* decode(const char* start, const char* limit, IndexMetaDataKey* result) 833 { 834 KeyPrefix prefix; 835 const char* p = KeyPrefix::decode(start, limit, &prefix); 836 if (!p) 837 return 0; 838 ASSERT(prefix.m_databaseId); 839 ASSERT(!prefix.m_objectStoreId); 840 ASSERT(!prefix.m_indexId); 841 if (p == limit) 842 return 0; 843 unsigned char typeByte = *p++; 844 ASSERT_UNUSED(typeByte, typeByte == kIndexMetaDataTypeByte); 845 if (p == limit) 846 return 0; 847 p = decodeVarInt(p, limit, result->m_objectStoreId); 848 if (!p) 849 return 0; 850 p = decodeVarInt(p, limit, result->m_indexId); 851 if (!p) 852 return 0; 853 if (p == limit) 854 return 0; 855 result->m_metaDataType = *p++; 856 return p; 857 } 858 859 static Vector<char> encode(int64_t databaseId, int64_t objectStoreId, int64_t indexId, unsigned char metaDataType) 860 { 861 KeyPrefix prefix(databaseId, 0, 0); 862 Vector<char> ret = prefix.encode(); 863 ret.append(encodeByte(kIndexMetaDataTypeByte)); 864 ret.append(encodeVarInt(objectStoreId)); 865 ret.append(encodeVarInt(indexId)); 866 ret.append(encodeByte(metaDataType)); 867 return ret; 868 } 869 870 int compare(const IndexMetaDataKey& other) 871 { 872 ASSERT(m_objectStoreId >= 0); 873 ASSERT(m_indexId >= 0); 874 875 if (int x = m_objectStoreId - other.m_objectStoreId) 876 return x; 877 if (int x = m_indexId - other.m_indexId) 878 return x; 879 return m_metaDataType - other.m_metaDataType; 880 } 881 882 int64_t indexId() const 883 { 884 ASSERT(m_indexId >= 0); 885 return m_indexId; 886 } 887 888 unsigned char metaDataType() const { return m_metaDataType; } 889 890 private: 891 int64_t m_objectStoreId; 892 int64_t m_indexId; 893 unsigned char m_metaDataType; 894 }; 895 896 class ObjectStoreFreeListKey { 897 public: 898 ObjectStoreFreeListKey() 899 : m_objectStoreId(-1) 900 { 901 } 902 903 static const char* decode(const char* start, const char* limit, ObjectStoreFreeListKey* result) 904 { 905 KeyPrefix prefix; 906 const char *p = KeyPrefix::decode(start, limit, &prefix); 907 if (!p) 908 return 0; 909 ASSERT(prefix.m_databaseId); 910 ASSERT(!prefix.m_objectStoreId); 911 ASSERT(!prefix.m_indexId); 912 if (p == limit) 913 return 0; 914 unsigned char typeByte = *p++; 915 ASSERT_UNUSED(typeByte, typeByte == kObjectStoreFreeListTypeByte); 916 if (p == limit) 917 return 0; 918 return decodeVarInt(p, limit, result->m_objectStoreId); 919 } 920 921 static Vector<char> encode(int64_t databaseId, int64_t objectStoreId) 922 { 923 KeyPrefix prefix(databaseId, 0, 0); 924 Vector<char> ret = prefix.encode(); 925 ret.append(encodeByte(kObjectStoreFreeListTypeByte)); 926 ret.append(encodeVarInt(objectStoreId)); 927 return ret; 928 } 929 930 int64_t objectStoreId() const 931 { 932 ASSERT(m_objectStoreId >= 0); 933 return m_objectStoreId; 934 } 935 936 int compare(const ObjectStoreFreeListKey& other) 937 { 938 // FIXME: It may seem strange that we're not comparing database id's, 939 // but that comparison will have been made earlier. 940 // We should probably make this more clear, though... 941 ASSERT(m_objectStoreId >= 0); 942 return m_objectStoreId - other.m_objectStoreId; 943 } 944 945 private: 946 int64_t m_objectStoreId; 947 }; 948 949 class IndexFreeListKey { 950 public: 951 IndexFreeListKey() 952 : m_objectStoreId(-1) 953 , m_indexId(-1) 954 { 955 } 956 957 static const char* decode(const char* start, const char* limit, IndexFreeListKey* result) 958 { 959 KeyPrefix prefix; 960 const char* p = KeyPrefix::decode(start, limit, &prefix); 961 if (!p) 962 return 0; 963 ASSERT(prefix.m_databaseId); 964 ASSERT(!prefix.m_objectStoreId); 965 ASSERT(!prefix.m_indexId); 966 if (p == limit) 967 return 0; 968 unsigned char typeByte = *p++; 969 ASSERT_UNUSED(typeByte, typeByte == kIndexFreeListTypeByte); 970 if (p == limit) 971 return 0; 972 p = decodeVarInt(p, limit, result->m_objectStoreId); 973 if (!p) 974 return 0; 975 return decodeVarInt(p, limit, result->m_indexId); 976 } 977 978 static Vector<char> encode(int64_t databaseId, int64_t objectStoreId, int64_t indexId) 979 { 980 KeyPrefix prefix(databaseId, 0, 0); 981 Vector<char> ret = prefix.encode(); 982 ret.append(encodeByte(kIndexFreeListTypeByte)); 983 ret.append(encodeVarInt(objectStoreId)); 984 ret.append(encodeVarInt(indexId)); 985 return ret; 986 } 987 988 int compare(const IndexFreeListKey& other) 989 { 990 ASSERT(m_objectStoreId >= 0); 991 ASSERT(m_indexId >= 0); 992 if (int x = m_objectStoreId - other.m_objectStoreId) 993 return x; 994 return m_indexId - other.m_indexId; 995 } 996 997 int64_t objectStoreId() const 998 { 999 ASSERT(m_objectStoreId >= 0); 1000 return m_objectStoreId; 1001 } 1002 1003 int64_t indexId() const 1004 { 1005 ASSERT(m_indexId >= 0); 1006 return m_indexId; 1007 } 1008 1009 private: 1010 int64_t m_objectStoreId; 1011 int64_t m_indexId; 1012 }; 1013 1014 class ObjectStoreNamesKey { 1015 public: 1016 // FIXME: We never use this to look up object store ids, because a mapping 1017 // is kept in the IDBDatabaseBackendImpl. Can the mapping become unreliable? 1018 // Can we remove this? 1019 static const char* decode(const char* start, const char* limit, ObjectStoreNamesKey* result) 1020 { 1021 KeyPrefix prefix; 1022 const char* p = KeyPrefix::decode(start, limit, &prefix); 1023 if (!p) 1024 return 0; 1025 ASSERT(prefix.m_databaseId); 1026 ASSERT(!prefix.m_objectStoreId); 1027 ASSERT(!prefix.m_indexId); 1028 if (p == limit) 1029 return 0; 1030 unsigned char typeByte = *p++; 1031 ASSERT_UNUSED(typeByte, typeByte == kObjectStoreNamesTypeByte); 1032 return decodeStringWithLength(p, limit, result->m_objectStoreName); 1033 } 1034 1035 static Vector<char> encode(int64_t databaseId, const String& objectStoreName) 1036 { 1037 KeyPrefix prefix(databaseId, 0, 0); 1038 Vector<char> ret = prefix.encode(); 1039 ret.append(encodeByte(kSchemaVersionTypeByte)); 1040 ret.append(encodeByte(kObjectStoreNamesTypeByte)); 1041 ret.append(encodeStringWithLength(objectStoreName)); 1042 return ret; 1043 } 1044 1045 int compare(const ObjectStoreNamesKey& other) 1046 { 1047 return codePointCompare(m_objectStoreName, other.m_objectStoreName); 1048 } 1049 1050 String objectStoreName() const { return m_objectStoreName; } 1051 1052 private: 1053 String m_objectStoreName; // FIXME: Store the encoded string, or just pointers to it. 1054 }; 1055 1056 class IndexNamesKey { 1057 public: 1058 IndexNamesKey() 1059 : m_objectStoreId(-1) 1060 { 1061 } 1062 1063 // FIXME: We never use this to look up index ids, because a mapping 1064 // is kept at a higher level. 1065 static const char* decode(const char* start, const char* limit, IndexNamesKey* result) 1066 { 1067 KeyPrefix prefix; 1068 const char* p = KeyPrefix::decode(start, limit, &prefix); 1069 if (!p) 1070 return 0; 1071 ASSERT(prefix.m_databaseId); 1072 ASSERT(!prefix.m_objectStoreId); 1073 ASSERT(!prefix.m_indexId); 1074 if (p == limit) 1075 return 0; 1076 unsigned char typeByte = *p++; 1077 ASSERT_UNUSED(typeByte, typeByte == kIndexNamesKeyTypeByte); 1078 if (p == limit) 1079 return 0; 1080 p = decodeVarInt(p, limit, result->m_objectStoreId); 1081 if (!p) 1082 return 0; 1083 return decodeStringWithLength(p, limit, result->m_indexName); 1084 } 1085 1086 static Vector<char> encode(int64_t databaseId, int64_t objectStoreId, const String& indexName) 1087 { 1088 KeyPrefix prefix(databaseId, 0, 0); 1089 Vector<char> ret = prefix.encode(); 1090 ret.append(encodeByte(kIndexNamesKeyTypeByte)); 1091 ret.append(encodeVarInt(objectStoreId)); 1092 ret.append(encodeStringWithLength(indexName)); 1093 return ret; 1094 } 1095 1096 int compare(const IndexNamesKey& other) 1097 { 1098 ASSERT(m_objectStoreId >= 0); 1099 if (int x = m_objectStoreId - other.m_objectStoreId) 1100 return x; 1101 return codePointCompare(m_indexName, other.m_indexName); 1102 } 1103 1104 String indexName() const { return m_indexName; } 1105 1106 private: 1107 int64_t m_objectStoreId; 1108 String m_indexName; 1109 }; 1110 1111 class ObjectStoreDataKey { 1112 public: 1113 static const char* decode(const char* start, const char* end, ObjectStoreDataKey* result) 1114 { 1115 KeyPrefix prefix; 1116 const char* p = KeyPrefix::decode(start, end, &prefix); 1117 if (!p) 1118 return 0; 1119 ASSERT(prefix.m_databaseId); 1120 ASSERT(prefix.m_objectStoreId); 1121 ASSERT(prefix.m_indexId == kSpecialIndexNumber); 1122 if (p == end) 1123 return 0; 1124 return extractEncodedIDBKey(p, end, &result->m_encodedUserKey); 1125 } 1126 1127 static Vector<char> encode(int64_t databaseId, int64_t objectStoreId, const Vector<char> encodedUserKey) 1128 { 1129 KeyPrefix prefix(databaseId, objectStoreId, kSpecialIndexNumber); 1130 Vector<char> ret = prefix.encode(); 1131 ret.append(encodedUserKey); 1132 1133 return ret; 1134 } 1135 1136 static Vector<char> encode(int64_t databaseId, int64_t objectStoreId, const IDBKey& userKey) 1137 { 1138 return encode(databaseId, objectStoreId, encodeIDBKey(userKey)); 1139 } 1140 1141 int compare(const ObjectStoreDataKey& other) 1142 { 1143 return compareEncodedIDBKeys(m_encodedUserKey, other.m_encodedUserKey); 1144 } 1145 1146 PassRefPtr<IDBKey> userKey() const 1147 { 1148 RefPtr<IDBKey> key; 1149 decodeIDBKey(m_encodedUserKey.begin(), m_encodedUserKey.end(), key); 1150 return key; 1151 } 1152 1153 static const int64_t kSpecialIndexNumber = kObjectStoreDataIndexId; 1154 1155 private: 1156 Vector<char> m_encodedUserKey; 1157 }; 1158 1159 class ExistsEntryKey { 1160 public: 1161 static const char* decode(const char* start, const char* end, ExistsEntryKey* result) 1162 { 1163 KeyPrefix prefix; 1164 const char* p = KeyPrefix::decode(start, end, &prefix); 1165 if (!p) 1166 return 0; 1167 ASSERT(prefix.m_databaseId); 1168 ASSERT(prefix.m_objectStoreId); 1169 ASSERT(prefix.m_indexId == kSpecialIndexNumber); 1170 if (p == end) 1171 return 0; 1172 return extractEncodedIDBKey(p, end, &result->m_encodedUserKey); 1173 } 1174 1175 static Vector<char> encode(int64_t databaseId, int64_t objectStoreId, const Vector<char>& encodedKey) 1176 { 1177 KeyPrefix prefix(databaseId, objectStoreId, kSpecialIndexNumber); 1178 Vector<char> ret = prefix.encode(); 1179 ret.append(encodedKey); 1180 return ret; 1181 } 1182 1183 static Vector<char> encode(int64_t databaseId, int64_t objectStoreId, const IDBKey& userKey) 1184 { 1185 return encode(databaseId, objectStoreId, encodeIDBKey(userKey)); 1186 } 1187 1188 int compare(const ExistsEntryKey& other) 1189 { 1190 return compareEncodedIDBKeys(m_encodedUserKey, other.m_encodedUserKey); 1191 } 1192 1193 PassRefPtr<IDBKey> userKey() const 1194 { 1195 RefPtr<IDBKey> key; 1196 decodeIDBKey(m_encodedUserKey.begin(), m_encodedUserKey.end(), key); 1197 return key; 1198 } 1199 1200 static const int64_t kSpecialIndexNumber = kExistsEntryIndexId; 1201 1202 private: 1203 Vector<char> m_encodedUserKey; 1204 }; 1205 1206 class IndexDataKey { 1207 public: 1208 IndexDataKey() 1209 : m_databaseId(-1) 1210 , m_objectStoreId(-1) 1211 , m_indexId(-1) 1212 , m_sequenceNumber(-1) 1213 { 1214 } 1215 1216 static const char* decode(const char* start, const char* limit, IndexDataKey* result) 1217 { 1218 KeyPrefix prefix; 1219 const char* p = KeyPrefix::decode(start, limit, &prefix); 1220 if (!p) 1221 return 0; 1222 ASSERT(prefix.m_databaseId); 1223 ASSERT(prefix.m_objectStoreId); 1224 ASSERT(prefix.m_indexId >= kMinimumIndexId); 1225 result->m_databaseId = prefix.m_databaseId; 1226 result->m_objectStoreId = prefix.m_objectStoreId; 1227 result->m_indexId = prefix.m_indexId; 1228 p = extractEncodedIDBKey(p, limit, &result->m_encodedUserKey); 1229 if (!p) 1230 return 0; 1231 if (p == limit) { 1232 result->m_sequenceNumber = -1; // FIXME: We should change it so that all keys have a sequence number. Shouldn't need to handle this case. 1233 return p; 1234 } 1235 return decodeVarInt(p, limit, result->m_sequenceNumber); 1236 } 1237 1238 static Vector<char> encode(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const Vector<char>& encodedUserKey, int64_t sequenceNumber) 1239 { 1240 KeyPrefix prefix(databaseId, objectStoreId, indexId); 1241 Vector<char> ret = prefix.encode(); 1242 ret.append(encodedUserKey); 1243 ret.append(encodeVarInt(sequenceNumber)); 1244 return ret; 1245 } 1246 1247 static Vector<char> encode(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& userKey, int64_t sequenceNumber) 1248 { 1249 return encode(databaseId, objectStoreId, indexId, encodeIDBKey(userKey), sequenceNumber); 1250 } 1251 1252 static Vector<char> encodeMaxKey(int64_t databaseId, int64_t objectStoreId) 1253 { 1254 return encode(databaseId, objectStoreId, INT32_MAX, maxIDBKey(), INT64_MAX); 1255 } 1256 1257 int compare(const IndexDataKey& other, bool ignoreSequenceNumber) 1258 { 1259 ASSERT(m_databaseId >= 0); 1260 ASSERT(m_objectStoreId >= 0); 1261 ASSERT(m_indexId >= 0); 1262 if (int x = compareEncodedIDBKeys(m_encodedUserKey, other.m_encodedUserKey)) 1263 return x; 1264 if (ignoreSequenceNumber) 1265 return 0; 1266 return m_sequenceNumber - other.m_sequenceNumber; 1267 } 1268 1269 int64_t databaseId() const 1270 { 1271 ASSERT(m_databaseId >= 0); 1272 return m_databaseId; 1273 } 1274 1275 int64_t objectStoreId() const 1276 { 1277 ASSERT(m_objectStoreId >= 0); 1278 return m_objectStoreId; 1279 } 1280 1281 int64_t indexId() const 1282 { 1283 ASSERT(m_indexId >= 0); 1284 return m_indexId; 1285 } 1286 1287 PassRefPtr<IDBKey> userKey() const 1288 { 1289 RefPtr<IDBKey> key; 1290 decodeIDBKey(m_encodedUserKey.begin(), m_encodedUserKey.end(), key); 1291 return key; 1292 } 1293 1294 private: 1295 int64_t m_databaseId; 1296 int64_t m_objectStoreId; 1297 int64_t m_indexId; 1298 Vector<char> m_encodedUserKey; 1299 int64_t m_sequenceNumber; 1300 }; 1301 1302 namespace { 1303 template<typename KeyType> 1304 int decodeAndCompare(const LevelDBSlice& a, const LevelDBSlice& b) 1305 { 1306 KeyType keyA; 1307 KeyType keyB; 1308 1309 const char* ptrA = KeyType::decode(a.begin(), a.end(), &keyA); 1310 ASSERT_UNUSED(ptrA, ptrA); 1311 const char* ptrB = KeyType::decode(b.begin(), b.end(), &keyB); 1312 ASSERT_UNUSED(ptrB, ptrB); 1313 1314 return keyA.compare(keyB); 1315 } 1316 } 1317 1318 static int realCompare(const LevelDBSlice& a, const LevelDBSlice& b, bool indexKeys = false) 1319 { 1320 const char* ptrA = a.begin(); 1321 const char* ptrB = b.begin(); 1322 const char* endA = a.end(); 1323 const char* endB = b.end(); 1324 1325 KeyPrefix prefixA; 1326 KeyPrefix prefixB; 1327 1328 ptrA = KeyPrefix::decode(ptrA, endA, &prefixA); 1329 ptrB = KeyPrefix::decode(ptrB, endB, &prefixB); 1330 ASSERT(ptrA); 1331 ASSERT(ptrB); 1332 1333 if (int x = prefixA.compare(prefixB)) 1334 return x; 1335 1336 if (prefixA.type() == KeyPrefix::kGlobalMetaData) { 1337 ASSERT(ptrA != endA); 1338 ASSERT(ptrB != endB); 1339 1340 unsigned char typeByteA = *ptrA++; 1341 unsigned char typeByteB = *ptrB++; 1342 1343 if (int x = typeByteA - typeByteB) 1344 return x; 1345 1346 if (typeByteA <= 1) 1347 return 0; 1348 if (typeByteA == kDatabaseFreeListTypeByte) 1349 return decodeAndCompare<DatabaseFreeListKey>(a, b); 1350 if (typeByteA == kDatabaseNameTypeByte) 1351 return decodeAndCompare<DatabaseNameKey>(a, b); 1352 } 1353 1354 if (prefixA.type() == KeyPrefix::kDatabaseMetaData) { 1355 ASSERT(ptrA != endA); 1356 ASSERT(ptrB != endB); 1357 1358 unsigned char typeByteA = *ptrA++; 1359 unsigned char typeByteB = *ptrB++; 1360 1361 if (int x = typeByteA - typeByteB) 1362 return x; 1363 1364 if (typeByteA <= 3) 1365 return 0; 1366 1367 if (typeByteA == kObjectStoreMetaDataTypeByte) 1368 return decodeAndCompare<ObjectStoreMetaDataKey>(a, b); 1369 if (typeByteA == kIndexMetaDataTypeByte) 1370 return decodeAndCompare<IndexMetaDataKey>(a, b); 1371 if (typeByteA == kObjectStoreFreeListTypeByte) 1372 return decodeAndCompare<ObjectStoreFreeListKey>(a, b); 1373 if (typeByteA == kIndexFreeListTypeByte) 1374 return decodeAndCompare<IndexFreeListKey>(a, b); 1375 if (typeByteA == kObjectStoreNamesTypeByte) 1376 return decodeAndCompare<ObjectStoreNamesKey>(a, b); 1377 if (typeByteA == kIndexNamesKeyTypeByte) 1378 return decodeAndCompare<IndexNamesKey>(a, b); 1379 1380 return 0; 1381 ASSERT_NOT_REACHED(); 1382 } 1383 1384 if (prefixA.type() == KeyPrefix::kObjectStoreData) { 1385 if (ptrA == endA && ptrB == endB) 1386 return 0; 1387 if (ptrA == endA) 1388 return -1; 1389 if (ptrB == endB) 1390 return 1; // FIXME: This case of non-existing user keys should not have to be handled this way. 1391 1392 return decodeAndCompare<ObjectStoreDataKey>(a, b); 1393 } 1394 if (prefixA.type() == KeyPrefix::kExistsEntry) { 1395 if (ptrA == endA && ptrB == endB) 1396 return 0; 1397 if (ptrA == endA) 1398 return -1; 1399 if (ptrB == endB) 1400 return 1; // FIXME: This case of non-existing user keys should not have to be handled this way. 1401 1402 return decodeAndCompare<ExistsEntryKey>(a, b); 1403 } 1404 if (prefixA.type() == KeyPrefix::kIndexData) { 1405 if (ptrA == endA && ptrB == endB) 1406 return 0; 1407 if (ptrA == endA) 1408 return -1; 1409 if (ptrB == endB) 1410 return 1; // FIXME: This case of non-existing user keys should not have to be handled this way. 1411 1412 IndexDataKey indexDataKeyA; 1413 IndexDataKey indexDataKeyB; 1414 1415 ptrA = IndexDataKey::decode(a.begin(), endA, &indexDataKeyA); 1416 ptrB = IndexDataKey::decode(b.begin(), endB, &indexDataKeyB); 1417 ASSERT(ptrA); 1418 ASSERT(ptrB); 1419 1420 bool ignoreSequenceNumber = indexKeys; 1421 return indexDataKeyA.compare(indexDataKeyB, ignoreSequenceNumber); 1422 } 1423 1424 ASSERT_NOT_REACHED(); 1425 return 0; 1426 } 1427 1428 static int compareKeys(const LevelDBSlice& a, const LevelDBSlice& b) 1429 { 1430 return realCompare(a, b); 1431 } 1432 1433 static int compareIndexKeys(const LevelDBSlice& a, const LevelDBSlice& b) 1434 { 1435 return realCompare(a, b, true); 1436 } 1437 1438 class Comparator : public LevelDBComparator { 1439 public: 1440 virtual int compare(const LevelDBSlice& a, const LevelDBSlice& b) const { return realCompare(a, b); } 1441 virtual const char* name() const { return "idb_cmp1"; } 1442 }; 1443 } 1444 1445 static bool setUpMetadata(LevelDBDatabase* db) 1446 { 1447 const Vector<char> metaDataKey = SchemaVersionKey::encode(); 1448 1449 int64_t schemaVersion; 1450 if (!getInt(db, metaDataKey, schemaVersion)) { 1451 schemaVersion = 0; 1452 if (!putInt(db, metaDataKey, schemaVersion)) 1453 return false; 1454 } 1455 1456 // FIXME: Eventually, we'll need to be able to transition between schemas. 1457 if (schemaVersion) 1458 return false; // Don't know what to do with this version. 1459 1460 return true; 1461 } 1462 1463 IDBLevelDBBackingStore::IDBLevelDBBackingStore(String identifier, IDBFactoryBackendImpl* factory, LevelDBDatabase* db) 38 1464 : m_identifier(identifier) 39 1465 , m_factory(factory) … … 48 1474 } 49 1475 50 PassRefPtr<IDBBackingStore> IDBLevelDBBackingStore::open(SecurityOrigin*, const String&, int64_t, const String&, IDBFactoryBackendImpl*) 51 { 52 ASSERT_NOT_REACHED(); // FIXME: Implement. 53 return adoptRef(new IDBLevelDBBackingStore("", 0, 0)); 54 } 55 56 bool IDBLevelDBBackingStore::extractIDBDatabaseMetaData(const String&, String&, int64_t&) 57 { 58 ASSERT_NOT_REACHED(); // FIXME: Implement. 59 return false; 60 } 61 62 63 bool IDBLevelDBBackingStore::setIDBDatabaseMetaData(const String&, const String&, int64_t&, bool) 64 { 65 ASSERT_NOT_REACHED(); // FIXME: Implement. 66 return false; 67 } 68 69 void IDBLevelDBBackingStore::getObjectStores(int64_t, Vector<int64_t>&, Vector<String>&, Vector<String>&, Vector<bool>&) 70 { 71 ASSERT_NOT_REACHED(); // FIXME: Implement. 72 } 73 74 bool IDBLevelDBBackingStore::createObjectStore(int64_t, const String&, const String&, bool, int64_t&) 75 { 76 ASSERT_NOT_REACHED(); // FIXME: Implement. 77 return false; 78 } 79 80 void IDBLevelDBBackingStore::deleteObjectStore(int64_t, int64_t) 81 { 82 ASSERT_NOT_REACHED(); // FIXME: Implement. 83 } 84 85 String IDBLevelDBBackingStore::getObjectStoreRecord(int64_t, int64_t, const IDBKey&) 86 { 87 ASSERT_NOT_REACHED(); // FIXME: Implement. 88 return String(); 89 } 90 91 bool IDBLevelDBBackingStore::putObjectStoreRecord(int64_t, int64_t, const IDBKey&, const String&, ObjectStoreRecordIdentifier*) 92 { 93 ASSERT_NOT_REACHED(); // FIXME: Implement. 94 return false; 95 } 96 97 void IDBLevelDBBackingStore::clearObjectStore(int64_t, int64_t) 98 { 99 ASSERT_NOT_REACHED(); // FIXME: Implement. 1476 PassRefPtr<IDBBackingStore> IDBLevelDBBackingStore::open(SecurityOrigin* securityOrigin, const String& pathBaseArg, int64_t maximumSize, const String& fileIdentifier, IDBFactoryBackendImpl* factory) 1477 { 1478 String pathBase = pathBaseArg; 1479 1480 if (pathBase.isEmpty()) { 1481 ASSERT_NOT_REACHED(); // FIXME: We need to handle this case for incognito and DumpRenderTree. 1482 return 0; 1483 } 1484 1485 if (!makeAllDirectories(pathBase)) { 1486 LOG_ERROR("Unable to create IndexedDB database path %s", pathBase.utf8().data()); 1487 return 0; 1488 } 1489 // FIXME: We should eventually use the same LevelDB database for all origins. 1490 String path = pathByAppendingComponent(pathBase, securityOrigin->databaseIdentifier() + ".indexeddb.leveldb"); 1491 1492 OwnPtr<LevelDBComparator> comparator(new Comparator()); 1493 LevelDBDatabase* db = LevelDBDatabase::open(path, comparator.get()); 1494 if (!db) 1495 return 0; 1496 1497 // FIXME: Handle comparator name changes. 1498 1499 RefPtr<IDBLevelDBBackingStore> backingStore(adoptRef(new IDBLevelDBBackingStore(fileIdentifier, factory, db))); 1500 backingStore->m_comparator = comparator.release(); 1501 1502 if (!setUpMetadata(backingStore->m_db.get())) 1503 return 0; 1504 1505 return backingStore.release(); 1506 } 1507 1508 bool IDBLevelDBBackingStore::extractIDBDatabaseMetaData(const String& name, String& foundVersion, int64_t& foundId) 1509 { 1510 const Vector<char> key = DatabaseNameKey::encode(m_identifier, name); 1511 1512 bool ok = getInt(m_db.get(), key, foundId); 1513 if (!ok) 1514 return false; 1515 1516 ok = getString(m_db.get(), DatabaseMetaDataKey::encode(foundId, DatabaseMetaDataKey::kUserVersion), foundVersion); 1517 if (!ok) 1518 return false; 1519 1520 return true; 1521 } 1522 1523 static int64_t getNewDatabaseId(LevelDBDatabase* db) 1524 { 1525 const Vector<char> freeListStartKey = DatabaseFreeListKey::encode(0); 1526 const Vector<char> freeListStopKey = DatabaseFreeListKey::encode(INT64_MAX); 1527 1528 OwnPtr<LevelDBIterator> it(db->newIterator()); 1529 for (it->seek(freeListStartKey); it->isValid() && compareKeys(it->key(), freeListStopKey) < 0; it->next()) { 1530 const char *p = it->key().begin(); 1531 const char *limit = it->key().end(); 1532 1533 DatabaseFreeListKey freeListKey; 1534 p = DatabaseFreeListKey::decode(p, limit, &freeListKey); 1535 ASSERT(p); 1536 1537 bool ok = db->remove(it->key()); 1538 ASSERT_UNUSED(ok, ok); 1539 1540 return freeListKey.databaseId(); 1541 } 1542 1543 // If we got here, there was no free-list. 1544 int64_t maxDatabaseId = -1; 1545 if (!getInt(db, MaxDatabaseIdKey::encode(), maxDatabaseId)) 1546 maxDatabaseId = 0; 1547 1548 ASSERT(maxDatabaseId >= 0); 1549 1550 int64_t databaseId = maxDatabaseId + 1; 1551 bool ok = putInt(db, MaxDatabaseIdKey::encode(), databaseId); 1552 ASSERT_UNUSED(ok, ok); 1553 1554 return databaseId; 1555 1556 } 1557 1558 bool IDBLevelDBBackingStore::setIDBDatabaseMetaData(const String& name, const String& version, int64_t& rowId, bool invalidRowId) 1559 { 1560 if (invalidRowId) { 1561 rowId = getNewDatabaseId(m_db.get()); 1562 1563 const Vector<char> key = DatabaseNameKey::encode(m_identifier, name); 1564 if (!putInt(m_db.get(), key, rowId)) 1565 return false; 1566 } 1567 1568 if (!putString(m_db.get(), DatabaseMetaDataKey::encode(rowId, DatabaseMetaDataKey::kUserVersion), version)) 1569 return false; 1570 1571 return true; 1572 } 1573 1574 void IDBLevelDBBackingStore::getObjectStores(int64_t databaseId, Vector<int64_t>& foundIds, Vector<String>& foundNames, Vector<String>& foundKeyPaths, Vector<bool>& foundAutoIncrementFlags) 1575 { 1576 const Vector<char> startKey = ObjectStoreMetaDataKey::encode(databaseId, 1, 0); 1577 const Vector<char> stopKey = ObjectStoreMetaDataKey::encode(databaseId, INT64_MAX, 0); 1578 1579 OwnPtr<LevelDBIterator> it(m_db->newIterator()); 1580 for (it->seek(startKey); it->isValid() && compareKeys(it->key(), stopKey) < 0; it->next()) { 1581 const char *p = it->key().begin(); 1582 const char *limit = it->key().end(); 1583 1584 ObjectStoreMetaDataKey metaDataKey; 1585 p = ObjectStoreMetaDataKey::decode(p, limit, &metaDataKey); 1586 ASSERT(p); 1587 1588 int64_t objectStoreId = metaDataKey.objectStoreId(); 1589 1590 String objectStoreName = decodeString(it->value().begin(), it->value().end()); 1591 1592 it->next(); 1593 if (!it->isValid()) { 1594 LOG_ERROR("Internal Indexed DB error."); 1595 return; 1596 } 1597 String keyPath = decodeString(it->value().begin(), it->value().end()); 1598 1599 it->next(); 1600 if (!it->isValid()) { 1601 LOG_ERROR("Internal Indexed DB error."); 1602 return; 1603 } 1604 bool autoIncrement = *it->value().begin(); 1605 1606 it->next(); // Is evicatble. 1607 if (!it->isValid()) { 1608 LOG_ERROR("Internal Indexed DB error."); 1609 return; 1610 } 1611 1612 it->next(); // Last version. 1613 if (!it->isValid()) { 1614 LOG_ERROR("Internal Indexed DB error."); 1615 return; 1616 } 1617 1618 it->next(); // Maxium index id allocated. 1619 if (!it->isValid()) { 1620 LOG_ERROR("Internal Indexed DB error."); 1621 return; 1622 } 1623 1624 foundIds.append(objectStoreId); 1625 foundNames.append(objectStoreName); 1626 foundKeyPaths.append(keyPath); 1627 foundAutoIncrementFlags.append(autoIncrement); 1628 } 1629 } 1630 1631 static int64_t getNewObjectStoreId(LevelDBDatabase* db, int64_t databaseId) 1632 { 1633 const Vector<char> freeListStartKey = ObjectStoreFreeListKey::encode(databaseId, 0); 1634 const Vector<char> freeListStopKey = ObjectStoreFreeListKey::encode(databaseId, INT64_MAX); 1635 1636 OwnPtr<LevelDBIterator> it(db->newIterator()); 1637 for (it->seek(freeListStartKey); it->isValid() && compareKeys(it->key(), freeListStopKey) < 0; it->next()) { 1638 const char* p = it->key().begin(); 1639 const char* limit = it->key().end(); 1640 1641 ObjectStoreFreeListKey freeListKey; 1642 p = ObjectStoreFreeListKey::decode(p, limit, &freeListKey); 1643 ASSERT(p); 1644 1645 bool ok = db->remove(it->key()); 1646 ASSERT_UNUSED(ok, ok); 1647 1648 return freeListKey.objectStoreId(); 1649 } 1650 1651 int64_t maxObjectStoreId; 1652 const Vector<char> maxObjectStoreIdKey = DatabaseMetaDataKey::encode(databaseId, DatabaseMetaDataKey::kMaxObjectStoreId); 1653 if (!getInt(db, maxObjectStoreIdKey, maxObjectStoreId)) 1654 maxObjectStoreId = 0; 1655 1656 int64_t objectStoreId = maxObjectStoreId + 1; 1657 bool ok = putInt(db, maxObjectStoreIdKey, objectStoreId); 1658 ASSERT_UNUSED(ok, ok); 1659 1660 return objectStoreId; 1661 } 1662 1663 bool IDBLevelDBBackingStore::createObjectStore(int64_t databaseId, const String& name, const String& keyPath, bool autoIncrement, int64_t& assignedObjectStoreId) 1664 { 1665 int64_t objectStoreId = getNewObjectStoreId(m_db.get(), databaseId); 1666 1667 const Vector<char> nameKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, 0); 1668 const Vector<char> keyPathKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, 1); 1669 const Vector<char> autoIncrementKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, 2); 1670 const Vector<char> evictableKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, 3); 1671 const Vector<char> lastVersionKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, 4); 1672 const Vector<char> maxIndexIdKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, 5); 1673 const Vector<char> namesKey = ObjectStoreNamesKey::encode(databaseId, name); 1674 1675 bool ok = putString(m_db.get(), nameKey, name); 1676 if (!ok) { 1677 LOG_ERROR("Internal Indexed DB error."); 1678 return false; 1679 } 1680 1681 ok = putString(m_db.get(), keyPathKey, keyPath); 1682 if (!ok) { 1683 LOG_ERROR("Internal Indexed DB error."); 1684 return false; 1685 } 1686 1687 ok = putInt(m_db.get(), autoIncrementKey, autoIncrement); 1688 if (!ok) { 1689 LOG_ERROR("Internal Indexed DB error."); 1690 return false; 1691 } 1692 1693 ok = putInt(m_db.get(), evictableKey, false); 1694 if (!ok) { 1695 LOG_ERROR("Internal Indexed DB error."); 1696 return false; 1697 } 1698 1699 ok = putInt(m_db.get(), lastVersionKey, 1); 1700 if (!ok) { 1701 LOG_ERROR("Internal Indexed DB error."); 1702 return false; 1703 } 1704 1705 ok = putInt(m_db.get(), maxIndexIdKey, kMinimumIndexId); 1706 if (!ok) { 1707 LOG_ERROR("Internal Indexed DB error."); 1708 return false; 1709 } 1710 1711 ok = putInt(m_db.get(), namesKey, objectStoreId); 1712 if (!ok) { 1713 LOG_ERROR("Internal Indexed DB error."); 1714 return false; 1715 } 1716 1717 assignedObjectStoreId = objectStoreId; 1718 1719 return true; 1720 } 1721 1722 static bool deleteRange(LevelDBDatabase* db, const Vector<char>& begin, const Vector<char>& end) 1723 { 1724 // FIXME: LevelDB may be able to provide a bulk operation that we can do first. 1725 OwnPtr<LevelDBIterator> it(db->newIterator()); 1726 for (it->seek(begin); it->isValid() && compareKeys(it->key(), end) < 0; it->next()) { 1727 if (!db->remove(it->key())) 1728 return false; 1729 } 1730 1731 return true; 1732 } 1733 1734 void IDBLevelDBBackingStore::deleteObjectStore(int64_t databaseId, int64_t objectStoreId) 1735 { 1736 String objectStoreName; 1737 getString(m_db.get(), ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, 0), objectStoreName); 1738 1739 if (!deleteRange(m_db.get(), ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, 0), ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, 6))) 1740 return; // FIXME: Report error. 1741 1742 putString(m_db.get(), ObjectStoreFreeListKey::encode(databaseId, objectStoreId), ""); 1743 m_db->remove(ObjectStoreNamesKey::encode(databaseId, objectStoreName)); 1744 1745 if (!deleteRange(m_db.get(), IndexFreeListKey::encode(databaseId, objectStoreId, 0), IndexFreeListKey::encode(databaseId, objectStoreId, INT64_MAX))) 1746 return; // FIXME: Report error. 1747 if (!deleteRange(m_db.get(), IndexMetaDataKey::encode(databaseId, objectStoreId, 0, 0), IndexMetaDataKey::encode(databaseId, objectStoreId, INT64_MAX, 0))) 1748 return; // FIXME: Report error. 1749 1750 clearObjectStore(databaseId, objectStoreId); 1751 } 1752 1753 String IDBLevelDBBackingStore::getObjectStoreRecord(int64_t databaseId, int64_t objectStoreId, const IDBKey& key) 1754 { 1755 const Vector<char> leveldbKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, key); 1756 Vector<char> data; 1757 1758 if (!m_db->get(leveldbKey, data)) 1759 return String(); 1760 1761 int64_t version; 1762 const char* p = decodeVarInt(data.begin(), data.end(), version); 1763 if (!p) 1764 return String(); 1765 (void) version; 1766 1767 return decodeString(p, data.end()); 1768 } 1769 1770 namespace { 1771 class LevelDBRecordIdentifier : public IDBBackingStore::ObjectStoreRecordIdentifier { 1772 public: 1773 static PassRefPtr<LevelDBRecordIdentifier> create(const Vector<char>& primaryKey, int64_t version) { return adoptRef(new LevelDBRecordIdentifier(primaryKey, version)); } 1774 static PassRefPtr<LevelDBRecordIdentifier> create() { return adoptRef(new LevelDBRecordIdentifier()); } 1775 1776 virtual bool isValid() const { return m_primaryKey.isEmpty(); } 1777 Vector<char> primaryKey() const { return m_primaryKey; } 1778 void setPrimaryKey(const Vector<char>& primaryKey) { m_primaryKey = primaryKey; } 1779 int64_t version() const { return m_version; } 1780 void setVersion(int64_t version) { m_version = version; } 1781 1782 private: 1783 LevelDBRecordIdentifier(const Vector<char>& primaryKey, int64_t version) : m_primaryKey(primaryKey), m_version(version) { ASSERT(!primaryKey.isEmpty()); } 1784 LevelDBRecordIdentifier() : m_primaryKey(), m_version(-1) {} 1785 1786 Vector<char> m_primaryKey; // FIXME: Make it more clear that this is the *encoded* version of the key. 1787 int64_t m_version; 1788 }; 1789 } 1790 1791 static int64_t getNewVersionNumber(LevelDBDatabase* db, int64_t databaseId, int64_t objectStoreId) 1792 { 1793 const Vector<char> lastVersionKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, 4); 1794 1795 int64_t lastVersion = -1; 1796 if (!getInt(db, lastVersionKey, lastVersion)) 1797 lastVersion = 0; 1798 1799 ASSERT(lastVersion >= 0); 1800 1801 int64_t version = lastVersion + 1; 1802 bool ok = putInt(db, lastVersionKey, version); 1803 ASSERT_UNUSED(ok, ok); 1804 1805 ASSERT(version > lastVersion); // FIXME: Think about how we want to handle the overflow scenario. 1806 1807 return version; 1808 } 1809 1810 bool IDBLevelDBBackingStore::putObjectStoreRecord(int64_t databaseId, int64_t objectStoreId, const IDBKey& key, const String& value, ObjectStoreRecordIdentifier* recordIdentifier) 1811 { 1812 int64_t version = getNewVersionNumber(m_db.get(), databaseId, objectStoreId); 1813 const Vector<char> objectStoredataKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, key); 1814 1815 Vector<char> v; 1816 v.append(encodeVarInt(version)); 1817 v.append(encodeString(value)); 1818 1819 if (!m_db->put(objectStoredataKey, v)) 1820 return false; 1821 1822 const Vector<char> existsEntryKey = ExistsEntryKey::encode(databaseId, objectStoreId, key); 1823 if (!m_db->put(existsEntryKey, encodeInt(version))) 1824 return false; 1825 1826 LevelDBRecordIdentifier* levelDBRecordIdentifier = static_cast<LevelDBRecordIdentifier*>(recordIdentifier); 1827 levelDBRecordIdentifier->setPrimaryKey(encodeIDBKey(key)); 1828 levelDBRecordIdentifier->setVersion(version); 1829 return true; 1830 } 1831 1832 void IDBLevelDBBackingStore::clearObjectStore(int64_t databaseId, int64_t objectStoreId) 1833 { 1834 const Vector<char> startKey = KeyPrefix(databaseId, objectStoreId, 0).encode(); 1835 const Vector<char> stopKey = KeyPrefix(databaseId, objectStoreId + 1, 0).encode(); 1836 1837 deleteRange(m_db.get(), startKey, stopKey); 100 1838 } 101 1839 102 1840 PassRefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> IDBLevelDBBackingStore::createInvalidRecordIdentifier() 103 1841 { 104 ASSERT_NOT_REACHED(); // FIXME: Implement. 105 return 0; 106 } 107 108 void IDBLevelDBBackingStore::deleteObjectStoreRecord(int64_t, int64_t, const ObjectStoreRecordIdentifier*) 109 { 110 ASSERT_NOT_REACHED(); // FIXME: Implement. 111 } 112 113 double IDBLevelDBBackingStore::nextAutoIncrementNumber(int64_t, int64_t) 114 { 115 ASSERT_NOT_REACHED(); // FIXME: Implement. 116 return 0; 117 } 118 119 bool IDBLevelDBBackingStore::keyExistsInObjectStore(int64_t, int64_t, const IDBKey&, ObjectStoreRecordIdentifier*) 120 { 121 ASSERT_NOT_REACHED(); // FIXME: Implement. 122 return false; 123 } 124 125 bool IDBLevelDBBackingStore::forEachObjectStoreRecord(int64_t, int64_t, ObjectStoreRecordCallback&) 126 { 127 ASSERT_NOT_REACHED(); // FIXME: Implement. 128 return false; 129 } 130 131 void IDBLevelDBBackingStore::getIndexes(int64_t, int64_t, Vector<int64_t>&, Vector<String>&, Vector<String>&, Vector<bool>&) 132 { 133 ASSERT_NOT_REACHED(); // FIXME: Implement. 134 } 135 136 bool IDBLevelDBBackingStore::createIndex(int64_t, int64_t, const String&, const String&, bool, int64_t&) 137 { 138 ASSERT_NOT_REACHED(); // FIXME: Implement. 139 return false; 1842 return LevelDBRecordIdentifier::create(); 1843 } 1844 1845 void IDBLevelDBBackingStore::deleteObjectStoreRecord(int64_t databaseId, int64_t objectStoreId, const ObjectStoreRecordIdentifier* recordIdentifier) 1846 { 1847 const LevelDBRecordIdentifier* levelDBRecordIdentifier = static_cast<const LevelDBRecordIdentifier*>(recordIdentifier); 1848 const Vector<char> key = ObjectStoreDataKey::encode(databaseId, objectStoreId, levelDBRecordIdentifier->primaryKey()); 1849 m_db->remove(key); 1850 } 1851 1852 double IDBLevelDBBackingStore::nextAutoIncrementNumber(int64_t databaseId, int64_t objectStoreId) 1853 { 1854 const Vector<char> startKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, minIDBKey()); 1855 const Vector<char> stopKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, maxIDBKey()); 1856 1857 OwnPtr<LevelDBIterator> it(m_db->newIterator()); 1858 1859 int maxNumericKey = 0; 1860 1861 // FIXME: Be more efficient: seek to something after the object store data, then reverse. 1862 1863 for (it->seek(startKey); it->isValid() && compareKeys(it->key(), stopKey) < 0; it->next()) { 1864 const char *p = it->key().begin(); 1865 const char *limit = it->key().end(); 1866 1867 ObjectStoreDataKey dataKey; 1868 p = ObjectStoreDataKey::decode(p, limit, &dataKey); 1869 ASSERT(p); 1870 1871 if (dataKey.userKey()->type() == IDBKey::NumberType) { 1872 int64_t n = static_cast<int64_t>(dataKey.userKey()->number()); 1873 if (n > maxNumericKey) 1874 maxNumericKey = n; 1875 } 1876 } 1877 1878 return maxNumericKey + 1; 1879 } 1880 1881 bool IDBLevelDBBackingStore::keyExistsInObjectStore(int64_t databaseId, int64_t objectStoreId, const IDBKey& key, ObjectStoreRecordIdentifier* foundRecordIdentifier) 1882 { 1883 const Vector<char> leveldbKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, key); 1884 Vector<char> data; 1885 1886 if (!m_db->get(leveldbKey, data)) 1887 return false; 1888 1889 int64_t version; 1890 if (!decodeVarInt(data.begin(), data.end(), version)) 1891 return false; 1892 1893 LevelDBRecordIdentifier* levelDBRecordIdentifier = static_cast<LevelDBRecordIdentifier*>(foundRecordIdentifier); 1894 levelDBRecordIdentifier->setPrimaryKey(encodeIDBKey(key)); 1895 levelDBRecordIdentifier->setVersion(version); 1896 return true; 1897 } 1898 1899 bool IDBLevelDBBackingStore::forEachObjectStoreRecord(int64_t databaseId, int64_t objectStoreId, ObjectStoreRecordCallback& callback) 1900 { 1901 const Vector<char> startKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, minIDBKey()); 1902 const Vector<char> stopKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, maxIDBKey()); 1903 1904 OwnPtr<LevelDBIterator> it(m_db->newIterator()); 1905 for (it->seek(startKey); it->isValid() && compareKeys(it->key(), stopKey) < 0; it->next()) { 1906 const char *p = it->key().begin(); 1907 const char *limit = it->key().end(); 1908 ObjectStoreDataKey dataKey; 1909 p = ObjectStoreDataKey::decode(p, limit, &dataKey); 1910 ASSERT(p); 1911 1912 RefPtr<IDBKey> primaryKey = dataKey.userKey(); 1913 1914 int64_t version; 1915 const char* q = decodeVarInt(it->value().begin(), it->value().end(), version); 1916 if (!q) 1917 return false; 1918 1919 RefPtr<LevelDBRecordIdentifier> ri = LevelDBRecordIdentifier::create(encodeIDBKey(*primaryKey), version); 1920 String idbValue = decodeString(q, it->value().end()); 1921 1922 callback.callback(ri.get(), idbValue); 1923 } 1924 1925 return true; 1926 } 1927 1928 void IDBLevelDBBackingStore::getIndexes(int64_t databaseId, int64_t objectStoreId, Vector<int64_t>& foundIds, Vector<String>& foundNames, Vector<String>& foundKeyPaths, Vector<bool>& foundUniqueFlags) 1929 { 1930 const Vector<char> startKey = IndexMetaDataKey::encode(databaseId, objectStoreId, 0, 0); 1931 const Vector<char> stopKey = IndexMetaDataKey::encode(databaseId, objectStoreId + 1, 0, 0); 1932 1933 OwnPtr<LevelDBIterator> it(m_db->newIterator()); 1934 for (it->seek(startKey); it->isValid() && compareKeys(it->key(), stopKey) < 0; it->next()) { 1935 const char* p = it->key().begin(); 1936 const char* limit = it->key().end(); 1937 1938 IndexMetaDataKey metaDataKey; 1939 p = IndexMetaDataKey::decode(p, limit, &metaDataKey); 1940 ASSERT(p); 1941 1942 int64_t indexId = metaDataKey.indexId(); 1943 ASSERT(!metaDataKey.metaDataType()); 1944 1945 String indexName = decodeString(it->value().begin(), it->value().end()); 1946 it->next(); 1947 if (!it->isValid()) { 1948 LOG_ERROR("Internal Indexed DB error."); 1949 return; 1950 } 1951 1952 bool indexUnique = *it->value().begin(); 1953 it->next(); 1954 if (!it->isValid()) { 1955 LOG_ERROR("Internal Indexed DB error."); 1956 return; 1957 } 1958 1959 String keyPath = decodeString(it->value().begin(), it->value().end()); 1960 1961 foundIds.append(indexId); 1962 foundNames.append(indexName); 1963 foundKeyPaths.append(keyPath); 1964 foundUniqueFlags.append(indexUnique); 1965 } 1966 } 1967 1968 static int64_t getNewIndexId(LevelDBDatabase* db, int64_t databaseId, int64_t objectStoreId) 1969 { 1970 const Vector<char> startKey = IndexFreeListKey::encode(databaseId, objectStoreId, 0); 1971 const Vector<char> stopKey = IndexFreeListKey::encode(databaseId, objectStoreId, INT64_MAX); 1972 1973 OwnPtr<LevelDBIterator> it(db->newIterator()); 1974 for (it->seek(startKey); it->isValid() && compareKeys(it->key(), stopKey) < 0; it->next()) { 1975 const char* p = it->key().begin(); 1976 const char* limit = it->key().end(); 1977 1978 IndexFreeListKey freeListKey; 1979 p = IndexFreeListKey::decode(p, limit, &freeListKey); 1980 ASSERT(p); 1981 1982 bool ok = db->remove(it->key()); 1983 ASSERT_UNUSED(ok, ok); 1984 1985 ASSERT(freeListKey.indexId() >= kMinimumIndexId); 1986 return freeListKey.indexId(); 1987 } 1988 1989 int64_t maxIndexId; 1990 const Vector<char> maxIndexIdKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, 5); 1991 if (!getInt(db, maxIndexIdKey, maxIndexId)) 1992 maxIndexId = kMinimumIndexId; 1993 1994 int64_t indexId = maxIndexId + 1; 1995 bool ok = putInt(db, maxIndexIdKey, indexId); 1996 if (!ok) 1997 return false; 1998 1999 return indexId; 2000 } 2001 2002 bool IDBLevelDBBackingStore::createIndex(int64_t databaseId, int64_t objectStoreId, const String& name, const String& keyPath, bool isUnique, int64_t& indexId) 2003 { 2004 indexId = getNewIndexId(m_db.get(), databaseId, objectStoreId); 2005 2006 const Vector<char> nameKey = IndexMetaDataKey::encode(databaseId, objectStoreId, indexId, 0); 2007 const Vector<char> uniqueKey = IndexMetaDataKey::encode(databaseId, objectStoreId, indexId, 1); 2008 const Vector<char> keyPathKey = IndexMetaDataKey::encode(databaseId, objectStoreId, indexId, 2); 2009 2010 bool ok = putString(m_db.get(), nameKey, name); 2011 if (!ok) { 2012 LOG_ERROR("Internal Indexed DB error."); 2013 return false; 2014 } 2015 2016 ok = putInt(m_db.get(), uniqueKey, isUnique); 2017 if (!ok) { 2018 LOG_ERROR("Internal Indexed DB error."); 2019 return false; 2020 } 2021 2022 ok = putString(m_db.get(), keyPathKey, keyPath); 2023 if (!ok) { 2024 LOG_ERROR("Internal Indexed DB error."); 2025 return false; 2026 } 2027 2028 return true; 140 2029 } 141 2030 142 2031 void IDBLevelDBBackingStore::deleteIndex(int64_t, int64_t, int64_t) 143 2032 { 144 ASSERT_NOT_REACHED(); // FIXME: Implement. 145 } 146 147 bool IDBLevelDBBackingStore::putIndexDataForRecord(int64_t, int64_t, int64_t, const IDBKey&, const ObjectStoreRecordIdentifier*) 148 { 149 ASSERT_NOT_REACHED(); // FIXME: Implement. 150 return false; 2033 ASSERT_NOT_REACHED(); // FIXME: Implement and add layout test. 2034 return; 2035 } 2036 2037 bool IDBLevelDBBackingStore::putIndexDataForRecord(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& key, const ObjectStoreRecordIdentifier* recordIdentifier) 2038 { 2039 ASSERT(indexId >= kMinimumIndexId); 2040 const LevelDBRecordIdentifier* levelDBRecordIdentifier = static_cast<const LevelDBRecordIdentifier*>(recordIdentifier); 2041 2042 const int64_t globalSequenceNumber = getNewVersionNumber(m_db.get(), databaseId, objectStoreId); 2043 const Vector<char> indexDataKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, key, globalSequenceNumber); 2044 2045 Vector<char> data; 2046 data.append(encodeVarInt(levelDBRecordIdentifier->version())); 2047 data.append(levelDBRecordIdentifier->primaryKey()); 2048 2049 return m_db->put(indexDataKey, data); 2050 } 2051 2052 static bool findGreatestKeyLessThan(LevelDBDatabase* db, const Vector<char>& target, Vector<char>& foundKey) 2053 { 2054 OwnPtr<LevelDBIterator> it(db->newIterator()); 2055 it->seek(target); 2056 2057 if (!it->isValid()) { 2058 it->seekToLast(); 2059 if (!it->isValid()) 2060 return false; 2061 } 2062 2063 while (compareIndexKeys(it->key(), target) >= 0) { 2064 it->prev(); 2065 if (!it->isValid()) 2066 return false; 2067 } 2068 2069 foundKey.clear(); 2070 foundKey.append(it->key().begin(), it->key().end() - it->key().begin()); 2071 return true; 151 2072 } 152 2073 153 2074 bool IDBLevelDBBackingStore::deleteIndexDataForRecord(int64_t, int64_t, int64_t, const ObjectStoreRecordIdentifier*) 154 2075 { 155 ASSERT_NOT_REACHED(); // FIXME: Implement. 156 return false; 157 } 158 159 String IDBLevelDBBackingStore::getObjectViaIndex(int64_t, int64_t, int64_t, const IDBKey&) 160 { 161 ASSERT_NOT_REACHED(); // FIXME: Implement. 162 return String(); 163 } 164 165 PassRefPtr<IDBKey> IDBLevelDBBackingStore::getPrimaryKeyViaIndex(int64_t, int64_t, int64_t, const IDBKey&) 166 { 167 ASSERT_NOT_REACHED(); // FIXME: Implement. 168 return 0; 169 } 170 171 bool IDBLevelDBBackingStore::keyExistsInIndex(int64_t, int64_t, int64_t, const IDBKey&) 172 { 173 ASSERT_NOT_REACHED(); // FIXME: Implement. 174 return false; 175 } 176 177 PassRefPtr<IDBBackingStore::Cursor> IDBLevelDBBackingStore::openObjectStoreCursor(int64_t, int64_t, const IDBKeyRange*, IDBCursor::Direction) 178 { 179 ASSERT_NOT_REACHED(); // FIXME: Implement. 180 return 0; 181 } 182 183 PassRefPtr<IDBBackingStore::Cursor> IDBLevelDBBackingStore::openIndexKeyCursor(int64_t, int64_t, int64_t, const IDBKeyRange*, IDBCursor::Direction) 184 { 185 ASSERT_NOT_REACHED(); // FIXME: Implement. 186 return 0; 187 } 188 189 PassRefPtr<IDBBackingStore::Cursor> IDBLevelDBBackingStore::openIndexCursor(int64_t, int64_t, int64_t, const IDBKeyRange*, IDBCursor::Direction) 190 { 191 ASSERT_NOT_REACHED(); // FIXME: Implement. 192 return 0; 2076 // FIXME: This isn't needed since we invalidate index data via the version number mechanism. 2077 return true; 2078 } 2079 2080 String IDBLevelDBBackingStore::getObjectViaIndex(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& key) 2081 { 2082 RefPtr<IDBKey> primaryKey = getPrimaryKeyViaIndex(databaseId, objectStoreId, indexId, key); 2083 if (!primaryKey) 2084 return String(); 2085 2086 return getObjectStoreRecord(databaseId, objectStoreId, *primaryKey); 2087 } 2088 2089 static bool versionExists(LevelDBDatabase* db, int64_t databaseId, int64_t objectStoreId, int64_t version, const Vector<char>& encodedPrimaryKey) 2090 { 2091 const Vector<char> key = ExistsEntryKey::encode(databaseId, objectStoreId, encodedPrimaryKey); 2092 Vector<char> data; 2093 2094 if (!db->get(key, data)) 2095 return false; 2096 2097 return decodeInt(data.begin(), data.end()) == version; 2098 } 2099 2100 PassRefPtr<IDBKey> IDBLevelDBBackingStore::getPrimaryKeyViaIndex(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& key) 2101 { 2102 const Vector<char> leveldbKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, key, 0); 2103 OwnPtr<LevelDBIterator> it(m_db->newIterator()); 2104 it->seek(leveldbKey); 2105 2106 for (;;) { 2107 if (!it->isValid()) 2108 return 0; 2109 if (compareIndexKeys(it->key(), leveldbKey) > 0) 2110 return 0; 2111 2112 int64_t version; 2113 const char* p = decodeVarInt(it->value().begin(), it->value().end(), version); 2114 if (!p) 2115 return 0; 2116 Vector<char> encodedPrimaryKey; 2117 encodedPrimaryKey.append(p, it->value().end() - p); 2118 2119 if (!versionExists(m_db.get(), databaseId, objectStoreId, version, encodedPrimaryKey)) { 2120 // Delete stale index data entry and continue. 2121 m_db->remove(it->key()); 2122 it->next(); 2123 continue; 2124 } 2125 2126 RefPtr<IDBKey> primaryKey; 2127 decodeIDBKey(encodedPrimaryKey.begin(), encodedPrimaryKey.end(), primaryKey); 2128 return primaryKey.release(); 2129 } 2130 } 2131 2132 bool IDBLevelDBBackingStore::keyExistsInIndex(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& key) 2133 { 2134 const Vector<char> levelDBKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, key, 0); 2135 OwnPtr<LevelDBIterator> it(m_db->newIterator()); 2136 2137 bool found = false; 2138 2139 it->seek(levelDBKey); 2140 if (it->isValid() && !compareIndexKeys(it->key(), levelDBKey)) 2141 found = true; 2142 2143 return found; 2144 } 2145 2146 namespace { 2147 class CursorImplCommon : public IDBBackingStore::Cursor { 2148 public: 2149 // IDBBackingStore::Cursor 2150 virtual bool continueFunction(const IDBKey*); 2151 virtual PassRefPtr<IDBKey> key() { return m_currentKey; } 2152 virtual PassRefPtr<IDBKey> primaryKey() { return m_currentKey; } 2153 virtual String value() = 0; 2154 virtual PassRefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> objectStoreRecordIdentifier() = 0; // FIXME: I don't think this is actually used, so drop it. 2155 virtual int64_t indexDataId() = 0; 2156 2157 virtual bool loadCurrentRow() = 0; 2158 bool firstSeek(); 2159 2160 protected: 2161 CursorImplCommon(LevelDBDatabase* db, const Vector<char>& lowKey, bool lowOpen, const Vector<char>& highKey, bool highOpen, bool forward) 2162 : m_db(db) 2163 , m_lowKey(lowKey) 2164 , m_lowOpen(lowOpen) 2165 , m_highKey(highKey) 2166 , m_highOpen(highOpen) 2167 , m_forward(forward) 2168 { 2169 } 2170 virtual ~CursorImplCommon() {} 2171 2172 LevelDBDatabase* m_db; 2173 OwnPtr<LevelDBIterator> m_iterator; 2174 Vector<char> m_lowKey; 2175 bool m_lowOpen; 2176 Vector<char> m_highKey; 2177 bool m_highOpen; 2178 bool m_forward; 2179 RefPtr<IDBKey> m_currentKey; 2180 }; 2181 2182 bool CursorImplCommon::firstSeek() 2183 { 2184 m_iterator = m_db->newIterator(); 2185 2186 if (m_forward) 2187 m_iterator->seek(m_lowKey); 2188 else 2189 m_iterator->seek(m_highKey); 2190 2191 for (;;) { 2192 if (!m_iterator->isValid()) 2193 return false; 2194 2195 if (m_forward && m_highOpen && compareIndexKeys(m_iterator->key(), m_highKey) >= 0) 2196 return false; 2197 if (m_forward && !m_highOpen && compareIndexKeys(m_iterator->key(), m_highKey) > 0) 2198 return false; 2199 if (!m_forward && m_lowOpen && compareIndexKeys(m_iterator->key(), m_lowKey) <= 0) 2200 return false; 2201 if (!m_forward && !m_lowOpen && compareIndexKeys(m_iterator->key(), m_lowKey) < 0) 2202 return false; 2203 2204 if (m_forward && m_lowOpen) { 2205 // lowKey not included in the range. 2206 if (compareIndexKeys(m_iterator->key(), m_lowKey) <= 0) { 2207 m_iterator->next(); 2208 continue; 2209 } 2210 } 2211 if (!m_forward && m_highOpen) { 2212 // highKey not included in the range. 2213 if (compareIndexKeys(m_iterator->key(), m_highKey) >= 0) { 2214 m_iterator->prev(); 2215 continue; 2216 } 2217 } 2218 2219 if (!loadCurrentRow()) { 2220 if (m_forward) 2221 m_iterator->next(); 2222 else 2223 m_iterator->prev(); 2224 continue; 2225 } 2226 2227 return true; 2228 } 2229 } 2230 2231 bool CursorImplCommon::continueFunction(const IDBKey* key) 2232 { 2233 // FIXME: This shares a lot of code with firstSeek. 2234 2235 for (;;) { 2236 if (m_forward) 2237 m_iterator->next(); 2238 else 2239 m_iterator->prev(); 2240 2241 if (!m_iterator->isValid()) 2242 return false; 2243 2244 Vector<char> trash; 2245 if (!m_db->get(m_iterator->key(), trash)) 2246 continue; 2247 2248 if (m_forward && m_highOpen && compareIndexKeys(m_iterator->key(), m_highKey) >= 0) // high key not included in range 2249 return false; 2250 if (m_forward && !m_highOpen && compareIndexKeys(m_iterator->key(), m_highKey) > 0) 2251 return false; 2252 if (!m_forward && m_lowOpen && compareIndexKeys(m_iterator->key(), m_lowKey) <= 0) // low key not included in range 2253 return false; 2254 if (!m_forward && !m_lowOpen && compareIndexKeys(m_iterator->key(), m_lowKey) < 0) 2255 return false; 2256 2257 if (!loadCurrentRow()) 2258 continue; 2259 2260 if (key) { 2261 if (m_forward) { 2262 if (m_currentKey->isLessThan(key)) 2263 continue; 2264 } else { 2265 if (key->isLessThan(m_currentKey.get())) 2266 continue; 2267 } 2268 } 2269 2270 // FIXME: Obey the uniqueness constraint (and test for it!) 2271 2272 break; 2273 } 2274 2275 return true; 2276 } 2277 2278 class ObjectStoreCursorImpl : public CursorImplCommon { 2279 public: 2280 static PassRefPtr<ObjectStoreCursorImpl> create(LevelDBDatabase* db, const Vector<char>& lowKey, bool lowOpen, const Vector<char>& highKey, bool highOpen, bool forward) 2281 { 2282 return adoptRef(new ObjectStoreCursorImpl(db, lowKey, lowOpen, highKey, highOpen, forward)); 2283 } 2284 2285 // CursorImplCommon 2286 virtual String value() { return m_currentValue; } 2287 virtual PassRefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> objectStoreRecordIdentifier() { ASSERT_NOT_REACHED(); return 0; } 2288 virtual int64_t indexDataId() { ASSERT_NOT_REACHED(); return 0; } 2289 virtual bool loadCurrentRow(); 2290 2291 private: 2292 ObjectStoreCursorImpl(LevelDBDatabase* db, const Vector<char>& lowKey, bool lowOpen, const Vector<char>& highKey, bool highOpen, bool forward) 2293 : CursorImplCommon(db, lowKey, lowOpen, highKey, highOpen, forward) 2294 { 2295 } 2296 2297 String m_currentValue; 2298 }; 2299 2300 bool ObjectStoreCursorImpl::loadCurrentRow() 2301 { 2302 const char* p = m_iterator->key().begin(); 2303 const char* keyLimit = m_iterator->key().end(); 2304 2305 ObjectStoreDataKey objectStoreDataKey; 2306 p = ObjectStoreDataKey::decode(p, keyLimit, &objectStoreDataKey); 2307 ASSERT(p); 2308 if (!p) 2309 return false; 2310 2311 m_currentKey = objectStoreDataKey.userKey(); 2312 2313 int64_t version; 2314 const char* q = decodeVarInt(m_iterator->value().begin(), m_iterator->value().end(), version); 2315 ASSERT(q); 2316 if (!q) 2317 return false; 2318 (void) version; 2319 2320 m_currentValue = decodeString(q, m_iterator->value().end()); 2321 2322 return true; 2323 } 2324 2325 class IndexKeyCursorImpl : public CursorImplCommon { 2326 public: 2327 static PassRefPtr<IndexKeyCursorImpl> create(LevelDBDatabase* db, const Vector<char>& lowKey, bool lowOpen, const Vector<char>& highKey, bool highOpen, bool forward) 2328 { 2329 return adoptRef(new IndexKeyCursorImpl(db, lowKey, lowOpen, highKey, highOpen, forward)); 2330 } 2331 2332 // CursorImplCommon 2333 virtual String value() { ASSERT_NOT_REACHED(); return String(); } 2334 virtual PassRefPtr<IDBKey> primaryKey() { return m_primaryKey; } 2335 virtual PassRefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> objectStoreRecordIdentifier() { ASSERT_NOT_REACHED(); return 0; } 2336 virtual int64_t indexDataId() { ASSERT_NOT_REACHED(); return 0; } 2337 virtual bool loadCurrentRow(); 2338 2339 private: 2340 IndexKeyCursorImpl(LevelDBDatabase* db, const Vector<char>& lowKey, bool lowOpen, const Vector<char>& highKey, bool highOpen, bool forward) 2341 : CursorImplCommon(db, lowKey, lowOpen, highKey, highOpen, forward) 2342 { 2343 } 2344 2345 RefPtr<IDBKey> m_primaryKey; 2346 }; 2347 2348 bool IndexKeyCursorImpl::loadCurrentRow() 2349 { 2350 const char* p = m_iterator->key().begin(); 2351 const char* keyLimit = m_iterator->key().end(); 2352 IndexDataKey indexDataKey; 2353 p = IndexDataKey::decode(p, keyLimit, &indexDataKey); 2354 2355 m_currentKey = indexDataKey.userKey(); 2356 2357 int64_t indexDataVersion; 2358 const char* q = decodeVarInt(m_iterator->value().begin(), m_iterator->value().end(), indexDataVersion); 2359 ASSERT(q); 2360 if (!q) 2361 return false; 2362 2363 q = decodeIDBKey(q, m_iterator->value().end(), m_primaryKey); 2364 ASSERT(q); 2365 if (!q) 2366 return false; 2367 2368 Vector<char> primaryLevelDBKey = ObjectStoreDataKey::encode(indexDataKey.databaseId(), indexDataKey.objectStoreId(), *m_primaryKey); 2369 2370 Vector<char> result; 2371 if (!m_db->get(primaryLevelDBKey, result)) 2372 return false; 2373 2374 int64_t objectStoreDataVersion; 2375 const char* t = decodeVarInt(result.begin(), result.end(), objectStoreDataVersion); 2376 ASSERT(t); 2377 if (!t) 2378 return false; 2379 2380 if (objectStoreDataVersion != indexDataVersion) { // FIXME: This is probably not very well covered by the layout tests. 2381 m_db->remove(m_iterator->key()); 2382 return false; 2383 } 2384 2385 return true; 2386 } 2387 2388 class IndexCursorImpl : public CursorImplCommon { 2389 public: 2390 static PassRefPtr<IndexCursorImpl> create(LevelDBDatabase* db, const Vector<char>& lowKey, bool lowOpen, const Vector<char>& highKey, bool highOpen, bool forward) 2391 { 2392 return adoptRef(new IndexCursorImpl(db, lowKey, lowOpen, highKey, highOpen, forward)); 2393 } 2394 2395 // CursorImplCommon 2396 virtual String value() { return m_value; } 2397 virtual PassRefPtr<IDBKey> primaryKey() { return m_primaryKey; } 2398 virtual PassRefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> objectStoreRecordIdentifier() { ASSERT_NOT_REACHED(); return 0; } 2399 virtual int64_t indexDataId() { ASSERT_NOT_REACHED(); return 0; } 2400 bool loadCurrentRow(); 2401 2402 private: 2403 IndexCursorImpl(LevelDBDatabase* db, const Vector<char>& lowKey, bool lowOpen, const Vector<char>& highKey, bool highOpen, bool forward) 2404 : CursorImplCommon(db, lowKey, lowOpen, highKey, highOpen, forward) 2405 { 2406 } 2407 2408 RefPtr<IDBKey> m_primaryKey; 2409 String m_value; 2410 Vector<char> m_primaryLevelDBKey; 2411 }; 2412 2413 bool IndexCursorImpl::loadCurrentRow() 2414 { 2415 const char *p = m_iterator->key().begin(); 2416 const char *limit = m_iterator->key().end(); 2417 2418 IndexDataKey indexDataKey; 2419 p = IndexDataKey::decode(p, limit, &indexDataKey); 2420 2421 m_currentKey = indexDataKey.userKey(); 2422 2423 const char *q = m_iterator->value().begin(); 2424 const char *valueLimit = m_iterator->value().end(); 2425 2426 int64_t indexDataVersion; 2427 q = decodeVarInt(q, valueLimit, indexDataVersion); 2428 ASSERT(q); 2429 if (!q) 2430 return false; 2431 q = decodeIDBKey(q, valueLimit, m_primaryKey); 2432 ASSERT(q); 2433 if (!q) 2434 return false; 2435 2436 m_primaryLevelDBKey = ObjectStoreDataKey::encode(indexDataKey.databaseId(), indexDataKey.objectStoreId(), *m_primaryKey); 2437 2438 Vector<char> result; 2439 if (!m_db->get(m_primaryLevelDBKey, result)) 2440 return false; 2441 2442 int64_t objectStoreDataVersion; 2443 const char* t = decodeVarInt(result.begin(), result.end(), objectStoreDataVersion); 2444 ASSERT(t); 2445 if (!t) 2446 return false; 2447 2448 if (objectStoreDataVersion != indexDataVersion) { 2449 m_db->remove(m_iterator->key()); 2450 return false; 2451 } 2452 2453 m_value = decodeString(t, result.end()); 2454 return true; 2455 } 2456 2457 } 2458 2459 static bool findLastIndexKeyEqualTo(LevelDBDatabase* db, const Vector<char>& target, Vector<char>& foundKey) 2460 { 2461 OwnPtr<LevelDBIterator> it(db->newIterator()); 2462 it->seek(target); 2463 2464 if (!it->isValid()) 2465 return false; 2466 2467 while (it->isValid() && !compareIndexKeys(it->key(), target)) { 2468 foundKey.clear(); 2469 foundKey.append(it->key().begin(), it->key().end() - it->key().begin()); 2470 it->next(); 2471 } 2472 2473 return true; 2474 } 2475 2476 PassRefPtr<IDBBackingStore::Cursor> IDBLevelDBBackingStore::openObjectStoreCursor(int64_t databaseId, int64_t objectStoreId, const IDBKeyRange* range, IDBCursor::Direction direction) 2477 { 2478 bool lowerBound = range && range->lower(); 2479 bool upperBound = range && range->upper(); 2480 bool forward = (direction == IDBCursor::NEXT_NO_DUPLICATE || direction == IDBCursor::NEXT); 2481 2482 bool lowerOpen, upperOpen; 2483 Vector<char> startKey, stopKey; 2484 2485 if (!lowerBound) { 2486 startKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, minIDBKey()); 2487 lowerOpen = true; // Not included. 2488 } else { 2489 startKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, *range->lower()); 2490 lowerOpen = range->lowerOpen(); 2491 } 2492 2493 if (!upperBound) { 2494 stopKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, maxIDBKey()); 2495 upperOpen = true; // Not included. 2496 2497 if (!forward) { // We need a key that exists. 2498 if (!findGreatestKeyLessThan(m_db.get(), stopKey, stopKey)) 2499 return 0; 2500 upperOpen = false; 2501 } 2502 } else { 2503 stopKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, *range->upper()); 2504 upperOpen = range->upperOpen(); 2505 } 2506 2507 RefPtr<ObjectStoreCursorImpl> cursor = ObjectStoreCursorImpl::create(m_db.get(), startKey, lowerOpen, stopKey, upperOpen, forward); 2508 if (!cursor->firstSeek()) 2509 return 0; 2510 2511 return cursor.release(); 2512 } 2513 2514 PassRefPtr<IDBBackingStore::Cursor> IDBLevelDBBackingStore::openIndexKeyCursor(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange* range, IDBCursor::Direction direction) 2515 { 2516 bool lowerBound = range && range->lower(); 2517 bool upperBound = range && range->upper(); 2518 bool forward = (direction == IDBCursor::NEXT_NO_DUPLICATE || direction == IDBCursor::NEXT); 2519 2520 bool lowerOpen, upperOpen; 2521 Vector<char> startKey, stopKey; 2522 2523 if (!lowerBound) { 2524 startKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, minIDBKey(), 0); 2525 lowerOpen = false; // Included. 2526 } else { 2527 startKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, *range->lower(), 0); 2528 lowerOpen = range->lowerOpen(); 2529 } 2530 2531 if (!upperBound) { 2532 stopKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, maxIDBKey(), 0); 2533 upperOpen = false; // Included. 2534 2535 if (!forward) { // We need a key that exists. 2536 if (!findGreatestKeyLessThan(m_db.get(), stopKey, stopKey)) 2537 return 0; 2538 upperOpen = false; 2539 } 2540 } else { 2541 stopKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, *range->upper(), 0); 2542 if (!findLastIndexKeyEqualTo(m_db.get(), stopKey, stopKey)) // Seek to the *last* key in the set of non-unique keys. 2543 return 0; 2544 upperOpen = range->upperOpen(); 2545 } 2546 2547 RefPtr<IndexKeyCursorImpl> cursor = IndexKeyCursorImpl::create(m_db.get(), startKey, lowerOpen, stopKey, upperOpen, forward); 2548 if (!cursor->firstSeek()) 2549 return 0; 2550 2551 return cursor.release(); 2552 } 2553 2554 PassRefPtr<IDBBackingStore::Cursor> IDBLevelDBBackingStore::openIndexCursor(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange* range, IDBCursor::Direction direction) 2555 { 2556 bool lowerBound = range && range->lower(); 2557 bool upperBound = range && range->upper(); 2558 bool forward = (direction == IDBCursor::NEXT_NO_DUPLICATE || direction == IDBCursor::NEXT); 2559 2560 bool lowerOpen, upperOpen; 2561 Vector<char> startKey, stopKey; 2562 2563 if (!lowerBound) { 2564 startKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, minIDBKey(), 0); 2565 lowerOpen = false; // Included. 2566 } else { 2567 startKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, *range->lower(), 0); 2568 lowerOpen = range->lowerOpen(); 2569 } 2570 2571 if (!upperBound) { 2572 stopKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, maxIDBKey(), 0); 2573 upperOpen = false; // Included. 2574 2575 if (!forward) { // We need a key that exists. 2576 if (!findGreatestKeyLessThan(m_db.get(), stopKey, stopKey)) 2577 return 0; 2578 upperOpen = false; 2579 } 2580 } else { 2581 stopKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, *range->upper(), 0); 2582 if (!findLastIndexKeyEqualTo(m_db.get(), stopKey, stopKey)) // Seek to the *last* key in the set of non-unique keys. 2583 return 0; 2584 upperOpen = range->upperOpen(); 2585 } 2586 2587 RefPtr<IndexCursorImpl> cursor = IndexCursorImpl::create(m_db.get(), startKey, lowerOpen, stopKey, upperOpen, forward); 2588 if (!cursor->firstSeek()) 2589 return 0; 2590 2591 return cursor.release(); 2592 } 2593 2594 namespace { 2595 class DummyTransaction : public IDBBackingStore::Transaction { 2596 public: 2597 virtual void begin() {} 2598 virtual void commit() {} 2599 virtual void rollback() {} 2600 }; 193 2601 } 194 2602 195 2603 PassRefPtr<IDBBackingStore::Transaction> IDBLevelDBBackingStore::createTransaction() 196 2604 { 197 ASSERT_NOT_REACHED(); // FIXME: Implement. 198 return 0; 199 } 2605 // FIXME: We need to implement a transaction abstraction that allows for roll-backs, and write tests for it. 2606 return adoptRef(new DummyTransaction()); 2607 } 2608 2609 // FIXME: deleteDatabase should be part of IDBBackingStore. 200 2610 201 2611 } // namespace WebCore -
trunk/Source/WebCore/storage/IDBLevelDBBackingStore.h
r83443 r84149 33 33 #include <wtf/OwnPtr.h> 34 34 35 namespace leveldb {36 class DB;37 }38 35 namespace WebCore { 36 37 class LevelDBComparator; 38 class LevelDBDatabase; 39 39 40 40 class IDBLevelDBBackingStore : public IDBBackingStore { … … 75 75 76 76 private: 77 IDBLevelDBBackingStore(String identifier, IDBFactoryBackendImpl*, leveldb::DB*);77 IDBLevelDBBackingStore(String identifier, IDBFactoryBackendImpl*, LevelDBDatabase*); 78 78 79 79 String m_identifier; 80 80 RefPtr<IDBFactoryBackendImpl> m_factory; 81 OwnPtr<leveldb::DB> m_db; 81 OwnPtr<LevelDBDatabase> m_db; 82 OwnPtr<LevelDBComparator> m_comparator; 82 83 }; 83 84
Note: See TracChangeset
for help on using the changeset viewer.