2 * Copyright (C) 2011 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "IDBBackingStoreLevelDB.h"
29 #if ENABLE(INDEXED_DATABASE) && USE(LEVELDB)
31 #include "FileSystem.h"
32 #include "HistogramSupport.h"
33 #include "IDBBackingStoreCursorLevelDB.h"
34 #include "IDBBackingStoreTransactionLevelDB.h"
35 #include "IDBIndexWriter.h"
37 #include "IDBKeyPath.h"
38 #include "IDBKeyRange.h"
39 #include "IDBLevelDBCoding.h"
40 #include "IDBMetadata.h"
41 #include "IDBTransactionBackendInterface.h"
42 #include "LevelDBComparator.h"
43 #include "LevelDBDatabase.h"
44 #include "LevelDBIterator.h"
45 #include "LevelDBSlice.h"
46 #include "LevelDBTransaction.h"
48 #include "SecurityOrigin.h"
49 #include "SharedBuffer.h"
50 #include <wtf/Assertions.h>
54 using namespace IDBLevelDBCoding;
56 const int64_t KeyGeneratorInitialNumber = 1; // From the IndexedDB specification.
58 enum IDBBackingStoreLevelDBErrorSource {
59 // 0 - 2 are no longer used.
61 GetIDBDatabaseMetaData,
63 GetKeyGeneratorCurrentNumber,
66 KeyExistsInObjectStore,
69 GetPrimaryKeyViaIndex,
77 CreateIDBDatabaseMetaData,
79 IDBLevelDBBackingStoreInternalErrorMax,
82 static void recordInternalError(const char* type, IDBBackingStoreLevelDBErrorSource location)
84 String name = String::format("WebCore.IndexedDB.BackingStore.%sError", type);
85 HistogramSupport::histogramEnumeration(name.utf8().data(), location, IDBLevelDBBackingStoreInternalErrorMax);
88 // Use to signal conditions that usually indicate developer error, but could be caused by data corruption.
89 // A macro is used instead of an inline function so that the assert and log report the line number.
90 #define REPORT_ERROR(type, location) \
92 LOG_ERROR("IndexedDB %s Error: %s", type, #location); \
93 ASSERT_NOT_REACHED(); \
94 recordInternalError(type, location); \
97 #define INTERNAL_READ_ERROR(location) REPORT_ERROR("Read", location)
98 #define INTERNAL_CONSISTENCY_ERROR(location) REPORT_ERROR("Consistency", location)
99 #define INTERNAL_WRITE_ERROR(location) REPORT_ERROR("Write", location)
101 static void putBool(LevelDBTransaction* transaction, const LevelDBSlice& key, bool value)
103 transaction->put(key, encodeBool(value));
106 template <typename DBOrTransaction>
107 static bool getInt(DBOrTransaction* db, const LevelDBSlice& key, int64_t& foundInt, bool& found)
110 bool ok = db->safeGet(key, result, found);
116 foundInt = decodeInt(result.begin(), result.end());
120 static void putInt(LevelDBTransaction* transaction, const LevelDBSlice& key, int64_t value)
123 transaction->put(key, encodeInt(value));
126 template <typename DBOrTransaction>
127 WARN_UNUSED_RETURN static bool getVarInt(DBOrTransaction* db, const LevelDBSlice& key, int64_t& foundInt, bool& found)
130 bool ok = db->safeGet(key, result, found);
136 found = decodeVarInt(result.begin(), result.end(), foundInt) == result.end();
140 static void putVarInt(LevelDBTransaction* transaction, const LevelDBSlice& key, int64_t value)
142 transaction->put(key, encodeVarInt(value));
145 template <typename DBOrTransaction>
146 WARN_UNUSED_RETURN static bool getString(DBOrTransaction* db, const LevelDBSlice& key, String& foundString, bool& found)
150 bool ok = db->safeGet(key, result, found);
156 foundString = decodeString(result.begin(), result.end());
160 static void putString(LevelDBTransaction* transaction, const LevelDBSlice& key, const String& value)
162 transaction->put(key, encodeString(value));
165 static void putIDBKeyPath(LevelDBTransaction* transaction, const LevelDBSlice& key, const IDBKeyPath& value)
167 transaction->put(key, encodeIDBKeyPath(value));
170 static int compareKeys(const LevelDBSlice& a, const LevelDBSlice& b)
172 return compare(a, b);
175 int IDBBackingStoreLevelDB::compareIndexKeys(const LevelDBSlice& a, const LevelDBSlice& b)
177 return compare(a, b, true);
180 class Comparator : public LevelDBComparator {
182 virtual int compare(const LevelDBSlice& a, const LevelDBSlice& b) const { return IDBLevelDBCoding::compare(a, b); }
183 virtual const char* name() const { return "idb_cmp1"; }
186 // 0 - Initial version.
187 // 1 - Adds UserIntVersion to DatabaseMetaData.
188 // 2 - Adds DataVersion to to global metadata.
189 const int64_t latestKnownSchemaVersion = 2;
190 WARN_UNUSED_RETURN static bool isSchemaKnown(LevelDBDatabase* db, bool& known)
192 int64_t dbSchemaVersion = 0;
194 bool ok = getInt(db, SchemaVersionKey::encode(), dbSchemaVersion, found);
201 if (dbSchemaVersion > latestKnownSchemaVersion) {
206 const uint32_t latestKnownDataVersion = SerializedScriptValue::wireFormatVersion();
207 int64_t dbDataVersion = 0;
208 ok = getInt(db, DataVersionKey::encode(), dbDataVersion, found);
216 if (dbDataVersion > latestKnownDataVersion) {
225 WARN_UNUSED_RETURN static bool setUpMetadata(LevelDBDatabase* db, const String& origin)
227 const uint32_t latestKnownDataVersion = SerializedScriptValue::wireFormatVersion();
228 const Vector<char> schemaVersionKey = SchemaVersionKey::encode();
229 const Vector<char> dataVersionKey = DataVersionKey::encode();
231 RefPtr<LevelDBTransaction> transaction = LevelDBTransaction::create(db);
233 int64_t dbSchemaVersion = 0;
234 int64_t dbDataVersion = 0;
236 bool ok = getInt(transaction.get(), schemaVersionKey, dbSchemaVersion, found);
238 INTERNAL_READ_ERROR(SetupMetadata);
242 // Initialize new backing store.
243 dbSchemaVersion = latestKnownSchemaVersion;
244 putInt(transaction.get(), schemaVersionKey, dbSchemaVersion);
245 dbDataVersion = latestKnownDataVersion;
246 putInt(transaction.get(), dataVersionKey, dbDataVersion);
248 // Upgrade old backing store.
249 ASSERT(dbSchemaVersion <= latestKnownSchemaVersion);
250 if (dbSchemaVersion < 1) {
252 putInt(transaction.get(), schemaVersionKey, dbSchemaVersion);
253 const Vector<char> startKey = DatabaseNameKey::encodeMinKeyForOrigin(origin);
254 const Vector<char> stopKey = DatabaseNameKey::encodeStopKeyForOrigin(origin);
255 OwnPtr<LevelDBIterator> it = db->createIterator();
256 for (it->seek(startKey); it->isValid() && compareKeys(it->key(), stopKey) < 0; it->next()) {
257 int64_t databaseId = 0;
259 bool ok = getInt(transaction.get(), it->key(), databaseId, found);
261 INTERNAL_READ_ERROR(SetupMetadata);
265 INTERNAL_CONSISTENCY_ERROR(SetupMetadata);
268 Vector<char> intVersionKey = DatabaseMetaDataKey::encode(databaseId, DatabaseMetaDataKey::UserIntVersion);
269 putVarInt(transaction.get(), intVersionKey, IDBDatabaseMetadata::DefaultIntVersion);
272 if (dbSchemaVersion < 2) {
274 putInt(transaction.get(), schemaVersionKey, dbSchemaVersion);
275 dbDataVersion = SerializedScriptValue::wireFormatVersion();
276 putInt(transaction.get(), dataVersionKey, dbDataVersion);
280 // All new values will be written using this serialization version.
282 ok = getInt(transaction.get(), dataVersionKey, dbDataVersion, found);
284 INTERNAL_READ_ERROR(SetupMetadata);
288 INTERNAL_CONSISTENCY_ERROR(SetupMetadata);
291 if (dbDataVersion < latestKnownDataVersion) {
292 dbDataVersion = latestKnownDataVersion;
293 putInt(transaction.get(), dataVersionKey, dbDataVersion);
296 ASSERT(dbSchemaVersion == latestKnownSchemaVersion);
297 ASSERT(dbDataVersion == latestKnownDataVersion);
299 if (!transaction->commit()) {
300 INTERNAL_WRITE_ERROR(SetupMetadata);
306 template <typename DBOrTransaction>
307 WARN_UNUSED_RETURN static bool getMaxObjectStoreId(DBOrTransaction* db, int64_t databaseId, int64_t& maxObjectStoreId)
309 const Vector<char> maxObjectStoreIdKey = DatabaseMetaDataKey::encode(databaseId, DatabaseMetaDataKey::MaxObjectStoreId);
310 bool ok = getMaxObjectStoreId(db, maxObjectStoreIdKey, maxObjectStoreId);
314 template <typename DBOrTransaction>
315 WARN_UNUSED_RETURN static bool getMaxObjectStoreId(DBOrTransaction* db, const Vector<char>& maxObjectStoreIdKey, int64_t& maxObjectStoreId)
317 maxObjectStoreId = -1;
319 bool ok = getInt(db, maxObjectStoreIdKey, maxObjectStoreId, found);
323 maxObjectStoreId = 0;
325 ASSERT(maxObjectStoreId >= 0);
329 class DefaultLevelDBFactory : public LevelDBFactory {
331 virtual PassOwnPtr<LevelDBDatabase> openLevelDB(const String& fileName, const LevelDBComparator* comparator)
333 return LevelDBDatabase::open(fileName, comparator);
335 virtual bool destroyLevelDB(const String& fileName)
337 return LevelDBDatabase::destroy(fileName);
341 IDBBackingStoreLevelDB::IDBBackingStoreLevelDB(const String& identifier, PassOwnPtr<LevelDBDatabase> db, PassOwnPtr<LevelDBComparator> comparator)
342 : m_identifier(identifier)
344 , m_comparator(comparator)
345 , m_weakFactory(this)
349 IDBBackingStoreLevelDB::~IDBBackingStoreLevelDB()
351 // m_db's destructor uses m_comparator. The order of destruction is important.
353 m_comparator.clear();
356 enum IDBLevelDBBackingStoreOpenResult {
357 IDBLevelDBBackingStoreOpenMemorySuccess,
358 IDBLevelDBBackingStoreOpenSuccess,
359 IDBLevelDBBackingStoreOpenFailedDirectory,
360 IDBLevelDBBackingStoreOpenFailedUnknownSchema,
361 IDBLevelDBBackingStoreOpenCleanupDestroyFailed,
362 IDBLevelDBBackingStoreOpenCleanupReopenFailed,
363 IDBLevelDBBackingStoreOpenCleanupReopenSuccess,
364 IDBLevelDBBackingStoreOpenFailedIOErrCheckingSchema,
365 IDBLevelDBBackingStoreOpenFailedUnknownErr,
366 IDBLevelDBBackingStoreOpenMemoryFailed,
367 IDBLevelDBBackingStoreOpenAttemptNonASCII,
368 IDBLevelDBBackingStoreOpenMax,
371 PassRefPtr<IDBBackingStoreLevelDB> IDBBackingStoreLevelDB::open(const SecurityOrigin& securityOrigin, const String& pathBaseArg, const String& fileIdentifier)
373 DefaultLevelDBFactory levelDBFactory;
374 return IDBBackingStoreLevelDB::open(securityOrigin, pathBaseArg, fileIdentifier, &levelDBFactory);
377 PassRefPtr<IDBBackingStoreLevelDB> IDBBackingStoreLevelDB::open(const SecurityOrigin& securityOrigin, const String& pathBaseArg, const String& fileIdentifier, LevelDBFactory* levelDBFactory)
379 LOG(StorageAPI, "IDBBackingStoreLevelDB::open");
380 ASSERT(!pathBaseArg.isEmpty());
381 String pathBase = pathBaseArg;
383 OwnPtr<LevelDBComparator> comparator = adoptPtr(new Comparator());
384 OwnPtr<LevelDBDatabase> db;
386 if (!pathBase.containsOnlyASCII())
387 HistogramSupport::histogramEnumeration("WebCore.IndexedDB.BackingStore.OpenStatus", IDBLevelDBBackingStoreOpenAttemptNonASCII, IDBLevelDBBackingStoreOpenMax);
388 if (!makeAllDirectories(pathBase)) {
389 LOG_ERROR("Unable to create IndexedDB database path %s", pathBase.utf8().data());
390 HistogramSupport::histogramEnumeration("WebCore.IndexedDB.BackingStore.OpenStatus", IDBLevelDBBackingStoreOpenFailedDirectory, IDBLevelDBBackingStoreOpenMax);
391 return PassRefPtr<IDBBackingStoreLevelDB>();
394 String path = pathByAppendingComponent(pathBase, securityOrigin.databaseIdentifier() + ".indexeddb.leveldb");
396 db = levelDBFactory->openLevelDB(path, comparator.get());
399 bool ok = isSchemaKnown(db.get(), known);
401 LOG_ERROR("IndexedDB had IO error checking schema, treating it as failure to open");
402 HistogramSupport::histogramEnumeration("WebCore.IndexedDB.BackingStore.OpenStatus", IDBLevelDBBackingStoreOpenFailedIOErrCheckingSchema, IDBLevelDBBackingStoreOpenMax);
405 LOG_ERROR("IndexedDB backing store had unknown schema, treating it as failure to open");
406 HistogramSupport::histogramEnumeration("WebCore.IndexedDB.BackingStore.OpenStatus", IDBLevelDBBackingStoreOpenFailedUnknownSchema, IDBLevelDBBackingStoreOpenMax);
412 HistogramSupport::histogramEnumeration("WebCore.IndexedDB.BackingStore.OpenStatus", IDBLevelDBBackingStoreOpenSuccess, IDBLevelDBBackingStoreOpenMax);
414 LOG_ERROR("IndexedDB backing store open failed, attempting cleanup");
415 bool success = levelDBFactory->destroyLevelDB(path);
417 LOG_ERROR("IndexedDB backing store cleanup failed");
418 HistogramSupport::histogramEnumeration("WebCore.IndexedDB.BackingStore.OpenStatus", IDBLevelDBBackingStoreOpenCleanupDestroyFailed, IDBLevelDBBackingStoreOpenMax);
419 return PassRefPtr<IDBBackingStoreLevelDB>();
422 LOG_ERROR("IndexedDB backing store cleanup succeeded, reopening");
423 db = levelDBFactory->openLevelDB(path, comparator.get());
425 LOG_ERROR("IndexedDB backing store reopen after recovery failed");
426 HistogramSupport::histogramEnumeration("WebCore.IndexedDB.BackingStore.OpenStatus", IDBLevelDBBackingStoreOpenCleanupReopenFailed, IDBLevelDBBackingStoreOpenMax);
427 return PassRefPtr<IDBBackingStoreLevelDB>();
429 HistogramSupport::histogramEnumeration("WebCore.IndexedDB.BackingStore.OpenStatus", IDBLevelDBBackingStoreOpenCleanupReopenSuccess, IDBLevelDBBackingStoreOpenMax);
433 ASSERT_NOT_REACHED();
434 HistogramSupport::histogramEnumeration("WebCore.IndexedDB.BackingStore.OpenStatus", IDBLevelDBBackingStoreOpenFailedUnknownErr, IDBLevelDBBackingStoreOpenMax);
435 return PassRefPtr<IDBBackingStoreLevelDB>();
438 return create(fileIdentifier, db.release(), comparator.release());
441 PassRefPtr<IDBBackingStoreLevelDB> IDBBackingStoreLevelDB::openInMemory(const String& identifier)
443 DefaultLevelDBFactory levelDBFactory;
444 return IDBBackingStoreLevelDB::openInMemory(identifier, &levelDBFactory);
447 PassRefPtr<IDBBackingStoreLevelDB> IDBBackingStoreLevelDB::openInMemory(const String& identifier, LevelDBFactory*)
449 LOG(StorageAPI, "IDBBackingStoreLevelDB::openInMemory");
451 OwnPtr<LevelDBComparator> comparator = adoptPtr(new Comparator());
452 OwnPtr<LevelDBDatabase> db = LevelDBDatabase::openInMemory(comparator.get());
454 LOG_ERROR("LevelDBDatabase::openInMemory failed.");
455 HistogramSupport::histogramEnumeration("WebCore.IndexedDB.BackingStore.OpenStatus", IDBLevelDBBackingStoreOpenMemoryFailed, IDBLevelDBBackingStoreOpenMax);
456 return PassRefPtr<IDBBackingStoreLevelDB>();
458 HistogramSupport::histogramEnumeration("WebCore.IndexedDB.BackingStore.OpenStatus", IDBLevelDBBackingStoreOpenMemorySuccess, IDBLevelDBBackingStoreOpenMax);
460 return create(identifier, db.release(), comparator.release());
463 PassRefPtr<IDBBackingStoreLevelDB> IDBBackingStoreLevelDB::create(const String& identifier, PassOwnPtr<LevelDBDatabase> db, PassOwnPtr<LevelDBComparator> comparator)
465 // FIXME: Handle comparator name changes.
466 RefPtr<IDBBackingStoreLevelDB> backingStore(adoptRef(new IDBBackingStoreLevelDB(identifier, db, comparator)));
468 if (!setUpMetadata(backingStore->m_db.get(), identifier))
469 return PassRefPtr<IDBBackingStoreLevelDB>();
471 return backingStore.release();
474 Vector<String> IDBBackingStoreLevelDB::getDatabaseNames()
476 Vector<String> foundNames;
477 const Vector<char> startKey = DatabaseNameKey::encodeMinKeyForOrigin(m_identifier);
478 const Vector<char> stopKey = DatabaseNameKey::encodeStopKeyForOrigin(m_identifier);
480 ASSERT(foundNames.isEmpty());
482 OwnPtr<LevelDBIterator> it = m_db->createIterator();
483 for (it->seek(startKey); it->isValid() && compareKeys(it->key(), stopKey) < 0; it->next()) {
484 const char* p = it->key().begin();
485 const char* limit = it->key().end();
487 DatabaseNameKey databaseNameKey;
488 p = DatabaseNameKey::decode(p, limit, &databaseNameKey);
491 foundNames.append(databaseNameKey.databaseName());
496 bool IDBBackingStoreLevelDB::getIDBDatabaseMetaData(const String& name, IDBDatabaseMetadata* metadata, bool& found)
498 const Vector<char> key = DatabaseNameKey::encode(m_identifier, name);
501 bool ok = getInt(m_db.get(), key, metadata->id, found);
503 INTERNAL_READ_ERROR(GetIDBDatabaseMetaData);
509 // FIXME: The string version is no longer supported, so the levelDB ports should consider refactoring off of it.
510 String stringVersion;
511 ok = getString(m_db.get(), DatabaseMetaDataKey::encode(metadata->id, DatabaseMetaDataKey::UserVersion), stringVersion, found);
513 INTERNAL_READ_ERROR(GetIDBDatabaseMetaData);
517 INTERNAL_CONSISTENCY_ERROR(GetIDBDatabaseMetaData);
522 ok = getVarInt(m_db.get(), DatabaseMetaDataKey::encode(metadata->id, DatabaseMetaDataKey::UserIntVersion), version, found);
524 INTERNAL_READ_ERROR(GetIDBDatabaseMetaData);
528 INTERNAL_CONSISTENCY_ERROR(GetIDBDatabaseMetaData);
532 // FIXME: The versioning semantics have changed since this original code was written, and what was once a negative number
533 // stored in the database is no longer a valid version.
536 metadata->version = version;
538 ok = getMaxObjectStoreId(m_db.get(), metadata->id, metadata->maxObjectStoreId);
540 INTERNAL_READ_ERROR(GetIDBDatabaseMetaData);
547 void IDBBackingStoreLevelDB::getOrEstablishIDBDatabaseMetadata(const String& name, GetIDBDatabaseMetadataFunction metadataFunction)
549 const Vector<char> key = DatabaseNameKey::encode(m_identifier, name);
552 IDBDatabaseMetadata resultMetadata;
554 bool ok = getInt(m_db.get(), key, resultMetadata.id, found);
556 INTERNAL_READ_ERROR(GetIDBDatabaseMetaData);
557 metadataFunction(resultMetadata, false);
562 resultMetadata.name = name;
563 resultMetadata.version = IDBDatabaseMetadata::DefaultIntVersion;
565 metadataFunction(resultMetadata, createIDBDatabaseMetaData(resultMetadata));
570 ok = getVarInt(m_db.get(), DatabaseMetaDataKey::encode(resultMetadata.id, DatabaseMetaDataKey::UserIntVersion), version, found);
572 INTERNAL_READ_ERROR(GetIDBDatabaseMetaData);
573 metadataFunction(resultMetadata, false);
577 INTERNAL_CONSISTENCY_ERROR(GetIDBDatabaseMetaData);
578 metadataFunction(resultMetadata, false);
582 // FIXME: The versioning semantics have changed since this original code was written, and what was once a negative number
583 // stored in the database is no longer a valid version.
586 resultMetadata.version = version;
588 ok = getMaxObjectStoreId(m_db.get(), resultMetadata.id, resultMetadata.maxObjectStoreId);
590 INTERNAL_READ_ERROR(GetIDBDatabaseMetaData);
591 metadataFunction(resultMetadata, false);
595 ok = getObjectStores(resultMetadata.id, &resultMetadata.objectStores);
597 INTERNAL_READ_ERROR(GetIDBDatabaseMetaData);
598 metadataFunction(resultMetadata, false);
602 metadataFunction(resultMetadata, true);
605 WARN_UNUSED_RETURN static bool getNewDatabaseId(LevelDBDatabase* db, int64_t& newId)
607 RefPtr<LevelDBTransaction> transaction = LevelDBTransaction::create(db);
610 int64_t maxDatabaseId = -1;
612 bool ok = getInt(transaction.get(), MaxDatabaseIdKey::encode(), maxDatabaseId, found);
614 INTERNAL_READ_ERROR(GetNewDatabaseId);
620 ASSERT(maxDatabaseId >= 0);
622 int64_t databaseId = maxDatabaseId + 1;
623 putInt(transaction.get(), MaxDatabaseIdKey::encode(), databaseId);
624 if (!transaction->commit()) {
625 INTERNAL_WRITE_ERROR(GetNewDatabaseId);
632 // FIXME: LevelDB needs to support uint64_t as the version type.
633 bool IDBBackingStoreLevelDB::createIDBDatabaseMetaData(IDBDatabaseMetadata& metadata)
635 bool ok = getNewDatabaseId(m_db.get(), metadata.id);
638 ASSERT(metadata.id >= 0);
640 RefPtr<LevelDBTransaction> transaction = LevelDBTransaction::create(m_db.get());
641 putInt(transaction.get(), DatabaseNameKey::encode(m_identifier, metadata.name), metadata.id);
642 putVarInt(transaction.get(), DatabaseMetaDataKey::encode(metadata.id, DatabaseMetaDataKey::UserIntVersion), metadata.version);
643 if (!transaction->commit()) {
644 INTERNAL_WRITE_ERROR(CreateIDBDatabaseMetaData);
650 bool IDBBackingStoreLevelDB::updateIDBDatabaseVersion(IDBBackingStoreTransactionInterface& transaction, int64_t rowId, uint64_t version)
652 if (version == IDBDatabaseMetadata::NoIntVersion)
653 version = IDBDatabaseMetadata::DefaultIntVersion;
654 putVarInt(IDBBackingStoreTransactionLevelDB::levelDBTransactionFrom(transaction), DatabaseMetaDataKey::encode(rowId, DatabaseMetaDataKey::UserIntVersion), version);
658 static void deleteRange(LevelDBTransaction* transaction, const Vector<char>& begin, const Vector<char>& end)
660 OwnPtr<LevelDBIterator> it = transaction->createIterator();
661 for (it->seek(begin); it->isValid() && compareKeys(it->key(), end) < 0; it->next())
662 transaction->remove(it->key());
665 void IDBBackingStoreLevelDB::deleteDatabase(const String& name, BoolCallbackFunction boolCallbackFunction)
667 LOG(StorageAPI, "IDBBackingStoreLevelDB::deleteDatabase");
668 OwnPtr<LevelDBWriteOnlyTransaction> transaction = LevelDBWriteOnlyTransaction::create(m_db.get());
670 IDBDatabaseMetadata metadata;
671 bool success = false;
672 bool ok = getIDBDatabaseMetaData(name, &metadata, success);
674 boolCallbackFunction(false);
679 boolCallbackFunction(true);
683 const Vector<char> startKey = DatabaseMetaDataKey::encode(metadata.id, DatabaseMetaDataKey::OriginName);
684 const Vector<char> stopKey = DatabaseMetaDataKey::encode(metadata.id + 1, DatabaseMetaDataKey::OriginName);
685 OwnPtr<LevelDBIterator> it = m_db->createIterator();
686 for (it->seek(startKey); it->isValid() && compareKeys(it->key(), stopKey) < 0; it->next())
687 transaction->remove(it->key());
689 const Vector<char> key = DatabaseNameKey::encode(m_identifier, name);
690 transaction->remove(key);
692 if (!transaction->commit()) {
693 INTERNAL_WRITE_ERROR(DeleteDatabase);
694 boolCallbackFunction(false);
697 boolCallbackFunction(true);
700 static bool checkObjectStoreAndMetaDataType(const LevelDBIterator* it, const Vector<char>& stopKey, int64_t objectStoreId, int64_t metaDataType)
702 if (!it->isValid() || compareKeys(it->key(), stopKey) >= 0)
705 ObjectStoreMetaDataKey metaDataKey;
706 const char* p = ObjectStoreMetaDataKey::decode(it->key().begin(), it->key().end(), &metaDataKey);
708 if (metaDataKey.objectStoreId() != objectStoreId)
710 if (metaDataKey.metaDataType() != metaDataType)
715 // FIXME: This should do some error handling rather than plowing ahead when bad data is encountered.
716 bool IDBBackingStoreLevelDB::getObjectStores(int64_t databaseId, IDBDatabaseMetadata::ObjectStoreMap* objectStores)
718 LOG(StorageAPI, "IDBBackingStoreLevelDB::getObjectStores");
719 if (!KeyPrefix::isValidDatabaseId(databaseId))
721 const Vector<char> startKey = ObjectStoreMetaDataKey::encode(databaseId, 1, 0);
722 const Vector<char> stopKey = ObjectStoreMetaDataKey::encodeMaxKey(databaseId);
724 ASSERT(objectStores->isEmpty());
726 OwnPtr<LevelDBIterator> it = m_db->createIterator();
728 while (it->isValid() && compareKeys(it->key(), stopKey) < 0) {
729 const char* p = it->key().begin();
730 const char* limit = it->key().end();
732 ObjectStoreMetaDataKey metaDataKey;
733 p = ObjectStoreMetaDataKey::decode(p, limit, &metaDataKey);
735 if (metaDataKey.metaDataType() != ObjectStoreMetaDataKey::Name) {
736 INTERNAL_CONSISTENCY_ERROR(GetObjectStores);
737 // Possible stale metadata, but don't fail the load.
742 int64_t objectStoreId = metaDataKey.objectStoreId();
744 // FIXME: Do this by direct key lookup rather than iteration, to simplify.
745 String objectStoreName = decodeString(it->value().begin(), it->value().end());
748 if (!checkObjectStoreAndMetaDataType(it.get(), stopKey, objectStoreId, ObjectStoreMetaDataKey::KeyPath)) {
749 INTERNAL_CONSISTENCY_ERROR(GetObjectStores);
752 IDBKeyPath keyPath = decodeIDBKeyPath(it->value().begin(), it->value().end());
755 if (!checkObjectStoreAndMetaDataType(it.get(), stopKey, objectStoreId, ObjectStoreMetaDataKey::AutoIncrement)) {
756 INTERNAL_CONSISTENCY_ERROR(GetObjectStores);
759 bool autoIncrement = decodeBool(it->value().begin(), it->value().end());
761 it->next(); // Is evicatble.
762 if (!checkObjectStoreAndMetaDataType(it.get(), stopKey, objectStoreId, ObjectStoreMetaDataKey::Evictable)) {
763 INTERNAL_CONSISTENCY_ERROR(GetObjectStores);
767 it->next(); // Last version.
768 if (!checkObjectStoreAndMetaDataType(it.get(), stopKey, objectStoreId, ObjectStoreMetaDataKey::LastVersion)) {
769 INTERNAL_CONSISTENCY_ERROR(GetObjectStores);
773 it->next(); // Maximum index id allocated.
774 if (!checkObjectStoreAndMetaDataType(it.get(), stopKey, objectStoreId, ObjectStoreMetaDataKey::MaxIndexId)) {
775 INTERNAL_CONSISTENCY_ERROR(GetObjectStores);
778 int64_t maxIndexId = decodeInt(it->value().begin(), it->value().end());
780 it->next(); // [optional] has key path (is not null)
781 if (checkObjectStoreAndMetaDataType(it.get(), stopKey, objectStoreId, ObjectStoreMetaDataKey::HasKeyPath)) {
782 bool hasKeyPath = decodeBool(it->value().begin(), it->value().end());
783 // This check accounts for two layers of legacy coding:
784 // (1) Initially, hasKeyPath was added to distinguish null vs. string.
785 // (2) Later, null vs. string vs. array was stored in the keyPath itself.
786 // So this check is only relevant for string-type keyPaths.
787 if (!hasKeyPath && (keyPath.type() == IDBKeyPath::StringType && !keyPath.string().isEmpty())) {
788 INTERNAL_CONSISTENCY_ERROR(GetObjectStores);
792 keyPath = IDBKeyPath();
796 int64_t keyGeneratorCurrentNumber = -1;
797 if (checkObjectStoreAndMetaDataType(it.get(), stopKey, objectStoreId, ObjectStoreMetaDataKey::KeyGeneratorCurrentNumber)) {
798 keyGeneratorCurrentNumber = decodeInt(it->value().begin(), it->value().end());
799 // FIXME: Return keyGeneratorCurrentNumber, cache in object store, and write lazily to backing store.
800 // For now, just assert that if it was written it was valid.
801 ASSERT_UNUSED(keyGeneratorCurrentNumber, keyGeneratorCurrentNumber >= KeyGeneratorInitialNumber);
805 IDBObjectStoreMetadata metadata(objectStoreName, objectStoreId, keyPath, autoIncrement, maxIndexId);
806 if (!getIndexes(databaseId, objectStoreId, &metadata.indexes))
808 objectStores->set(objectStoreId, metadata);
813 WARN_UNUSED_RETURN static bool setMaxObjectStoreId(LevelDBTransaction* transaction, int64_t databaseId, int64_t objectStoreId)
815 const Vector<char> maxObjectStoreIdKey = DatabaseMetaDataKey::encode(databaseId, DatabaseMetaDataKey::MaxObjectStoreId);
816 int64_t maxObjectStoreId = -1;
817 bool ok = getMaxObjectStoreId(transaction, maxObjectStoreIdKey, maxObjectStoreId);
819 INTERNAL_READ_ERROR(SetMaxObjectStoreId);
823 if (objectStoreId <= maxObjectStoreId) {
824 INTERNAL_CONSISTENCY_ERROR(SetMaxObjectStoreId);
827 putInt(transaction, maxObjectStoreIdKey, objectStoreId);
831 bool IDBBackingStoreLevelDB::createObjectStore(IDBBackingStoreTransactionInterface& transaction, int64_t databaseId, int64_t objectStoreId, const String& name, const IDBKeyPath& keyPath, bool autoIncrement)
833 LOG(StorageAPI, "IDBBackingStoreLevelDB::createObjectStore");
834 if (!KeyPrefix::validIds(databaseId, objectStoreId))
836 LevelDBTransaction* levelDBTransaction = IDBBackingStoreTransactionLevelDB::levelDBTransactionFrom(transaction);
837 if (!setMaxObjectStoreId(levelDBTransaction, databaseId, objectStoreId))
840 const Vector<char> nameKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::Name);
841 const Vector<char> keyPathKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::KeyPath);
842 const Vector<char> autoIncrementKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::AutoIncrement);
843 const Vector<char> evictableKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::Evictable);
844 const Vector<char> lastVersionKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::LastVersion);
845 const Vector<char> maxIndexIdKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::MaxIndexId);
846 const Vector<char> hasKeyPathKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::HasKeyPath);
847 const Vector<char> keyGeneratorCurrentNumberKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::KeyGeneratorCurrentNumber);
848 const Vector<char> namesKey = ObjectStoreNamesKey::encode(databaseId, name);
850 putString(levelDBTransaction, nameKey, name);
851 putIDBKeyPath(levelDBTransaction, keyPathKey, keyPath);
852 putInt(levelDBTransaction, autoIncrementKey, autoIncrement);
853 putInt(levelDBTransaction, evictableKey, false);
854 putInt(levelDBTransaction, lastVersionKey, 1);
855 putInt(levelDBTransaction, maxIndexIdKey, MinimumIndexId);
856 putBool(levelDBTransaction, hasKeyPathKey, !keyPath.isNull());
857 putInt(levelDBTransaction, keyGeneratorCurrentNumberKey, KeyGeneratorInitialNumber);
858 putInt(levelDBTransaction, namesKey, objectStoreId);
862 bool IDBBackingStoreLevelDB::deleteObjectStore(IDBBackingStoreTransactionInterface& transaction, int64_t databaseId, int64_t objectStoreId)
864 LOG(StorageAPI, "IDBBackingStoreLevelDB::deleteObjectStore");
865 if (!KeyPrefix::validIds(databaseId, objectStoreId))
867 LevelDBTransaction* levelDBTransaction = IDBBackingStoreTransactionLevelDB::levelDBTransactionFrom(transaction);
869 String objectStoreName;
871 bool ok = getString(levelDBTransaction, ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::Name), objectStoreName, found);
873 INTERNAL_READ_ERROR(DeleteObjectStore);
877 INTERNAL_CONSISTENCY_ERROR(DeleteObjectStore);
881 deleteRange(levelDBTransaction, ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, 0), ObjectStoreMetaDataKey::encodeMaxKey(databaseId, objectStoreId));
883 levelDBTransaction->remove(ObjectStoreNamesKey::encode(databaseId, objectStoreName));
885 deleteRange(levelDBTransaction, IndexFreeListKey::encode(databaseId, objectStoreId, 0), IndexFreeListKey::encodeMaxKey(databaseId, objectStoreId));
886 deleteRange(levelDBTransaction, IndexMetaDataKey::encode(databaseId, objectStoreId, 0, 0), IndexMetaDataKey::encodeMaxKey(databaseId, objectStoreId));
888 return clearObjectStore(transaction, databaseId, objectStoreId);
891 bool IDBBackingStoreLevelDB::getRecord(IDBBackingStoreTransactionInterface& transaction, int64_t databaseId, int64_t objectStoreId, const IDBKey& key, Vector<char>& record)
893 LOG(StorageAPI, "IDBBackingStoreLevelDB::getRecord");
894 if (!KeyPrefix::validIds(databaseId, objectStoreId))
896 LevelDBTransaction* levelDBTransaction = IDBBackingStoreTransactionLevelDB::levelDBTransactionFrom(transaction);
898 const Vector<char> leveldbKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, key);
904 bool ok = levelDBTransaction->safeGet(leveldbKey, data, found);
906 INTERNAL_READ_ERROR(GetRecord);
913 const char* p = decodeVarInt(data.begin(), data.end(), version);
915 INTERNAL_READ_ERROR(GetRecord);
919 record.appendRange(p, static_cast<const char*>(data.end()));
923 WARN_UNUSED_RETURN static bool getNewVersionNumber(LevelDBTransaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t& newVersionNumber)
925 const Vector<char> lastVersionKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::LastVersion);
927 newVersionNumber = -1;
928 int64_t lastVersion = -1;
930 bool ok = getInt(transaction, lastVersionKey, lastVersion, found);
932 INTERNAL_READ_ERROR(GetNewVersionNumber);
938 ASSERT(lastVersion >= 0);
940 int64_t version = lastVersion + 1;
941 putInt(transaction, lastVersionKey, version);
943 ASSERT(version > lastVersion); // FIXME: Think about how we want to handle the overflow scenario.
945 newVersionNumber = version;
949 bool IDBBackingStoreLevelDB::putRecord(IDBBackingStoreTransactionInterface& transaction, int64_t databaseId, int64_t objectStoreId, const IDBKey& key, PassRefPtr<SharedBuffer> prpValue, IDBRecordIdentifier* recordIdentifier)
951 LOG(StorageAPI, "IDBBackingStoreLevelDB::putRecord");
952 if (!KeyPrefix::validIds(databaseId, objectStoreId))
954 ASSERT(key.isValid());
956 LevelDBTransaction* levelDBTransaction = IDBBackingStoreTransactionLevelDB::levelDBTransactionFrom(transaction);
957 int64_t version = -1;
958 bool ok = getNewVersionNumber(levelDBTransaction, databaseId, objectStoreId, version);
961 ASSERT(version >= 0);
962 const Vector<char> objectStoredataKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, key);
965 v.appendVector(encodeVarInt(version));
966 RefPtr<SharedBuffer> value = prpValue;
968 v.append(value->data(), value->size());
970 levelDBTransaction->put(objectStoredataKey, v);
972 const Vector<char> existsEntryKey = ExistsEntryKey::encode(databaseId, objectStoreId, key);
973 levelDBTransaction->put(existsEntryKey, encodeInt(version));
975 recordIdentifier->reset(encodeIDBKey(key), version);
979 bool IDBBackingStoreLevelDB::clearObjectStore(IDBBackingStoreTransactionInterface& transaction, int64_t databaseId, int64_t objectStoreId)
981 LOG(StorageAPI, "IDBBackingStoreLevelDB::clearObjectStore");
982 if (!KeyPrefix::validIds(databaseId, objectStoreId))
984 LevelDBTransaction* levelDBTransaction = IDBBackingStoreTransactionLevelDB::levelDBTransactionFrom(transaction);
985 const Vector<char> startKey = KeyPrefix(databaseId, objectStoreId).encode();
986 const Vector<char> stopKey = KeyPrefix(databaseId, objectStoreId + 1).encode();
988 deleteRange(levelDBTransaction, startKey, stopKey);
992 bool IDBBackingStoreLevelDB::deleteRecord(IDBBackingStoreTransactionInterface& transaction, int64_t databaseId, int64_t objectStoreId, const IDBRecordIdentifier& recordIdentifier)
994 LOG(StorageAPI, "IDBBackingStoreLevelDB::deleteRecord");
996 if (!KeyPrefix::validIds(databaseId, objectStoreId))
998 LevelDBTransaction* levelDBTransaction = IDBBackingStoreTransactionLevelDB::levelDBTransactionFrom(transaction);
1000 const Vector<char> objectStoreDataKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, recordIdentifier.encodedPrimaryKey());
1001 levelDBTransaction->remove(objectStoreDataKey);
1003 const Vector<char> existsEntryKey = ExistsEntryKey::encode(databaseId, objectStoreId, recordIdentifier.encodedPrimaryKey());
1004 levelDBTransaction->remove(existsEntryKey);
1009 bool IDBBackingStoreLevelDB::getKeyGeneratorCurrentNumber(IDBBackingStoreTransactionInterface& transaction, int64_t databaseId, int64_t objectStoreId, int64_t& keyGeneratorCurrentNumber)
1011 if (!KeyPrefix::validIds(databaseId, objectStoreId))
1013 LevelDBTransaction* levelDBTransaction = IDBBackingStoreTransactionLevelDB::levelDBTransactionFrom(transaction);
1015 const Vector<char> keyGeneratorCurrentNumberKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::KeyGeneratorCurrentNumber);
1017 keyGeneratorCurrentNumber = -1;
1021 bool ok = levelDBTransaction->safeGet(keyGeneratorCurrentNumberKey, data, found);
1023 INTERNAL_READ_ERROR(GetKeyGeneratorCurrentNumber);
1027 keyGeneratorCurrentNumber = decodeInt(data.begin(), data.end());
1029 // Previously, the key generator state was not stored explicitly but derived from the
1030 // maximum numeric key present in existing data. This violates the spec as the data may
1031 // be cleared but the key generator state must be preserved.
1032 const Vector<char> startKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, minIDBKey());
1033 const Vector<char> stopKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, maxIDBKey());
1035 OwnPtr<LevelDBIterator> it = levelDBTransaction->createIterator();
1036 int64_t maxNumericKey = 0;
1038 for (it->seek(startKey); it->isValid() && compareKeys(it->key(), stopKey) < 0; it->next()) {
1039 const char* p = it->key().begin();
1040 const char* limit = it->key().end();
1042 ObjectStoreDataKey dataKey;
1043 p = ObjectStoreDataKey::decode(p, limit, &dataKey);
1046 if (dataKey.userKey()->type() == IDBKey::NumberType) {
1047 int64_t n = static_cast<int64_t>(dataKey.userKey()->number());
1048 if (n > maxNumericKey)
1053 keyGeneratorCurrentNumber = maxNumericKey + 1;
1056 return keyGeneratorCurrentNumber;
1059 bool IDBBackingStoreLevelDB::maybeUpdateKeyGeneratorCurrentNumber(IDBBackingStoreTransactionInterface& transaction, int64_t databaseId, int64_t objectStoreId, int64_t newNumber, bool checkCurrent)
1061 if (!KeyPrefix::validIds(databaseId, objectStoreId))
1063 LevelDBTransaction* levelDBTransaction = IDBBackingStoreTransactionLevelDB::levelDBTransactionFrom(transaction);
1066 int64_t currentNumber;
1067 bool ok = getKeyGeneratorCurrentNumber(transaction, databaseId, objectStoreId, currentNumber);
1070 if (newNumber <= currentNumber)
1074 const Vector<char> keyGeneratorCurrentNumberKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::KeyGeneratorCurrentNumber);
1075 putInt(levelDBTransaction, keyGeneratorCurrentNumberKey, newNumber);
1079 bool IDBBackingStoreLevelDB::keyExistsInObjectStore(IDBBackingStoreTransactionInterface& transaction, int64_t databaseId, int64_t objectStoreId, const IDBKey& key, RefPtr<IDBRecordIdentifier>& foundIDBRecordIdentifier)
1081 LOG(StorageAPI, "IDBBackingStoreLevelDB::keyExistsInObjectStore");
1082 if (!KeyPrefix::validIds(databaseId, objectStoreId))
1085 LevelDBTransaction* levelDBTransaction = IDBBackingStoreTransactionLevelDB::levelDBTransactionFrom(transaction);
1086 const Vector<char> leveldbKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, key);
1089 bool ok = levelDBTransaction->safeGet(leveldbKey, data, found);
1091 INTERNAL_READ_ERROR(KeyExistsInObjectStore);
1098 if (!decodeVarInt(data.begin(), data.end(), version))
1101 foundIDBRecordIdentifier = IDBRecordIdentifier::create(encodeIDBKey(key), version);
1105 static bool checkIndexAndMetaDataKey(const LevelDBIterator* it, const Vector<char>& stopKey, int64_t indexId, unsigned char metaDataType)
1107 if (!it->isValid() || compareKeys(it->key(), stopKey) >= 0)
1110 IndexMetaDataKey metaDataKey;
1111 const char* p = IndexMetaDataKey::decode(it->key().begin(), it->key().end(), &metaDataKey);
1112 ASSERT_UNUSED(p, p);
1113 if (metaDataKey.indexId() != indexId)
1115 if (metaDataKey.metaDataType() != metaDataType)
1121 // FIXME: This should do some error handling rather than plowing ahead when bad data is encountered.
1122 bool IDBBackingStoreLevelDB::getIndexes(int64_t databaseId, int64_t objectStoreId, IDBObjectStoreMetadata::IndexMap* indexes)
1124 LOG(StorageAPI, "IDBBackingStoreLevelDB::getIndexes");
1125 if (!KeyPrefix::validIds(databaseId, objectStoreId))
1127 const Vector<char> startKey = IndexMetaDataKey::encode(databaseId, objectStoreId, 0, 0);
1128 const Vector<char> stopKey = IndexMetaDataKey::encode(databaseId, objectStoreId + 1, 0, 0);
1130 ASSERT(indexes->isEmpty());
1132 OwnPtr<LevelDBIterator> it = m_db->createIterator();
1134 while (it->isValid() && compareKeys(it->key(), stopKey) < 0) {
1135 const char* p = it->key().begin();
1136 const char* limit = it->key().end();
1138 IndexMetaDataKey metaDataKey;
1139 p = IndexMetaDataKey::decode(p, limit, &metaDataKey);
1141 if (metaDataKey.metaDataType() != IndexMetaDataKey::Name) {
1142 INTERNAL_CONSISTENCY_ERROR(GetIndexes);
1143 // Possible stale metadata due to http://webkit.org/b/85557 but don't fail the load.
1148 // FIXME: Do this by direct key lookup rather than iteration, to simplify.
1149 int64_t indexId = metaDataKey.indexId();
1150 String indexName = decodeString(it->value().begin(), it->value().end());
1152 it->next(); // unique flag
1153 if (!checkIndexAndMetaDataKey(it.get(), stopKey, indexId, IndexMetaDataKey::Unique)) {
1154 INTERNAL_CONSISTENCY_ERROR(GetIndexes);
1157 bool indexUnique = decodeBool(it->value().begin(), it->value().end());
1159 it->next(); // keyPath
1160 if (!checkIndexAndMetaDataKey(it.get(), stopKey, indexId, IndexMetaDataKey::KeyPath)) {
1161 INTERNAL_CONSISTENCY_ERROR(GetIndexes);
1164 IDBKeyPath keyPath = decodeIDBKeyPath(it->value().begin(), it->value().end());
1166 it->next(); // [optional] multiEntry flag
1167 bool indexMultiEntry = false;
1168 if (checkIndexAndMetaDataKey(it.get(), stopKey, indexId, IndexMetaDataKey::MultiEntry)) {
1169 indexMultiEntry = decodeBool(it->value().begin(), it->value().end());
1173 indexes->set(indexId, IDBIndexMetadata(indexName, indexId, keyPath, indexUnique, indexMultiEntry));
1178 WARN_UNUSED_RETURN static bool setMaxIndexId(LevelDBTransaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId)
1180 int64_t maxIndexId = -1;
1181 const Vector<char> maxIndexIdKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::MaxIndexId);
1183 bool ok = getInt(transaction, maxIndexIdKey, maxIndexId, found);
1185 INTERNAL_READ_ERROR(SetMaxIndexId);
1189 maxIndexId = MinimumIndexId;
1191 if (indexId <= maxIndexId) {
1192 INTERNAL_CONSISTENCY_ERROR(SetMaxIndexId);
1196 putInt(transaction, maxIndexIdKey, indexId);
1200 bool IDBBackingStoreLevelDB::createIndex(IDBBackingStoreTransactionInterface& transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const String& name, const IDBKeyPath& keyPath, bool isUnique, bool isMultiEntry)
1202 LOG(StorageAPI, "IDBBackingStoreLevelDB::createIndex");
1203 if (!KeyPrefix::validIds(databaseId, objectStoreId, indexId))
1205 LevelDBTransaction* levelDBTransaction = IDBBackingStoreTransactionLevelDB::levelDBTransactionFrom(transaction);
1206 if (!setMaxIndexId(levelDBTransaction, databaseId, objectStoreId, indexId))
1209 const Vector<char> nameKey = IndexMetaDataKey::encode(databaseId, objectStoreId, indexId, IndexMetaDataKey::Name);
1210 const Vector<char> uniqueKey = IndexMetaDataKey::encode(databaseId, objectStoreId, indexId, IndexMetaDataKey::Unique);
1211 const Vector<char> keyPathKey = IndexMetaDataKey::encode(databaseId, objectStoreId, indexId, IndexMetaDataKey::KeyPath);
1212 const Vector<char> multiEntryKey = IndexMetaDataKey::encode(databaseId, objectStoreId, indexId, IndexMetaDataKey::MultiEntry);
1214 putString(levelDBTransaction, nameKey, name);
1215 putBool(levelDBTransaction, uniqueKey, isUnique);
1216 putIDBKeyPath(levelDBTransaction, keyPathKey, keyPath);
1217 putBool(levelDBTransaction, multiEntryKey, isMultiEntry);
1221 bool IDBBackingStoreLevelDB::deleteIndex(IDBBackingStoreTransactionInterface& transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId)
1223 LOG(StorageAPI, "IDBBackingStoreLevelDB::deleteIndex");
1224 if (!KeyPrefix::validIds(databaseId, objectStoreId, indexId))
1226 LevelDBTransaction* levelDBTransaction = IDBBackingStoreTransactionLevelDB::levelDBTransactionFrom(transaction);
1228 const Vector<char> indexMetaDataStart = IndexMetaDataKey::encode(databaseId, objectStoreId, indexId, 0);
1229 const Vector<char> indexMetaDataEnd = IndexMetaDataKey::encodeMaxKey(databaseId, objectStoreId, indexId);
1230 deleteRange(levelDBTransaction, indexMetaDataStart, indexMetaDataEnd);
1232 const Vector<char> indexDataStart = IndexDataKey::encodeMinKey(databaseId, objectStoreId, indexId);
1233 const Vector<char> indexDataEnd = IndexDataKey::encodeMaxKey(databaseId, objectStoreId, indexId);
1234 deleteRange(levelDBTransaction, indexDataStart, indexDataEnd);
1238 bool IDBBackingStoreLevelDB::putIndexDataForRecord(IDBBackingStoreTransactionInterface& transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& key, const IDBRecordIdentifier* recordIdentifier)
1240 LOG(StorageAPI, "IDBBackingStoreLevelDB::putIndexDataForRecord");
1241 ASSERT(key.isValid());
1242 ASSERT(recordIdentifier);
1243 if (!KeyPrefix::validIds(databaseId, objectStoreId, indexId))
1246 LevelDBTransaction* levelDBTransaction = IDBBackingStoreTransactionLevelDB::levelDBTransactionFrom(transaction);
1247 const Vector<char> indexDataKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, encodeIDBKey(key), recordIdentifier->encodedPrimaryKey());
1250 data.appendVector(encodeVarInt(recordIdentifier->version()));
1251 data.appendVector(recordIdentifier->encodedPrimaryKey());
1253 levelDBTransaction->put(indexDataKey, data);
1257 static bool findGreatestKeyLessThanOrEqual(LevelDBTransaction* transaction, const Vector<char>& target, Vector<char>& foundKey)
1259 OwnPtr<LevelDBIterator> it = transaction->createIterator();
1262 if (!it->isValid()) {
1268 while (IDBBackingStoreLevelDB::compareIndexKeys(it->key(), target) > 0) {
1276 foundKey.append(it->key().begin(), it->key().end() - it->key().begin());
1278 // There can be several index keys that compare equal. We want the last one.
1280 } while (it->isValid() && !IDBBackingStoreLevelDB::compareIndexKeys(it->key(), target));
1285 static bool versionExists(LevelDBTransaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t version, const Vector<char>& encodedPrimaryKey, bool& exists)
1287 const Vector<char> key = ExistsEntryKey::encode(databaseId, objectStoreId, encodedPrimaryKey);
1290 bool ok = transaction->safeGet(key, data, exists);
1292 INTERNAL_READ_ERROR(VersionExists);
1298 exists = (decodeInt(data.begin(), data.end()) == version);
1302 bool IDBBackingStoreLevelDB::findKeyInIndex(IDBBackingStoreTransactionInterface& transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& key, Vector<char>& foundEncodedPrimaryKey, bool& found)
1304 LOG(StorageAPI, "IDBBackingStoreLevelDB::findKeyInIndex");
1305 ASSERT(KeyPrefix::validIds(databaseId, objectStoreId, indexId));
1307 ASSERT(foundEncodedPrimaryKey.isEmpty());
1310 LevelDBTransaction* levelDBTransaction = IDBBackingStoreTransactionLevelDB::levelDBTransactionFrom(transaction);
1311 const Vector<char> leveldbKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, key);
1312 OwnPtr<LevelDBIterator> it = levelDBTransaction->createIterator();
1313 it->seek(leveldbKey);
1318 if (compareIndexKeys(it->key(), leveldbKey) > 0)
1322 const char* p = decodeVarInt(it->value().begin(), it->value().end(), version);
1324 INTERNAL_READ_ERROR(FindKeyInIndex);
1327 foundEncodedPrimaryKey.append(p, it->value().end() - p);
1329 bool exists = false;
1330 bool ok = versionExists(levelDBTransaction, databaseId, objectStoreId, version, foundEncodedPrimaryKey, exists);
1334 // Delete stale index data entry and continue.
1335 levelDBTransaction->remove(it->key());
1344 bool IDBBackingStoreLevelDB::getPrimaryKeyViaIndex(IDBBackingStoreTransactionInterface& transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& key, RefPtr<IDBKey>& primaryKey)
1346 LOG(StorageAPI, "IDBBackingStoreLevelDB::getPrimaryKeyViaIndex");
1347 if (!KeyPrefix::validIds(databaseId, objectStoreId, indexId))
1351 Vector<char> foundEncodedPrimaryKey;
1352 bool ok = findKeyInIndex(transaction, databaseId, objectStoreId, indexId, key, foundEncodedPrimaryKey, found);
1354 INTERNAL_READ_ERROR(GetPrimaryKeyViaIndex);
1358 decodeIDBKey(foundEncodedPrimaryKey.begin(), foundEncodedPrimaryKey.end(), primaryKey);
1365 bool IDBBackingStoreLevelDB::keyExistsInIndex(IDBBackingStoreTransactionInterface& transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& indexKey, RefPtr<IDBKey>& foundPrimaryKey, bool& exists)
1367 LOG(StorageAPI, "IDBBackingStoreLevelDB::keyExistsInIndex");
1368 if (!KeyPrefix::validIds(databaseId, objectStoreId, indexId))
1372 Vector<char> foundEncodedPrimaryKey;
1373 bool ok = findKeyInIndex(transaction, databaseId, objectStoreId, indexId, indexKey, foundEncodedPrimaryKey, exists);
1375 INTERNAL_READ_ERROR(KeyExistsInIndex);
1381 decodeIDBKey(foundEncodedPrimaryKey.begin(), foundEncodedPrimaryKey.end(), foundPrimaryKey);
1386 bool IDBBackingStoreLevelDB::makeIndexWriters(IDBTransactionBackendInterface& transaction, int64_t databaseId, const IDBObjectStoreMetadata& objectStore, IDBKey& primaryKey, bool keyWasGenerated, const Vector<int64_t>& indexIds, const Vector<IndexKeys>& indexKeys, Vector<RefPtr<IDBIndexWriter>>& indexWriters, String* errorMessage, bool& completed)
1388 ASSERT(indexIds.size() == indexKeys.size());
1391 HashMap<int64_t, IndexKeys> indexKeyMap;
1392 for (size_t i = 0; i < indexIds.size(); ++i)
1393 indexKeyMap.add(indexIds[i], indexKeys[i]);
1395 for (IDBObjectStoreMetadata::IndexMap::const_iterator it = objectStore.indexes.begin(); it != objectStore.indexes.end(); ++it) {
1396 const IDBIndexMetadata& index = it->value;
1398 IndexKeys keys = indexKeyMap.get(it->key);
1399 // If the objectStore is using autoIncrement, then any indexes with an identical keyPath need to also use the primary (generated) key as a key.
1400 if (keyWasGenerated && (index.keyPath == objectStore.keyPath))
1401 keys.append(&primaryKey);
1403 RefPtr<IDBIndexWriter> indexWriter = IDBIndexWriter::create(index, keys);
1404 bool canAddKeys = false;
1405 bool backingStoreSuccess = indexWriter->verifyIndexKeys(*this, transaction.backingStoreTransaction(), databaseId, objectStore.id, index.id, canAddKeys, &primaryKey, errorMessage);
1406 if (!backingStoreSuccess)
1411 indexWriters.append(indexWriter.release());
1418 PassRefPtr<IDBKey> IDBBackingStoreLevelDB::generateKey(IDBTransactionBackendInterface& transaction, int64_t databaseId, int64_t objectStoreId)
1420 const int64_t maxGeneratorValue = 9007199254740992LL; // Maximum integer storable as ECMAScript number.
1421 int64_t currentNumber;
1422 bool ok = getKeyGeneratorCurrentNumber(transaction.backingStoreTransaction(), databaseId, objectStoreId, currentNumber);
1424 LOG_ERROR("Failed to getKeyGeneratorCurrentNumber");
1425 return IDBKey::createInvalid();
1427 if (currentNumber < 0 || currentNumber > maxGeneratorValue)
1428 return IDBKey::createInvalid();
1430 return IDBKey::createNumber(currentNumber);
1434 bool IDBBackingStoreLevelDB::updateKeyGenerator(IDBTransactionBackendInterface& transaction, int64_t databaseId, int64_t objectStoreId, const IDBKey& key, bool checkCurrent)
1436 ASSERT(key.type() == IDBKey::NumberType);
1437 return maybeUpdateKeyGeneratorCurrentNumber(transaction.backingStoreTransaction(), databaseId, objectStoreId, static_cast<int64_t>(floor(key.number())) + 1, checkCurrent);
1440 class ObjectStoreKeyCursorImpl : public IDBBackingStoreCursorLevelDB {
1442 static PassRefPtr<ObjectStoreKeyCursorImpl> create(LevelDBTransaction* transaction, const IDBBackingStoreCursorLevelDB::CursorOptions& cursorOptions)
1444 return adoptRef(new ObjectStoreKeyCursorImpl(transaction, cursorOptions));
1447 virtual PassRefPtr<IDBBackingStoreCursorInterface> clone()
1449 return adoptRef(new ObjectStoreKeyCursorImpl(this));
1452 // IDBBackingStoreCursorLevelDB
1453 virtual PassRefPtr<SharedBuffer> value() const OVERRIDE { ASSERT_NOT_REACHED(); return 0; }
1454 virtual bool loadCurrentRow() OVERRIDE;
1457 virtual Vector<char> encodeKey(const IDBKey &key)
1459 return ObjectStoreDataKey::encode(m_cursorOptions.databaseId, m_cursorOptions.objectStoreId, key);
1463 ObjectStoreKeyCursorImpl(LevelDBTransaction* transaction, const IDBBackingStoreCursorLevelDB::CursorOptions& cursorOptions)
1464 : IDBBackingStoreCursorLevelDB(transaction, cursorOptions)
1468 ObjectStoreKeyCursorImpl(const ObjectStoreKeyCursorImpl* other)
1469 : IDBBackingStoreCursorLevelDB(other)
1474 bool ObjectStoreKeyCursorImpl::loadCurrentRow()
1476 const char* keyPosition = m_iterator->key().begin();
1477 const char* keyLimit = m_iterator->key().end();
1479 ObjectStoreDataKey objectStoreDataKey;
1480 keyPosition = ObjectStoreDataKey::decode(keyPosition, keyLimit, &objectStoreDataKey);
1482 INTERNAL_READ_ERROR(LoadCurrentRow);
1486 m_currentKey = objectStoreDataKey.userKey();
1489 const char* valuePosition = decodeVarInt(m_iterator->value().begin(), m_iterator->value().end(), version);
1490 if (!valuePosition) {
1491 INTERNAL_READ_ERROR(LoadCurrentRow);
1495 // FIXME: This re-encodes what was just decoded; try and optimize.
1496 m_recordIdentifier->reset(encodeIDBKey(*m_currentKey), version);
1501 class ObjectStoreCursorImpl : public IDBBackingStoreCursorLevelDB {
1503 static PassRefPtr<ObjectStoreCursorImpl> create(LevelDBTransaction* transaction, const IDBBackingStoreCursorLevelDB::CursorOptions& cursorOptions)
1505 return adoptRef(new ObjectStoreCursorImpl(transaction, cursorOptions));
1508 virtual PassRefPtr<IDBBackingStoreCursorInterface> clone()
1510 return adoptRef(new ObjectStoreCursorImpl(this));
1513 // IDBBackingStoreCursorLevelDB
1514 virtual PassRefPtr<SharedBuffer> value() const OVERRIDE { return m_currentValue; }
1515 virtual bool loadCurrentRow() OVERRIDE;
1518 virtual Vector<char> encodeKey(const IDBKey &key)
1520 return ObjectStoreDataKey::encode(m_cursorOptions.databaseId, m_cursorOptions.objectStoreId, key);
1524 ObjectStoreCursorImpl(LevelDBTransaction* transaction, const IDBBackingStoreCursorLevelDB::CursorOptions& cursorOptions)
1525 : IDBBackingStoreCursorLevelDB(transaction, cursorOptions)
1529 ObjectStoreCursorImpl(const ObjectStoreCursorImpl* other)
1530 : IDBBackingStoreCursorLevelDB(other)
1531 , m_currentValue(other->m_currentValue)
1535 RefPtr<SharedBuffer> m_currentValue;
1538 bool ObjectStoreCursorImpl::loadCurrentRow()
1540 const char* keyPosition = m_iterator->key().begin();
1541 const char* keyLimit = m_iterator->key().end();
1543 ObjectStoreDataKey objectStoreDataKey;
1544 keyPosition = ObjectStoreDataKey::decode(keyPosition, keyLimit, &objectStoreDataKey);
1546 INTERNAL_READ_ERROR(LoadCurrentRow);
1550 m_currentKey = objectStoreDataKey.userKey();
1553 const char* valuePosition = decodeVarInt(m_iterator->value().begin(), m_iterator->value().end(), version);
1554 if (!valuePosition) {
1555 INTERNAL_READ_ERROR(LoadCurrentRow);
1559 // FIXME: This re-encodes what was just decoded; try and optimize.
1560 m_recordIdentifier->reset(encodeIDBKey(*m_currentKey), version);
1563 value.append(valuePosition, m_iterator->value().end() - valuePosition);
1564 m_currentValue = SharedBuffer::adoptVector(value);
1568 class IndexKeyCursorImpl FINAL : public IDBBackingStoreCursorLevelDB {
1570 static PassRefPtr<IndexKeyCursorImpl> create(LevelDBTransaction* transaction, const IDBBackingStoreCursorLevelDB::CursorOptions& cursorOptions)
1572 return adoptRef(new IndexKeyCursorImpl(transaction, cursorOptions));
1575 virtual PassRefPtr<IDBBackingStoreCursorInterface> clone()
1577 return adoptRef(new IndexKeyCursorImpl(this));
1580 // IDBBackingStoreCursorLevelDB
1581 virtual PassRefPtr<SharedBuffer> value() const OVERRIDE { ASSERT_NOT_REACHED(); return 0; }
1582 virtual PassRefPtr<IDBKey> primaryKey() const OVERRIDE { return m_primaryKey; }
1583 virtual const IDBRecordIdentifier& recordIdentifier() const OVERRIDE { ASSERT_NOT_REACHED(); return *m_recordIdentifier; }
1584 virtual bool loadCurrentRow() OVERRIDE;
1587 virtual Vector<char> encodeKey(const IDBKey &key)
1589 return IndexDataKey::encode(m_cursorOptions.databaseId, m_cursorOptions.objectStoreId, m_cursorOptions.indexId, key);
1593 IndexKeyCursorImpl(LevelDBTransaction* transaction, const IDBBackingStoreCursorLevelDB::CursorOptions& cursorOptions)
1594 : IDBBackingStoreCursorLevelDB(transaction, cursorOptions)
1598 IndexKeyCursorImpl(const IndexKeyCursorImpl* other)
1599 : IDBBackingStoreCursorLevelDB(other)
1600 , m_primaryKey(other->m_primaryKey)
1604 RefPtr<IDBKey> m_primaryKey;
1607 bool IndexKeyCursorImpl::loadCurrentRow()
1609 const char* keyPosition = m_iterator->key().begin();
1610 const char* keyLimit = m_iterator->key().end();
1612 IndexDataKey indexDataKey;
1613 keyPosition = IndexDataKey::decode(keyPosition, keyLimit, &indexDataKey);
1615 m_currentKey = indexDataKey.userKey();
1617 int64_t indexDataVersion;
1618 const char* valuePosition = decodeVarInt(m_iterator->value().begin(), m_iterator->value().end(), indexDataVersion);
1619 if (!valuePosition) {
1620 INTERNAL_READ_ERROR(LoadCurrentRow);
1624 valuePosition = decodeIDBKey(valuePosition, m_iterator->value().end(), m_primaryKey);
1625 if (!valuePosition) {
1626 INTERNAL_READ_ERROR(LoadCurrentRow);
1630 Vector<char> primaryLevelDBKey = ObjectStoreDataKey::encode(indexDataKey.databaseId(), indexDataKey.objectStoreId(), *m_primaryKey);
1632 Vector<char> result;
1634 bool ok = m_transaction->safeGet(primaryLevelDBKey, result, found);
1636 INTERNAL_READ_ERROR(LoadCurrentRow);
1640 m_transaction->remove(m_iterator->key());
1644 int64_t objectStoreDataVersion;
1645 const char* t = decodeVarInt(result.begin(), result.end(), objectStoreDataVersion);
1647 INTERNAL_READ_ERROR(LoadCurrentRow);
1651 if (objectStoreDataVersion != indexDataVersion) {
1652 m_transaction->remove(m_iterator->key());
1659 class IndexCursorImpl FINAL : public IDBBackingStoreCursorLevelDB {
1661 static PassRefPtr<IndexCursorImpl> create(LevelDBTransaction* transaction, const IDBBackingStoreCursorLevelDB::CursorOptions& cursorOptions)
1663 return adoptRef(new IndexCursorImpl(transaction, cursorOptions));
1666 virtual PassRefPtr<IDBBackingStoreCursorInterface> clone()
1668 return adoptRef(new IndexCursorImpl(this));
1671 // IDBBackingStoreCursorLevelDB
1672 virtual PassRefPtr<SharedBuffer> value() const OVERRIDE { return m_currentValue; }
1673 virtual PassRefPtr<IDBKey> primaryKey() const OVERRIDE { return m_primaryKey; }
1674 virtual const IDBRecordIdentifier& recordIdentifier() const OVERRIDE { ASSERT_NOT_REACHED(); return *m_recordIdentifier; }
1675 virtual bool loadCurrentRow() OVERRIDE;
1678 virtual Vector<char> encodeKey(const IDBKey &key)
1680 return IndexDataKey::encode(m_cursorOptions.databaseId, m_cursorOptions.objectStoreId, m_cursorOptions.indexId, key);
1684 IndexCursorImpl(LevelDBTransaction* transaction, const IDBBackingStoreCursorLevelDB::CursorOptions& cursorOptions)
1685 : IDBBackingStoreCursorLevelDB(transaction, cursorOptions)
1689 IndexCursorImpl(const IndexCursorImpl* other)
1690 : IDBBackingStoreCursorLevelDB(other)
1691 , m_primaryKey(other->m_primaryKey)
1692 , m_currentValue(other->m_currentValue)
1693 , m_primaryLevelDBKey(other->m_primaryLevelDBKey)
1697 RefPtr<IDBKey> m_primaryKey;
1698 RefPtr<SharedBuffer> m_currentValue;
1699 Vector<char> m_primaryLevelDBKey;
1702 bool IndexCursorImpl::loadCurrentRow()
1704 const char* keyPosition = m_iterator->key().begin();
1705 const char* keyLimit = m_iterator->key().end();
1707 IndexDataKey indexDataKey;
1708 keyPosition = IndexDataKey::decode(keyPosition, keyLimit, &indexDataKey);
1710 m_currentKey = indexDataKey.userKey();
1712 const char* valuePosition = m_iterator->value().begin();
1713 const char* valueLimit = m_iterator->value().end();
1715 int64_t indexDataVersion;
1716 valuePosition = decodeVarInt(valuePosition, valueLimit, indexDataVersion);
1717 if (!valuePosition) {
1718 INTERNAL_READ_ERROR(LoadCurrentRow);
1721 valuePosition = decodeIDBKey(valuePosition, valueLimit, m_primaryKey);
1722 if (!valuePosition) {
1723 INTERNAL_READ_ERROR(LoadCurrentRow);
1727 m_primaryLevelDBKey = ObjectStoreDataKey::encode(indexDataKey.databaseId(), indexDataKey.objectStoreId(), *m_primaryKey);
1729 Vector<char> result;
1731 bool ok = m_transaction->safeGet(m_primaryLevelDBKey, result, found);
1733 INTERNAL_READ_ERROR(LoadCurrentRow);
1737 m_transaction->remove(m_iterator->key());
1741 int64_t objectStoreDataVersion;
1742 valuePosition = decodeVarInt(result.begin(), result.end(), objectStoreDataVersion);
1743 if (!valuePosition) {
1744 INTERNAL_READ_ERROR(LoadCurrentRow);
1748 if (objectStoreDataVersion != indexDataVersion) {
1749 m_transaction->remove(m_iterator->key());
1754 value.append(valuePosition, result.end() - valuePosition);
1755 m_currentValue = SharedBuffer::adoptVector(value);
1759 static bool objectStoreCursorOptions(LevelDBTransaction* transaction, int64_t databaseId, int64_t objectStoreId, const IDBKeyRange* range, IndexedDB::CursorDirection direction, IDBBackingStoreCursorLevelDB::CursorOptions& cursorOptions)
1761 cursorOptions.databaseId = databaseId;
1762 cursorOptions.objectStoreId = objectStoreId;
1764 bool lowerBound = range && range->lower();
1765 bool upperBound = range && range->upper();
1766 cursorOptions.forward = (direction == IndexedDB::CursorNextNoDuplicate || direction == IndexedDB::CursorNext);
1767 cursorOptions.unique = (direction == IndexedDB::CursorNextNoDuplicate || direction == IndexedDB::CursorPrevNoDuplicate);
1770 cursorOptions.lowKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, minIDBKey());
1771 cursorOptions.lowOpen = true; // Not included.
1773 cursorOptions.lowKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, *range->lower());
1774 cursorOptions.lowOpen = range->lowerOpen();
1778 cursorOptions.highKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, maxIDBKey());
1780 if (cursorOptions.forward)
1781 cursorOptions.highOpen = true; // Not included.
1783 // We need a key that exists.
1784 if (!findGreatestKeyLessThanOrEqual(transaction, cursorOptions.highKey, cursorOptions.highKey))
1786 cursorOptions.highOpen = false;
1789 cursorOptions.highKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, *range->upper());
1790 cursorOptions.highOpen = range->upperOpen();
1792 if (!cursorOptions.forward) {
1793 // For reverse cursors, we need a key that exists.
1794 Vector<char> foundHighKey;
1795 if (!findGreatestKeyLessThanOrEqual(transaction, cursorOptions.highKey, foundHighKey))
1798 // If the target key should not be included, but we end up with a smaller key, we should include that.
1799 if (cursorOptions.highOpen && IDBBackingStoreLevelDB::compareIndexKeys(foundHighKey, cursorOptions.highKey) < 0)
1800 cursorOptions.highOpen = false;
1802 cursorOptions.highKey = foundHighKey;
1809 static bool indexCursorOptions(LevelDBTransaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange* range, IndexedDB::CursorDirection direction, IDBBackingStoreCursorLevelDB::CursorOptions& cursorOptions)
1811 ASSERT(transaction);
1812 if (!KeyPrefix::validIds(databaseId, objectStoreId, indexId))
1815 cursorOptions.databaseId = databaseId;
1816 cursorOptions.objectStoreId = objectStoreId;
1817 cursorOptions.indexId = indexId;
1819 bool lowerBound = range && range->lower();
1820 bool upperBound = range && range->upper();
1821 cursorOptions.forward = (direction == IndexedDB::CursorNextNoDuplicate || direction == IndexedDB::CursorNext);
1822 cursorOptions.unique = (direction == IndexedDB::CursorNextNoDuplicate || direction == IndexedDB::CursorPrevNoDuplicate);
1825 cursorOptions.lowKey = IndexDataKey::encodeMinKey(databaseId, objectStoreId, indexId);
1826 cursorOptions.lowOpen = false; // Included.
1828 cursorOptions.lowKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, *range->lower());
1829 cursorOptions.lowOpen = range->lowerOpen();
1833 cursorOptions.highKey = IndexDataKey::encodeMaxKey(databaseId, objectStoreId, indexId);
1834 cursorOptions.highOpen = false; // Included.
1836 if (!cursorOptions.forward) { // We need a key that exists.
1837 if (!findGreatestKeyLessThanOrEqual(transaction, cursorOptions.highKey, cursorOptions.highKey))
1839 cursorOptions.highOpen = false;
1842 cursorOptions.highKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, *range->upper());
1843 cursorOptions.highOpen = range->upperOpen();
1845 Vector<char> foundHighKey;
1846 if (!findGreatestKeyLessThanOrEqual(transaction, cursorOptions.highKey, foundHighKey)) // Seek to the *last* key in the set of non-unique keys.
1849 // If the target key should not be included, but we end up with a smaller key, we should include that.
1850 if (cursorOptions.highOpen && IDBBackingStoreLevelDB::compareIndexKeys(foundHighKey, cursorOptions.highKey) < 0)
1851 cursorOptions.highOpen = false;
1853 cursorOptions.highKey = foundHighKey;
1858 PassRefPtr<IDBBackingStoreCursorInterface> IDBBackingStoreLevelDB::openObjectStoreCursor(IDBBackingStoreTransactionInterface& transaction, int64_t databaseId, int64_t objectStoreId, const IDBKeyRange* range, IndexedDB::CursorDirection direction)
1861 LOG(StorageAPI, "IDBBackingStoreLevelDB::openObjectStoreCursor");
1862 LevelDBTransaction* levelDBTransaction = IDBBackingStoreTransactionLevelDB::levelDBTransactionFrom(transaction);
1863 IDBBackingStoreCursorLevelDB::CursorOptions cursorOptions;
1864 if (!objectStoreCursorOptions(levelDBTransaction, databaseId, objectStoreId, range, direction, cursorOptions))
1866 RefPtr<ObjectStoreCursorImpl> cursor = ObjectStoreCursorImpl::create(levelDBTransaction, cursorOptions);
1867 if (!cursor->firstSeek())
1870 return cursor.release();
1873 PassRefPtr<IDBBackingStoreCursorInterface> IDBBackingStoreLevelDB::openObjectStoreKeyCursor(IDBBackingStoreTransactionInterface& transaction, int64_t databaseId, int64_t objectStoreId, const IDBKeyRange* range, IndexedDB::CursorDirection direction)
1875 LOG(StorageAPI, "IDBBackingStoreLevelDB::openObjectStoreKeyCursor");
1876 LevelDBTransaction* levelDBTransaction = IDBBackingStoreTransactionLevelDB::levelDBTransactionFrom(transaction);
1877 IDBBackingStoreCursorLevelDB::CursorOptions cursorOptions;
1878 if (!objectStoreCursorOptions(levelDBTransaction, databaseId, objectStoreId, range, direction, cursorOptions))
1880 RefPtr<ObjectStoreKeyCursorImpl> cursor = ObjectStoreKeyCursorImpl::create(levelDBTransaction, cursorOptions);
1881 if (!cursor->firstSeek())
1884 return cursor.release();
1887 PassRefPtr<IDBBackingStoreCursorInterface> IDBBackingStoreLevelDB::openIndexKeyCursor(IDBBackingStoreTransactionInterface& transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange* range, IndexedDB::CursorDirection direction)
1889 LOG(StorageAPI, "IDBBackingStoreLevelDB::openIndexKeyCursor");
1890 LevelDBTransaction* levelDBTransaction = IDBBackingStoreTransactionLevelDB::levelDBTransactionFrom(transaction);
1891 IDBBackingStoreCursorLevelDB::CursorOptions cursorOptions;
1892 if (!indexCursorOptions(levelDBTransaction, databaseId, objectStoreId, indexId, range, direction, cursorOptions))
1894 RefPtr<IndexKeyCursorImpl> cursor = IndexKeyCursorImpl::create(levelDBTransaction, cursorOptions);
1895 if (!cursor->firstSeek())
1898 return cursor.release();
1901 PassRefPtr<IDBBackingStoreCursorInterface> IDBBackingStoreLevelDB::openIndexCursor(IDBBackingStoreTransactionInterface& transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange* range, IndexedDB::CursorDirection direction)
1903 LOG(StorageAPI, "IDBBackingStoreLevelDB::openIndexCursor");
1904 LevelDBTransaction* levelDBTransaction = IDBBackingStoreTransactionLevelDB::levelDBTransactionFrom(transaction);
1905 IDBBackingStoreCursorLevelDB::CursorOptions cursorOptions;
1906 if (!indexCursorOptions(levelDBTransaction, databaseId, objectStoreId, indexId, range, direction, cursorOptions))
1908 RefPtr<IndexCursorImpl> cursor = IndexCursorImpl::create(levelDBTransaction, cursorOptions);
1909 if (!cursor->firstSeek())
1912 return cursor.release();
1915 std::unique_ptr<IDBBackingStoreTransactionInterface> IDBBackingStoreLevelDB::createBackingStoreTransaction()
1917 return std::unique_ptr<IDBBackingStoreTransactionInterface>(new IDBBackingStoreTransactionLevelDB(this));
1920 } // namespace WebCore
1922 #endif // ENABLE(INDEXED_DATABASE) && USE(LEVELDB)