Changeset 84149 in webkit


Ignore:
Timestamp:
Apr 18, 2011 9:13:25 AM (13 years ago)
Author:
hans@chromium.org
Message:

2011-04-18 Hans Wennborg <hans@chromium.org>

Reviewed by Steve Block.

LevelDB backend for IndexedDB
https://bugs.webkit.org/show_bug.cgi?id=57372

Add LevelDB wrappers to Android.mk.

  • Source/Android.mk:

2011-04-18 Hans Wennborg <hans@chromium.org>

Reviewed by Steve Block.

LevelDB backend for IndexedDB
https://bugs.webkit.org/show_bug.cgi?id=57372

Only available behind a run-time flag. Covered by existing layout
tests.

  • Android.mk:
  • CMakeLists.txt:
  • GNUmakefile.am:
  • GNUmakefile.list.am:
  • WebCore.gyp/WebCore.gyp:
  • WebCore.gypi:
  • WebCore.pri:
  • WebCore.pro:
  • WebCore.xcodeproj/project.pbxproj:
  • platform/leveldb/LevelDBComparator.h: Added. (WebCore::LevelDBComparator::~LevelDBComparator):
  • platform/leveldb/LevelDBDatabase.cpp: Added. (WebCore::makeSlice): (WebCore::makeLevelDBSlice): (WebCore::makeVector): (WebCore::LevelDBDatabase::LevelDBDatabase): (WebCore::LevelDBDatabase::~LevelDBDatabase): (WebCore::LevelDBDatabase::open): (WebCore::LevelDBDatabase::put): (WebCore::LevelDBDatabase::remove): (WebCore::LevelDBDatabase::get): (WebCore::LevelDBDatabase::newIterator):
  • platform/leveldb/LevelDBDatabase.h: Added.
  • platform/leveldb/LevelDBIterator.cpp: Added. (WebCore::LevelDBIterator::~LevelDBIterator): (WebCore::LevelDBIterator::LevelDBIterator): (WebCore::makeSlice): (WebCore::makeLevelDBSlice): (WebCore::LevelDBIterator::isValid): (WebCore::LevelDBIterator::seekToLast): (WebCore::LevelDBIterator::seek): (WebCore::LevelDBIterator::next): (WebCore::LevelDBIterator::prev): (WebCore::LevelDBIterator::key): (WebCore::LevelDBIterator::value):
  • platform/leveldb/LevelDBIterator.h: Added.
  • platform/leveldb/LevelDBSlice.h: Added. (WebCore::LevelDBSlice::LevelDBSlice): (WebCore::LevelDBSlice::~LevelDBSlice): (WebCore::LevelDBSlice::begin): (WebCore::LevelDBSlice::end):
  • storage/IDBLevelDBBackingStore.cpp: (WebCore::encodeByte): (WebCore::maxIDBKey): (WebCore::minIDBKey): (WebCore::encodeInt): (WebCore::decodeInt): (WebCore::encodeVarInt): (WebCore::decodeVarInt): (WebCore::encodeString): (WebCore::decodeString): (WebCore::encodeStringWithLength): (WebCore::decodeStringWithLength): (WebCore::encodeDouble): (WebCore::decodeDouble): (WebCore::encodeIDBKey): (WebCore::decodeIDBKey): (WebCore::extractEncodedIDBKey): (WebCore::compareEncodedIDBKeys): (WebCore::getInt): (WebCore::putInt): (WebCore::getString): (WebCore::putString): (WebCore::KeyPrefix::SchemaVersionKey::encode): (WebCore::KeyPrefix::MaxDatabaseIdKey::encode): (WebCore::KeyPrefix::DatabaseFreeListKey::DatabaseFreeListKey): (WebCore::KeyPrefix::DatabaseFreeListKey::decode): (WebCore::KeyPrefix::DatabaseFreeListKey::encode): (WebCore::KeyPrefix::DatabaseFreeListKey::databaseId): (WebCore::KeyPrefix::DatabaseFreeListKey::compare): (WebCore::KeyPrefix::DatabaseNameKey::decode): (WebCore::KeyPrefix::DatabaseNameKey::encode): (WebCore::KeyPrefix::DatabaseNameKey::origin): (WebCore::KeyPrefix::DatabaseNameKey::databaseName): (WebCore::KeyPrefix::DatabaseNameKey::compare): (WebCore::KeyPrefix::DatabaseMetaDataKey::encode): (WebCore::KeyPrefix::ObjectStoreMetaDataKey::ObjectStoreMetaDataKey): (WebCore::KeyPrefix::ObjectStoreMetaDataKey::decode): (WebCore::KeyPrefix::ObjectStoreMetaDataKey::encode): (WebCore::KeyPrefix::ObjectStoreMetaDataKey::objectStoreId): (WebCore::KeyPrefix::ObjectStoreMetaDataKey::metaDataType): (WebCore::KeyPrefix::ObjectStoreMetaDataKey::compare): (WebCore::KeyPrefix::IndexMetaDataKey::IndexMetaDataKey): (WebCore::KeyPrefix::IndexMetaDataKey::decode): (WebCore::KeyPrefix::IndexMetaDataKey::encode): (WebCore::KeyPrefix::IndexMetaDataKey::compare): (WebCore::KeyPrefix::IndexMetaDataKey::indexId): (WebCore::KeyPrefix::IndexMetaDataKey::metaDataType): (WebCore::KeyPrefix::ObjectStoreFreeListKey::ObjectStoreFreeListKey): (WebCore::KeyPrefix::ObjectStoreFreeListKey::decode): (WebCore::KeyPrefix::ObjectStoreFreeListKey::encode): (WebCore::KeyPrefix::ObjectStoreFreeListKey::objectStoreId): (WebCore::KeyPrefix::ObjectStoreFreeListKey::compare): (WebCore::KeyPrefix::IndexFreeListKey::IndexFreeListKey): (WebCore::KeyPrefix::IndexFreeListKey::decode): (WebCore::KeyPrefix::IndexFreeListKey::encode): (WebCore::KeyPrefix::IndexFreeListKey::compare): (WebCore::KeyPrefix::IndexFreeListKey::objectStoreId): (WebCore::KeyPrefix::IndexFreeListKey::indexId): (WebCore::KeyPrefix::ObjectStoreNamesKey::decode): (WebCore::KeyPrefix::ObjectStoreNamesKey::encode): (WebCore::KeyPrefix::ObjectStoreNamesKey::compare): (WebCore::KeyPrefix::ObjectStoreNamesKey::objectStoreName): (WebCore::KeyPrefix::IndexNamesKey::IndexNamesKey): (WebCore::KeyPrefix::IndexNamesKey::decode): (WebCore::KeyPrefix::IndexNamesKey::encode): (WebCore::KeyPrefix::IndexNamesKey::compare): (WebCore::KeyPrefix::IndexNamesKey::indexName): (WebCore::KeyPrefix::ObjectStoreDataKey::decode): (WebCore::KeyPrefix::ObjectStoreDataKey::encode): (WebCore::KeyPrefix::ObjectStoreDataKey::compare): (WebCore::KeyPrefix::ObjectStoreDataKey::userKey): (WebCore::KeyPrefix::ExistsEntryKey::decode): (WebCore::KeyPrefix::ExistsEntryKey::encode): (WebCore::KeyPrefix::ExistsEntryKey::compare): (WebCore::KeyPrefix::ExistsEntryKey::userKey): (WebCore::KeyPrefix::IndexDataKey::IndexDataKey): (WebCore::KeyPrefix::IndexDataKey::decode): (WebCore::KeyPrefix::IndexDataKey::encode): (WebCore::KeyPrefix::IndexDataKey::encodeMaxKey): (WebCore::KeyPrefix::IndexDataKey::compare): (WebCore::KeyPrefix::IndexDataKey::databaseId): (WebCore::KeyPrefix::IndexDataKey::objectStoreId): (WebCore::KeyPrefix::IndexDataKey::indexId): (WebCore::KeyPrefix::IndexDataKey::userKey): (WebCore::KeyPrefix::realCompare): (WebCore::KeyPrefix::compareKeys): (WebCore::KeyPrefix::compareIndexKeys): (WebCore::KeyPrefix::Comparator::compare): (WebCore::KeyPrefix::Comparator::name): (WebCore::setUpMetadata): (WebCore::IDBLevelDBBackingStore::IDBLevelDBBackingStore): (WebCore::IDBLevelDBBackingStore::open): (WebCore::IDBLevelDBBackingStore::extractIDBDatabaseMetaData): (WebCore::getNewDatabaseId): (WebCore::IDBLevelDBBackingStore::setIDBDatabaseMetaData): (WebCore::IDBLevelDBBackingStore::getObjectStores): (WebCore::getNewObjectStoreId): (WebCore::IDBLevelDBBackingStore::createObjectStore): (WebCore::deleteRange): (WebCore::IDBLevelDBBackingStore::deleteObjectStore): (WebCore::IDBLevelDBBackingStore::getObjectStoreRecord): (WebCore::getNewVersionNumber): (WebCore::IDBLevelDBBackingStore::putObjectStoreRecord): (WebCore::IDBLevelDBBackingStore::clearObjectStore): (WebCore::IDBLevelDBBackingStore::createInvalidRecordIdentifier): (WebCore::IDBLevelDBBackingStore::deleteObjectStoreRecord): (WebCore::IDBLevelDBBackingStore::nextAutoIncrementNumber): (WebCore::IDBLevelDBBackingStore::keyExistsInObjectStore): (WebCore::IDBLevelDBBackingStore::forEachObjectStoreRecord): (WebCore::IDBLevelDBBackingStore::getIndexes): (WebCore::getNewIndexId): (WebCore::IDBLevelDBBackingStore::createIndex): (WebCore::IDBLevelDBBackingStore::deleteIndex): (WebCore::IDBLevelDBBackingStore::putIndexDataForRecord): (WebCore::findGreatestKeyLessThan): (WebCore::IDBLevelDBBackingStore::deleteIndexDataForRecord): (WebCore::IDBLevelDBBackingStore::getObjectViaIndex): (WebCore::versionExists): (WebCore::IDBLevelDBBackingStore::getPrimaryKeyViaIndex): (WebCore::IDBLevelDBBackingStore::keyExistsInIndex): (WebCore::findLastIndexKeyEqualTo): (WebCore::IDBLevelDBBackingStore::openObjectStoreCursor): (WebCore::IDBLevelDBBackingStore::openIndexKeyCursor): (WebCore::IDBLevelDBBackingStore::openIndexCursor): (WebCore::IDBLevelDBBackingStore::createTransaction):
  • storage/IDBLevelDBBackingStore.h:
