IndexedDB: simplify RecordIdentifier
[WebKit-https.git] / Source / WebCore / Modules / indexeddb / IDBBackingStore.cpp
1 /*
2  * Copyright (C) 2011 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
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.
13  *
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.
24  */
25
26 #include "config.h"
27 #include "IDBBackingStore.h"
28
29 #if ENABLE(INDEXED_DATABASE)
30
31 #include "FileSystem.h"
32 #include "HistogramSupport.h"
33 #include "IDBFactoryBackendImpl.h"
34 #include "IDBKey.h"
35 #include "IDBKeyPath.h"
36 #include "IDBKeyRange.h"
37 #include "IDBLevelDBCoding.h"
38 #include "IDBMetadata.h"
39 #include "IDBTracing.h"
40 #include "LevelDBComparator.h"
41 #include "LevelDBDatabase.h"
42 #include "LevelDBIterator.h"
43 #include "LevelDBSlice.h"
44 #include "LevelDBTransaction.h"
45 #include "SecurityOrigin.h"
46 #include <wtf/Assertions.h>
47
48 namespace WebCore {
49
50 using namespace IDBLevelDBCoding;
51
52 const int64_t KeyGeneratorInitialNumber = 1; // From the IndexedDB specification.
53
54 enum IDBLevelDBBackingStoreInternalErrorType {
55     IDBLevelDBBackingStoreReadError,
56     IDBLevelDBBackingStoreWriteError,
57     IDBLevelDBBackingStoreConsistencyError,
58     IDBLevelDBBackingStoreInternalErrorMax,
59 };
60 static inline void recordInternalError(IDBLevelDBBackingStoreInternalErrorType type)
61 {
62     HistogramSupport::histogramEnumeration("WebCore.IndexedDB.BackingStore.InternalError", type, IDBLevelDBBackingStoreInternalErrorMax);
63 }
64
65 // Use to signal conditions that usually indicate developer error, but could be caused by data corruption.
66 // A macro is used instead of an inline function so that the assert and log report the line number.
67 #define InternalError(type) \
68     do { \
69         ASSERT_NOT_REACHED(); \
70         LOG_ERROR("Internal IndexedDB Error: %s", #type); \
71         recordInternalError(type); \
72     } while (0)
73
74 template <typename DBOrTransaction>
75 static bool getBool(DBOrTransaction* db, const LevelDBSlice& key, bool& foundBool)
76 {
77     Vector<char> result;
78     if (!db->get(key, result))
79         return false;
80
81     foundBool = decodeBool(result.begin(), result.end());
82     return true;
83 }
84
85 static void putBool(LevelDBTransaction* transaction, const LevelDBSlice& key, bool value)
86 {
87     transaction->put(key, encodeBool(value));
88 }
89
90 template <typename DBOrTransaction>
91 static bool getInt(DBOrTransaction* db, const LevelDBSlice& key, int64_t& foundInt)
92 {
93     Vector<char> result;
94     if (!db->get(key, result))
95         return false;
96
97     foundInt = decodeInt(result.begin(), result.end());
98     return true;
99 }
100
101 static void putInt(LevelDBTransaction* transaction, const LevelDBSlice& key, int64_t value)
102 {
103     ASSERT(value >= 0);
104     transaction->put(key, encodeInt(value));
105 }
106
107 template <typename DBOrTransaction>
108 static bool getVarInt(DBOrTransaction* db, const LevelDBSlice& key, int64_t& foundInt)
109 {
110     Vector<char> result;
111     if (!db->get(key, result))
112         return false;
113
114     return decodeVarInt(result.begin(), result.end(), foundInt) == result.end();
115 }
116
117 static void putVarInt(LevelDBTransaction* transaction, const LevelDBSlice& key, int64_t value)
118 {
119     transaction->put(key, encodeVarInt(value));
120 }
121
122 template <typename DBOrTransaction>
123 static bool getString(DBOrTransaction* db, const LevelDBSlice& key, String& foundString)
124 {
125     Vector<char> result;
126     if (!db->get(key, result))
127         return false;
128
129     foundString = decodeString(result.begin(), result.end());
130     return true;
131 }
132
133 static void putString(LevelDBTransaction* transaction, const LevelDBSlice& key, const String& value)
134 {
135     transaction->put(key, encodeString(value));
136 }
137
138 static void putIDBKeyPath(LevelDBTransaction* transaction, const LevelDBSlice& key, const IDBKeyPath& value)
139 {
140     transaction->put(key, encodeIDBKeyPath(value));
141 }
142
143 static int compareKeys(const LevelDBSlice& a, const LevelDBSlice& b)
144 {
145     return compare(a, b);
146 }
147
148 static int compareIndexKeys(const LevelDBSlice& a, const LevelDBSlice& b)
149 {
150     return compare(a, b, true);
151 }
152
153 class Comparator : public LevelDBComparator {
154 public:
155     virtual int compare(const LevelDBSlice& a, const LevelDBSlice& b) const { return IDBLevelDBCoding::compare(a, b); }
156     virtual const char* name() const { return "idb_cmp1"; }
157 };
158
159 const int64_t latestSchemaVersion = 1;
160 static bool isSchemaKnown(LevelDBDatabase* db)
161 {
162     int64_t schemaVersion = 0;
163     const Vector<char> metaDataKey = SchemaVersionKey::encode();
164     if (!getInt(db, metaDataKey, schemaVersion))
165         return true;
166     return schemaVersion <= latestSchemaVersion;
167 }
168
169 static bool setUpMetadata(LevelDBDatabase* db, const String& origin)
170 {
171     const Vector<char> metaDataKey = SchemaVersionKey::encode();
172     RefPtr<LevelDBTransaction> transaction = LevelDBTransaction::create(db);
173
174     int64_t schemaVersion = 0;
175     if (!getInt(transaction.get(), metaDataKey, schemaVersion)) {
176         schemaVersion = latestSchemaVersion;
177         putInt(transaction.get(), metaDataKey, latestSchemaVersion);
178     } else {
179         ASSERT(schemaVersion <= latestSchemaVersion);
180         if (!schemaVersion) {
181             schemaVersion = latestSchemaVersion;
182             putInt(transaction.get(), metaDataKey, schemaVersion);
183             const Vector<char> startKey = DatabaseNameKey::encodeMinKeyForOrigin(origin);
184             const Vector<char> stopKey = DatabaseNameKey::encodeStopKeyForOrigin(origin);
185             OwnPtr<LevelDBIterator> it = db->createIterator();
186             for (it->seek(startKey); it->isValid() && compareKeys(it->key(), stopKey) < 0; it->next()) {
187                 int64_t databaseId = 0;
188                 if (!getInt(transaction.get(), it->key(), databaseId)) {
189                     InternalError(IDBLevelDBBackingStoreReadError);
190                     return false;
191                 }
192                 Vector<char> intVersionKey = DatabaseMetaDataKey::encode(databaseId, DatabaseMetaDataKey::UserIntVersion);
193                 putVarInt(transaction.get(), intVersionKey, IDBDatabaseMetadata::DefaultIntVersion);
194             }
195         }
196     }
197
198     ASSERT(schemaVersion == latestSchemaVersion);
199     if (!transaction->commit()) {
200         InternalError(IDBLevelDBBackingStoreWriteError);
201         return false;
202     }
203     return true;
204 }
205
206 template <typename DBOrTransaction>
207 static int64_t getMaxObjectStoreId(DBOrTransaction* db, int64_t databaseId)
208 {
209     const Vector<char> maxObjectStoreIdKey = DatabaseMetaDataKey::encode(databaseId, DatabaseMetaDataKey::MaxObjectStoreId);
210     return getMaxObjectStoreId(db, maxObjectStoreIdKey);
211 }
212
213 template <typename DBOrTransaction>
214 static int64_t getMaxObjectStoreId(DBOrTransaction* db, const Vector<char>& maxObjectStoreIdKey)
215 {
216     int64_t maxObjectStoreId = -1;
217     if (!getInt(db, maxObjectStoreIdKey, maxObjectStoreId))
218         maxObjectStoreId = 0;
219
220     ASSERT(maxObjectStoreId >= 0);
221     return maxObjectStoreId;
222 }
223
224 IDBBackingStore::IDBBackingStore(const String& identifier, IDBFactoryBackendImpl* factory, PassOwnPtr<LevelDBDatabase> db)
225     : m_identifier(identifier)
226     , m_factory(factory)
227     , m_db(db)
228 {
229     m_factory->addIDBBackingStore(identifier, this);
230 }
231
232 IDBBackingStore::IDBBackingStore()
233 {
234 }
235
236 IDBBackingStore::~IDBBackingStore()
237 {
238     // Only null in tests.
239     if (m_factory)
240         m_factory->removeIDBBackingStore(m_identifier);
241
242     // m_db's destructor uses m_comparator. The order of destruction is important.
243     m_db.clear();
244     m_comparator.clear();
245 }
246
247 enum IDBLevelDBBackingStoreOpenResult {
248     IDBLevelDBBackingStoreOpenMemory,
249     IDBLevelDBBackingStoreOpenSuccess,
250     IDBLevelDBBackingStoreOpenFailedDirectory,
251     IDBLevelDBBackingStoreOpenFailedUnknownSchema,
252     IDBLevelDBBackingStoreOpenCleanupDestroyFailed,
253     IDBLevelDBBackingStoreOpenCleanupReopenFailed,
254     IDBLevelDBBackingStoreOpenCleanupReopenSuccess,
255     IDBLevelDBBackingStoreOpenMax,
256 };
257
258 PassRefPtr<IDBBackingStore> IDBBackingStore::open(SecurityOrigin* securityOrigin, const String& pathBaseArg, const String& fileIdentifier, IDBFactoryBackendImpl* factory)
259 {
260     IDB_TRACE("IDBBackingStore::open");
261     String pathBase = pathBaseArg;
262
263     OwnPtr<LevelDBComparator> comparator = adoptPtr(new Comparator());
264     OwnPtr<LevelDBDatabase> db;
265
266     if (pathBase.isEmpty()) {
267         HistogramSupport::histogramEnumeration("WebCore.IndexedDB.BackingStore.OpenStatus", IDBLevelDBBackingStoreOpenMemory, IDBLevelDBBackingStoreOpenMax);
268         db = LevelDBDatabase::openInMemory(comparator.get());
269     } else {
270         if (!makeAllDirectories(pathBase)) {
271             LOG_ERROR("Unable to create IndexedDB database path %s", pathBase.utf8().data());
272             HistogramSupport::histogramEnumeration("WebCore.IndexedDB.BackingStore.OpenStatus", IDBLevelDBBackingStoreOpenFailedDirectory, IDBLevelDBBackingStoreOpenMax);
273             return PassRefPtr<IDBBackingStore>();
274         }
275
276         String path = pathByAppendingComponent(pathBase, securityOrigin->databaseIdentifier() + ".indexeddb.leveldb");
277
278         db = LevelDBDatabase::open(path, comparator.get());
279         if (db && !isSchemaKnown(db.get())) {
280             LOG_ERROR("IndexedDB backing store had unknown schema, treating it as failure to open");
281             HistogramSupport::histogramEnumeration("WebCore.IndexedDB.BackingStore.OpenStatus", IDBLevelDBBackingStoreOpenFailedUnknownSchema, IDBLevelDBBackingStoreOpenMax);
282             db.clear();
283         }
284
285         if (db)
286             HistogramSupport::histogramEnumeration("WebCore.IndexedDB.BackingStore.OpenStatus", IDBLevelDBBackingStoreOpenSuccess, IDBLevelDBBackingStoreOpenMax);
287         else {
288             LOG_ERROR("IndexedDB backing store open failed, attempting cleanup");
289             bool success = LevelDBDatabase::destroy(path);
290             if (!success) {
291                 LOG_ERROR("IndexedDB backing store cleanup failed");
292                 HistogramSupport::histogramEnumeration("WebCore.IndexedDB.BackingStore.OpenStatus", IDBLevelDBBackingStoreOpenCleanupDestroyFailed, IDBLevelDBBackingStoreOpenMax);
293                 return PassRefPtr<IDBBackingStore>();
294             }
295
296             LOG_ERROR("IndexedDB backing store cleanup succeeded, reopening");
297             db = LevelDBDatabase::open(path, comparator.get());
298             if (!db) {
299                 LOG_ERROR("IndexedDB backing store reopen after recovery failed");
300                 HistogramSupport::histogramEnumeration("WebCore.IndexedDB.BackingStore.OpenStatus", IDBLevelDBBackingStoreOpenCleanupReopenFailed, IDBLevelDBBackingStoreOpenMax);
301                 return PassRefPtr<IDBBackingStore>();
302             }
303             HistogramSupport::histogramEnumeration("WebCore.IndexedDB.BackingStore.OpenStatus", IDBLevelDBBackingStoreOpenCleanupReopenSuccess, IDBLevelDBBackingStoreOpenMax);
304         }
305     }
306
307     if (!db)
308         return PassRefPtr<IDBBackingStore>();
309
310     // FIXME: Handle comparator name changes.
311
312     RefPtr<IDBBackingStore> backingStore(adoptRef(new IDBBackingStore(fileIdentifier, factory, db.release())));
313     backingStore->m_comparator = comparator.release();
314
315     if (!setUpMetadata(backingStore->m_db.get(), fileIdentifier))
316         return PassRefPtr<IDBBackingStore>();
317
318     return backingStore.release();
319 }
320
321 Vector<String> IDBBackingStore::getDatabaseNames()
322 {
323     Vector<String> foundNames;
324     const Vector<char> startKey = DatabaseNameKey::encodeMinKeyForOrigin(m_identifier);
325     const Vector<char> stopKey = DatabaseNameKey::encodeStopKeyForOrigin(m_identifier);
326
327     ASSERT(foundNames.isEmpty());
328
329     OwnPtr<LevelDBIterator> it = m_db->createIterator();
330     for (it->seek(startKey); it->isValid() && compareKeys(it->key(), stopKey) < 0; it->next()) {
331         const char* p = it->key().begin();
332         const char* limit = it->key().end();
333
334         DatabaseNameKey databaseNameKey;
335         p = DatabaseNameKey::decode(p, limit, &databaseNameKey);
336         ASSERT(p);
337
338         foundNames.append(databaseNameKey.databaseName());
339     }
340     return foundNames;
341 }
342
343 bool IDBBackingStore::getIDBDatabaseMetaData(const String& name, IDBDatabaseMetadata* metadata)
344 {
345     const Vector<char> key = DatabaseNameKey::encode(m_identifier, name);
346
347     bool ok = getInt(m_db.get(), key, metadata->id);
348     if (!ok)
349         return false;
350
351     ok = getString(m_db.get(), DatabaseMetaDataKey::encode(metadata->id, DatabaseMetaDataKey::UserVersion), metadata->version);
352     if (!ok) {
353         InternalError(IDBLevelDBBackingStoreReadError);
354         return false;
355     }
356
357     ok = getVarInt(m_db.get(), DatabaseMetaDataKey::encode(metadata->id, DatabaseMetaDataKey::UserIntVersion), metadata->intVersion);
358     if (!ok) {
359         InternalError(IDBLevelDBBackingStoreReadError);
360         return false;
361     }
362     if (metadata->intVersion == IDBDatabaseMetadata::DefaultIntVersion)
363         metadata->intVersion = IDBDatabaseMetadata::NoIntVersion;
364
365     metadata->maxObjectStoreId = getMaxObjectStoreId(m_db.get(), metadata->id);
366
367     return true;
368 }
369
370 static int64_t getNewDatabaseId(LevelDBDatabase* db)
371 {
372     RefPtr<LevelDBTransaction> transaction = LevelDBTransaction::create(db);
373
374     int64_t maxDatabaseId = -1;
375     if (!getInt(transaction.get(), MaxDatabaseIdKey::encode(), maxDatabaseId))
376         maxDatabaseId = 0;
377
378     ASSERT(maxDatabaseId >= 0);
379
380     int64_t databaseId = maxDatabaseId + 1;
381     putInt(transaction.get(), MaxDatabaseIdKey::encode(), databaseId);
382     if (!transaction->commit()) {
383         InternalError(IDBLevelDBBackingStoreWriteError);
384         return -1;
385     }
386     return databaseId;
387 }
388
389 bool IDBBackingStore::createIDBDatabaseMetaData(const String& name, const String& version, int64_t intVersion, int64_t& rowId)
390 {
391     rowId = getNewDatabaseId(m_db.get());
392     if (rowId < 0)
393         return false;
394
395     if (intVersion == IDBDatabaseMetadata::NoIntVersion)
396         intVersion = IDBDatabaseMetadata::DefaultIntVersion;
397
398     RefPtr<LevelDBTransaction> transaction = LevelDBTransaction::create(m_db.get());
399     putInt(transaction.get(), DatabaseNameKey::encode(m_identifier, name), rowId);
400     putString(transaction.get(), DatabaseMetaDataKey::encode(rowId, DatabaseMetaDataKey::UserVersion), version);
401     putVarInt(transaction.get(), DatabaseMetaDataKey::encode(rowId, DatabaseMetaDataKey::UserIntVersion), intVersion);
402     if (!transaction->commit()) {
403         InternalError(IDBLevelDBBackingStoreWriteError);
404         return false;
405     }
406     return true;
407 }
408
409 bool IDBBackingStore::updateIDBDatabaseIntVersion(IDBBackingStore::Transaction* transaction, int64_t rowId, int64_t intVersion)
410 {
411     if (intVersion == IDBDatabaseMetadata::NoIntVersion)
412         intVersion = IDBDatabaseMetadata::DefaultIntVersion;
413     ASSERT_WITH_MESSAGE(intVersion >= 0, "intVersion was %lld", static_cast<long long>(intVersion));
414     putVarInt(Transaction::levelDBTransactionFrom(transaction), DatabaseMetaDataKey::encode(rowId, DatabaseMetaDataKey::UserIntVersion), intVersion);
415     return true;
416 }
417
418 bool IDBBackingStore::updateIDBDatabaseMetaData(IDBBackingStore::Transaction* transaction, int64_t rowId, const String& version)
419 {
420     putString(Transaction::levelDBTransactionFrom(transaction), DatabaseMetaDataKey::encode(rowId, DatabaseMetaDataKey::UserVersion), version);
421     return true;
422 }
423
424 static void deleteRange(LevelDBTransaction* transaction, const Vector<char>& begin, const Vector<char>& end)
425 {
426     OwnPtr<LevelDBIterator> it = transaction->createIterator();
427     for (it->seek(begin); it->isValid() && compareKeys(it->key(), end) < 0; it->next())
428         transaction->remove(it->key());
429 }
430
431
432 bool IDBBackingStore::deleteDatabase(const String& name)
433 {
434     IDB_TRACE("IDBBackingStore::deleteDatabase");
435     OwnPtr<LevelDBWriteOnlyTransaction> transaction = LevelDBWriteOnlyTransaction::create(m_db.get());
436
437     IDBDatabaseMetadata metadata;
438     if (!getIDBDatabaseMetaData(name, &metadata))
439         return true;
440
441     const Vector<char> startKey = DatabaseMetaDataKey::encode(metadata.id, DatabaseMetaDataKey::OriginName);
442     const Vector<char> stopKey = DatabaseMetaDataKey::encode(metadata.id + 1, DatabaseMetaDataKey::OriginName);
443     OwnPtr<LevelDBIterator> it = m_db->createIterator();
444     for (it->seek(startKey); it->isValid() && compareKeys(it->key(), stopKey) < 0; it->next())
445         transaction->remove(it->key());
446
447     const Vector<char> key = DatabaseNameKey::encode(m_identifier, name);
448     transaction->remove(key);
449
450     return transaction->commit();
451 }
452
453 static bool checkObjectStoreAndMetaDataType(const LevelDBIterator* it, const Vector<char>& stopKey, int64_t objectStoreId, int64_t metaDataType)
454 {
455     if (!it->isValid() || compareKeys(it->key(), stopKey) >= 0)
456         return false;
457
458     ObjectStoreMetaDataKey metaDataKey;
459     const char* p = ObjectStoreMetaDataKey::decode(it->key().begin(), it->key().end(), &metaDataKey);
460     ASSERT_UNUSED(p, p);
461     if (metaDataKey.objectStoreId() != objectStoreId)
462         return false;
463     if (metaDataKey.metaDataType() != metaDataType)
464         return false;
465     return true;
466 }
467
468 Vector<IDBObjectStoreMetadata> IDBBackingStore::getObjectStores(int64_t databaseId)
469 {
470     IDB_TRACE("IDBBackingStore::getObjectStores");
471     Vector<IDBObjectStoreMetadata> objectStores;
472     const Vector<char> startKey = ObjectStoreMetaDataKey::encode(databaseId, 1, 0);
473     const Vector<char> stopKey = ObjectStoreMetaDataKey::encodeMaxKey(databaseId);
474
475     OwnPtr<LevelDBIterator> it = m_db->createIterator();
476     it->seek(startKey);
477     while (it->isValid() && compareKeys(it->key(), stopKey) < 0) {
478         const char* p = it->key().begin();
479         const char* limit = it->key().end();
480
481         ObjectStoreMetaDataKey metaDataKey;
482         p = ObjectStoreMetaDataKey::decode(p, limit, &metaDataKey);
483         ASSERT(p);
484         if (metaDataKey.metaDataType() != ObjectStoreMetaDataKey::Name) {
485             InternalError(IDBLevelDBBackingStoreReadError);
486             // Possible stale metadata, but don't fail the load.
487             it->next();
488             continue;
489         }
490
491         int64_t objectStoreId = metaDataKey.objectStoreId();
492
493         // FIXME: Do this by direct key lookup rather than iteration, to simplify.
494         String objectStoreName = decodeString(it->value().begin(), it->value().end());
495
496         it->next();
497         if (!checkObjectStoreAndMetaDataType(it.get(), stopKey, objectStoreId, ObjectStoreMetaDataKey::KeyPath)) {
498             InternalError(IDBLevelDBBackingStoreReadError);
499             break;
500         }
501         IDBKeyPath keyPath = decodeIDBKeyPath(it->value().begin(), it->value().end());
502
503         it->next();
504         if (!checkObjectStoreAndMetaDataType(it.get(), stopKey, objectStoreId, ObjectStoreMetaDataKey::AutoIncrement)) {
505             InternalError(IDBLevelDBBackingStoreReadError);
506             break;
507         }
508         bool autoIncrement = decodeBool(it->value().begin(), it->value().end());
509
510         it->next(); // Is evicatble.
511         if (!checkObjectStoreAndMetaDataType(it.get(), stopKey, objectStoreId, ObjectStoreMetaDataKey::Evictable)) {
512             InternalError(IDBLevelDBBackingStoreReadError);
513             break;
514         }
515
516         it->next(); // Last version.
517         if (!checkObjectStoreAndMetaDataType(it.get(), stopKey, objectStoreId, ObjectStoreMetaDataKey::LastVersion)) {
518             InternalError(IDBLevelDBBackingStoreReadError);
519             break;
520         }
521
522         it->next(); // Maximum index id allocated.
523         if (!checkObjectStoreAndMetaDataType(it.get(), stopKey, objectStoreId, ObjectStoreMetaDataKey::MaxIndexId)) {
524             InternalError(IDBLevelDBBackingStoreReadError);
525             break;
526         }
527         int64_t maxIndexId = decodeInt(it->value().begin(), it->value().end());
528
529         it->next(); // [optional] has key path (is not null)
530         if (checkObjectStoreAndMetaDataType(it.get(), stopKey, objectStoreId, ObjectStoreMetaDataKey::HasKeyPath)) {
531             bool hasKeyPath = decodeBool(it->value().begin(), it->value().end());
532             // This check accounts for two layers of legacy coding:
533             // (1) Initially, hasKeyPath was added to distinguish null vs. string.
534             // (2) Later, null vs. string vs. array was stored in the keyPath itself.
535             // So this check is only relevant for string-type keyPaths.
536             if (!hasKeyPath && (keyPath.type() == IDBKeyPath::StringType && !keyPath.string().isEmpty())) {
537                 InternalError(IDBLevelDBBackingStoreReadError);
538                 break;
539             }
540             if (!hasKeyPath)
541                 keyPath = IDBKeyPath();
542             it->next();
543         }
544
545         int64_t keyGeneratorCurrentNumber = -1;
546         if (checkObjectStoreAndMetaDataType(it.get(), stopKey, objectStoreId, ObjectStoreMetaDataKey::KeyGeneratorCurrentNumber)) {
547             keyGeneratorCurrentNumber = decodeInt(it->value().begin(), it->value().end());
548             // FIXME: Return keyGeneratorCurrentNumber, cache in object store, and write lazily to backing store.
549             // For now, just assert that if it was written it was valid.
550             ASSERT_UNUSED(keyGeneratorCurrentNumber, keyGeneratorCurrentNumber >= KeyGeneratorInitialNumber);
551             it->next();
552         }
553
554         objectStores.append(IDBObjectStoreMetadata(objectStoreName, objectStoreId, keyPath, autoIncrement, maxIndexId));
555     }
556     return objectStores;
557 }
558
559 static bool setMaxObjectStoreId(LevelDBTransaction* transaction, int64_t databaseId, int64_t objectStoreId)
560 {
561     const Vector<char> maxObjectStoreIdKey = DatabaseMetaDataKey::encode(databaseId, DatabaseMetaDataKey::MaxObjectStoreId);
562     int64_t maxObjectStoreId = getMaxObjectStoreId(transaction, maxObjectStoreIdKey);
563
564     if (objectStoreId <= maxObjectStoreId) {
565         InternalError(IDBLevelDBBackingStoreConsistencyError);
566         return false;
567     }
568     putInt(transaction, maxObjectStoreIdKey, objectStoreId);
569     return true;
570 }
571
572 bool IDBBackingStore::createObjectStore(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId, const String& name, const IDBKeyPath& keyPath, bool autoIncrement)
573 {
574     IDB_TRACE("IDBBackingStore::createObjectStore");
575     LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction);
576     if (!setMaxObjectStoreId(levelDBTransaction, databaseId, objectStoreId))
577         return false;
578
579     const Vector<char> nameKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::Name);
580     const Vector<char> keyPathKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::KeyPath);
581     const Vector<char> autoIncrementKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::AutoIncrement);
582     const Vector<char> evictableKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::Evictable);
583     const Vector<char> lastVersionKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::LastVersion);
584     const Vector<char> maxIndexIdKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::MaxIndexId);
585     const Vector<char> hasKeyPathKey  = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::HasKeyPath);
586     const Vector<char> keyGeneratorCurrentNumberKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::KeyGeneratorCurrentNumber);
587     const Vector<char> namesKey = ObjectStoreNamesKey::encode(databaseId, name);
588
589     putString(levelDBTransaction, nameKey, name);
590     putIDBKeyPath(levelDBTransaction, keyPathKey, keyPath);
591     putInt(levelDBTransaction, autoIncrementKey, autoIncrement);
592     putInt(levelDBTransaction, evictableKey, false);
593     putInt(levelDBTransaction, lastVersionKey, 1);
594     putInt(levelDBTransaction, maxIndexIdKey, MinimumIndexId);
595     putBool(levelDBTransaction, hasKeyPathKey, !keyPath.isNull());
596     putInt(levelDBTransaction, keyGeneratorCurrentNumberKey, KeyGeneratorInitialNumber);
597     putInt(levelDBTransaction, namesKey, objectStoreId);
598     return true;
599 }
600
601 void IDBBackingStore::deleteObjectStore(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId)
602 {
603     IDB_TRACE("IDBBackingStore::deleteObjectStore");
604     LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction);
605
606     String objectStoreName;
607     getString(levelDBTransaction, ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::Name), objectStoreName);
608
609     deleteRange(levelDBTransaction, ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, 0), ObjectStoreMetaDataKey::encodeMaxKey(databaseId, objectStoreId));
610
611     levelDBTransaction->remove(ObjectStoreNamesKey::encode(databaseId, objectStoreName));
612
613     deleteRange(levelDBTransaction, IndexFreeListKey::encode(databaseId, objectStoreId, 0), IndexFreeListKey::encodeMaxKey(databaseId, objectStoreId));
614     deleteRange(levelDBTransaction, IndexMetaDataKey::encode(databaseId, objectStoreId, 0, 0), IndexMetaDataKey::encodeMaxKey(databaseId, objectStoreId));
615
616     clearObjectStore(transaction, databaseId, objectStoreId);
617 }
618
619 String IDBBackingStore::getRecord(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId, const IDBKey& key)
620 {
621     IDB_TRACE("IDBBackingStore::getRecord");
622     LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction);
623
624     const Vector<char> leveldbKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, key);
625     Vector<char> data;
626
627     if (!levelDBTransaction->get(leveldbKey, data))
628         return String();
629
630     int64_t version;
631     const char* p = decodeVarInt(data.begin(), data.end(), version);
632     if (!p) {
633         InternalError(IDBLevelDBBackingStoreReadError);
634         return String();
635     }
636     (void) version;
637
638     return decodeString(p, data.end());
639 }
640
641 static int64_t getNewVersionNumber(LevelDBTransaction* transaction, int64_t databaseId, int64_t objectStoreId)
642 {
643     const Vector<char> lastVersionKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::LastVersion);
644
645     int64_t lastVersion = -1;
646     if (!getInt(transaction, lastVersionKey, lastVersion))
647         lastVersion = 0;
648
649     ASSERT(lastVersion >= 0);
650
651     int64_t version = lastVersion + 1;
652     putInt(transaction, lastVersionKey, version);
653
654     ASSERT(version > lastVersion); // FIXME: Think about how we want to handle the overflow scenario.
655
656     return version;
657 }
658
659 void IDBBackingStore::putRecord(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId, const IDBKey& key, const String& value, RecordIdentifier* recordIdentifier)
660 {
661     IDB_TRACE("IDBBackingStore::putRecord");
662     ASSERT(key.isValid());
663     LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction);
664     int64_t version = getNewVersionNumber(levelDBTransaction, databaseId, objectStoreId);
665     const Vector<char> objectStoredataKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, key);
666
667     Vector<char> v;
668     v.append(encodeVarInt(version));
669     v.append(encodeString(value));
670
671     levelDBTransaction->put(objectStoredataKey, v);
672
673     const Vector<char> existsEntryKey = ExistsEntryKey::encode(databaseId, objectStoreId, key);
674     levelDBTransaction->put(existsEntryKey, encodeInt(version));
675
676     recordIdentifier->reset(encodeIDBKey(key), version);
677 }
678
679 void IDBBackingStore::clearObjectStore(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId)
680 {
681     IDB_TRACE("IDBBackingStore::clearObjectStore");
682     LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction);
683     const Vector<char> startKey = KeyPrefix(databaseId, objectStoreId, 0).encode();
684     const Vector<char> stopKey = KeyPrefix(databaseId, objectStoreId + 1, 0).encode();
685
686     deleteRange(levelDBTransaction, startKey, stopKey);
687 }
688
689 void IDBBackingStore::deleteRecord(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId, const RecordIdentifier& recordIdentifier)
690 {
691     IDB_TRACE("IDBBackingStore::deleteRecord");
692     LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction);
693
694     const Vector<char> objectStoreDataKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, recordIdentifier.primaryKey());
695     levelDBTransaction->remove(objectStoreDataKey);
696
697     const Vector<char> existsEntryKey = ExistsEntryKey::encode(databaseId, objectStoreId, recordIdentifier.primaryKey());
698     levelDBTransaction->remove(existsEntryKey);
699 }
700
701
702 int64_t IDBBackingStore::getKeyGeneratorCurrentNumber(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId)
703 {
704     LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction);
705
706     const Vector<char> keyGeneratorCurrentNumberKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::KeyGeneratorCurrentNumber);
707
708     int64_t keyGeneratorCurrentNumber = -1;
709     Vector<char> data;
710
711     if (levelDBTransaction->get(keyGeneratorCurrentNumberKey, data))
712         keyGeneratorCurrentNumber = decodeInt(data.begin(), data.end());
713     else {
714         // Previously, the key generator state was not stored explicitly but derived from the
715         // maximum numeric key present in existing data. This violates the spec as the data may
716         // be cleared but the key generator state must be preserved.
717         const Vector<char> startKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, minIDBKey());
718         const Vector<char> stopKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, maxIDBKey());
719
720         OwnPtr<LevelDBIterator> it = levelDBTransaction->createIterator();
721         int64_t maxNumericKey = 0;
722
723         for (it->seek(startKey); it->isValid() && compareKeys(it->key(), stopKey) < 0; it->next()) {
724             const char* p = it->key().begin();
725             const char* limit = it->key().end();
726
727             ObjectStoreDataKey dataKey;
728             p = ObjectStoreDataKey::decode(p, limit, &dataKey);
729             ASSERT(p);
730
731             if (dataKey.userKey()->type() == IDBKey::NumberType) {
732                 int64_t n = static_cast<int64_t>(dataKey.userKey()->number());
733                 if (n > maxNumericKey)
734                     maxNumericKey = n;
735             }
736         }
737
738         keyGeneratorCurrentNumber = maxNumericKey + 1;
739     }
740
741     return keyGeneratorCurrentNumber;
742 }
743
744 void IDBBackingStore::maybeUpdateKeyGeneratorCurrentNumber(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t newNumber, bool checkCurrent)
745 {
746     LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction);
747
748     if (checkCurrent) {
749         int64_t currentNumber = getKeyGeneratorCurrentNumber(transaction, databaseId, objectStoreId);
750         if (newNumber <= currentNumber)
751             return;
752     }
753
754     const Vector<char> keyGeneratorCurrentNumberKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::KeyGeneratorCurrentNumber);
755     putInt(levelDBTransaction, keyGeneratorCurrentNumberKey, newNumber);
756 }
757
758 bool IDBBackingStore::keyExistsInObjectStore(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId, const IDBKey& key, RecordIdentifier* foundRecordIdentifier)
759 {
760     IDB_TRACE("IDBBackingStore::keyExistsInObjectStore");
761     LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction);
762     const Vector<char> leveldbKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, key);
763     Vector<char> data;
764
765     if (!levelDBTransaction->get(leveldbKey, data))
766         return false;
767
768     int64_t version;
769     if (!decodeVarInt(data.begin(), data.end(), version))
770         return false;
771
772     foundRecordIdentifier->reset(encodeIDBKey(key), version);
773     return true;
774 }
775
776 static bool checkIndexAndMetaDataKey(const LevelDBIterator* it, const Vector<char>& stopKey, int64_t indexId, unsigned char metaDataType)
777 {
778     if (!it->isValid() || compareKeys(it->key(), stopKey) >= 0)
779         return false;
780
781     IndexMetaDataKey metaDataKey;
782     const char* p = IndexMetaDataKey::decode(it->key().begin(), it->key().end(), &metaDataKey);
783     ASSERT_UNUSED(p, p);
784     if (metaDataKey.indexId() != indexId)
785         return false;
786     if (metaDataKey.metaDataType() != metaDataType)
787         return false;
788     return true;
789 }
790
791
792 Vector<IDBIndexMetadata> IDBBackingStore::getIndexes(int64_t databaseId, int64_t objectStoreId)
793 {
794     IDB_TRACE("IDBBackingStore::getIndexes");
795     Vector<IDBIndexMetadata> indexes;
796     const Vector<char> startKey = IndexMetaDataKey::encode(databaseId, objectStoreId, 0, 0);
797     const Vector<char> stopKey = IndexMetaDataKey::encode(databaseId, objectStoreId + 1, 0, 0);
798
799     ASSERT(indexes.isEmpty());
800
801     OwnPtr<LevelDBIterator> it = m_db->createIterator();
802     it->seek(startKey);
803     while (it->isValid() && compareKeys(it->key(), stopKey) < 0) {
804         const char* p = it->key().begin();
805         const char* limit = it->key().end();
806
807         IndexMetaDataKey metaDataKey;
808         p = IndexMetaDataKey::decode(p, limit, &metaDataKey);
809         ASSERT(p);
810         if (metaDataKey.metaDataType() != IndexMetaDataKey::Name) {
811             InternalError(IDBLevelDBBackingStoreReadError);
812             // Possible stale metadata due to http://webkit.org/b/85557 but don't fail the load.
813             it->next();
814             continue;
815         }
816
817         // FIXME: Do this by direct key lookup rather than iteration, to simplify.
818         int64_t indexId = metaDataKey.indexId();
819         String indexName = decodeString(it->value().begin(), it->value().end());
820
821         it->next(); // unique flag
822         if (!checkIndexAndMetaDataKey(it.get(), stopKey, indexId, IndexMetaDataKey::Unique)) {
823             InternalError(IDBLevelDBBackingStoreReadError);
824             break;
825         }
826         bool indexUnique = decodeBool(it->value().begin(), it->value().end());
827
828         it->next(); // keyPath
829         if (!checkIndexAndMetaDataKey(it.get(), stopKey, indexId, IndexMetaDataKey::KeyPath)) {
830             InternalError(IDBLevelDBBackingStoreReadError);
831             break;
832         }
833         IDBKeyPath keyPath = decodeIDBKeyPath(it->value().begin(), it->value().end());
834
835         it->next(); // [optional] multiEntry flag
836         bool indexMultiEntry = false;
837         if (checkIndexAndMetaDataKey(it.get(), stopKey, indexId, IndexMetaDataKey::MultiEntry)) {
838             indexMultiEntry = decodeBool(it->value().begin(), it->value().end());
839             it->next();
840         }
841
842         indexes.append(IDBIndexMetadata(indexName, indexId, keyPath, indexUnique, indexMultiEntry));
843     }
844     return indexes;
845 }
846
847 static bool setMaxIndexId(LevelDBTransaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId)
848 {
849     int64_t maxIndexId = -1;
850     const Vector<char> maxIndexIdKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, ObjectStoreMetaDataKey::MaxIndexId);
851     if (!getInt(transaction, maxIndexIdKey, maxIndexId))
852         maxIndexId = MinimumIndexId;
853
854     if (indexId <= maxIndexId) {
855         InternalError(IDBLevelDBBackingStoreConsistencyError);
856         return false;
857     }
858
859     putInt(transaction, maxIndexIdKey, indexId);
860     return true;
861 }
862
863 bool IDBBackingStore::createIndex(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const String& name, const IDBKeyPath& keyPath, bool isUnique, bool isMultiEntry)
864 {
865     IDB_TRACE("IDBBackingStore::createIndex");
866     LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction);
867     if (!setMaxIndexId(levelDBTransaction, databaseId, objectStoreId, indexId))
868         return false;
869
870     const Vector<char> nameKey = IndexMetaDataKey::encode(databaseId, objectStoreId, indexId, IndexMetaDataKey::Name);
871     const Vector<char> uniqueKey = IndexMetaDataKey::encode(databaseId, objectStoreId, indexId, IndexMetaDataKey::Unique);
872     const Vector<char> keyPathKey = IndexMetaDataKey::encode(databaseId, objectStoreId, indexId, IndexMetaDataKey::KeyPath);
873     const Vector<char> multiEntryKey = IndexMetaDataKey::encode(databaseId, objectStoreId, indexId, IndexMetaDataKey::MultiEntry);
874
875     putString(levelDBTransaction, nameKey, name);
876     putBool(levelDBTransaction, uniqueKey, isUnique);
877     putIDBKeyPath(levelDBTransaction, keyPathKey, keyPath);
878     putBool(levelDBTransaction, multiEntryKey, isMultiEntry);
879     return true;
880 }
881
882 void IDBBackingStore::deleteIndex(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId)
883 {
884     IDB_TRACE("IDBBackingStore::deleteIndex");
885     LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction);
886
887     const Vector<char> indexMetaDataStart = IndexMetaDataKey::encode(databaseId, objectStoreId, indexId, 0);
888     const Vector<char> indexMetaDataEnd = IndexMetaDataKey::encodeMaxKey(databaseId, objectStoreId, indexId);
889     deleteRange(levelDBTransaction, indexMetaDataStart, indexMetaDataEnd);
890
891     const Vector<char> indexDataStart = IndexDataKey::encodeMinKey(databaseId, objectStoreId, indexId);
892     const Vector<char> indexDataEnd = IndexDataKey::encodeMaxKey(databaseId, objectStoreId, indexId);
893     deleteRange(levelDBTransaction, indexDataStart, indexDataEnd);
894 }
895
896 void IDBBackingStore::putIndexDataForRecord(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& key, const RecordIdentifier& recordIdentifier)
897 {
898     IDB_TRACE("IDBBackingStore::putIndexDataForRecord");
899     ASSERT(key.isValid());
900     ASSERT(indexId >= MinimumIndexId);
901
902     LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction);
903     const Vector<char> indexDataKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, encodeIDBKey(key), recordIdentifier.primaryKey());
904
905     Vector<char> data;
906     data.append(encodeVarInt(recordIdentifier.version()));
907     data.append(recordIdentifier.primaryKey());
908
909     levelDBTransaction->put(indexDataKey, data);
910 }
911
912 static bool findGreatestKeyLessThanOrEqual(LevelDBTransaction* transaction, const Vector<char>& target, Vector<char>& foundKey)
913 {
914     OwnPtr<LevelDBIterator> it = transaction->createIterator();
915     it->seek(target);
916
917     if (!it->isValid()) {
918         it->seekToLast();
919         if (!it->isValid())
920             return false;
921     }
922
923     while (compareIndexKeys(it->key(), target) > 0) {
924         it->prev();
925         if (!it->isValid())
926             return false;
927     }
928
929     do {
930         foundKey.clear();
931         foundKey.append(it->key().begin(), it->key().end() - it->key().begin());
932
933         // There can be several index keys that compare equal. We want the last one.
934         it->next();
935     } while (it->isValid() && !compareIndexKeys(it->key(), target));
936
937     return true;
938 }
939
940 static bool versionExists(LevelDBTransaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t version, const Vector<char>& encodedPrimaryKey)
941 {
942     const Vector<char> key = ExistsEntryKey::encode(databaseId, objectStoreId, encodedPrimaryKey);
943     Vector<char> data;
944
945     if (!transaction->get(key, data))
946         return false;
947
948     return decodeInt(data.begin(), data.end()) == version;
949 }
950
951 bool IDBBackingStore::findKeyInIndex(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& key, Vector<char>& foundEncodedPrimaryKey)
952 {
953     IDB_TRACE("IDBBackingStore::findKeyInIndex");
954     ASSERT(foundEncodedPrimaryKey.isEmpty());
955
956     LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction);
957     const Vector<char> leveldbKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, key);
958     OwnPtr<LevelDBIterator> it = levelDBTransaction->createIterator();
959     it->seek(leveldbKey);
960
961     for (;;) {
962         if (!it->isValid())
963             return false;
964         if (compareIndexKeys(it->key(), leveldbKey) > 0)
965             return false;
966
967         int64_t version;
968         const char* p = decodeVarInt(it->value().begin(), it->value().end(), version);
969         if (!p) {
970             InternalError(IDBLevelDBBackingStoreReadError);
971             return false;
972         }
973         foundEncodedPrimaryKey.append(p, it->value().end() - p);
974
975         if (!versionExists(levelDBTransaction, databaseId, objectStoreId, version, foundEncodedPrimaryKey)) {
976             // Delete stale index data entry and continue.
977             levelDBTransaction->remove(it->key());
978             it->next();
979             continue;
980         }
981
982         return true;
983     }
984 }
985
986 PassRefPtr<IDBKey> IDBBackingStore::getPrimaryKeyViaIndex(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& key)
987 {
988     IDB_TRACE("IDBBackingStore::getPrimaryKeyViaIndex");
989
990     Vector<char> foundEncodedPrimaryKey;
991     if (findKeyInIndex(transaction, databaseId, objectStoreId, indexId, key, foundEncodedPrimaryKey)) {
992         RefPtr<IDBKey> primaryKey;
993         decodeIDBKey(foundEncodedPrimaryKey.begin(), foundEncodedPrimaryKey.end(), primaryKey);
994         return primaryKey.release();
995     }
996
997     return 0;
998 }
999
1000 bool IDBBackingStore::keyExistsInIndex(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& indexKey, RefPtr<IDBKey>& foundPrimaryKey)
1001 {
1002     IDB_TRACE("IDBBackingStore::keyExistsInIndex");
1003
1004     Vector<char> foundEncodedPrimaryKey;
1005     if (!findKeyInIndex(transaction, databaseId, objectStoreId, indexId, indexKey, foundEncodedPrimaryKey))
1006         return false;
1007
1008     decodeIDBKey(foundEncodedPrimaryKey.begin(), foundEncodedPrimaryKey.end(), foundPrimaryKey);
1009     return true;
1010 }
1011
1012 IDBBackingStore::Cursor::Cursor(const IDBBackingStore::Cursor* other)
1013     : m_transaction(other->m_transaction)
1014     , m_cursorOptions(other->m_cursorOptions)
1015     , m_currentKey(other->m_currentKey)
1016 {
1017     if (other->m_iterator) {
1018         m_iterator = m_transaction->createIterator();
1019
1020         if (other->m_iterator->isValid()) {
1021             m_iterator->seek(other->m_iterator->key());
1022             ASSERT(m_iterator->isValid());
1023         }
1024     }
1025 }
1026
1027 bool IDBBackingStore::Cursor::firstSeek()
1028 {
1029     m_iterator = m_transaction->createIterator();
1030     if (m_cursorOptions.forward)
1031         m_iterator->seek(m_cursorOptions.lowKey);
1032     else
1033         m_iterator->seek(m_cursorOptions.highKey);
1034
1035     return continueFunction(0, Ready);
1036 }
1037
1038 bool IDBBackingStore::Cursor::advance(unsigned long count)
1039 {
1040     while (count--) {
1041         if (!continueFunction())
1042             return false;
1043     }
1044     return true;
1045 }
1046
1047 bool IDBBackingStore::Cursor::continueFunction(const IDBKey* key, IteratorState nextState)
1048 {
1049     RefPtr<IDBKey> previousKey = m_currentKey;
1050
1051     // When iterating with PREV_NO_DUPLICATE, spec requires that the
1052     // value we yield for each key is the first duplicate in forwards
1053     // order.
1054     RefPtr<IDBKey> lastDuplicateKey;
1055
1056     bool forward = m_cursorOptions.forward;
1057
1058     for (;;) {
1059         if (nextState == Seek) {
1060             if (forward)
1061                 m_iterator->next();
1062             else
1063                 m_iterator->prev();
1064         } else
1065             nextState = Seek; // for subsequent iterations
1066
1067         if (!m_iterator->isValid()) {
1068             if (!forward && lastDuplicateKey.get()) {
1069                 // We need to walk forward because we hit the end of
1070                 // the data.
1071                 forward = true;
1072                 continue;
1073             }
1074
1075             return false;
1076         }
1077
1078         if (isPastBounds()) {
1079             if (!forward && lastDuplicateKey.get()) {
1080                 // We need to walk forward because now we're beyond the
1081                 // bounds defined by the cursor.
1082                 forward = true;
1083                 continue;
1084             }
1085
1086             return false;
1087         }
1088
1089         if (!haveEnteredRange())
1090             continue;
1091
1092         // The row may not load because there's a stale entry in the
1093         // index. This is not fatal.
1094         if (!loadCurrentRow())
1095             continue;
1096
1097         if (key) {
1098             if (forward) {
1099                 if (m_currentKey->isLessThan(key))
1100                     continue;
1101             } else {
1102                 if (key->isLessThan(m_currentKey.get()))
1103                     continue;
1104             }
1105         }
1106
1107         if (m_cursorOptions.unique) {
1108
1109             if (m_currentKey->isEqual(previousKey.get())) {
1110                 // We should never be able to walk forward all the way
1111                 // to the previous key.
1112                 ASSERT(!lastDuplicateKey.get());
1113                 continue;
1114             }
1115
1116             if (!forward) {
1117                 if (!lastDuplicateKey.get()) {
1118                     lastDuplicateKey = m_currentKey;
1119                     continue;
1120                 }
1121
1122                 // We need to walk forward because we hit the boundary
1123                 // between key ranges.
1124                 if (!lastDuplicateKey->isEqual(m_currentKey.get())) {
1125                     forward = true;
1126                     continue;
1127                 }
1128
1129                 continue;
1130             }
1131         }
1132         break;
1133     }
1134
1135     ASSERT(!lastDuplicateKey.get() || (forward && lastDuplicateKey->isEqual(m_currentKey.get())));
1136     return true;
1137 }
1138
1139 bool IDBBackingStore::Cursor::haveEnteredRange() const
1140 {
1141     if (m_cursorOptions.forward) {
1142         if (m_cursorOptions.lowOpen)
1143             return compareIndexKeys(m_iterator->key(), m_cursorOptions.lowKey) > 0;
1144
1145         return compareIndexKeys(m_iterator->key(), m_cursorOptions.lowKey) >= 0;
1146     }
1147     if (m_cursorOptions.highOpen)
1148         return compareIndexKeys(m_iterator->key(), m_cursorOptions.highKey) < 0;
1149
1150     return compareIndexKeys(m_iterator->key(), m_cursorOptions.highKey) <= 0;
1151 }
1152
1153 bool IDBBackingStore::Cursor::isPastBounds() const
1154 {
1155     if (m_cursorOptions.forward) {
1156         if (m_cursorOptions.highOpen)
1157             return compareIndexKeys(m_iterator->key(), m_cursorOptions.highKey) >= 0;
1158         return compareIndexKeys(m_iterator->key(), m_cursorOptions.highKey) > 0;
1159     }
1160
1161     if (m_cursorOptions.lowOpen)
1162         return compareIndexKeys(m_iterator->key(), m_cursorOptions.lowKey) <= 0;
1163     return compareIndexKeys(m_iterator->key(), m_cursorOptions.lowKey) < 0;
1164 }
1165
1166 class ObjectStoreKeyCursorImpl : public IDBBackingStore::Cursor {
1167 public:
1168     static PassRefPtr<ObjectStoreKeyCursorImpl> create(LevelDBTransaction* transaction, const IDBBackingStore::Cursor::CursorOptions& cursorOptions)
1169     {
1170         return adoptRef(new ObjectStoreKeyCursorImpl(transaction, cursorOptions));
1171     }
1172
1173     virtual PassRefPtr<IDBBackingStore::Cursor> clone()
1174     {
1175         return adoptRef(new ObjectStoreKeyCursorImpl(this));
1176     }
1177
1178     // IDBBackingStore::Cursor
1179     virtual String value() const { ASSERT_NOT_REACHED(); return String(); }
1180     virtual bool loadCurrentRow();
1181
1182 private:
1183     ObjectStoreKeyCursorImpl(LevelDBTransaction* transaction, const IDBBackingStore::Cursor::CursorOptions& cursorOptions)
1184         : IDBBackingStore::Cursor(transaction, cursorOptions)
1185     {
1186     }
1187
1188     ObjectStoreKeyCursorImpl(const ObjectStoreKeyCursorImpl* other)
1189         : IDBBackingStore::Cursor(other)
1190     {
1191     }
1192
1193 };
1194
1195 bool ObjectStoreKeyCursorImpl::loadCurrentRow()
1196 {
1197     const char* keyPosition = m_iterator->key().begin();
1198     const char* keyLimit = m_iterator->key().end();
1199
1200     ObjectStoreDataKey objectStoreDataKey;
1201     keyPosition = ObjectStoreDataKey::decode(keyPosition, keyLimit, &objectStoreDataKey);
1202     if (!keyPosition) {
1203         InternalError(IDBLevelDBBackingStoreReadError);
1204         return false;
1205     }
1206
1207     m_currentKey = objectStoreDataKey.userKey();
1208
1209     int64_t version;
1210     const char* valuePosition = decodeVarInt(m_iterator->value().begin(), m_iterator->value().end(), version);
1211     if (!valuePosition) {
1212         InternalError(IDBLevelDBBackingStoreReadError);
1213         return false;
1214     }
1215
1216     // FIXME: This re-encodes what was just decoded; try and optimize.
1217     m_recordIdentifier.reset(encodeIDBKey(*m_currentKey), version);
1218
1219     return true;
1220 }
1221
1222 class ObjectStoreCursorImpl : public IDBBackingStore::Cursor {
1223 public:
1224     static PassRefPtr<ObjectStoreCursorImpl> create(LevelDBTransaction* transaction, const IDBBackingStore::Cursor::CursorOptions& cursorOptions)
1225     {
1226         return adoptRef(new ObjectStoreCursorImpl(transaction, cursorOptions));
1227     }
1228
1229     virtual PassRefPtr<IDBBackingStore::Cursor> clone()
1230     {
1231         return adoptRef(new ObjectStoreCursorImpl(this));
1232     }
1233
1234     // IDBBackingStore::Cursor
1235     virtual String value() const { return m_currentValue; }
1236     virtual bool loadCurrentRow();
1237
1238 private:
1239     ObjectStoreCursorImpl(LevelDBTransaction* transaction, const IDBBackingStore::Cursor::CursorOptions& cursorOptions)
1240         : IDBBackingStore::Cursor(transaction, cursorOptions)
1241     {
1242     }
1243
1244     ObjectStoreCursorImpl(const ObjectStoreCursorImpl* other)
1245         : IDBBackingStore::Cursor(other)
1246         , m_currentValue(other->m_currentValue)
1247     {
1248     }
1249
1250     String m_currentValue;
1251 };
1252
1253 bool ObjectStoreCursorImpl::loadCurrentRow()
1254 {
1255     const char* keyPosition = m_iterator->key().begin();
1256     const char* keyLimit = m_iterator->key().end();
1257
1258     ObjectStoreDataKey objectStoreDataKey;
1259     keyPosition = ObjectStoreDataKey::decode(keyPosition, keyLimit, &objectStoreDataKey);
1260     if (!keyPosition) {
1261         InternalError(IDBLevelDBBackingStoreReadError);
1262         return false;
1263     }
1264
1265     m_currentKey = objectStoreDataKey.userKey();
1266
1267     int64_t version;
1268     const char* valuePosition = decodeVarInt(m_iterator->value().begin(), m_iterator->value().end(), version);
1269     if (!valuePosition) {
1270         InternalError(IDBLevelDBBackingStoreReadError);
1271         return false;
1272     }
1273
1274     // FIXME: This re-encodes what was just decoded; try and optimize.
1275     m_recordIdentifier.reset(encodeIDBKey(*m_currentKey), version);
1276
1277     m_currentValue = decodeString(valuePosition, m_iterator->value().end());
1278
1279     return true;
1280 }
1281
1282 class IndexKeyCursorImpl : public IDBBackingStore::Cursor {
1283 public:
1284     static PassRefPtr<IndexKeyCursorImpl> create(LevelDBTransaction* transaction, const IDBBackingStore::Cursor::CursorOptions& cursorOptions)
1285     {
1286         return adoptRef(new IndexKeyCursorImpl(transaction, cursorOptions));
1287     }
1288
1289     virtual PassRefPtr<IDBBackingStore::Cursor> clone()
1290     {
1291         return adoptRef(new IndexKeyCursorImpl(this));
1292     }
1293
1294     // IDBBackingStore::Cursor
1295     virtual String value() const { ASSERT_NOT_REACHED(); return String(); }
1296     virtual PassRefPtr<IDBKey> primaryKey() const { return m_primaryKey; }
1297     virtual const IDBBackingStore::RecordIdentifier& recordIdentifier() const { ASSERT_NOT_REACHED(); return m_recordIdentifier; }
1298     virtual bool loadCurrentRow();
1299
1300 private:
1301     IndexKeyCursorImpl(LevelDBTransaction* transaction, const IDBBackingStore::Cursor::CursorOptions& cursorOptions)
1302         : IDBBackingStore::Cursor(transaction, cursorOptions)
1303     {
1304     }
1305
1306     IndexKeyCursorImpl(const IndexKeyCursorImpl* other)
1307         : IDBBackingStore::Cursor(other)
1308         , m_primaryKey(other->m_primaryKey)
1309     {
1310     }
1311
1312     RefPtr<IDBKey> m_primaryKey;
1313 };
1314
1315 bool IndexKeyCursorImpl::loadCurrentRow()
1316 {
1317     const char* keyPosition = m_iterator->key().begin();
1318     const char* keyLimit = m_iterator->key().end();
1319
1320     IndexDataKey indexDataKey;
1321     keyPosition = IndexDataKey::decode(keyPosition, keyLimit, &indexDataKey);
1322
1323     m_currentKey = indexDataKey.userKey();
1324
1325     int64_t indexDataVersion;
1326     const char* valuePosition = decodeVarInt(m_iterator->value().begin(), m_iterator->value().end(), indexDataVersion);
1327     if (!valuePosition) {
1328         InternalError(IDBLevelDBBackingStoreReadError);
1329         return false;
1330     }
1331
1332     valuePosition = decodeIDBKey(valuePosition, m_iterator->value().end(), m_primaryKey);
1333     if (!valuePosition) {
1334         InternalError(IDBLevelDBBackingStoreReadError);
1335         return false;
1336     }
1337
1338     Vector<char> primaryLevelDBKey = ObjectStoreDataKey::encode(indexDataKey.databaseId(), indexDataKey.objectStoreId(), *m_primaryKey);
1339
1340     Vector<char> result;
1341     if (!m_transaction->get(primaryLevelDBKey, result)) {
1342         m_transaction->remove(m_iterator->key());
1343         return false;
1344     }
1345
1346     int64_t objectStoreDataVersion;
1347     const char* t = decodeVarInt(result.begin(), result.end(), objectStoreDataVersion);
1348     if (!t) {
1349         InternalError(IDBLevelDBBackingStoreReadError);
1350         return false;
1351     }
1352
1353     if (objectStoreDataVersion != indexDataVersion) {
1354         m_transaction->remove(m_iterator->key());
1355         return false;
1356     }
1357
1358     return true;
1359 }
1360
1361 class IndexCursorImpl : public IDBBackingStore::Cursor {
1362 public:
1363     static PassRefPtr<IndexCursorImpl> create(LevelDBTransaction* transaction, const IDBBackingStore::Cursor::CursorOptions& cursorOptions)
1364     {
1365         return adoptRef(new IndexCursorImpl(transaction, cursorOptions));
1366     }
1367
1368     virtual PassRefPtr<IDBBackingStore::Cursor> clone()
1369     {
1370         return adoptRef(new IndexCursorImpl(this));
1371     }
1372
1373     // IDBBackingStore::Cursor
1374     virtual String value() const { return m_value; }
1375     virtual PassRefPtr<IDBKey> primaryKey() const { return m_primaryKey; }
1376     virtual const IDBBackingStore::RecordIdentifier& recordIdentifier() const { ASSERT_NOT_REACHED(); return m_recordIdentifier; }
1377     bool loadCurrentRow();
1378
1379 private:
1380     IndexCursorImpl(LevelDBTransaction* transaction, const IDBBackingStore::Cursor::CursorOptions& cursorOptions)
1381         : IDBBackingStore::Cursor(transaction, cursorOptions)
1382     {
1383     }
1384
1385     IndexCursorImpl(const IndexCursorImpl* other)
1386         : IDBBackingStore::Cursor(other)
1387         , m_primaryKey(other->m_primaryKey)
1388         , m_value(other->m_value)
1389         , m_primaryLevelDBKey(other->m_primaryLevelDBKey)
1390     {
1391     }
1392
1393     RefPtr<IDBKey> m_primaryKey;
1394     String m_value;
1395     Vector<char> m_primaryLevelDBKey;
1396 };
1397
1398 bool IndexCursorImpl::loadCurrentRow()
1399 {
1400     const char* keyPosition = m_iterator->key().begin();
1401     const char* keyLimit = m_iterator->key().end();
1402
1403     IndexDataKey indexDataKey;
1404     keyPosition = IndexDataKey::decode(keyPosition, keyLimit, &indexDataKey);
1405
1406     m_currentKey = indexDataKey.userKey();
1407
1408     const char* valuePosition = m_iterator->value().begin();
1409     const char* valueLimit = m_iterator->value().end();
1410
1411     int64_t indexDataVersion;
1412     valuePosition = decodeVarInt(valuePosition, valueLimit, indexDataVersion);
1413     if (!valuePosition) {
1414         InternalError(IDBLevelDBBackingStoreReadError);
1415         return false;
1416     }
1417     valuePosition = decodeIDBKey(valuePosition, valueLimit, m_primaryKey);
1418     if (!valuePosition) {
1419         InternalError(IDBLevelDBBackingStoreReadError);
1420         return false;
1421     }
1422
1423     m_primaryLevelDBKey = ObjectStoreDataKey::encode(indexDataKey.databaseId(), indexDataKey.objectStoreId(), *m_primaryKey);
1424
1425     Vector<char> result;
1426     if (!m_transaction->get(m_primaryLevelDBKey, result)) {
1427         m_transaction->remove(m_iterator->key());
1428         return false;
1429     }
1430
1431     int64_t objectStoreDataVersion;
1432     const char* t = decodeVarInt(result.begin(), result.end(), objectStoreDataVersion);
1433     if (!t) {
1434         InternalError(IDBLevelDBBackingStoreReadError);
1435         return false;
1436     }
1437
1438     if (objectStoreDataVersion != indexDataVersion) {
1439         m_transaction->remove(m_iterator->key());
1440         return false;
1441     }
1442
1443     m_value = decodeString(t, result.end());
1444     return true;
1445 }
1446
1447 bool objectStoreCursorOptions(LevelDBTransaction* transaction, int64_t databaseId, int64_t objectStoreId, const IDBKeyRange* range, IDBCursor::Direction direction, IDBBackingStore::Cursor::CursorOptions& cursorOptions)
1448 {
1449     bool lowerBound = range && range->lower();
1450     bool upperBound = range && range->upper();
1451     cursorOptions.forward = (direction == IDBCursor::NEXT_NO_DUPLICATE || direction == IDBCursor::NEXT);
1452     cursorOptions.unique = (direction == IDBCursor::NEXT_NO_DUPLICATE || direction == IDBCursor::PREV_NO_DUPLICATE);
1453
1454     if (!lowerBound) {
1455         cursorOptions.lowKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, minIDBKey());
1456         cursorOptions.lowOpen = true; // Not included.
1457     } else {
1458         cursorOptions.lowKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, *range->lower());
1459         cursorOptions.lowOpen = range->lowerOpen();
1460     }
1461
1462     if (!upperBound) {
1463         cursorOptions.highKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, maxIDBKey());
1464
1465         if (cursorOptions.forward)
1466             cursorOptions.highOpen = true; // Not included.
1467         else {
1468             // We need a key that exists.
1469             if (!findGreatestKeyLessThanOrEqual(transaction, cursorOptions.highKey, cursorOptions.highKey))
1470                 return false;
1471             cursorOptions.highOpen = false;
1472         }
1473     } else {
1474         cursorOptions.highKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, *range->upper());
1475         cursorOptions.highOpen = range->upperOpen();
1476
1477         if (!cursorOptions.forward) {
1478             // For reverse cursors, we need a key that exists.
1479             Vector<char> foundHighKey;
1480             if (!findGreatestKeyLessThanOrEqual(transaction, cursorOptions.highKey, foundHighKey))
1481                 return false;
1482
1483             // If the target key should not be included, but we end up with a smaller key, we should include that.
1484             if (cursorOptions.highOpen && compareIndexKeys(foundHighKey, cursorOptions.highKey) < 0)
1485                 cursorOptions.highOpen = false;
1486
1487             cursorOptions.highKey = foundHighKey;
1488         }
1489     }
1490
1491     return true;
1492 }
1493
1494 bool indexCursorOptions(LevelDBTransaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange* range, IDBCursor::Direction direction, IDBBackingStore::Cursor::CursorOptions& cursorOptions)
1495 {
1496     ASSERT(transaction);
1497     bool lowerBound = range && range->lower();
1498     bool upperBound = range && range->upper();
1499     cursorOptions.forward = (direction == IDBCursor::NEXT_NO_DUPLICATE || direction == IDBCursor::NEXT);
1500     cursorOptions.unique = (direction == IDBCursor::NEXT_NO_DUPLICATE || direction == IDBCursor::PREV_NO_DUPLICATE);
1501
1502     if (!lowerBound) {
1503         cursorOptions.lowKey = IndexDataKey::encodeMinKey(databaseId, objectStoreId, indexId);
1504         cursorOptions.lowOpen = false; // Included.
1505     } else {
1506         cursorOptions.lowKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, *range->lower());
1507         cursorOptions.lowOpen = range->lowerOpen();
1508     }
1509
1510     if (!upperBound) {
1511         cursorOptions.highKey = IndexDataKey::encodeMaxKey(databaseId, objectStoreId, indexId);
1512         cursorOptions.highOpen = false; // Included.
1513
1514         if (!cursorOptions.forward) { // We need a key that exists.
1515             if (!findGreatestKeyLessThanOrEqual(transaction, cursorOptions.highKey, cursorOptions.highKey))
1516                 return false;
1517             cursorOptions.highOpen = false;
1518         }
1519     } else {
1520         cursorOptions.highKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, *range->upper());
1521         cursorOptions.highOpen = range->upperOpen();
1522
1523         Vector<char> foundHighKey;
1524         if (!findGreatestKeyLessThanOrEqual(transaction, cursorOptions.highKey, foundHighKey)) // Seek to the *last* key in the set of non-unique keys.
1525             return false;
1526
1527         // If the target key should not be included, but we end up with a smaller key, we should include that.
1528         if (cursorOptions.highOpen && compareIndexKeys(foundHighKey, cursorOptions.highKey) < 0)
1529             cursorOptions.highOpen = false;
1530
1531         cursorOptions.highKey = foundHighKey;
1532     }
1533
1534     return true;
1535 }
1536
1537 PassRefPtr<IDBBackingStore::Cursor> IDBBackingStore::openObjectStoreCursor(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId, const IDBKeyRange* range, IDBCursor::Direction direction)
1538 {
1539     IDB_TRACE("IDBBackingStore::openObjectStoreCursor");
1540     LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction);
1541     IDBBackingStore::Cursor::CursorOptions cursorOptions;
1542     if (!objectStoreCursorOptions(levelDBTransaction, databaseId, objectStoreId, range, direction, cursorOptions))
1543         return 0;
1544     RefPtr<ObjectStoreCursorImpl> cursor = ObjectStoreCursorImpl::create(levelDBTransaction, cursorOptions);
1545     if (!cursor->firstSeek())
1546         return 0;
1547
1548     return cursor.release();
1549 }
1550
1551 PassRefPtr<IDBBackingStore::Cursor> IDBBackingStore::openObjectStoreKeyCursor(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId, const IDBKeyRange* range, IDBCursor::Direction direction)
1552 {
1553     IDB_TRACE("IDBBackingStore::openObjectStoreKeyCursor");
1554     LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction);
1555     IDBBackingStore::Cursor::CursorOptions cursorOptions;
1556     if (!objectStoreCursorOptions(levelDBTransaction, databaseId, objectStoreId, range, direction, cursorOptions))
1557         return 0;
1558     RefPtr<ObjectStoreKeyCursorImpl> cursor = ObjectStoreKeyCursorImpl::create(levelDBTransaction, cursorOptions);
1559     if (!cursor->firstSeek())
1560         return 0;
1561
1562     return cursor.release();
1563 }
1564
1565 PassRefPtr<IDBBackingStore::Cursor> IDBBackingStore::openIndexKeyCursor(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange* range, IDBCursor::Direction direction)
1566 {
1567     IDB_TRACE("IDBBackingStore::openIndexKeyCursor");
1568     LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction);
1569     IDBBackingStore::Cursor::CursorOptions cursorOptions;
1570     if (!indexCursorOptions(levelDBTransaction, databaseId, objectStoreId, indexId, range, direction, cursorOptions))
1571         return 0;
1572     RefPtr<IndexKeyCursorImpl> cursor = IndexKeyCursorImpl::create(levelDBTransaction, cursorOptions);
1573     if (!cursor->firstSeek())
1574         return 0;
1575
1576     return cursor.release();
1577 }
1578
1579 PassRefPtr<IDBBackingStore::Cursor> IDBBackingStore::openIndexCursor(IDBBackingStore::Transaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange* range, IDBCursor::Direction direction)
1580 {
1581     IDB_TRACE("IDBBackingStore::openIndexCursor");
1582     LevelDBTransaction* levelDBTransaction = IDBBackingStore::Transaction::levelDBTransactionFrom(transaction);
1583     IDBBackingStore::Cursor::CursorOptions cursorOptions;
1584     if (!indexCursorOptions(levelDBTransaction, databaseId, objectStoreId, indexId, range, direction, cursorOptions))
1585         return 0;
1586     RefPtr<IndexCursorImpl> cursor = IndexCursorImpl::create(levelDBTransaction, cursorOptions);
1587     if (!cursor->firstSeek())
1588         return 0;
1589
1590     return cursor.release();
1591 }
1592
1593 IDBBackingStore::Transaction::Transaction(IDBBackingStore* backingStore)
1594     : m_backingStore(backingStore)
1595 {
1596 }
1597
1598 void IDBBackingStore::Transaction::begin()
1599 {
1600     IDB_TRACE("IDBBackingStore::Transaction::begin");
1601     ASSERT(!m_transaction);
1602     m_transaction = LevelDBTransaction::create(m_backingStore->m_db.get());
1603 }
1604
1605 bool IDBBackingStore::Transaction::commit()
1606 {
1607     IDB_TRACE("IDBBackingStore::Transaction::commit");
1608     ASSERT(m_transaction);
1609     bool result = m_transaction->commit();
1610     m_transaction.clear();
1611     return result;
1612 }
1613
1614 void IDBBackingStore::Transaction::rollback()
1615 {
1616     IDB_TRACE("IDBBackingStore::Transaction::rollback");
1617     ASSERT(m_transaction);
1618     m_transaction->rollback();
1619     m_transaction.clear();
1620 }
1621
1622 } // namespace WebCore
1623
1624 #endif // ENABLE(INDEXED_DATABASE)