12daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch/*
22daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * Copyright (C) 2011 Google Inc. All rights reserved.
32daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch *
42daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * Redistribution and use in source and binary forms, with or without
52daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * modification, are permitted provided that the following conditions
62daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * are met:
72daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch *
82daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * 1.  Redistributions of source code must retain the above copyright
92daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch *     notice, this list of conditions and the following disclaimer.
102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * 2.  Redistributions in binary form must reproduce the above copyright
112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch *     notice, this list of conditions and the following disclaimer in the
122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch *     documentation and/or other materials provided with the distribution.
132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch *
142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch */
252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "config.h"
272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "IDBLevelDBBackingStore.h"
282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if ENABLE(INDEXED_DATABASE)
302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if ENABLE(LEVELDB)
312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "Assertions.h"
332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "FileSystem.h"
342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "IDBFactoryBackendImpl.h"
352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "IDBKeyRange.h"
362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "LevelDBComparator.h"
372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "LevelDBDatabase.h"
382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "LevelDBIterator.h"
392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "LevelDBSlice.h"
402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "SecurityOrigin.h"
412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#ifndef INT64_MAX
432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// FIXME: We shouldn't need to rely on these macros.
442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#define INT64_MAX 0x7fffffffffffffffLL
452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#endif
462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#ifndef INT32_MAX
472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#define INT32_MAX 0x7fffffffL
482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#endif
492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// LevelDB stores key/value pairs. Keys and values are strings of bytes, normally of type Vector<char>.
512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// The keys in the backing store are variable-length tuples with different types
532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// of fields. Each key in the backing store starts with a ternary prefix: (database id, object store id, index id). For each, 0 is reserved for meta-data.
542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// The prefix makes sure that data for a specific database, object store, and index are grouped together. The locality is important for performance: common
552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// operations should only need a minimal number of seek operations. For example, all the meta-data for a database is grouped together so that reading that
562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// meta-data only requires one seek.
572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// Each key type has a class (in square brackets below) which knows how to encode, decode, and compare that key type.
592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// Global meta-data have keys with prefix (0,0,0), followed by a type byte:
612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     <0, 0, 0, 0>                                           => IndexedDB/LevelDB schema version (0 for now) [SchemaVersionKey]
632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     <0, 0, 0, 1>                                           => The maximum database id ever allocated [MaxDatabaseIdKey]
642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     <0, 0, 0, 100, database id>                            => Existence implies the database id is in the free list [DatabaseFreeListKey]
652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     <0, 0, 0, 201, utf16 origin name, utf16 database name> => Database id [DatabaseNameKey]
662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// Database meta-data:
692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     Again, the prefix is followed by a type byte.
712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     <database id, 0, 0, 0> => utf16 origin name [DatabaseMetaDataKey]
732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     <database id, 0, 0, 1> => utf16 database name [DatabaseMetaDataKey]
742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     <database id, 0, 0, 2> => utf16 user version data [DatabaseMetaDataKey]
752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     <database id, 0, 0, 3> => maximum object store id ever allocated [DatabaseMetaDataKey]
762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// Object store meta-data:
792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     The prefix is followed by a type byte, then a variable-length integer, and then another variable-length integer (FIXME: this should be a byte).
812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     <database id, 0, 0, 50, object store id, 0> => utf16 object store name [ObjectStoreMetaDataKey]
832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     <database id, 0, 0, 50, object store id, 1> => utf16 key path [ObjectStoreMetaDataKey]
842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     <database id, 0, 0, 50, object store id, 2> => has auto increment [ObjectStoreMetaDataKey]
852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     <database id, 0, 0, 50, object store id, 3> => is evictable [ObjectStoreMetaDataKey]
862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     <database id, 0, 0, 50, object store id, 4> => last "version" number [ObjectStoreMetaDataKey]
872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     <database id, 0, 0, 50, object store id, 5> => maximum index id ever allocated [ObjectStoreMetaDataKey]
882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// Index meta-data:
912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     The prefix is followed by a type byte, then two variable-length integers, and then another type byte.
932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     <database id, 0, 0, 100, object store id, index id, 0> => utf16 index name [IndexMetaDataKey]
952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     <database id, 0, 0, 100, object store id, index id, 1> => are index keys unique [IndexMetaDataKey]
962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     <database id, 0, 0, 100, object store id, index id, 2> => utf16 key path [IndexMetaDataKey]
972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// Other object store and index meta-data:
1002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
1012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     The prefix is followed by a type byte. The object store and index id are variable length integers, the utf16 strings are variable length strings.
1022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
1032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     <database id, 0, 0, 150, object store id>                   => existence implies the object store id is in the free list [ObjectStoreFreeListKey]
1042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     <database id, 0, 0, 151, object store id, index id>         => existence implies the index id is in the free list [IndexFreeListKey]
1052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     <database id, 0, 0, 200, utf16 object store name>           => object store id [ObjectStoreNamesKey]
1062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     <database id, 0, 0, 201, object store id, utf16 index name> => index id [IndexNamesKey]
1072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
1082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
1092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// Object store data:
1102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
1112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     The prefix is followed by a type byte. The user key is an encoded IDBKey.
1122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
1132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     <database id, object store id, 1, user key> => "version", serialized script value [ObjectStoreDataKey]
1142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
1152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
1162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// "Exists" entry:
1172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
1182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     The prefix is followed by a type byte. The user key is an encoded IDBKey.
1192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
1202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     <database id, object store id, 2, user key> => "version" [ExistsEntryKey]
1212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
1222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
1232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// Index data:
1242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
1252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     The prefix is followed by a type byte. The user key is an encoded IDBKey. The sequence number is a variable length integer.
1262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
1272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     <database id, object store id, index id, user key, sequence number> => "version", user key [IndexDataKey]
1282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//
1292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     (The sequence number is used to allow two entries with the same user key
1302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     in non-unique indexes. The "version" field is used to weed out stale
1312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     index data. Whenever new object store data is inserted, it gets a new
1322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     "version" number, and new index data is written with this number. When
1332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     the index is used for look-ups, entries are validated against the
1342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     "exists" entries, and records with old "version" numbers are deleted
1352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     when they are encountered in getPrimaryKeyViaIndex,
1362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch//     IndexCursorImpl::loadCurrentRow, and IndexKeyCursorImpl::loadCurrentRow).
1372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic const unsigned char kIDBKeyNullTypeByte = 0;
1392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic const unsigned char kIDBKeyStringTypeByte = 1;
1402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic const unsigned char kIDBKeyDateTypeByte = 2;
1412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic const unsigned char kIDBKeyNumberTypeByte = 3;
1422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic const unsigned char kIDBKeyMinKeyTypeByte = 4;
1432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic const unsigned char kMinimumIndexId = 30;
1452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic const unsigned char kObjectStoreDataIndexId = 1;
1462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic const unsigned char kExistsEntryIndexId = 2;
1472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic const unsigned char kSchemaVersionTypeByte = 0;
1492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic const unsigned char kMaxDatabaseIdTypeByte = 1;
1502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic const unsigned char kDatabaseFreeListTypeByte = 100;
1512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic const unsigned char kDatabaseNameTypeByte = 201;
1522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic const unsigned char kObjectStoreMetaDataTypeByte = 50;
1542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic const unsigned char kIndexMetaDataTypeByte = 100;
1552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic const unsigned char kObjectStoreFreeListTypeByte = 150;
1562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic const unsigned char kIndexFreeListTypeByte = 151;
1572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic const unsigned char kObjectStoreNamesTypeByte = 200;
1582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic const unsigned char kIndexNamesKeyTypeByte = 201;
1592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochnamespace WebCore {
1612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic Vector<char> encodeByte(unsigned char c)
1632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
1642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> v;
1652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    v.append(c);
1662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return v;
1672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
1682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic Vector<char> maxIDBKey()
1702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
1712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return encodeByte(kIDBKeyNullTypeByte);
1722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
1732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic Vector<char> minIDBKey()
1752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
1762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return encodeByte(kIDBKeyMinKeyTypeByte);
1772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
1782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic Vector<char> encodeInt(int64_t n)
1802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
1812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(n >= 0);
1822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> ret; // FIXME: Size this at creation.
1832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    do {
1852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned char c = n;
1862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(c);
1872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        n >>= 8;
1882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    } while (n);
1892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return ret;
1912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
1922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic int64_t decodeInt(const char* begin, const char* end)
1942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
1952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(begin <= end);
1962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t ret = 0;
1972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    while (begin < end) {
1992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned char c = *begin++;
2002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret = (ret << 8) | c;
2012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
2022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return ret;
2042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
2052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic Vector<char> encodeVarInt(int64_t n)
2072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
2082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> ret; // FIXME: Size this at creation.
2092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    do {
2112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned char c = n & 0x7f;
2122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        n >>= 7;
2132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (n)
2142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            c |= 128;
2152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(c);
2162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    } while (n);
2172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return ret;
2192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
2202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic const char* decodeVarInt(const char *p, const char* limit, int64_t& foundInt)
2222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
2232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(limit >= p);
2242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    foundInt = 0;
2252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    do {
2272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (p >= limit)
2282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
2292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        foundInt = (foundInt << 7) | (*p & 0x7f);
2312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    } while (*p++ & 128);
2322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return p;
2332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
2342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic Vector<char> encodeString(const String& s)
2362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
2372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> ret; // FIXME: Size this at creation.
2382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for (unsigned i = 0; i < s.length(); ++i) {
2402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        UChar u = s[i];
2412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned char hi = u >> 8;
2422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned char lo = u;
2432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(hi);
2442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(lo);
2452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
2462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return ret;
2482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
2492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic String decodeString(const char* p, const char* end)
2512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
2522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(end >= p);
2532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(!((end - p) % 2));
2542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    size_t len = (end - p) / 2;
2562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<UChar> vector(len);
2572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for (size_t i = 0; i < len; ++i) {
2592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned char hi = *p++;
2602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned char lo = *p++;
2612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        vector[i] = (hi << 8) | lo;
2632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
2642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return String::adopt(vector);
2662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
2672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic Vector<char> encodeStringWithLength(const String& s)
2692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
2702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> ret = encodeVarInt(s.length());
2712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ret.append(encodeString(s));
2722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return ret;
2732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
2742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic const char* decodeStringWithLength(const char* p, const char* limit, String& foundString)
2762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
2772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(limit >= p);
2782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t len;
2792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    p = decodeVarInt(p, limit, len);
2802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!p)
2812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return 0;
2822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (p + len * 2 > limit)
2832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return 0;
2842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    foundString = decodeString(p, p + len * 2);
2862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    p += len * 2;
2872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return p;
2882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
2892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic Vector<char> encodeDouble(double x)
2912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
2922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // FIXME: It would be nice if we could be byte order independent.
2932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const char* p = reinterpret_cast<char*>(&x);
2942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> v;
2952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    v.append(p, sizeof(x));
2962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(v.size() == sizeof(x));
2972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return v;
2982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
2992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic const char* decodeDouble(const char* p, const char* limit, double* d)
3012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
3022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (p + sizeof(*d) > limit)
3032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return 0;
3042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    char* x = reinterpret_cast<char*>(d);
3062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for (size_t i = 0; i < sizeof(*d); ++i)
3072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        *x++ = *p++;
3082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return p;
3092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
3102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic Vector<char> encodeIDBKey(const IDBKey& key)
3122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
3132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> ret;
3142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    switch (key.type()) {
3162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case IDBKey::NullType:
3172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return encodeByte(kIDBKeyNullTypeByte);
3182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case IDBKey::StringType:
3192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret = encodeByte(kIDBKeyStringTypeByte);
3202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeStringWithLength(key.string()));
3212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return ret;
3222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case IDBKey::DateType:
3232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret = encodeByte(kIDBKeyDateTypeByte);
3242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeDouble(key.date()));
3252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(ret.size() == 9);
3262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return ret;
3272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case IDBKey::NumberType:
3282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret = encodeByte(kIDBKeyNumberTypeByte);
3292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeDouble(key.number()));
3302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(ret.size() == 9);
3312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return ret;
3322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
3332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT_NOT_REACHED();
3352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return Vector<char>();
3362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
3372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic const char* decodeIDBKey(const char* p, const char* limit, RefPtr<IDBKey>& foundKey)
3392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
3402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(limit >= p);
3412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (p >= limit)
3422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return 0;
3432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    unsigned char type = *p++;
3452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    String s;
3462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    double d;
3472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    switch (type) {
3492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case kIDBKeyNullTypeByte:
3502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // Null.
3512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        foundKey = IDBKey::createNull();
3522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return p;
3532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case kIDBKeyStringTypeByte:
3542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // String.
3552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        p = decodeStringWithLength(p, limit, s);
3562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!p)
3572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
3582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        foundKey = IDBKey::createString(s);
3592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return p;
3602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case kIDBKeyDateTypeByte:
3612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // Date.
3622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        p = decodeDouble(p, limit, &d);
3632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!p)
3642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
3652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        foundKey = IDBKey::createDate(d);
3662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return p;
3672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case kIDBKeyNumberTypeByte:
3682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // Number.
3692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        p = decodeDouble(p, limit, &d);
3702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!p)
3712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
3722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        foundKey = IDBKey::createNumber(d);
3732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return p;
3742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
3752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT_NOT_REACHED();
3772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return 0;
3782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
3792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic const char* extractEncodedIDBKey(const char* start, const char* limit, Vector<char>* result)
3812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
3822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const char* p = start;
3832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (p >= limit)
3842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return 0;
3852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    unsigned char type = *p++;
3872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t stringLen;
3892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    switch (type) {
3912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case kIDBKeyNullTypeByte:
3922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case kIDBKeyMinKeyTypeByte:
3932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        *result = encodeByte(type);
3942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return p;
3952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case kIDBKeyStringTypeByte:
3962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // String.
3972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        p = decodeVarInt(p, limit, stringLen);
3982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!p)
3992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
4002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (p + stringLen * 2 > limit)
4012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
4022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        result->clear();
4032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        result->append(start, p - start + stringLen * 2);
4042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return p + stringLen * 2;
4052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case kIDBKeyDateTypeByte:
4062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case kIDBKeyNumberTypeByte:
4072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // Date or number.
4082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (p + sizeof(double) > limit)
4092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
4102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        result->clear();
4112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        result->append(start, 1 + sizeof(double));
4122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return p + sizeof(double);
4132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
4142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT_NOT_REACHED();
4152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return 0;
4162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
4172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
4182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic int compareEncodedIDBKeys(const Vector<char>& keyA, const Vector<char>& keyB)
4192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
4202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(keyA.size() >= 1);
4212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(keyB.size() >= 1);
4222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
4232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const char* p = keyA.data();
4242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const char* limitA = p + keyA.size();
4252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const char* q = keyB.data();
4262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const char* limitB = q + keyB.size();
4272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
4282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    unsigned char typeA = *p++;
4292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    unsigned char typeB = *q++;
4302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
4312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    String s, t;
4322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    double d, e;
4332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
4342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (int x = typeB - typeA) // FIXME: Note the subtleness!
4352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return x;
4362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
4372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    switch (typeA) {
4382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case kIDBKeyNullTypeByte:
4392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case kIDBKeyMinKeyTypeByte:
4402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // Null type or max type; no payload to compare.
4412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return 0;
4422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case kIDBKeyStringTypeByte:
4432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // String type.
4442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        p = decodeStringWithLength(p, limitA, s); // FIXME: Compare without actually decoding the String!
4452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(p);
4462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        q = decodeStringWithLength(q, limitB, t);
4472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(q);
4482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return codePointCompare(s, t);
4492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case kIDBKeyDateTypeByte:
4502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    case kIDBKeyNumberTypeByte:
4512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // Date or number.
4522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        p = decodeDouble(p, limitA, &d);
4532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(p);
4542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        q = decodeDouble(q, limitB, &e);
4552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(q);
4562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (d < e)
4572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return -1;
4582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (d > e)
4592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 1;
4602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return 0;
4612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
4622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
4632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT_NOT_REACHED();
4642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return 0;
4652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
4662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
4672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic bool getInt(LevelDBDatabase* db, const Vector<char>& key, int64_t& foundInt)
4682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
4692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> result;
4702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!db->get(key, result))
4712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
4722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
4732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    foundInt = decodeInt(result.begin(), result.end());
4742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return true;
4752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
4762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
4772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic bool putInt(LevelDBDatabase* db, const Vector<char>& key, int64_t value)
4782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
4792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return db->put(key, encodeInt(value));
4802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
4812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
4822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic bool getString(LevelDBDatabase* db, const Vector<char>& key, String& foundString)
4832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
4842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> result;
4852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!db->get(key, result))
4862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
4872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
4882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    foundString = decodeString(result.begin(), result.end());
4892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return true;
4902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
4912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
4922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic bool putString(LevelDBDatabase* db, const Vector<char> key, const String& value)
4932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
4942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!db->put(key, encodeString(value)))
4952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
4962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return true;
4972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
4982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
4992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochnamespace {
5002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochclass KeyPrefix {
5012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochpublic:
5022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    KeyPrefix()
5032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        : m_databaseId(kInvalidType)
5042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_objectStoreId(kInvalidType)
5052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_indexId(kInvalidType)
5062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
5072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
5082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    KeyPrefix(int64_t databaseId, int64_t objectStoreId, int64_t indexId)
5102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        : m_databaseId(databaseId)
5112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_objectStoreId(objectStoreId)
5122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_indexId(indexId)
5132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
5142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
5152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static const char* decode(const char* start, const char* limit, KeyPrefix* result)
5172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
5182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (start == limit)
5192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
5202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned char firstByte = *start++;
5222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        int databaseIdBytes = ((firstByte >> 5) & 0x7) + 1;
5242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        int objectStoreIdBytes = ((firstByte >> 2) & 0x7) + 1;
5252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        int indexIdBytes = (firstByte & 0x3) + 1;
5262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (start + databaseIdBytes + objectStoreIdBytes + indexIdBytes > limit)
5282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
5292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        result->m_databaseId = decodeInt(start, start + databaseIdBytes);
5312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        start += databaseIdBytes;
5322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        result->m_objectStoreId = decodeInt(start, start + objectStoreIdBytes);
5332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        start += objectStoreIdBytes;
5342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        result->m_indexId = decodeInt(start, start + indexIdBytes);
5352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        start += indexIdBytes;
5362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return start;
5382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
5392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> encode() const
5412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
5422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_databaseId != kInvalidId);
5432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_objectStoreId != kInvalidId);
5442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_indexId != kInvalidId);
5452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        Vector<char> databaseIdString = encodeInt(m_databaseId);
5472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        Vector<char> objectStoreIdString = encodeInt(m_objectStoreId);
5482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        Vector<char> indexIdString = encodeInt(m_indexId);
5492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(databaseIdString.size() <= 8);
5512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(objectStoreIdString.size() <= 8);
5522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(indexIdString.size() <= 4);
5532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned char firstByte = (databaseIdString.size() - 1) << 5 | (objectStoreIdString.size() - 1) << 2 | (indexIdString.size() - 1);
5562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        Vector<char> ret;
5572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(firstByte);
5582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(databaseIdString);
5592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(objectStoreIdString);
5602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(indexIdString);
5612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return ret;
5632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
5642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int compare(const KeyPrefix& other) const
5662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
5672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_databaseId != kInvalidId);
5682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_objectStoreId != kInvalidId);
5692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_indexId != kInvalidId);
5702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (m_databaseId != other.m_databaseId)
5722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return m_databaseId - other.m_databaseId;
5732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (m_objectStoreId != other.m_objectStoreId)
5742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return m_objectStoreId - other.m_objectStoreId;
5752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (m_indexId != other.m_indexId)
5762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return m_indexId - other.m_indexId;
5772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return 0;
5782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
5792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    enum Type {
5812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        kGlobalMetaData,
5822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        kDatabaseMetaData,
5832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        kObjectStoreData,
5842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        kExistsEntry,
5852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        kIndexData,
5862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        kInvalidType
5872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    };
5882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Type type() const
5902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
5912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_databaseId != kInvalidId);
5922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_objectStoreId != kInvalidId);
5932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_indexId != kInvalidId);
5942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!m_databaseId)
5962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return kGlobalMetaData;
5972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!m_objectStoreId)
5982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return kDatabaseMetaData;
5992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (m_indexId == kObjectStoreDataIndexId)
6002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return kObjectStoreData;
6012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (m_indexId == kExistsEntryIndexId)
6022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return kExistsEntry;
6032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (m_indexId >= kMinimumIndexId)
6042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return kIndexData;
6052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
6062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT_NOT_REACHED();
6072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return kInvalidType;
6082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
6092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
6102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t m_databaseId;
6112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t m_objectStoreId;
6122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t m_indexId;
6132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
6142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static const int64_t kInvalidId = -1;
6152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch};
6162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
6172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochclass SchemaVersionKey {
6182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochpublic:
6192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static Vector<char> encode()
6202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
6212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        KeyPrefix prefix(0, 0, 0);
6222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        Vector<char> ret = prefix.encode();
6232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeByte(kSchemaVersionTypeByte));
6242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return ret;
6252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
6262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch};
6272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
6282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochclass MaxDatabaseIdKey {
6292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochpublic:
6302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static Vector<char> encode()
6312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
6322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        KeyPrefix prefix(0, 0, 0);
6332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        Vector<char> ret = prefix.encode();
6342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeByte(kMaxDatabaseIdTypeByte));
6352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return ret;
6362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
6372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch};
6382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
6392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochclass DatabaseFreeListKey {
6402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochpublic:
6412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    DatabaseFreeListKey()
6422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        : m_databaseId(-1)
6432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
6442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
6452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
6462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static const char* decode(const char* start, const char* limit, DatabaseFreeListKey* result)
6472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
6482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        KeyPrefix prefix;
6492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const char *p = KeyPrefix::decode(start, limit, &prefix);
6502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!p)
6512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
6522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(!prefix.m_databaseId);
6532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(!prefix.m_objectStoreId);
6542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(!prefix.m_indexId);
6552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (p == limit)
6562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
6572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned char typeByte = *p++;
6582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT_UNUSED(typeByte, typeByte == kDatabaseFreeListTypeByte);
6592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (p == limit)
6602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
6612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return decodeVarInt(p, limit, result->m_databaseId);
6622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
6632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
6642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static Vector<char> encode(int64_t databaseId)
6652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
6662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        KeyPrefix prefix(0, 0, 0);
6672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        Vector<char> ret = prefix.encode();
6682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeByte(kDatabaseFreeListTypeByte));
6692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeVarInt(databaseId));
6702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return ret;
6712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
6722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
6732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t databaseId() const
6742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
6752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_databaseId >= 0);
6762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return m_databaseId;
6772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
6782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
6792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int compare(const DatabaseFreeListKey& other) const
6802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
6812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_databaseId >= 0);
6822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return m_databaseId - other.m_databaseId;
6832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
6842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
6852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochprivate:
6862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t m_databaseId;
6872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch};
6882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
6892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochclass DatabaseNameKey {
6902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochpublic:
6912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static const char* decode(const char* start, const char* limit, DatabaseNameKey* result)
6922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
6932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        KeyPrefix prefix;
6942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const char* p = KeyPrefix::decode(start, limit, &prefix);
6952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!p)
6962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return p;
6972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(!prefix.m_databaseId);
6982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(!prefix.m_objectStoreId);
6992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(!prefix.m_indexId);
7002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (p == limit)
7012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
7022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned char typeByte = *p++;
7032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT_UNUSED(typeByte, typeByte == kDatabaseNameTypeByte);
7042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (p == limit)
7052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
7062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        p = decodeStringWithLength(p, limit, result->m_origin);
7072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!p)
7082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
7092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return decodeStringWithLength(p, limit, result->m_databaseName);
7102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
7112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static Vector<char> encode(const String& origin, const String& databaseName)
7132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
7142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        KeyPrefix prefix(0, 0, 0);
7152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        Vector<char> ret = prefix.encode();
7162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeByte(kDatabaseNameTypeByte));
7172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeStringWithLength(origin));
7182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeStringWithLength(databaseName));
7192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return ret;
7202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
7212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    String origin() const { return m_origin; }
7232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    String databaseName() const { return m_databaseName; }
7242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int compare(const DatabaseNameKey& other)
7262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
7272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (int x = codePointCompare(m_origin, other.m_origin))
7282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return x;
7292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return codePointCompare(m_databaseName, other.m_databaseName);
7302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
7312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochprivate:
7332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    String m_origin; // FIXME: Store encoded strings, or just pointers.
7342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    String m_databaseName;
7352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch};
7362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochclass DatabaseMetaDataKey {
7382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochpublic:
7392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    enum MetaDataType {
7402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        kOriginName = 0,
7412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        kDatabaseName = 1,
7422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        kUserVersion = 2,
7432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        kMaxObjectStoreId = 3
7442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    };
7452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static Vector<char> encode(int64_t databaseId, MetaDataType metaDataType)
7472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
7482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        KeyPrefix prefix(databaseId, 0, 0);
7492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        Vector<char> ret = prefix.encode();
7502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeByte(metaDataType));
7512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return ret;
7522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
7532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch};
7542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochclass ObjectStoreMetaDataKey {
7562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochpublic:
7572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ObjectStoreMetaDataKey()
7582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        : m_objectStoreId(-1)
7592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_metaDataType(-1)
7602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
7612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
7622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static const char* decode(const char* start, const char* limit, ObjectStoreMetaDataKey* result)
7642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
7652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        KeyPrefix prefix;
7662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const char* p = KeyPrefix::decode(start, limit, &prefix);
7672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!p)
7682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
7692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(prefix.m_databaseId);
7702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(!prefix.m_objectStoreId);
7712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(!prefix.m_indexId);
7722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (p == limit)
7732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
7742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned char typeByte = *p++;
7752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT_UNUSED(typeByte, typeByte == kObjectStoreMetaDataTypeByte);
7762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (p == limit)
7772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
7782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        p = decodeVarInt(p, limit, result->m_objectStoreId);
7792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!p)
7802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
7812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(result->m_objectStoreId);
7822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (p == limit)
7832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
7842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return decodeVarInt(p, limit, result->m_metaDataType);
7852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
7862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static Vector<char> encode(int64_t databaseId, int64_t objectStoreId, int64_t metaDataType)
7882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
7892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        KeyPrefix prefix(databaseId, 0, 0);
7902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        Vector<char> ret = prefix.encode();
7912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeByte(kObjectStoreMetaDataTypeByte));
7922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeVarInt(objectStoreId));
7932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeVarInt(metaDataType));
7942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return ret;
7952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
7962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t objectStoreId() const
7982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
7992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_objectStoreId >= 0);
8002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return m_objectStoreId;
8012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
8022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t metaDataType() const
8032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
8042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_metaDataType >= 0);
8052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return m_metaDataType;
8062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
8072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int compare(const ObjectStoreMetaDataKey& other)
8092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
8102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_objectStoreId >= 0);
8112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_metaDataType >= 0);
8122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (int x = m_objectStoreId - other.m_objectStoreId)
8132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return x; // FIXME: Is this cast safe? I.e., will it preserve the sign?
8142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return m_metaDataType - other.m_metaDataType;
8152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
8162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochprivate:
8182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t m_objectStoreId;
8192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t m_metaDataType; // FIXME: Make this a byte.
8202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch};
8212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochclass IndexMetaDataKey {
8232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochpublic:
8242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    IndexMetaDataKey()
8252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        : m_objectStoreId(-1)
8262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_indexId(-1)
8272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_metaDataType(0)
8282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
8292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
8302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static const char* decode(const char* start, const char* limit, IndexMetaDataKey* result)
8322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
8332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        KeyPrefix prefix;
8342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const char* p = KeyPrefix::decode(start, limit, &prefix);
8352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!p)
8362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
8372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(prefix.m_databaseId);
8382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(!prefix.m_objectStoreId);
8392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(!prefix.m_indexId);
8402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (p == limit)
8412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
8422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned char typeByte = *p++;
8432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT_UNUSED(typeByte, typeByte == kIndexMetaDataTypeByte);
8442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (p == limit)
8452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
8462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        p = decodeVarInt(p, limit, result->m_objectStoreId);
8472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!p)
8482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
8492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        p = decodeVarInt(p, limit, result->m_indexId);
8502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!p)
8512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
8522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (p == limit)
8532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
8542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        result->m_metaDataType = *p++;
8552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return p;
8562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
8572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static Vector<char> encode(int64_t databaseId, int64_t objectStoreId, int64_t indexId, unsigned char metaDataType)
8592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
8602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        KeyPrefix prefix(databaseId, 0, 0);
8612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        Vector<char> ret = prefix.encode();
8622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeByte(kIndexMetaDataTypeByte));
8632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeVarInt(objectStoreId));
8642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeVarInt(indexId));
8652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeByte(metaDataType));
8662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return ret;
8672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
8682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int compare(const IndexMetaDataKey& other)
8702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
8712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_objectStoreId >= 0);
8722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_indexId >= 0);
8732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (int x = m_objectStoreId - other.m_objectStoreId)
8752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return x;
8762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (int x = m_indexId - other.m_indexId)
8772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return x;
8782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return m_metaDataType - other.m_metaDataType;
8792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
8802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t indexId() const
8822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
8832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_indexId >= 0);
8842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return m_indexId;
8852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
8862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    unsigned char metaDataType() const { return m_metaDataType; }
8882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochprivate:
8902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t m_objectStoreId;
8912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t m_indexId;
8922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    unsigned char m_metaDataType;
8932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch};
8942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochclass ObjectStoreFreeListKey {
8962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochpublic:
8972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ObjectStoreFreeListKey()
8982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        : m_objectStoreId(-1)
8992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
9002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
9012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static const char* decode(const char* start, const char* limit, ObjectStoreFreeListKey* result)
9032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
9042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        KeyPrefix prefix;
9052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const char *p = KeyPrefix::decode(start, limit, &prefix);
9062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!p)
9072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
9082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(prefix.m_databaseId);
9092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(!prefix.m_objectStoreId);
9102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(!prefix.m_indexId);
9112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (p == limit)
9122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
9132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned char typeByte = *p++;
9142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT_UNUSED(typeByte, typeByte == kObjectStoreFreeListTypeByte);
9152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (p == limit)
9162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
9172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return decodeVarInt(p, limit, result->m_objectStoreId);
9182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
9192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static Vector<char> encode(int64_t databaseId, int64_t objectStoreId)
9212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
9222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        KeyPrefix prefix(databaseId, 0, 0);
9232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        Vector<char> ret = prefix.encode();
9242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeByte(kObjectStoreFreeListTypeByte));
9252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeVarInt(objectStoreId));
9262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return ret;
9272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
9282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t objectStoreId() const
9302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
9312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_objectStoreId >= 0);
9322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return m_objectStoreId;
9332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
9342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int compare(const ObjectStoreFreeListKey& other)
9362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
9372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // FIXME: It may seem strange that we're not comparing database id's,
9382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // but that comparison will have been made earlier.
9392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // We should probably make this more clear, though...
9402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_objectStoreId >= 0);
9412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return m_objectStoreId - other.m_objectStoreId;
9422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
9432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochprivate:
9452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t m_objectStoreId;
9462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch};
9472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochclass IndexFreeListKey {
9492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochpublic:
9502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    IndexFreeListKey()
9512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        : m_objectStoreId(-1)
9522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_indexId(-1)
9532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
9542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
9552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static const char* decode(const char* start, const char* limit, IndexFreeListKey* result)
9572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
9582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        KeyPrefix prefix;
9592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const char* p = KeyPrefix::decode(start, limit, &prefix);
9602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!p)
9612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
9622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(prefix.m_databaseId);
9632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(!prefix.m_objectStoreId);
9642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(!prefix.m_indexId);
9652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (p == limit)
9662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
9672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned char typeByte = *p++;
9682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT_UNUSED(typeByte, typeByte == kIndexFreeListTypeByte);
9692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (p == limit)
9702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
9712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        p = decodeVarInt(p, limit, result->m_objectStoreId);
9722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!p)
9732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
9742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return decodeVarInt(p, limit, result->m_indexId);
9752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
9762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static Vector<char> encode(int64_t databaseId, int64_t objectStoreId, int64_t indexId)
9782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
9792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        KeyPrefix prefix(databaseId, 0, 0);
9802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        Vector<char> ret = prefix.encode();
9812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeByte(kIndexFreeListTypeByte));
9822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeVarInt(objectStoreId));
9832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeVarInt(indexId));
9842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return ret;
9852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
9862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int compare(const IndexFreeListKey& other)
9882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
9892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_objectStoreId >= 0);
9902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_indexId >= 0);
9912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (int x = m_objectStoreId - other.m_objectStoreId)
9922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return x;
9932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return m_indexId - other.m_indexId;
9942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
9952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t objectStoreId() const
9972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
9982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_objectStoreId >= 0);
9992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return m_objectStoreId;
10002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
10012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t indexId() const
10032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
10042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_indexId >= 0);
10052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return m_indexId;
10062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
10072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochprivate:
10092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t m_objectStoreId;
10102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t m_indexId;
10112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch};
10122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochclass ObjectStoreNamesKey {
10142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochpublic:
10152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // FIXME: We never use this to look up object store ids, because a mapping
10162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // is kept in the IDBDatabaseBackendImpl. Can the mapping become unreliable?
10172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // Can we remove this?
10182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static const char* decode(const char* start, const char* limit, ObjectStoreNamesKey* result)
10192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
10202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        KeyPrefix prefix;
10212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const char* p = KeyPrefix::decode(start, limit, &prefix);
10222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!p)
10232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
10242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(prefix.m_databaseId);
10252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(!prefix.m_objectStoreId);
10262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(!prefix.m_indexId);
10272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (p == limit)
10282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
10292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned char typeByte = *p++;
10302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT_UNUSED(typeByte, typeByte == kObjectStoreNamesTypeByte);
10312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return decodeStringWithLength(p, limit, result->m_objectStoreName);
10322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
10332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static Vector<char> encode(int64_t databaseId, const String& objectStoreName)
10352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
10362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        KeyPrefix prefix(databaseId, 0, 0);
10372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        Vector<char> ret = prefix.encode();
10382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeByte(kSchemaVersionTypeByte));
10392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeByte(kObjectStoreNamesTypeByte));
10402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeStringWithLength(objectStoreName));
10412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return ret;
10422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
10432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int compare(const ObjectStoreNamesKey& other)
10452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
10462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return codePointCompare(m_objectStoreName, other.m_objectStoreName);
10472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
10482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    String objectStoreName() const { return m_objectStoreName; }
10502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochprivate:
10522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    String m_objectStoreName; // FIXME: Store the encoded string, or just pointers to it.
10532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch};
10542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochclass IndexNamesKey {
10562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochpublic:
10572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    IndexNamesKey()
10582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        : m_objectStoreId(-1)
10592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
10602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
10612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // FIXME: We never use this to look up index ids, because a mapping
10632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // is kept at a higher level.
10642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static const char* decode(const char* start, const char* limit, IndexNamesKey* result)
10652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
10662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        KeyPrefix prefix;
10672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const char* p = KeyPrefix::decode(start, limit, &prefix);
10682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!p)
10692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
10702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(prefix.m_databaseId);
10712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(!prefix.m_objectStoreId);
10722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(!prefix.m_indexId);
10732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (p == limit)
10742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
10752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned char typeByte = *p++;
10762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT_UNUSED(typeByte, typeByte == kIndexNamesKeyTypeByte);
10772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (p == limit)
10782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
10792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        p = decodeVarInt(p, limit, result->m_objectStoreId);
10802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!p)
10812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
10822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return decodeStringWithLength(p, limit, result->m_indexName);
10832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
10842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static Vector<char> encode(int64_t databaseId, int64_t objectStoreId, const String& indexName)
10862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
10872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        KeyPrefix prefix(databaseId, 0, 0);
10882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        Vector<char> ret = prefix.encode();
10892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeByte(kIndexNamesKeyTypeByte));
10902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeVarInt(objectStoreId));
10912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeStringWithLength(indexName));
10922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return ret;
10932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
10942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int compare(const IndexNamesKey& other)
10962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
10972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_objectStoreId >= 0);
10982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (int x = m_objectStoreId - other.m_objectStoreId)
10992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return x;
11002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return codePointCompare(m_indexName, other.m_indexName);
11012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
11022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
11032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    String indexName() const { return m_indexName; }
11042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
11052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochprivate:
11062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t m_objectStoreId;
11072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    String m_indexName;
11082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch};
11092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
11102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochclass ObjectStoreDataKey {
11112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochpublic:
11122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static const char* decode(const char* start, const char* end, ObjectStoreDataKey* result)
11132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
11142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        KeyPrefix prefix;
11152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const char* p = KeyPrefix::decode(start, end, &prefix);
11162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!p)
11172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
11182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(prefix.m_databaseId);
11192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(prefix.m_objectStoreId);
11202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(prefix.m_indexId == kSpecialIndexNumber);
11212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (p == end)
11222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
11232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return extractEncodedIDBKey(p, end, &result->m_encodedUserKey);
11242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
11252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
11262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static Vector<char> encode(int64_t databaseId, int64_t objectStoreId, const Vector<char> encodedUserKey)
11272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
11282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        KeyPrefix prefix(databaseId, objectStoreId, kSpecialIndexNumber);
11292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        Vector<char> ret = prefix.encode();
11302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodedUserKey);
11312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
11322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return ret;
11332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
11342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
11352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static Vector<char> encode(int64_t databaseId, int64_t objectStoreId, const IDBKey& userKey)
11362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
11372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return encode(databaseId, objectStoreId, encodeIDBKey(userKey));
11382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
11392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
11402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int compare(const ObjectStoreDataKey& other)
11412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
11422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return compareEncodedIDBKeys(m_encodedUserKey, other.m_encodedUserKey);
11432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
11442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
11452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    PassRefPtr<IDBKey> userKey() const
11462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
11472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        RefPtr<IDBKey> key;
11482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        decodeIDBKey(m_encodedUserKey.begin(), m_encodedUserKey.end(), key);
11492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return key;
11502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
11512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
11522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static const int64_t kSpecialIndexNumber = kObjectStoreDataIndexId;
11532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
11542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochprivate:
11552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> m_encodedUserKey;
11562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch};
11572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
11582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochclass ExistsEntryKey {
11592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochpublic:
11602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static const char* decode(const char* start, const char* end, ExistsEntryKey* result)
11612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
11622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        KeyPrefix prefix;
11632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const char* p = KeyPrefix::decode(start, end, &prefix);
11642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!p)
11652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
11662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(prefix.m_databaseId);
11672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(prefix.m_objectStoreId);
11682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(prefix.m_indexId == kSpecialIndexNumber);
11692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (p == end)
11702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
11712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return extractEncodedIDBKey(p, end, &result->m_encodedUserKey);
11722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
11732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
11742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static Vector<char> encode(int64_t databaseId, int64_t objectStoreId, const Vector<char>& encodedKey)
11752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
11762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        KeyPrefix prefix(databaseId, objectStoreId, kSpecialIndexNumber);
11772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        Vector<char> ret = prefix.encode();
11782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodedKey);
11792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return ret;
11802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
11812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
11822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static Vector<char> encode(int64_t databaseId, int64_t objectStoreId, const IDBKey& userKey)
11832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
11842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return encode(databaseId, objectStoreId, encodeIDBKey(userKey));
11852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
11862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
11872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int compare(const ExistsEntryKey& other)
11882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
11892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return compareEncodedIDBKeys(m_encodedUserKey, other.m_encodedUserKey);
11902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
11912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
11922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    PassRefPtr<IDBKey> userKey() const
11932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
11942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        RefPtr<IDBKey> key;
11952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        decodeIDBKey(m_encodedUserKey.begin(), m_encodedUserKey.end(), key);
11962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return key;
11972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
11982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
11992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static const int64_t kSpecialIndexNumber = kExistsEntryIndexId;
12002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochprivate:
12022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> m_encodedUserKey;
12032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch};
12042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochclass IndexDataKey {
12062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochpublic:
12072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    IndexDataKey()
12082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        : m_databaseId(-1)
12092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_objectStoreId(-1)
12102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_indexId(-1)
12112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_sequenceNumber(-1)
12122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
12132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
12142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static const char* decode(const char* start, const char* limit, IndexDataKey* result)
12162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
12172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        KeyPrefix prefix;
12182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const char* p = KeyPrefix::decode(start, limit, &prefix);
12192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!p)
12202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
12212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(prefix.m_databaseId);
12222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(prefix.m_objectStoreId);
12232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(prefix.m_indexId >= kMinimumIndexId);
12242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        result->m_databaseId = prefix.m_databaseId;
12252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        result->m_objectStoreId = prefix.m_objectStoreId;
12262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        result->m_indexId = prefix.m_indexId;
12272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        p = extractEncodedIDBKey(p, limit, &result->m_encodedUserKey);
12282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!p)
12292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
12302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (p == limit) {
12312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            result->m_sequenceNumber = -1; // FIXME: We should change it so that all keys have a sequence number. Shouldn't need to handle this case.
12322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return p;
12332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
12342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return decodeVarInt(p, limit, result->m_sequenceNumber);
12352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
12362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static Vector<char> encode(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const Vector<char>& encodedUserKey, int64_t sequenceNumber)
12382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
12392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        KeyPrefix prefix(databaseId, objectStoreId, indexId);
12402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        Vector<char> ret = prefix.encode();
12412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodedUserKey);
12422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ret.append(encodeVarInt(sequenceNumber));
12432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return ret;
12442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
12452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static Vector<char> encode(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& userKey, int64_t sequenceNumber)
12472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
12482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return encode(databaseId, objectStoreId, indexId, encodeIDBKey(userKey), sequenceNumber);
12492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
12502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static Vector<char> encodeMaxKey(int64_t databaseId, int64_t objectStoreId)
12522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
12532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return encode(databaseId, objectStoreId, INT32_MAX, maxIDBKey(), INT64_MAX);
12542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
12552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int compare(const IndexDataKey& other, bool ignoreSequenceNumber)
12572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
12582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_databaseId >= 0);
12592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_objectStoreId >= 0);
12602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_indexId >= 0);
12612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (int x = compareEncodedIDBKeys(m_encodedUserKey, other.m_encodedUserKey))
12622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return x;
12632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (ignoreSequenceNumber)
12642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
12652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return m_sequenceNumber - other.m_sequenceNumber;
12662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
12672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t databaseId() const
12692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
12702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_databaseId >= 0);
12712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return m_databaseId;
12722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
12732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t objectStoreId() const
12752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
12762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_objectStoreId >= 0);
12772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return m_objectStoreId;
12782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
12792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t indexId() const
12812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
12822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_indexId >= 0);
12832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return m_indexId;
12842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
12852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    PassRefPtr<IDBKey> userKey() const
12872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
12882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        RefPtr<IDBKey> key;
12892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        decodeIDBKey(m_encodedUserKey.begin(), m_encodedUserKey.end(), key);
12902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return key;
12912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
12922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
12932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochprivate:
12942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t m_databaseId;
12952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t m_objectStoreId;
12962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t m_indexId;
12972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> m_encodedUserKey;
12982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t m_sequenceNumber;
12992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch};
13002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochnamespace {
13022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochtemplate<typename KeyType>
13032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochint decodeAndCompare(const LevelDBSlice& a, const LevelDBSlice& b)
13042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
13052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    KeyType keyA;
13062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    KeyType keyB;
13072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const char* ptrA = KeyType::decode(a.begin(), a.end(), &keyA);
13092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT_UNUSED(ptrA, ptrA);
13102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const char* ptrB = KeyType::decode(b.begin(), b.end(), &keyB);
13112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT_UNUSED(ptrB, ptrB);
13122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return keyA.compare(keyB);
13142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
13152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
13162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic int realCompare(const LevelDBSlice& a, const LevelDBSlice& b, bool indexKeys = false)
13182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
13192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const char* ptrA = a.begin();
13202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const char* ptrB = b.begin();
13212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const char* endA = a.end();
13222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const char* endB = b.end();
13232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    KeyPrefix prefixA;
13252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    KeyPrefix prefixB;
13262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ptrA = KeyPrefix::decode(ptrA, endA, &prefixA);
13282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ptrB = KeyPrefix::decode(ptrB, endB, &prefixB);
13292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(ptrA);
13302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(ptrB);
13312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (int x = prefixA.compare(prefixB))
13332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return x;
13342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (prefixA.type() == KeyPrefix::kGlobalMetaData) {
13362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(ptrA != endA);
13372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(ptrB != endB);
13382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned char typeByteA = *ptrA++;
13402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned char typeByteB = *ptrB++;
13412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (int x = typeByteA - typeByteB)
13432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return x;
13442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (typeByteA <= 1)
13462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
13472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (typeByteA == kDatabaseFreeListTypeByte)
13482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return decodeAndCompare<DatabaseFreeListKey>(a, b);
13492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (typeByteA == kDatabaseNameTypeByte)
13502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return decodeAndCompare<DatabaseNameKey>(a, b);
13512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
13522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (prefixA.type() == KeyPrefix::kDatabaseMetaData) {
13542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(ptrA != endA);
13552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(ptrB != endB);
13562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned char typeByteA = *ptrA++;
13582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned char typeByteB = *ptrB++;
13592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (int x = typeByteA - typeByteB)
13612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return x;
13622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (typeByteA <= 3)
13642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
13652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (typeByteA == kObjectStoreMetaDataTypeByte)
13672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return decodeAndCompare<ObjectStoreMetaDataKey>(a, b);
13682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (typeByteA == kIndexMetaDataTypeByte)
13692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return decodeAndCompare<IndexMetaDataKey>(a, b);
13702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (typeByteA == kObjectStoreFreeListTypeByte)
13712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return decodeAndCompare<ObjectStoreFreeListKey>(a, b);
13722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (typeByteA == kIndexFreeListTypeByte)
13732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return decodeAndCompare<IndexFreeListKey>(a, b);
13742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (typeByteA == kObjectStoreNamesTypeByte)
13752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return decodeAndCompare<ObjectStoreNamesKey>(a, b);
13762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (typeByteA == kIndexNamesKeyTypeByte)
13772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return decodeAndCompare<IndexNamesKey>(a, b);
13782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return 0;
13802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT_NOT_REACHED();
13812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
13822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (prefixA.type() == KeyPrefix::kObjectStoreData) {
13842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (ptrA == endA && ptrB == endB)
13852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
13862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (ptrA == endA)
13872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return -1;
13882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (ptrB == endB)
13892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 1; // FIXME: This case of non-existing user keys should not have to be handled this way.
13902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
13912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return decodeAndCompare<ObjectStoreDataKey>(a, b);
13922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
13932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (prefixA.type() == KeyPrefix::kExistsEntry) {
13942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (ptrA == endA && ptrB == endB)
13952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
13962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (ptrA == endA)
13972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return -1;
13982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (ptrB == endB)
13992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 1; // FIXME: This case of non-existing user keys should not have to be handled this way.
14002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return decodeAndCompare<ExistsEntryKey>(a, b);
14022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
14032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (prefixA.type() == KeyPrefix::kIndexData) {
14042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (ptrA == endA && ptrB == endB)
14052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
14062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (ptrA == endA)
14072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return -1;
14082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (ptrB == endB)
14092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 1; // FIXME: This case of non-existing user keys should not have to be handled this way.
14102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        IndexDataKey indexDataKeyA;
14122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        IndexDataKey indexDataKeyB;
14132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ptrA = IndexDataKey::decode(a.begin(), endA, &indexDataKeyA);
14152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ptrB = IndexDataKey::decode(b.begin(), endB, &indexDataKeyB);
14162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(ptrA);
14172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(ptrB);
14182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        bool ignoreSequenceNumber = indexKeys;
14202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return indexDataKeyA.compare(indexDataKeyB, ignoreSequenceNumber);
14212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
14222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT_NOT_REACHED();
14242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return 0;
14252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
14262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic int compareKeys(const LevelDBSlice& a, const LevelDBSlice& b)
14282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
14292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return realCompare(a, b);
14302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
14312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic int compareIndexKeys(const LevelDBSlice& a, const LevelDBSlice& b)
14332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
14342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return realCompare(a, b, true);
14352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
14362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochclass Comparator : public LevelDBComparator {
14382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochpublic:
14392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual int compare(const LevelDBSlice& a, const LevelDBSlice& b) const { return realCompare(a, b); }
14402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual const char* name() const { return "idb_cmp1"; }
14412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch};
14422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
14432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic bool setUpMetadata(LevelDBDatabase* db)
14452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
14462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> metaDataKey = SchemaVersionKey::encode();
14472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t schemaVersion;
14492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!getInt(db, metaDataKey, schemaVersion)) {
14502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        schemaVersion = 0;
14512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!putInt(db, metaDataKey, schemaVersion))
14522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return false;
14532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
14542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // FIXME: Eventually, we'll need to be able to transition between schemas.
14562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (schemaVersion)
14572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false; // Don't know what to do with this version.
14582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return true;
14602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
14612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochIDBLevelDBBackingStore::IDBLevelDBBackingStore(String identifier, IDBFactoryBackendImpl* factory, LevelDBDatabase* db)
14632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    : m_identifier(identifier)
14642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    , m_factory(factory)
14652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    , m_db(db)
14662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
14672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_factory->addIDBBackingStore(identifier, this);
14682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
14692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochIDBLevelDBBackingStore::~IDBLevelDBBackingStore()
14712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
14722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_factory->removeIDBBackingStore(m_identifier);
14732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
14742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochPassRefPtr<IDBBackingStore> IDBLevelDBBackingStore::open(SecurityOrigin* securityOrigin, const String& pathBaseArg, int64_t maximumSize, const String& fileIdentifier, IDBFactoryBackendImpl* factory)
14762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
14772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    String pathBase = pathBaseArg;
14782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (pathBase.isEmpty()) {
14802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT_NOT_REACHED(); // FIXME: We need to handle this case for incognito and DumpRenderTree.
14812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return 0;
14822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
14832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!makeAllDirectories(pathBase)) {
14852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        LOG_ERROR("Unable to create IndexedDB database path %s", pathBase.utf8().data());
14862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return 0;
14872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
14882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // FIXME: We should eventually use the same LevelDB database for all origins.
14892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    String path = pathByAppendingComponent(pathBase, securityOrigin->databaseIdentifier() + ".indexeddb.leveldb");
14902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    OwnPtr<LevelDBComparator> comparator(new Comparator());
14922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    LevelDBDatabase* db = LevelDBDatabase::open(path, comparator.get());
14932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!db)
14942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return 0;
14952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // FIXME: Handle comparator name changes.
14972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
14982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RefPtr<IDBLevelDBBackingStore> backingStore(adoptRef(new IDBLevelDBBackingStore(fileIdentifier, factory, db)));
14992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    backingStore->m_comparator = comparator.release();
15002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!setUpMetadata(backingStore->m_db.get()))
15022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return 0;
15032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return backingStore.release();
15052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
15062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochbool IDBLevelDBBackingStore::extractIDBDatabaseMetaData(const String& name, String& foundVersion, int64_t& foundId)
15082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
15092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> key = DatabaseNameKey::encode(m_identifier, name);
15102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool ok = getInt(m_db.get(), key, foundId);
15122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!ok)
15132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
15142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ok = getString(m_db.get(), DatabaseMetaDataKey::encode(foundId, DatabaseMetaDataKey::kUserVersion), foundVersion);
15162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!ok)
15172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
15182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return true;
15202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
15212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic int64_t getNewDatabaseId(LevelDBDatabase* db)
15232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
15242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> freeListStartKey = DatabaseFreeListKey::encode(0);
15252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> freeListStopKey = DatabaseFreeListKey::encode(INT64_MAX);
15262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    OwnPtr<LevelDBIterator> it(db->newIterator());
15282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for (it->seek(freeListStartKey); it->isValid() && compareKeys(it->key(), freeListStopKey) < 0; it->next()) {
15292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const char *p = it->key().begin();
15302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const char *limit = it->key().end();
15312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        DatabaseFreeListKey freeListKey;
15332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        p = DatabaseFreeListKey::decode(p, limit, &freeListKey);
15342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(p);
15352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        bool ok = db->remove(it->key());
15372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT_UNUSED(ok, ok);
15382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return freeListKey.databaseId();
15402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
15412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // If we got here, there was no free-list.
15432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t maxDatabaseId = -1;
15442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!getInt(db, MaxDatabaseIdKey::encode(), maxDatabaseId))
15452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        maxDatabaseId = 0;
15462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(maxDatabaseId >= 0);
15482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t databaseId = maxDatabaseId + 1;
15502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool ok = putInt(db, MaxDatabaseIdKey::encode(), databaseId);
15512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT_UNUSED(ok, ok);
15522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return databaseId;
15542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
15562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochbool IDBLevelDBBackingStore::setIDBDatabaseMetaData(const String& name, const String& version, int64_t& rowId, bool invalidRowId)
15582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
15592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (invalidRowId) {
15602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        rowId = getNewDatabaseId(m_db.get());
15612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const Vector<char> key = DatabaseNameKey::encode(m_identifier, name);
15632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!putInt(m_db.get(), key, rowId))
15642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return false;
15652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
15662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!putString(m_db.get(), DatabaseMetaDataKey::encode(rowId, DatabaseMetaDataKey::kUserVersion), version))
15682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
15692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return true;
15712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
15722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid IDBLevelDBBackingStore::getObjectStores(int64_t databaseId, Vector<int64_t>& foundIds, Vector<String>& foundNames, Vector<String>& foundKeyPaths, Vector<bool>& foundAutoIncrementFlags)
15742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
15752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> startKey = ObjectStoreMetaDataKey::encode(databaseId, 1, 0);
15762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> stopKey = ObjectStoreMetaDataKey::encode(databaseId, INT64_MAX, 0);
15772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    OwnPtr<LevelDBIterator> it(m_db->newIterator());
15792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for (it->seek(startKey); it->isValid() && compareKeys(it->key(), stopKey) < 0; it->next()) {
15802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const char *p = it->key().begin();
15812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const char *limit = it->key().end();
15822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ObjectStoreMetaDataKey metaDataKey;
15842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        p = ObjectStoreMetaDataKey::decode(p, limit, &metaDataKey);
15852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(p);
15862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        int64_t objectStoreId = metaDataKey.objectStoreId();
15882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        String objectStoreName = decodeString(it->value().begin(), it->value().end());
15902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        it->next();
15922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!it->isValid()) {
15932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            LOG_ERROR("Internal Indexed DB error.");
15942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return;
15952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
15962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        String keyPath = decodeString(it->value().begin(), it->value().end());
15972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
15982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        it->next();
15992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!it->isValid()) {
16002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            LOG_ERROR("Internal Indexed DB error.");
16012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return;
16022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
16032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        bool autoIncrement = *it->value().begin();
16042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
16052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        it->next(); // Is evicatble.
16062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!it->isValid()) {
16072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            LOG_ERROR("Internal Indexed DB error.");
16082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return;
16092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
16102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
16112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        it->next(); // Last version.
16122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!it->isValid()) {
16132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            LOG_ERROR("Internal Indexed DB error.");
16142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return;
16152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
16162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
16172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        it->next(); // Maxium index id allocated.
16182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!it->isValid()) {
16192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            LOG_ERROR("Internal Indexed DB error.");
16202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return;
16212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
16222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
16232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        foundIds.append(objectStoreId);
16242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        foundNames.append(objectStoreName);
16252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        foundKeyPaths.append(keyPath);
16262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        foundAutoIncrementFlags.append(autoIncrement);
16272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
16282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
16292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
16302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic int64_t getNewObjectStoreId(LevelDBDatabase* db, int64_t databaseId)
16312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
16322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> freeListStartKey = ObjectStoreFreeListKey::encode(databaseId, 0);
16332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> freeListStopKey = ObjectStoreFreeListKey::encode(databaseId, INT64_MAX);
16342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
16352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    OwnPtr<LevelDBIterator> it(db->newIterator());
16362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for (it->seek(freeListStartKey); it->isValid() && compareKeys(it->key(), freeListStopKey) < 0; it->next()) {
16372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const char* p = it->key().begin();
16382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const char* limit = it->key().end();
16392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
16402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ObjectStoreFreeListKey freeListKey;
16412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        p = ObjectStoreFreeListKey::decode(p, limit, &freeListKey);
16422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(p);
16432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
16442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        bool ok = db->remove(it->key());
16452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT_UNUSED(ok, ok);
16462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
16472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return freeListKey.objectStoreId();
16482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
16492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
16502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t maxObjectStoreId;
16512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> maxObjectStoreIdKey = DatabaseMetaDataKey::encode(databaseId, DatabaseMetaDataKey::kMaxObjectStoreId);
16522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!getInt(db, maxObjectStoreIdKey, maxObjectStoreId))
16532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        maxObjectStoreId = 0;
16542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
16552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t objectStoreId = maxObjectStoreId + 1;
16562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool ok = putInt(db, maxObjectStoreIdKey, objectStoreId);
16572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT_UNUSED(ok, ok);
16582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
16592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return objectStoreId;
16602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
16612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
16622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochbool IDBLevelDBBackingStore::createObjectStore(int64_t databaseId, const String& name, const String& keyPath, bool autoIncrement, int64_t& assignedObjectStoreId)
16632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
16642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t objectStoreId = getNewObjectStoreId(m_db.get(), databaseId);
16652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
16662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> nameKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, 0);
16672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> keyPathKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, 1);
16682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> autoIncrementKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, 2);
16692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> evictableKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, 3);
16702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> lastVersionKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, 4);
16712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> maxIndexIdKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, 5);
16722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> namesKey = ObjectStoreNamesKey::encode(databaseId, name);
16732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
16742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool ok = putString(m_db.get(), nameKey, name);
16752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!ok) {
16762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        LOG_ERROR("Internal Indexed DB error.");
16772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
16782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
16792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
16802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ok = putString(m_db.get(), keyPathKey, keyPath);
16812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!ok) {
16822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        LOG_ERROR("Internal Indexed DB error.");
16832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
16842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
16852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
16862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ok = putInt(m_db.get(), autoIncrementKey, autoIncrement);
16872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!ok) {
16882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        LOG_ERROR("Internal Indexed DB error.");
16892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
16902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
16912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
16922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ok = putInt(m_db.get(), evictableKey, false);
16932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!ok) {
16942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        LOG_ERROR("Internal Indexed DB error.");
16952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
16962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
16972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
16982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ok = putInt(m_db.get(), lastVersionKey, 1);
16992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!ok) {
17002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        LOG_ERROR("Internal Indexed DB error.");
17012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
17022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
17032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ok = putInt(m_db.get(), maxIndexIdKey, kMinimumIndexId);
17052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!ok) {
17062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        LOG_ERROR("Internal Indexed DB error.");
17072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
17082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
17092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ok = putInt(m_db.get(), namesKey, objectStoreId);
17112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!ok) {
17122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        LOG_ERROR("Internal Indexed DB error.");
17132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
17142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
17152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    assignedObjectStoreId = objectStoreId;
17172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return true;
17192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
17202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic bool deleteRange(LevelDBDatabase* db, const Vector<char>& begin, const Vector<char>& end)
17222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
17232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // FIXME: LevelDB may be able to provide a bulk operation that we can do first.
17242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    OwnPtr<LevelDBIterator> it(db->newIterator());
17252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for (it->seek(begin); it->isValid() && compareKeys(it->key(), end) < 0; it->next()) {
17262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!db->remove(it->key()))
17272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return false;
17282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
17292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return true;
17312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
17322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid IDBLevelDBBackingStore::deleteObjectStore(int64_t databaseId, int64_t objectStoreId)
17342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
17352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    String objectStoreName;
17362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    getString(m_db.get(), ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, 0), objectStoreName);
17372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!deleteRange(m_db.get(), ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, 0), ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, 6)))
17392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return; // FIXME: Report error.
17402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    putString(m_db.get(), ObjectStoreFreeListKey::encode(databaseId, objectStoreId), "");
17422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_db->remove(ObjectStoreNamesKey::encode(databaseId, objectStoreName));
17432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!deleteRange(m_db.get(), IndexFreeListKey::encode(databaseId, objectStoreId, 0), IndexFreeListKey::encode(databaseId, objectStoreId, INT64_MAX)))
17452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return; // FIXME: Report error.
17462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!deleteRange(m_db.get(), IndexMetaDataKey::encode(databaseId, objectStoreId, 0, 0), IndexMetaDataKey::encode(databaseId, objectStoreId, INT64_MAX, 0)))
17472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return; // FIXME: Report error.
17482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    clearObjectStore(databaseId, objectStoreId);
17502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
17512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochString IDBLevelDBBackingStore::getObjectStoreRecord(int64_t databaseId, int64_t objectStoreId, const IDBKey& key)
17532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
17542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> leveldbKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, key);
17552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> data;
17562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!m_db->get(leveldbKey, data))
17582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return String();
17592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t version;
17612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const char* p = decodeVarInt(data.begin(), data.end(), version);
17622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!p)
17632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return String();
17642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    (void) version;
17652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return decodeString(p, data.end());
17672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
17682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochnamespace {
17702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochclass LevelDBRecordIdentifier : public IDBBackingStore::ObjectStoreRecordIdentifier {
17712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochpublic:
17722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static PassRefPtr<LevelDBRecordIdentifier> create(const Vector<char>& primaryKey, int64_t version) { return adoptRef(new LevelDBRecordIdentifier(primaryKey, version)); }
17732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static PassRefPtr<LevelDBRecordIdentifier> create() { return adoptRef(new LevelDBRecordIdentifier()); }
17742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual bool isValid() const { return m_primaryKey.isEmpty(); }
17762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> primaryKey() const { return m_primaryKey; }
17772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    void setPrimaryKey(const Vector<char>& primaryKey) { m_primaryKey = primaryKey; }
17782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t version() const { return m_version; }
17792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    void setVersion(int64_t version) { m_version = version; }
17802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochprivate:
17822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    LevelDBRecordIdentifier(const Vector<char>& primaryKey, int64_t version) : m_primaryKey(primaryKey), m_version(version) { ASSERT(!primaryKey.isEmpty()); }
17832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    LevelDBRecordIdentifier() : m_primaryKey(), m_version(-1) {}
17842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> m_primaryKey; // FIXME: Make it more clear that this is the *encoded* version of the key.
17862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t m_version;
17872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch};
17882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
17892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic int64_t getNewVersionNumber(LevelDBDatabase* db, int64_t databaseId, int64_t objectStoreId)
17912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
17922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> lastVersionKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, 4);
17932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t lastVersion = -1;
17952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!getInt(db, lastVersionKey, lastVersion))
17962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        lastVersion = 0;
17972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
17982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(lastVersion >= 0);
17992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
18002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t version = lastVersion + 1;
18012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool ok = putInt(db, lastVersionKey, version);
18022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT_UNUSED(ok, ok);
18032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
18042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(version > lastVersion); // FIXME: Think about how we want to handle the overflow scenario.
18052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
18062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return version;
18072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
18082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
18092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochbool IDBLevelDBBackingStore::putObjectStoreRecord(int64_t databaseId, int64_t objectStoreId, const IDBKey& key, const String& value, ObjectStoreRecordIdentifier* recordIdentifier)
18102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
18112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t version = getNewVersionNumber(m_db.get(), databaseId, objectStoreId);
18122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> objectStoredataKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, key);
18132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
18142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> v;
18152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    v.append(encodeVarInt(version));
18162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    v.append(encodeString(value));
18172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
18182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!m_db->put(objectStoredataKey, v))
18192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
18202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
18212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> existsEntryKey = ExistsEntryKey::encode(databaseId, objectStoreId, key);
18222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!m_db->put(existsEntryKey, encodeInt(version)))
18232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
18242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
18252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    LevelDBRecordIdentifier* levelDBRecordIdentifier = static_cast<LevelDBRecordIdentifier*>(recordIdentifier);
18262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    levelDBRecordIdentifier->setPrimaryKey(encodeIDBKey(key));
18272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    levelDBRecordIdentifier->setVersion(version);
18282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return true;
18292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
18302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
18312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid IDBLevelDBBackingStore::clearObjectStore(int64_t databaseId, int64_t objectStoreId)
18322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
18332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> startKey = KeyPrefix(databaseId, objectStoreId, 0).encode();
18342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> stopKey = KeyPrefix(databaseId, objectStoreId + 1, 0).encode();
18352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
18362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    deleteRange(m_db.get(), startKey, stopKey);
18372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
18382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
18392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochPassRefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> IDBLevelDBBackingStore::createInvalidRecordIdentifier()
18402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
18412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return LevelDBRecordIdentifier::create();
18422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
18432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
18442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid IDBLevelDBBackingStore::deleteObjectStoreRecord(int64_t databaseId, int64_t objectStoreId, const ObjectStoreRecordIdentifier* recordIdentifier)
18452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
18462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const LevelDBRecordIdentifier* levelDBRecordIdentifier = static_cast<const LevelDBRecordIdentifier*>(recordIdentifier);
18472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> key = ObjectStoreDataKey::encode(databaseId, objectStoreId, levelDBRecordIdentifier->primaryKey());
18482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_db->remove(key);
18492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
18502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
18512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochdouble IDBLevelDBBackingStore::nextAutoIncrementNumber(int64_t databaseId, int64_t objectStoreId)
18522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
18532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> startKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, minIDBKey());
18542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> stopKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, maxIDBKey());
18552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
18562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    OwnPtr<LevelDBIterator> it(m_db->newIterator());
18572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
18582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int maxNumericKey = 0;
18592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
18602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // FIXME: Be more efficient: seek to something after the object store data, then reverse.
18612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
18622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for (it->seek(startKey); it->isValid() && compareKeys(it->key(), stopKey) < 0; it->next()) {
18632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const char *p = it->key().begin();
18642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const char *limit = it->key().end();
18652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
18662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ObjectStoreDataKey dataKey;
18672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        p = ObjectStoreDataKey::decode(p, limit, &dataKey);
18682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(p);
18692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
18702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (dataKey.userKey()->type() == IDBKey::NumberType) {
18712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            int64_t n = static_cast<int64_t>(dataKey.userKey()->number());
18722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (n > maxNumericKey)
18732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                maxNumericKey = n;
18742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
18752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
18762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
18772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return maxNumericKey + 1;
18782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
18792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
18802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochbool IDBLevelDBBackingStore::keyExistsInObjectStore(int64_t databaseId, int64_t objectStoreId, const IDBKey& key, ObjectStoreRecordIdentifier* foundRecordIdentifier)
18812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
18822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> leveldbKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, key);
18832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> data;
18842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
18852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!m_db->get(leveldbKey, data))
18862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
18872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
18882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t version;
18892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!decodeVarInt(data.begin(), data.end(), version))
18902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
18912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
18922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    LevelDBRecordIdentifier* levelDBRecordIdentifier = static_cast<LevelDBRecordIdentifier*>(foundRecordIdentifier);
18932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    levelDBRecordIdentifier->setPrimaryKey(encodeIDBKey(key));
18942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    levelDBRecordIdentifier->setVersion(version);
18952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return true;
18962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
18972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
18982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochbool IDBLevelDBBackingStore::forEachObjectStoreRecord(int64_t databaseId, int64_t objectStoreId, ObjectStoreRecordCallback& callback)
18992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
19002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> startKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, minIDBKey());
19012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> stopKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, maxIDBKey());
19022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
19032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    OwnPtr<LevelDBIterator> it(m_db->newIterator());
19042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for (it->seek(startKey); it->isValid() && compareKeys(it->key(), stopKey) < 0; it->next()) {
19052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const char *p = it->key().begin();
19062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const char *limit = it->key().end();
19072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ObjectStoreDataKey dataKey;
19082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        p = ObjectStoreDataKey::decode(p, limit, &dataKey);
19092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(p);
19102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
19112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        RefPtr<IDBKey> primaryKey = dataKey.userKey();
19122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
19132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        int64_t version;
19142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const char* q = decodeVarInt(it->value().begin(), it->value().end(), version);
19152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!q)
19162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return false;
19172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
19182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        RefPtr<LevelDBRecordIdentifier> ri = LevelDBRecordIdentifier::create(encodeIDBKey(*primaryKey), version);
19192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        String idbValue = decodeString(q, it->value().end());
19202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
19212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        callback.callback(ri.get(), idbValue);
19222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
19232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
19242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return true;
19252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
19262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
19272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid IDBLevelDBBackingStore::getIndexes(int64_t databaseId, int64_t objectStoreId, Vector<int64_t>& foundIds, Vector<String>& foundNames, Vector<String>& foundKeyPaths, Vector<bool>& foundUniqueFlags)
19282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
19292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> startKey = IndexMetaDataKey::encode(databaseId, objectStoreId, 0, 0);
19302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> stopKey = IndexMetaDataKey::encode(databaseId, objectStoreId + 1, 0, 0);
19312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
19322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    OwnPtr<LevelDBIterator> it(m_db->newIterator());
19332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for (it->seek(startKey); it->isValid() && compareKeys(it->key(), stopKey) < 0; it->next()) {
19342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const char* p = it->key().begin();
19352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const char* limit = it->key().end();
19362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
19372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        IndexMetaDataKey metaDataKey;
19382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        p = IndexMetaDataKey::decode(p, limit, &metaDataKey);
19392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(p);
19402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
19412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        int64_t indexId = metaDataKey.indexId();
19422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(!metaDataKey.metaDataType());
19432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
19442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        String indexName = decodeString(it->value().begin(), it->value().end());
19452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        it->next();
19462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!it->isValid()) {
19472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            LOG_ERROR("Internal Indexed DB error.");
19482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return;
19492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
19502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
19512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        bool indexUnique = *it->value().begin();
19522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        it->next();
19532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!it->isValid()) {
19542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            LOG_ERROR("Internal Indexed DB error.");
19552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return;
19562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
19572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
19582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        String keyPath = decodeString(it->value().begin(), it->value().end());
19592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
19602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        foundIds.append(indexId);
19612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        foundNames.append(indexName);
19622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        foundKeyPaths.append(keyPath);
19632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        foundUniqueFlags.append(indexUnique);
19642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
19652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
19662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
19672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic int64_t getNewIndexId(LevelDBDatabase* db, int64_t databaseId, int64_t objectStoreId)
19682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
19692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> startKey = IndexFreeListKey::encode(databaseId, objectStoreId, 0);
19702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> stopKey = IndexFreeListKey::encode(databaseId, objectStoreId, INT64_MAX);
19712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
19722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    OwnPtr<LevelDBIterator> it(db->newIterator());
19732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for (it->seek(startKey); it->isValid() && compareKeys(it->key(), stopKey) < 0; it->next()) {
19742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const char* p = it->key().begin();
19752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const char* limit = it->key().end();
19762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
19772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        IndexFreeListKey freeListKey;
19782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        p = IndexFreeListKey::decode(p, limit, &freeListKey);
19792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(p);
19802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
19812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        bool ok = db->remove(it->key());
19822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT_UNUSED(ok, ok);
19832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
19842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(freeListKey.indexId() >= kMinimumIndexId);
19852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return freeListKey.indexId();
19862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
19872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
19882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t maxIndexId;
19892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> maxIndexIdKey = ObjectStoreMetaDataKey::encode(databaseId, objectStoreId, 5);
19902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!getInt(db, maxIndexIdKey, maxIndexId))
19912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        maxIndexId = kMinimumIndexId;
19922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
19932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t indexId = maxIndexId + 1;
19942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool ok = putInt(db, maxIndexIdKey, indexId);
19952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!ok)
19962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
19972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
19982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return indexId;
19992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
20002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
20012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochbool IDBLevelDBBackingStore::createIndex(int64_t databaseId, int64_t objectStoreId, const String& name, const String& keyPath, bool isUnique, int64_t& indexId)
20022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
20032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    indexId = getNewIndexId(m_db.get(), databaseId, objectStoreId);
20042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
20052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> nameKey = IndexMetaDataKey::encode(databaseId, objectStoreId, indexId, 0);
20062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> uniqueKey = IndexMetaDataKey::encode(databaseId, objectStoreId, indexId, 1);
20072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> keyPathKey = IndexMetaDataKey::encode(databaseId, objectStoreId, indexId, 2);
20082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
20092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool ok = putString(m_db.get(), nameKey, name);
20102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!ok) {
20112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        LOG_ERROR("Internal Indexed DB error.");
20122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
20132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
20142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
20152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ok = putInt(m_db.get(), uniqueKey, isUnique);
20162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!ok) {
20172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        LOG_ERROR("Internal Indexed DB error.");
20182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
20192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
20202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
20212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ok = putString(m_db.get(), keyPathKey, keyPath);
20222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!ok) {
20232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        LOG_ERROR("Internal Indexed DB error.");
20242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
20252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
20262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
20272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return true;
20282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
20292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
20302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid IDBLevelDBBackingStore::deleteIndex(int64_t, int64_t, int64_t)
20312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
20322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT_NOT_REACHED(); // FIXME: Implement and add layout test.
20332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return;
20342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
20352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
20362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochbool IDBLevelDBBackingStore::putIndexDataForRecord(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& key, const ObjectStoreRecordIdentifier* recordIdentifier)
20372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
20382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(indexId >= kMinimumIndexId);
20392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const LevelDBRecordIdentifier* levelDBRecordIdentifier = static_cast<const LevelDBRecordIdentifier*>(recordIdentifier);
20402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
20412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const int64_t globalSequenceNumber = getNewVersionNumber(m_db.get(), databaseId, objectStoreId);
20422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> indexDataKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, key, globalSequenceNumber);
20432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
20442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> data;
20452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    data.append(encodeVarInt(levelDBRecordIdentifier->version()));
20462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    data.append(levelDBRecordIdentifier->primaryKey());
20472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
20482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return m_db->put(indexDataKey, data);
20492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
20502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
20512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic bool findGreatestKeyLessThan(LevelDBDatabase* db, const Vector<char>& target, Vector<char>& foundKey)
20522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
20532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    OwnPtr<LevelDBIterator> it(db->newIterator());
20542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    it->seek(target);
20552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
20562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!it->isValid()) {
20572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        it->seekToLast();
20582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!it->isValid())
20592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return false;
20602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
20612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
20622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    while (compareIndexKeys(it->key(), target) >= 0) {
20632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        it->prev();
20642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!it->isValid())
20652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return false;
20662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
20672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
20682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    foundKey.clear();
20692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    foundKey.append(it->key().begin(), it->key().end() - it->key().begin());
20702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return true;
20712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
20722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
20732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochbool IDBLevelDBBackingStore::deleteIndexDataForRecord(int64_t, int64_t, int64_t, const ObjectStoreRecordIdentifier*)
20742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
20752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // FIXME: This isn't needed since we invalidate index data via the version number mechanism.
20762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return true;
20772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
20782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
20792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochString IDBLevelDBBackingStore::getObjectViaIndex(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& key)
20802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
20812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RefPtr<IDBKey> primaryKey = getPrimaryKeyViaIndex(databaseId, objectStoreId, indexId, key);
20822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!primaryKey)
20832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return String();
20842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
20852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return getObjectStoreRecord(databaseId, objectStoreId, *primaryKey);
20862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
20872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
20882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic bool versionExists(LevelDBDatabase* db, int64_t databaseId, int64_t objectStoreId, int64_t version, const Vector<char>& encodedPrimaryKey)
20892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
20902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> key = ExistsEntryKey::encode(databaseId, objectStoreId, encodedPrimaryKey);
20912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> data;
20922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
20932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!db->get(key, data))
20942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
20952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
20962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return decodeInt(data.begin(), data.end()) == version;
20972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
20982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
20992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochPassRefPtr<IDBKey> IDBLevelDBBackingStore::getPrimaryKeyViaIndex(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& key)
21002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
21012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> leveldbKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, key, 0);
21022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    OwnPtr<LevelDBIterator> it(m_db->newIterator());
21032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    it->seek(leveldbKey);
21042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
21052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for (;;) {
21062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!it->isValid())
21072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
21082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (compareIndexKeys(it->key(), leveldbKey) > 0)
21092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
21102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
21112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        int64_t version;
21122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const char* p = decodeVarInt(it->value().begin(), it->value().end(), version);
21132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!p)
21142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
21152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        Vector<char> encodedPrimaryKey;
21162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        encodedPrimaryKey.append(p, it->value().end() - p);
21172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
21182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!versionExists(m_db.get(), databaseId, objectStoreId, version, encodedPrimaryKey)) {
21192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            // Delete stale index data entry and continue.
21202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            m_db->remove(it->key());
21212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            it->next();
21222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            continue;
21232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
21242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
21252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        RefPtr<IDBKey> primaryKey;
21262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        decodeIDBKey(encodedPrimaryKey.begin(), encodedPrimaryKey.end(), primaryKey);
21272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return primaryKey.release();
21282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
21292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
21302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
21312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochbool IDBLevelDBBackingStore::keyExistsInIndex(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& key)
21322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
21332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const Vector<char> levelDBKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, key, 0);
21342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    OwnPtr<LevelDBIterator> it(m_db->newIterator());
21352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
21362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool found = false;
21372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
21382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    it->seek(levelDBKey);
21392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (it->isValid() && !compareIndexKeys(it->key(), levelDBKey))
21402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        found = true;
21412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
21422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return found;
21432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
21442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
21452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochnamespace {
21462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochclass CursorImplCommon : public IDBBackingStore::Cursor {
21472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochpublic:
21482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // IDBBackingStore::Cursor
21492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual bool continueFunction(const IDBKey*);
21502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual PassRefPtr<IDBKey> key() { return m_currentKey; }
21512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual PassRefPtr<IDBKey> primaryKey() { return m_currentKey; }
21522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual String value() = 0;
21532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual PassRefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> objectStoreRecordIdentifier() = 0; // FIXME: I don't think this is actually used, so drop it.
21542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual int64_t indexDataId() = 0;
21552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
21562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual bool loadCurrentRow() = 0;
21572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool firstSeek();
21582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
21592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochprotected:
21602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    CursorImplCommon(LevelDBDatabase* db, const Vector<char>& lowKey, bool lowOpen, const Vector<char>& highKey, bool highOpen, bool forward)
21612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        : m_db(db)
21622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_lowKey(lowKey)
21632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_lowOpen(lowOpen)
21642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_highKey(highKey)
21652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_highOpen(highOpen)
21662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_forward(forward)
21672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
21682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
21692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual ~CursorImplCommon() {}
21702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
21712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    LevelDBDatabase* m_db;
21722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    OwnPtr<LevelDBIterator> m_iterator;
21732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> m_lowKey;
21742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool m_lowOpen;
21752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> m_highKey;
21762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool m_highOpen;
21772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool m_forward;
21782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RefPtr<IDBKey> m_currentKey;
21792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch};
21802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
21812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochbool CursorImplCommon::firstSeek()
21822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
21832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_iterator = m_db->newIterator();
21842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
21852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (m_forward)
21862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_iterator->seek(m_lowKey);
21872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    else
21882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_iterator->seek(m_highKey);
21892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
21902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for (;;) {
21912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!m_iterator->isValid())
21922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return false;
21932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
21942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (m_forward && m_highOpen && compareIndexKeys(m_iterator->key(), m_highKey) >= 0)
21952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return false;
21962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (m_forward && !m_highOpen && compareIndexKeys(m_iterator->key(), m_highKey) > 0)
21972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return false;
21982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!m_forward && m_lowOpen && compareIndexKeys(m_iterator->key(), m_lowKey) <= 0)
21992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return false;
22002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!m_forward && !m_lowOpen && compareIndexKeys(m_iterator->key(), m_lowKey) < 0)
22012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return false;
22022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
22032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (m_forward && m_lowOpen) {
22042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            // lowKey not included in the range.
22052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (compareIndexKeys(m_iterator->key(), m_lowKey) <= 0) {
22062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                m_iterator->next();
22072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                continue;
22082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            }
22092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
22102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!m_forward && m_highOpen) {
22112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            // highKey not included in the range.
22122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (compareIndexKeys(m_iterator->key(), m_highKey) >= 0) {
22132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                m_iterator->prev();
22142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                continue;
22152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            }
22162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
22172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
22182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!loadCurrentRow()) {
22192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (m_forward)
22202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                m_iterator->next();
22212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            else
22222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                m_iterator->prev();
22232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            continue;
22242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
22252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
22262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return true;
22272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
22282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
22292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
22302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochbool CursorImplCommon::continueFunction(const IDBKey* key)
22312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
22322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // FIXME: This shares a lot of code with firstSeek.
22332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
22342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for (;;) {
22352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (m_forward)
22362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            m_iterator->next();
22372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        else
22382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            m_iterator->prev();
22392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
22402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!m_iterator->isValid())
22412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return false;
22422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
22432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        Vector<char> trash;
22442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!m_db->get(m_iterator->key(), trash))
22452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch             continue;
22462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
22472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (m_forward && m_highOpen && compareIndexKeys(m_iterator->key(), m_highKey) >= 0) // high key not included in range
22482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return false;
22492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (m_forward && !m_highOpen && compareIndexKeys(m_iterator->key(), m_highKey) > 0)
22502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return false;
22512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!m_forward && m_lowOpen && compareIndexKeys(m_iterator->key(), m_lowKey) <= 0) // low key not included in range
22522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return false;
22532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!m_forward && !m_lowOpen && compareIndexKeys(m_iterator->key(), m_lowKey) < 0)
22542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return false;
22552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
22562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!loadCurrentRow())
22572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            continue;
22582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
22592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (key) {
22602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (m_forward) {
22612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                if (m_currentKey->isLessThan(key))
22622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    continue;
22632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            } else {
22642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                if (key->isLessThan(m_currentKey.get()))
22652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    continue;
22662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            }
22672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
22682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
22692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // FIXME: Obey the uniqueness constraint (and test for it!)
22702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
22712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        break;
22722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
22732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
22742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return true;
22752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
22762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
22772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochclass ObjectStoreCursorImpl : public CursorImplCommon {
22782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochpublic:
22792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static PassRefPtr<ObjectStoreCursorImpl> create(LevelDBDatabase* db, const Vector<char>& lowKey, bool lowOpen, const Vector<char>& highKey, bool highOpen, bool forward)
22802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
22812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return adoptRef(new ObjectStoreCursorImpl(db, lowKey, lowOpen, highKey, highOpen, forward));
22822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
22832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
22842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // CursorImplCommon
22852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual String value() { return m_currentValue; }
22862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual PassRefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> objectStoreRecordIdentifier() { ASSERT_NOT_REACHED(); return 0; }
22872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual int64_t indexDataId() { ASSERT_NOT_REACHED(); return 0; }
22882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual bool loadCurrentRow();
22892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
22902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochprivate:
22912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ObjectStoreCursorImpl(LevelDBDatabase* db, const Vector<char>& lowKey, bool lowOpen, const Vector<char>& highKey, bool highOpen, bool forward)
22922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        : CursorImplCommon(db, lowKey, lowOpen, highKey, highOpen, forward)
22932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
22942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
22952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
22962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    String m_currentValue;
22972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch};
22982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
22992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochbool ObjectStoreCursorImpl::loadCurrentRow()
23002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
23012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const char* p = m_iterator->key().begin();
23022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const char* keyLimit = m_iterator->key().end();
23032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
23042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ObjectStoreDataKey objectStoreDataKey;
23052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    p = ObjectStoreDataKey::decode(p, keyLimit, &objectStoreDataKey);
23062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(p);
23072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!p)
23082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
23092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
23102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_currentKey = objectStoreDataKey.userKey();
23112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
23122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t version;
23132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const char* q = decodeVarInt(m_iterator->value().begin(), m_iterator->value().end(), version);
23142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(q);
23152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!q)
23162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
23172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    (void) version;
23182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
23192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_currentValue = decodeString(q, m_iterator->value().end());
23202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
23212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return true;
23222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
23232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
23242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochclass IndexKeyCursorImpl : public CursorImplCommon {
23252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochpublic:
23262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static PassRefPtr<IndexKeyCursorImpl> create(LevelDBDatabase* db, const Vector<char>& lowKey, bool lowOpen, const Vector<char>& highKey, bool highOpen, bool forward)
23272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
23282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return adoptRef(new IndexKeyCursorImpl(db, lowKey, lowOpen, highKey, highOpen, forward));
23292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
23302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
23312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // CursorImplCommon
23322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual String value() { ASSERT_NOT_REACHED(); return String(); }
23332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual PassRefPtr<IDBKey> primaryKey() { return m_primaryKey; }
23342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual PassRefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> objectStoreRecordIdentifier() { ASSERT_NOT_REACHED(); return 0; }
23352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual int64_t indexDataId() { ASSERT_NOT_REACHED(); return 0; }
23362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual bool loadCurrentRow();
23372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
23382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochprivate:
23392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    IndexKeyCursorImpl(LevelDBDatabase* db, const Vector<char>& lowKey, bool lowOpen, const Vector<char>& highKey, bool highOpen, bool forward)
23402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        : CursorImplCommon(db, lowKey, lowOpen, highKey, highOpen, forward)
23412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
23422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
23432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
23442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RefPtr<IDBKey> m_primaryKey;
23452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch};
23462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
23472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochbool IndexKeyCursorImpl::loadCurrentRow()
23482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
23492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const char* p = m_iterator->key().begin();
23502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const char* keyLimit = m_iterator->key().end();
23512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    IndexDataKey indexDataKey;
23522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    p = IndexDataKey::decode(p, keyLimit, &indexDataKey);
23532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
23542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_currentKey = indexDataKey.userKey();
23552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
23562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t indexDataVersion;
23572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const char* q = decodeVarInt(m_iterator->value().begin(), m_iterator->value().end(), indexDataVersion);
23582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(q);
23592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!q)
23602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
23612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
23622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    q = decodeIDBKey(q, m_iterator->value().end(), m_primaryKey);
23632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(q);
23642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!q)
23652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
23662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
23672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> primaryLevelDBKey = ObjectStoreDataKey::encode(indexDataKey.databaseId(), indexDataKey.objectStoreId(), *m_primaryKey);
23682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
23692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> result;
23702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!m_db->get(primaryLevelDBKey, result))
23712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
23722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
23732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t objectStoreDataVersion;
23742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const char* t = decodeVarInt(result.begin(), result.end(), objectStoreDataVersion);
23752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(t);
23762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!t)
23772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
23782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
23792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (objectStoreDataVersion != indexDataVersion) { // FIXME: This is probably not very well covered by the layout tests.
23802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_db->remove(m_iterator->key());
23812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
23822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
23832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
23842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return true;
23852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
23862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
23872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochclass IndexCursorImpl : public CursorImplCommon {
23882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochpublic:
23892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    static PassRefPtr<IndexCursorImpl> create(LevelDBDatabase* db, const Vector<char>& lowKey, bool lowOpen, const Vector<char>& highKey, bool highOpen, bool forward)
23902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
23912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return adoptRef(new IndexCursorImpl(db, lowKey, lowOpen, highKey, highOpen, forward));
23922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
23932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
23942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // CursorImplCommon
23952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual String value() { return m_value; }
23962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual PassRefPtr<IDBKey> primaryKey() { return m_primaryKey; }
23972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual PassRefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> objectStoreRecordIdentifier() { ASSERT_NOT_REACHED(); return 0; }
23982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual int64_t indexDataId() { ASSERT_NOT_REACHED(); return 0; }
23992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool loadCurrentRow();
24002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochprivate:
24022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    IndexCursorImpl(LevelDBDatabase* db, const Vector<char>& lowKey, bool lowOpen, const Vector<char>& highKey, bool highOpen, bool forward)
24032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        : CursorImplCommon(db, lowKey, lowOpen, highKey, highOpen, forward)
24042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
24052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
24062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RefPtr<IDBKey> m_primaryKey;
24082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    String m_value;
24092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> m_primaryLevelDBKey;
24102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch};
24112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochbool IndexCursorImpl::loadCurrentRow()
24132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
24142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const char *p = m_iterator->key().begin();
24152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const char *limit = m_iterator->key().end();
24162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    IndexDataKey indexDataKey;
24182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    p = IndexDataKey::decode(p, limit, &indexDataKey);
24192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_currentKey = indexDataKey.userKey();
24212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const char *q = m_iterator->value().begin();
24232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const char *valueLimit = m_iterator->value().end();
24242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t indexDataVersion;
24262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    q = decodeVarInt(q, valueLimit, indexDataVersion);
24272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(q);
24282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!q)
24292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
24302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    q = decodeIDBKey(q, valueLimit, m_primaryKey);
24312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(q);
24322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!q)
24332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
24342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_primaryLevelDBKey = ObjectStoreDataKey::encode(indexDataKey.databaseId(), indexDataKey.objectStoreId(), *m_primaryKey);
24362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> result;
24382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!m_db->get(m_primaryLevelDBKey, result))
24392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
24402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    int64_t objectStoreDataVersion;
24422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const char* t = decodeVarInt(result.begin(), result.end(), objectStoreDataVersion);
24432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(t);
24442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!t)
24452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
24462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (objectStoreDataVersion != indexDataVersion) {
24482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_db->remove(m_iterator->key());
24492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
24502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
24512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_value = decodeString(t, result.end());
24532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return true;
24542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
24552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
24572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic bool findLastIndexKeyEqualTo(LevelDBDatabase* db, const Vector<char>& target, Vector<char>& foundKey)
24592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
24602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    OwnPtr<LevelDBIterator> it(db->newIterator());
24612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    it->seek(target);
24622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!it->isValid())
24642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return false;
24652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    while (it->isValid() && !compareIndexKeys(it->key(), target)) {
24672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        foundKey.clear();
24682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        foundKey.append(it->key().begin(), it->key().end() - it->key().begin());
24692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        it->next();
24702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
24712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return true;
24732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
24742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochPassRefPtr<IDBBackingStore::Cursor> IDBLevelDBBackingStore::openObjectStoreCursor(int64_t databaseId, int64_t objectStoreId, const IDBKeyRange* range, IDBCursor::Direction direction)
24762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
24772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool lowerBound = range && range->lower();
24782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool upperBound = range && range->upper();
24792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool forward = (direction == IDBCursor::NEXT_NO_DUPLICATE || direction == IDBCursor::NEXT);
24802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool lowerOpen, upperOpen;
24822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> startKey, stopKey;
24832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!lowerBound) {
24852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        startKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, minIDBKey());
24862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        lowerOpen = true; // Not included.
24872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    } else {
24882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        startKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, *range->lower());
24892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        lowerOpen = range->lowerOpen();
24902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
24912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!upperBound) {
24932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        stopKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, maxIDBKey());
24942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        upperOpen = true; // Not included.
24952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
24962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!forward) { // We need a key that exists.
24972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (!findGreatestKeyLessThan(m_db.get(), stopKey, stopKey))
24982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                return 0;
24992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            upperOpen = false;
25002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
25012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    } else {
25022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        stopKey = ObjectStoreDataKey::encode(databaseId, objectStoreId, *range->upper());
25032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        upperOpen = range->upperOpen();
25042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
25052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
25062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RefPtr<ObjectStoreCursorImpl> cursor = ObjectStoreCursorImpl::create(m_db.get(), startKey, lowerOpen, stopKey, upperOpen, forward);
25072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!cursor->firstSeek())
25082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return 0;
25092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
25102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return cursor.release();
25112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
25122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
25132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochPassRefPtr<IDBBackingStore::Cursor> IDBLevelDBBackingStore::openIndexKeyCursor(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange* range, IDBCursor::Direction direction)
25142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
25152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool lowerBound = range && range->lower();
25162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool upperBound = range && range->upper();
25172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool forward = (direction == IDBCursor::NEXT_NO_DUPLICATE || direction == IDBCursor::NEXT);
25182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
25192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool lowerOpen, upperOpen;
25202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> startKey, stopKey;
25212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
25222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!lowerBound) {
25232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        startKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, minIDBKey(), 0);
25242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        lowerOpen = false; // Included.
25252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    } else {
25262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        startKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, *range->lower(), 0);
25272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        lowerOpen = range->lowerOpen();
25282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
25292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
25302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!upperBound) {
25312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        stopKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, maxIDBKey(), 0);
25322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        upperOpen = false; // Included.
25332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
25342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!forward) { // We need a key that exists.
25352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (!findGreatestKeyLessThan(m_db.get(), stopKey, stopKey))
25362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                return 0;
25372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            upperOpen = false;
25382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
25392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    } else {
25402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        stopKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, *range->upper(), 0);
25412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!findLastIndexKeyEqualTo(m_db.get(), stopKey, stopKey)) // Seek to the *last* key in the set of non-unique keys.
25422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
25432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        upperOpen = range->upperOpen();
25442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
25452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
25462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RefPtr<IndexKeyCursorImpl> cursor = IndexKeyCursorImpl::create(m_db.get(), startKey, lowerOpen, stopKey, upperOpen, forward);
25472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!cursor->firstSeek())
25482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return 0;
25492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
25502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return cursor.release();
25512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
25522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
25532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochPassRefPtr<IDBBackingStore::Cursor> IDBLevelDBBackingStore::openIndexCursor(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange* range, IDBCursor::Direction direction)
25542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
25552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool lowerBound = range && range->lower();
25562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool upperBound = range && range->upper();
25572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool forward = (direction == IDBCursor::NEXT_NO_DUPLICATE || direction == IDBCursor::NEXT);
25582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
25592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool lowerOpen, upperOpen;
25602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector<char> startKey, stopKey;
25612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
25622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!lowerBound) {
25632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        startKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, minIDBKey(), 0);
25642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        lowerOpen = false; // Included.
25652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    } else {
25662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        startKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, *range->lower(), 0);
25672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        lowerOpen = range->lowerOpen();
25682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
25692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
25702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!upperBound) {
25712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        stopKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, maxIDBKey(), 0);
25722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        upperOpen = false; // Included.
25732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
25742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!forward) { // We need a key that exists.
25752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (!findGreatestKeyLessThan(m_db.get(), stopKey, stopKey))
25762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                return 0;
25772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            upperOpen = false;
25782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
25792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    } else {
25802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        stopKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, *range->upper(), 0);
25812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!findLastIndexKeyEqualTo(m_db.get(), stopKey, stopKey)) // Seek to the *last* key in the set of non-unique keys.
25822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return 0;
25832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        upperOpen = range->upperOpen();
25842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
25852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
25862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    RefPtr<IndexCursorImpl> cursor = IndexCursorImpl::create(m_db.get(), startKey, lowerOpen, stopKey, upperOpen, forward);
25872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!cursor->firstSeek())
25882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return 0;
25892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
25902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return cursor.release();
25912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
25922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
25932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochnamespace {
25942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochclass DummyTransaction : public IDBBackingStore::Transaction {
25952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochpublic:
25962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual void begin() {}
25972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual void commit() {}
25982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    virtual void rollback() {}
25992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch};
26002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
26012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
26022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochPassRefPtr<IDBBackingStore::Transaction> IDBLevelDBBackingStore::createTransaction()
26032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
26042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // FIXME: We need to implement a transaction abstraction that allows for roll-backs, and write tests for it.
26052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return adoptRef(new DummyTransaction());
26062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
26072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
26082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// FIXME: deleteDatabase should be part of IDBBackingStore.
26092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
26102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch} // namespace WebCore
26112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
26122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#endif // ENABLE(LEVELDB)
26132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#endif // ENABLE(INDEXED_DATABASE)
2614