Location:
trunk
Files:
7 added
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/ChangeLog

    r84130 r84149  
     12011-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
    1122011-04-18  Patrick Gansterer  <paroga@webkit.org>
    213
  • trunk/Source/Android.mk

    r78107 r84149  
    117117        $(LOCAL_PATH)/WebCore/platform/graphics/transforms \
    118118        $(LOCAL_PATH)/WebCore/platform/image-decoders \
     119        $(LOCAL_PATH)/WebCore/platform/leveldb \
    119120        $(LOCAL_PATH)/WebCore/platform/mock \
    120121        $(LOCAL_PATH)/WebCore/platform/network \
  • trunk/Source/WebCore/Android.mk

    r84039 r84149  
    604604        platform/image-decoders/gif/GIFImageDecoder.cpp \
    605605        platform/image-decoders/gif/GIFImageReader.cpp \
     606        \
     607        platform/leveldb/LevelDBDatabase.cpp \
     608        platform/leveldb/LevelDBIterator.cpp \
    606609        \
    607610        platform/mock/DeviceOrientationClientMock.cpp \
  • trunk/Source/WebCore/CMakeLists.txt

    r84125 r84149  
    3939    "${WEBCORE_DIR}/platform/image-decoders/png"
    4040    "${WEBCORE_DIR}/platform/image-decoders/webp"
     41    "${WEBCORE_DIR}/platform/leveldb"
    4142    "${WEBCORE_DIR}/platform/mock"
    4243    "${WEBCORE_DIR}/platform/network"
     
    14471448        dom/DataTransferItem.cpp
    14481449        dom/StringCallback.cpp
     1450    )
     1451ENDIF ()
     1452
     1453IF (ENABLE_LEVELDB)
     1454    LIST(APPEND WebCore_SOURCES
     1455        platform/leveldb/LevelDBDatabase.cpp
     1456        platform/leveldb/LevelDBIterator.cpp
    14491457    )
    14501458ENDIF ()
  • trunk/Source/WebCore/ChangeLog

    r84148 r84149  
     12011-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
    11792011-04-18  Pavel Feldman  <pfeldman@google.com>
    2180
  • trunk/Source/WebCore/GNUmakefile.am

    r84053 r84149  
    5757        -I$(srcdir)/Source/WebCore/platform/image-decoders/webp \
    5858        -I$(srcdir)/Source/WebCore/platform/image-decoders/png \
     59        -I$(srcdir)/Source/WebCore/platform/leveldb \
    5960        -I$(srcdir)/Source/WebCore/platform/mock \
    6061        -I$(srcdir)/Source/WebCore/platform/network \
  • trunk/Source/WebCore/GNUmakefile.list.am

    r84125 r84149  
    25092509        Source/WebCore/platform/Length.h \
    25102510        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 \
    25112517        Source/WebCore/platform/LinkHash.cpp \
    25122518        Source/WebCore/platform/LinkHash.h \
  • trunk/Source/WebCore/WebCore.gyp/WebCore.gyp

    r83893 r84149  
    185185      '../platform/image-decoders/webp',
    186186      '../platform/image-encoders/skia',
     187      '../platform/leveldb',
    187188      '../platform/mock',
    188189      '../platform/network',
  • trunk/Source/WebCore/WebCore.gypi

    r84125 r84149  
    859859            'platform/graphics/transforms/TransformationMatrix.h',
    860860            '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',
    861867            'platform/mac/BlockExceptions.h',
    862868            'platform/mac/ClipboardMac.h',
  • trunk/Source/WebCore/WebCore.pri

    r83835 r84149  
    9898    $$SOURCE_DIR/WebCore/platform/graphics/transforms \
    9999    $$SOURCE_DIR/WebCore/platform/image-decoders \
     100    $$SOURCE_DIR/WebCore/platform/leveldb \
    100101    $$SOURCE_DIR/WebCore/platform/mock \
    101102    $$SOURCE_DIR/WebCore/platform/network \
  • trunk/Source/WebCore/WebCore.pro

    r84125 r84149  
    10121012    platform/Length.cpp \
    10131013    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 \
    10141020    platform/LinkHash.cpp \
    10151021    platform/Logging.cpp \
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r84125 r84149  
    27912791                8C6EA61911EF7E0400FD8EE3 /* RuntimeEnabledFeatures.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C6EA61711EF7E0400FD8EE3 /* RuntimeEnabledFeatures.cpp */; };
    27922792                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 */; };
    27932799                8F67561B1288B17B0047ACA3 /* EventQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 8F6756191288B17B0047ACA3 /* EventQueue.h */; };
    27942800                8F67561C1288B17B0047ACA3 /* EventQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8F67561A1288B17B0047ACA3 /* EventQueue.cpp */; };
     
    93509356                8C6EA61711EF7E0400FD8EE3 /* RuntimeEnabledFeatures.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RuntimeEnabledFeatures.cpp; path = generic/RuntimeEnabledFeatures.cpp; sourceTree = "<group>"; };
    93519357                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>"; };
    93529364                8F6756191288B17B0047ACA3 /* EventQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventQueue.h; sourceTree = "<group>"; };
    93539365                8F67561A1288B17B0047ACA3 /* EventQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EventQueue.cpp; sourceTree = "<group>"; };
     
    1561415626                        sourceTree = "<group>";
    1561515627                };
     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                };
    1561615641                93309D86099E64910056E581 /* editing */ = {
    1561715642                        isa = PBXGroup;
     
    1862818653                                B2A015910AF6CD53006BCE0E /* graphics */,
    1862918654                                A59E3C1B11580F340072928E /* iphone */,
     18655                                8CADF2A2135C7B36009EF43F /* leveldb */,
    1863018656                                6582A14809999D6C00BEEB6D /* mac */,
    1863118657                                59C77F101054591C00506104 /* mock */,
     
    2296722993                                E1BE512E0CF6C512002EA959 /* XSLTUnicodeSort.h in Headers */,
    2296822994                                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 */,
    2296922999                        );
    2297023000                        runOnlyForDeploymentPostprocessing = 0;
     
    2567325703                                E1BE512D0CF6C512002EA959 /* XSLTUnicodeSort.cpp in Sources */,
    2567425704                                977E2E0E12F0FC9C00C13379 /* XSSFilter.cpp in Sources */,
     25705                                8CADF2AA135C7B36009EF43F /* LevelDBDatabase.cpp in Sources */,
     25706                                8CADF2AC135C7B36009EF43F /* LevelDBIterator.cpp in Sources */,
    2567525707                        );
    2567625708                        runOnlyForDeploymentPostprocessing = 0;
  • trunk/Source/WebCore/storage/IDBLevelDBBackingStore.cpp

    r83443 r84149  
    3030#if ENABLE(LEVELDB)
    3131
     32#include "Assertions.h"
     33#include "FileSystem.h"
    3234#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
     139static const unsigned char kIDBKeyNullTypeByte = 0;
     140static const unsigned char kIDBKeyStringTypeByte = 1;
     141static const unsigned char kIDBKeyDateTypeByte = 2;
     142static const unsigned char kIDBKeyNumberTypeByte = 3;
     143static const unsigned char kIDBKeyMinKeyTypeByte = 4;
     144
     145static const unsigned char kMinimumIndexId = 30;
     146static const unsigned char kObjectStoreDataIndexId = 1;
     147static const unsigned char kExistsEntryIndexId = 2;
     148
     149static const unsigned char kSchemaVersionTypeByte = 0;
     150static const unsigned char kMaxDatabaseIdTypeByte = 1;
     151static const unsigned char kDatabaseFreeListTypeByte = 100;
     152static const unsigned char kDatabaseNameTypeByte = 201;
     153
     154static const unsigned char kObjectStoreMetaDataTypeByte = 50;
     155static const unsigned char kIndexMetaDataTypeByte = 100;
     156static const unsigned char kObjectStoreFreeListTypeByte = 150;
     157static const unsigned char kIndexFreeListTypeByte = 151;
     158static const unsigned char kObjectStoreNamesTypeByte = 200;
     159static const unsigned char kIndexNamesKeyTypeByte = 201;
    34160
    35161namespace WebCore {
    36162
    37 IDBLevelDBBackingStore::IDBLevelDBBackingStore(String identifier, IDBFactoryBackendImpl* factory, leveldb::DB* db)
     163static Vector<char> encodeByte(unsigned char c)
     164{
     165    Vector<char> v;
     166    v.append(c);
     167    return v;
     168}
     169
     170static Vector<char> maxIDBKey()
     171{
     172    return encodeByte(kIDBKeyNullTypeByte);
     173}
     174
     175static Vector<char> minIDBKey()
     176{
     177    return encodeByte(kIDBKeyMinKeyTypeByte);
     178}
     179
     180static 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
     194static 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
     207static 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
     222static 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
     236static 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
     251static 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
     269static Vector<char> encodeStringWithLength(const String& s)
     270{
     271    Vector<char> ret = encodeVarInt(s.length());
     272    ret.append(encodeString(s));
     273    return ret;
     274}
     275
     276static 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
     291static 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
     301static 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
     312static 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
     339static 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
     381static 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
     419static 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
     468static 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
     478static bool putInt(LevelDBDatabase* db, const Vector<char>& key, int64_t value)
     479{
     480    return db->put(key, encodeInt(value));
     481}
     482
     483static 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
     493static 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
     500namespace {
     501class KeyPrefix {
     502public:
     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
     618class SchemaVersionKey {
     619public:
     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
     629class MaxDatabaseIdKey {
     630public:
     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
     640class DatabaseFreeListKey {
     641public:
     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
     686private:
     687    int64_t m_databaseId;
     688};
     689
     690class DatabaseNameKey {
     691public:
     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
     733private:
     734    String m_origin; // FIXME: Store encoded strings, or just pointers.
     735    String m_databaseName;
     736};
     737
     738class DatabaseMetaDataKey {
     739public:
     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
     756class ObjectStoreMetaDataKey {
     757public:
     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
     818private:
     819    int64_t m_objectStoreId;
     820    int64_t m_metaDataType; // FIXME: Make this a byte.
     821};
     822
     823class IndexMetaDataKey {
     824public:
     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
     890private:
     891    int64_t m_objectStoreId;
     892    int64_t m_indexId;
     893    unsigned char m_metaDataType;
     894};
     895
     896class ObjectStoreFreeListKey {
     897public:
     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
     945private:
     946    int64_t m_objectStoreId;
     947};
     948
     949class IndexFreeListKey {
     950public:
     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
     1009private:
     1010    int64_t m_objectStoreId;
     1011    int64_t m_indexId;
     1012};
     1013
     1014class ObjectStoreNamesKey {
     1015public:
     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
     1052private:
     1053    String m_objectStoreName; // FIXME: Store the encoded string, or just pointers to it.
     1054};
     1055
     1056class IndexNamesKey {
     1057public:
     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
     1106private:
     1107    int64_t m_objectStoreId;
     1108    String m_indexName;
     1109};
     1110
     1111class ObjectStoreDataKey {
     1112public:
     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
     1155private:
     1156    Vector<char> m_encodedUserKey;
     1157};
     1158
     1159class ExistsEntryKey {
     1160public:
     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
     1202private:
     1203    Vector<char> m_encodedUserKey;
     1204};
     1205
     1206class IndexDataKey {
     1207public:
     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
     1294private:
     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
     1302namespace {
     1303template<typename KeyType>
     1304int 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
     1318static 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
     1428static int compareKeys(const LevelDBSlice& a, const LevelDBSlice& b)
     1429{
     1430    return realCompare(a, b);
     1431}
     1432
     1433static int compareIndexKeys(const LevelDBSlice& a, const LevelDBSlice& b)
     1434{
     1435    return realCompare(a, b, true);
     1436}
     1437
     1438class Comparator : public LevelDBComparator {
     1439public:
     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
     1445static 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
     1463IDBLevelDBBackingStore::IDBLevelDBBackingStore(String identifier, IDBFactoryBackendImpl* factory, LevelDBDatabase* db)
    381464    : m_identifier(identifier)
    391465    , m_factory(factory)
     
    481474}
    491475
    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.
     1476PassRefPtr<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
     1508bool 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
     1523static 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
     1558bool 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
     1574void 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
     1631static 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
     1663bool 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
     1722static 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
     1734void 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
     1753String 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
     1770namespace {
     1771class LevelDBRecordIdentifier : public IDBBackingStore::ObjectStoreRecordIdentifier {
     1772public:
     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
     1782private:
     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
     1791static 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
     1810bool 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
     1832void 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);
    1001838}
    1011839
    1021840PassRefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> IDBLevelDBBackingStore::createInvalidRecordIdentifier()
    1031841{
    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
     1845void 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
     1852double 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
     1881bool 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
     1899bool 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
     1928void 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
     1968static 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
     2002bool 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;
    1402029}
    1412030
    1422031void IDBLevelDBBackingStore::deleteIndex(int64_t, int64_t, int64_t)
    1432032{
    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
     2037bool 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
     2052static 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;
    1512072}
    1522073
    1532074bool IDBLevelDBBackingStore::deleteIndexDataForRecord(int64_t, int64_t, int64_t, const ObjectStoreRecordIdentifier*)
    1542075{
    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
     2080String 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
     2089static 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
     2100PassRefPtr<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
     2132bool 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
     2146namespace {
     2147class CursorImplCommon : public IDBBackingStore::Cursor {
     2148public:
     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
     2160protected:
     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
     2182bool 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
     2231bool 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
     2278class ObjectStoreCursorImpl : public CursorImplCommon {
     2279public:
     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
     2291private:
     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
     2300bool 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
     2325class IndexKeyCursorImpl : public CursorImplCommon {
     2326public:
     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
     2339private:
     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
     2348bool 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
     2388class IndexCursorImpl : public CursorImplCommon {
     2389public:
     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
     2402private:
     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
     2413bool 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
     2459static 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
     2476PassRefPtr<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
     2514PassRefPtr<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
     2554PassRefPtr<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
     2594namespace {
     2595class DummyTransaction : public IDBBackingStore::Transaction {
     2596public:
     2597    virtual void begin() {}
     2598    virtual void commit() {}
     2599    virtual void rollback() {}
     2600};
    1932601}
    1942602
    1952603PassRefPtr<IDBBackingStore::Transaction> IDBLevelDBBackingStore::createTransaction()
    1962604{
    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.
    2002610
    2012611} // namespace WebCore
  • trunk/Source/WebCore/storage/IDBLevelDBBackingStore.h

    r83443 r84149  
    3333#include <wtf/OwnPtr.h>
    3434
    35 namespace leveldb {
    36 class DB;
    37 }
    3835namespace WebCore {
     36
     37class LevelDBComparator;
     38class LevelDBDatabase;
    3939
    4040class IDBLevelDBBackingStore : public IDBBackingStore {
     
    7575
    7676private:
    77     IDBLevelDBBackingStore(String identifier, IDBFactoryBackendImpl*, leveldb::DB*);
     77    IDBLevelDBBackingStore(String identifier, IDBFactoryBackendImpl*, LevelDBDatabase*);
    7878
    7979    String m_identifier;
    8080    RefPtr<IDBFactoryBackendImpl> m_factory;
    81     OwnPtr<leveldb::DB> m_db;
     81    OwnPtr<LevelDBDatabase> m_db;
     82    OwnPtr<LevelDBComparator> m_comparator;
    8283};
    8384
Note: See TracChangeset for help on using the changeset viewer.