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