Release build with logging enabled fails
[WebKit-https.git] / Source / WebCore / Modules / indexeddb / server / MemoryIDBBackingStore.cpp
1 /*
2  * Copyright (C) 2015 Apple 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  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "MemoryIDBBackingStore.h"
28
29 #if ENABLE(INDEXED_DATABASE)
30
31 #include "IDBCursorInfo.h"
32 #include "IDBGetResult.h"
33 #include "IDBIndexInfo.h"
34 #include "IDBKeyRangeData.h"
35 #include "Logging.h"
36 #include "MemoryIndexCursor.h"
37 #include "MemoryObjectStore.h"
38 #include "MemoryObjectStoreCursor.h"
39
40 namespace WebCore {
41 namespace IDBServer {
42
43 // The IndexedDB spec states the value you can get from the key generator is 2^53
44 static uint64_t maxGeneratedKeyValue = 0x20000000000000;
45
46 std::unique_ptr<MemoryIDBBackingStore> MemoryIDBBackingStore::create(const IDBDatabaseIdentifier& identifier)
47 {
48     return std::make_unique<MemoryIDBBackingStore>(identifier);
49 }
50
51 MemoryIDBBackingStore::MemoryIDBBackingStore(const IDBDatabaseIdentifier& identifier)
52     : m_identifier(identifier)
53 {
54 }
55
56 MemoryIDBBackingStore::~MemoryIDBBackingStore()
57 {
58 }
59
60 IDBError MemoryIDBBackingStore::getOrEstablishDatabaseInfo(IDBDatabaseInfo& info)
61 {
62     if (!m_databaseInfo)
63         m_databaseInfo = std::make_unique<IDBDatabaseInfo>(m_identifier.databaseName(), 0);
64
65     info = *m_databaseInfo;
66     return { };
67 }
68
69 void MemoryIDBBackingStore::setDatabaseInfo(const IDBDatabaseInfo& info)
70 {
71     // It is not valid to directly set database info on a backing store that hasn't already set its own database info.
72     ASSERT(m_databaseInfo);
73
74     m_databaseInfo = std::make_unique<IDBDatabaseInfo>(info);
75 }
76
77 IDBError MemoryIDBBackingStore::beginTransaction(const IDBTransactionInfo& info)
78 {
79     LOG(IndexedDB, "MemoryIDBBackingStore::beginTransaction");
80
81     if (m_transactions.contains(info.identifier()))
82         return IDBError(IDBDatabaseException::InvalidStateError, "Backing store asked to create transaction it already has a record of");
83
84     auto transaction = MemoryBackingStoreTransaction::create(*this, info);
85
86     // VersionChange transactions are scoped to "every object store".
87     if (transaction->isVersionChange()) {
88         for (auto& objectStore : m_objectStoresByIdentifier.values())
89             transaction->addExistingObjectStore(*objectStore);
90     } else if (transaction->isWriting()) {
91         for (auto& iterator : m_objectStoresByName) {
92             if (info.objectStores().contains(iterator.key))
93                 transaction->addExistingObjectStore(*iterator.value);
94         }
95     }
96
97     m_transactions.set(info.identifier(), WTFMove(transaction));
98
99     return IDBError();
100 }
101
102 IDBError MemoryIDBBackingStore::abortTransaction(const IDBResourceIdentifier& transactionIdentifier)
103 {
104     LOG(IndexedDB, "MemoryIDBBackingStore::abortTransaction - %s", transactionIdentifier.loggingString().utf8().data());
105
106     auto transaction = m_transactions.take(transactionIdentifier);
107     if (!transaction)
108         return IDBError(IDBDatabaseException::InvalidStateError, "Backing store asked to abort transaction it didn't have record of");
109
110     transaction->abort();
111
112     return IDBError();
113 }
114
115 IDBError MemoryIDBBackingStore::commitTransaction(const IDBResourceIdentifier& transactionIdentifier)
116 {
117     LOG(IndexedDB, "MemoryIDBBackingStore::commitTransaction - %s", transactionIdentifier.loggingString().utf8().data());
118
119     auto transaction = m_transactions.take(transactionIdentifier);
120     if (!transaction)
121         return IDBError(IDBDatabaseException::InvalidStateError, "Backing store asked to commit transaction it didn't have record of");
122
123     transaction->commit();
124
125     return IDBError();
126 }
127
128 IDBError MemoryIDBBackingStore::createObjectStore(const IDBResourceIdentifier& transactionIdentifier, const IDBObjectStoreInfo& info)
129 {
130     LOG(IndexedDB, "MemoryIDBBackingStore::createObjectStore - adding OS %s with ID %" PRIu64, info.name().utf8().data(), info.identifier());
131
132     ASSERT(m_databaseInfo);
133     if (m_databaseInfo->hasObjectStore(info.name()))
134         return IDBError(IDBDatabaseException::ConstraintError);
135
136     ASSERT(!m_objectStoresByIdentifier.contains(info.identifier()));
137     auto objectStore = MemoryObjectStore::create(info);
138
139     m_databaseInfo->addExistingObjectStore(info);
140
141     auto rawTransaction = m_transactions.get(transactionIdentifier);
142     ASSERT(rawTransaction);
143     ASSERT(rawTransaction->isVersionChange());
144
145     rawTransaction->addNewObjectStore(objectStore.get());
146     registerObjectStore(WTFMove(objectStore));
147
148     return IDBError();
149 }
150
151 IDBError MemoryIDBBackingStore::deleteObjectStore(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier)
152 {
153     LOG(IndexedDB, "MemoryIDBBackingStore::deleteObjectStore");
154
155     ASSERT(m_databaseInfo);
156     if (!m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier))
157         return IDBError(IDBDatabaseException::ConstraintError);
158
159     auto transaction = m_transactions.get(transactionIdentifier);
160     ASSERT(transaction);
161     ASSERT(transaction->isVersionChange());
162
163     auto objectStore = takeObjectStoreByIdentifier(objectStoreIdentifier);
164     ASSERT(objectStore);
165     if (!objectStore)
166         return IDBError(IDBDatabaseException::ConstraintError);
167
168     m_databaseInfo->deleteObjectStore(objectStore->info().name());
169     transaction->objectStoreDeleted(*objectStore);
170
171     return IDBError();
172 }
173
174 IDBError MemoryIDBBackingStore::clearObjectStore(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier)
175 {
176     LOG(IndexedDB, "MemoryIDBBackingStore::clearObjectStore");
177     ASSERT(objectStoreIdentifier);
178
179     ASSERT_UNUSED(transactionIdentifier, m_transactions.contains(transactionIdentifier));
180
181 #if !LOG_DISABLED
182     auto transaction = m_transactions.get(transactionIdentifier);
183     ASSERT(transaction->isWriting());
184 #endif
185
186     auto objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
187     if (!objectStore)
188         return IDBError(IDBDatabaseException::ConstraintError);
189
190     objectStore->clear();
191
192     return IDBError();
193 }
194
195 IDBError MemoryIDBBackingStore::createIndex(const IDBResourceIdentifier& transactionIdentifier, const IDBIndexInfo& info)
196 {
197     LOG(IndexedDB, "MemoryIDBBackingStore::createIndex");
198
199     auto rawTransaction = m_transactions.get(transactionIdentifier);
200     ASSERT(rawTransaction);
201     ASSERT(rawTransaction->isVersionChange());
202
203     auto* objectStore = m_objectStoresByIdentifier.get(info.objectStoreIdentifier());
204     if (!objectStore)
205         return IDBError(IDBDatabaseException::ConstraintError);
206
207     return objectStore->createIndex(*rawTransaction, info);
208 }
209
210 IDBError MemoryIDBBackingStore::deleteIndex(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier)
211 {
212     LOG(IndexedDB, "MemoryIDBBackingStore::deleteIndex");
213
214     auto rawTransaction = m_transactions.get(transactionIdentifier);
215     ASSERT(rawTransaction);
216     ASSERT(rawTransaction->isVersionChange());
217
218     auto* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
219     if (!objectStore)
220         return IDBError(IDBDatabaseException::ConstraintError);
221
222     return objectStore->deleteIndex(*rawTransaction, indexIdentifier);
223 }
224
225 void MemoryIDBBackingStore::removeObjectStoreForVersionChangeAbort(MemoryObjectStore& objectStore)
226 {
227     LOG(IndexedDB, "MemoryIDBBackingStore::removeObjectStoreForVersionChangeAbort");
228
229     if (!m_objectStoresByIdentifier.contains(objectStore.info().identifier()))
230         return;
231
232     ASSERT(m_objectStoresByIdentifier.get(objectStore.info().identifier()) == &objectStore);
233
234     unregisterObjectStore(objectStore);
235 }
236
237 void MemoryIDBBackingStore::restoreObjectStoreForVersionChangeAbort(Ref<MemoryObjectStore>&& objectStore)
238 {
239     registerObjectStore(WTFMove(objectStore));
240 }
241
242 IDBError MemoryIDBBackingStore::keyExistsInObjectStore(const IDBResourceIdentifier&, uint64_t objectStoreIdentifier, const IDBKeyData& keyData, bool& keyExists)
243 {
244     LOG(IndexedDB, "MemoryIDBBackingStore::keyExistsInObjectStore");
245
246     ASSERT(objectStoreIdentifier);
247
248     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
249     RELEASE_ASSERT(objectStore);
250
251     keyExists = objectStore->containsRecord(keyData);
252     return IDBError();
253 }
254
255 IDBError MemoryIDBBackingStore::deleteRange(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData& range)
256 {
257     LOG(IndexedDB, "MemoryIDBBackingStore::deleteRange");
258
259     ASSERT(objectStoreIdentifier);
260
261     if (!m_transactions.contains(transactionIdentifier))
262         return IDBError(IDBDatabaseException::UnknownError, ASCIILiteral("No backing store transaction found to delete from"));
263
264     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
265     if (!objectStore)
266         return IDBError(IDBDatabaseException::UnknownError, ASCIILiteral("No backing store object store found"));
267
268     objectStore->deleteRange(range);
269     return IDBError();
270 }
271
272 IDBError MemoryIDBBackingStore::addRecord(const IDBResourceIdentifier& transactionIdentifier, const IDBObjectStoreInfo& objectStoreInfo, const IDBKeyData& keyData, const IDBValue& value)
273 {
274     LOG(IndexedDB, "MemoryIDBBackingStore::addRecord");
275
276     ASSERT(objectStoreInfo.identifier());
277
278     auto transaction = m_transactions.get(transactionIdentifier);
279     if (!transaction)
280         return IDBError(IDBDatabaseException::UnknownError, ASCIILiteral("No backing store transaction found to put record"));
281
282     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreInfo.identifier());
283     if (!objectStore)
284         return IDBError(IDBDatabaseException::UnknownError, ASCIILiteral("No backing store object store found to put record"));
285
286     return objectStore->addRecord(*transaction, keyData, value);
287 }
288
289 IDBError MemoryIDBBackingStore::getRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData& range, IDBGetResult& outValue)
290 {
291     LOG(IndexedDB, "MemoryIDBBackingStore::getRecord");
292
293     ASSERT(objectStoreIdentifier);
294
295     if (!m_transactions.contains(transactionIdentifier))
296         return IDBError(IDBDatabaseException::UnknownError, ASCIILiteral("No backing store transaction found to get record"));
297
298     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
299     if (!objectStore)
300         return IDBError(IDBDatabaseException::UnknownError, ASCIILiteral("No backing store object store found"));
301
302     outValue = objectStore->valueForKeyRange(range);
303     return IDBError();
304 }
305
306 IDBError MemoryIDBBackingStore::getIndexRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, IndexedDB::IndexRecordType recordType, const IDBKeyRangeData& range, IDBGetResult& outValue)
307 {
308     LOG(IndexedDB, "MemoryIDBBackingStore::getIndexRecord");
309
310     ASSERT(objectStoreIdentifier);
311
312     if (!m_transactions.contains(transactionIdentifier))
313         return IDBError(IDBDatabaseException::UnknownError, ASCIILiteral("No backing store transaction found to get record"));
314
315     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
316     if (!objectStore)
317         return IDBError(IDBDatabaseException::UnknownError, ASCIILiteral("No backing store object store found"));
318
319     outValue = objectStore->indexValueForKeyRange(indexIdentifier, recordType, range);
320     return IDBError();
321 }
322
323 IDBError MemoryIDBBackingStore::getCount(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const IDBKeyRangeData& range, uint64_t& outCount)
324 {
325     LOG(IndexedDB, "MemoryIDBBackingStore::getCount");
326
327     ASSERT(objectStoreIdentifier);
328
329     if (!m_transactions.contains(transactionIdentifier))
330         return IDBError(IDBDatabaseException::UnknownError, ASCIILiteral("No backing store transaction found to get count"));
331
332     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
333     if (!objectStore)
334         return IDBError(IDBDatabaseException::UnknownError, ASCIILiteral("No backing store object store found"));
335
336     outCount = objectStore->countForKeyRange(indexIdentifier, range);
337
338     return IDBError();
339 }
340
341 IDBError MemoryIDBBackingStore::generateKeyNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t& keyNumber)
342 {
343     LOG(IndexedDB, "MemoryIDBBackingStore::generateKeyNumber");
344     ASSERT(objectStoreIdentifier);
345     ASSERT_UNUSED(transactionIdentifier, m_transactions.contains(transactionIdentifier));
346     ASSERT_UNUSED(transactionIdentifier, m_transactions.get(transactionIdentifier)->isWriting());
347
348     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
349     RELEASE_ASSERT(objectStore);
350
351     keyNumber = objectStore->currentKeyGeneratorValue();
352     if (keyNumber > maxGeneratedKeyValue)
353         return { IDBDatabaseException::ConstraintError, "Cannot generate new key value over 2^53 for object store operation" };
354
355     objectStore->setKeyGeneratorValue(keyNumber + 1);
356
357     return IDBError();
358 }
359
360 IDBError MemoryIDBBackingStore::revertGeneratedKeyNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t keyNumber)
361 {
362     LOG(IndexedDB, "MemoryIDBBackingStore::revertGeneratedKeyNumber");
363     ASSERT(objectStoreIdentifier);
364     ASSERT_UNUSED(transactionIdentifier, m_transactions.contains(transactionIdentifier));
365     ASSERT_UNUSED(transactionIdentifier, m_transactions.get(transactionIdentifier)->isWriting());
366
367     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
368     RELEASE_ASSERT(objectStore);
369
370     objectStore->setKeyGeneratorValue(keyNumber);
371
372     return { };
373 }
374
375 IDBError MemoryIDBBackingStore::maybeUpdateKeyGeneratorNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, double newKeyNumber)
376 {
377     LOG(IndexedDB, "MemoryIDBBackingStore::maybeUpdateKeyGeneratorNumber");
378     ASSERT(objectStoreIdentifier);
379     ASSERT_UNUSED(transactionIdentifier, m_transactions.contains(transactionIdentifier));
380     ASSERT_UNUSED(transactionIdentifier, m_transactions.get(transactionIdentifier)->isWriting());
381
382     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
383     RELEASE_ASSERT(objectStore);
384
385     if (newKeyNumber < objectStore->currentKeyGeneratorValue())
386         return { };
387
388     uint64_t newKeyInteger(newKeyNumber);
389     if (newKeyInteger <= uint64_t(newKeyNumber))
390         ++newKeyInteger;
391
392     ASSERT(newKeyInteger > uint64_t(newKeyNumber));
393
394     objectStore->setKeyGeneratorValue(newKeyInteger);
395
396     return { };
397 }
398
399 IDBError MemoryIDBBackingStore::openCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBCursorInfo& info, IDBGetResult& outData)
400 {
401     LOG(IndexedDB, "MemoryIDBBackingStore::openCursor");
402
403     ASSERT(!MemoryCursor::cursorForIdentifier(info.identifier()));
404
405     if (!m_transactions.contains(transactionIdentifier))
406         return IDBError(IDBDatabaseException::UnknownError, ASCIILiteral("No backing store transaction found in which to open a cursor"));
407
408     switch (info.cursorSource()) {
409     case IndexedDB::CursorSource::ObjectStore: {
410         auto* objectStore = m_objectStoresByIdentifier.get(info.sourceIdentifier());
411         if (!objectStore)
412             return IDBError(IDBDatabaseException::UnknownError, ASCIILiteral("No backing store object store found"));
413
414         MemoryCursor* cursor = objectStore->maybeOpenCursor(info);
415         if (!cursor)
416             return IDBError(IDBDatabaseException::UnknownError, ASCIILiteral("Could not create object store cursor in backing store"));
417
418         cursor->currentData(outData);
419         break;
420     }
421     case IndexedDB::CursorSource::Index:
422         auto* objectStore = m_objectStoresByIdentifier.get(info.objectStoreIdentifier());
423         if (!objectStore)
424             return IDBError(IDBDatabaseException::UnknownError, ASCIILiteral("No backing store object store found"));
425
426         auto* index = objectStore->indexForIdentifier(info.sourceIdentifier());
427         if (!index)
428             return IDBError(IDBDatabaseException::UnknownError, ASCIILiteral("No backing store index found"));
429
430         MemoryCursor* cursor = index->maybeOpenCursor(info);
431         if (!cursor)
432             return IDBError(IDBDatabaseException::UnknownError, ASCIILiteral("Could not create index cursor in backing store"));
433
434         cursor->currentData(outData);
435         break;
436     }
437
438     return { };
439 }
440
441 IDBError MemoryIDBBackingStore::iterateCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBResourceIdentifier& cursorIdentifier, const IDBKeyData& key, uint32_t count, IDBGetResult& outData)
442 {
443     LOG(IndexedDB, "MemoryIDBBackingStore::iterateCursor");
444
445     if (!m_transactions.contains(transactionIdentifier))
446         return IDBError(IDBDatabaseException::UnknownError, ASCIILiteral("No backing store transaction found in which to iterate cursor"));
447
448     auto* cursor = MemoryCursor::cursorForIdentifier(cursorIdentifier);
449     if (!cursor)
450         return IDBError(IDBDatabaseException::UnknownError, ASCIILiteral("No backing store cursor found in which to iterate cursor"));
451
452     cursor->iterate(key, count, outData);
453
454     return { };
455 }
456
457 void MemoryIDBBackingStore::registerObjectStore(Ref<MemoryObjectStore>&& objectStore)
458 {
459     ASSERT(!m_objectStoresByIdentifier.contains(objectStore->info().identifier()));
460     ASSERT(!m_objectStoresByName.contains(objectStore->info().name()));
461
462     m_objectStoresByName.set(objectStore->info().name(), &objectStore.get());
463     m_objectStoresByIdentifier.set(objectStore->info().identifier(), WTFMove(objectStore));
464 }
465
466 void MemoryIDBBackingStore::unregisterObjectStore(MemoryObjectStore& objectStore)
467 {
468     ASSERT(m_objectStoresByIdentifier.contains(objectStore.info().identifier()));
469     ASSERT(m_objectStoresByName.contains(objectStore.info().name()));
470
471     m_objectStoresByName.remove(objectStore.info().name());
472     m_objectStoresByIdentifier.remove(objectStore.info().identifier());
473 }
474
475 RefPtr<MemoryObjectStore> MemoryIDBBackingStore::takeObjectStoreByIdentifier(uint64_t identifier)
476 {
477     auto objectStoreByIdentifier = m_objectStoresByIdentifier.take(identifier);
478     if (!objectStoreByIdentifier)
479         return nullptr;
480
481     auto objectStore = m_objectStoresByName.take(objectStoreByIdentifier->info().name());
482     ASSERT_UNUSED(objectStore, objectStore);
483
484     return objectStoreByIdentifier;
485 }
486
487 IDBObjectStoreInfo* MemoryIDBBackingStore::infoForObjectStore(uint64_t objectStoreIdentifier)
488 {
489     ASSERT(m_databaseInfo);
490     return m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
491 }
492
493 void MemoryIDBBackingStore::deleteBackingStore()
494 {
495     // The in-memory IDB backing store doesn't need to do any cleanup when it is deleted.
496 }
497
498 } // namespace IDBServer
499 } // namespace WebCore
500
501 #endif // ENABLE(INDEXED_DATABASE)