Modern IDB: Fill out IDBIndex, create MemoryIndex in backing store.
[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 "IDBIndexInfo.h"
32 #include "IDBKeyRangeData.h"
33 #include "Logging.h"
34 #include "MemoryObjectStore.h"
35
36 namespace WebCore {
37 namespace IDBServer {
38
39 std::unique_ptr<MemoryIDBBackingStore> MemoryIDBBackingStore::create(const IDBDatabaseIdentifier& identifier)
40 {
41     return std::make_unique<MemoryIDBBackingStore>(identifier);
42 }
43
44 MemoryIDBBackingStore::MemoryIDBBackingStore(const IDBDatabaseIdentifier& identifier)
45     : m_identifier(identifier)
46 {
47 }
48
49 MemoryIDBBackingStore::~MemoryIDBBackingStore()
50 {
51 }
52
53 const IDBDatabaseInfo& MemoryIDBBackingStore::getOrEstablishDatabaseInfo()
54 {
55     if (!m_databaseInfo)
56         m_databaseInfo = std::make_unique<IDBDatabaseInfo>(m_identifier.databaseName(), 0);
57
58     return *m_databaseInfo;
59 }
60
61 void MemoryIDBBackingStore::setDatabaseInfo(const IDBDatabaseInfo& info)
62 {
63     // It is not valid to directly set database info on a backing store that hasn't already set its own database info.
64     ASSERT(m_databaseInfo);
65
66     m_databaseInfo = std::make_unique<IDBDatabaseInfo>(info);
67 }
68
69 IDBError MemoryIDBBackingStore::beginTransaction(const IDBTransactionInfo& info)
70 {
71     LOG(IndexedDB, "MemoryIDBBackingStore::beginTransaction");
72
73     if (m_transactions.contains(info.identifier()))
74         return IDBError(IDBExceptionCode::InvalidStateError, "Backing store asked to create transaction it already has a record of");
75
76     auto transaction = MemoryBackingStoreTransaction::create(*this, info);
77
78     // VersionChange transactions are scoped to "every object store".
79     if (transaction->isVersionChange()) {
80         for (auto& objectStore : m_objectStoresByIdentifier.values())
81             transaction->addExistingObjectStore(*objectStore);
82     } else if (transaction->isWriting()) {
83         for (auto& iterator : m_objectStoresByName) {
84             if (info.objectStores().contains(iterator.key))
85                 transaction->addExistingObjectStore(*iterator.value);
86         }
87     }
88
89     m_transactions.set(info.identifier(), WTF::move(transaction));
90
91     return IDBError();
92 }
93
94 IDBError MemoryIDBBackingStore::abortTransaction(const IDBResourceIdentifier& transactionIdentifier)
95 {
96     LOG(IndexedDB, "MemoryIDBBackingStore::abortTransaction");
97
98     auto transaction = m_transactions.take(transactionIdentifier);
99     if (!transaction)
100         return IDBError(IDBExceptionCode::InvalidStateError, "Backing store asked to abort transaction it didn't have record of");
101
102     transaction->abort();
103
104     return IDBError();
105 }
106
107 IDBError MemoryIDBBackingStore::commitTransaction(const IDBResourceIdentifier& transactionIdentifier)
108 {
109     LOG(IndexedDB, "MemoryIDBBackingStore::commitTransaction");
110
111     auto transaction = m_transactions.take(transactionIdentifier);
112     if (!transaction)
113         return IDBError(IDBExceptionCode::InvalidStateError, "Backing store asked to commit transaction it didn't have record of");
114
115     transaction->commit();
116
117     return IDBError();
118 }
119
120 IDBError MemoryIDBBackingStore::createObjectStore(const IDBResourceIdentifier& transactionIdentifier, const IDBObjectStoreInfo& info)
121 {
122     LOG(IndexedDB, "MemoryIDBBackingStore::createObjectStore - adding OS %s with ID %" PRIu64, info.name().utf8().data(), info.identifier());
123
124     ASSERT(m_databaseInfo);
125     if (m_databaseInfo->hasObjectStore(info.name()))
126         return IDBError(IDBExceptionCode::ConstraintError);
127
128     ASSERT(!m_objectStoresByIdentifier.contains(info.identifier()));
129     auto objectStore = MemoryObjectStore::create(info);
130
131     m_databaseInfo->addExistingObjectStore(info);
132
133     auto rawTransaction = m_transactions.get(transactionIdentifier);
134     ASSERT(rawTransaction);
135     ASSERT(rawTransaction->isVersionChange());
136
137     rawTransaction->addNewObjectStore(*objectStore);
138     registerObjectStore(WTF::move(objectStore));
139
140     return IDBError();
141 }
142
143 IDBError MemoryIDBBackingStore::deleteObjectStore(const IDBResourceIdentifier& transactionIdentifier, const String& objectStoreName)
144 {
145     LOG(IndexedDB, "MemoryIDBBackingStore::deleteObjectStore");
146
147     ASSERT(m_databaseInfo);
148     if (!m_databaseInfo->hasObjectStore(objectStoreName))
149         return IDBError(IDBExceptionCode::ConstraintError);
150
151     auto transaction = m_transactions.get(transactionIdentifier);
152     ASSERT(transaction);
153     ASSERT(transaction->isVersionChange());
154
155     auto objectStore = takeObjectStoreByName(objectStoreName);
156     ASSERT(objectStore);
157     if (!objectStore)
158         return IDBError(IDBExceptionCode::ConstraintError);
159
160     m_databaseInfo->deleteObjectStore(objectStoreName);
161     transaction->objectStoreDeleted(WTF::move(objectStore));
162
163     return IDBError();
164 }
165
166 IDBError MemoryIDBBackingStore::clearObjectStore(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier)
167 {
168     LOG(IndexedDB, "MemoryIDBBackingStore::clearObjectStore");
169     ASSERT(objectStoreIdentifier);
170
171     ASSERT_UNUSED(transactionIdentifier, m_transactions.contains(transactionIdentifier));
172
173 #ifndef NDEBUG
174     auto transaction = m_transactions.get(transactionIdentifier);
175     ASSERT(transaction->isWriting());
176 #endif
177
178     auto objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
179     if (!objectStore)
180         return IDBError(IDBExceptionCode::ConstraintError);
181
182     objectStore->clear();
183
184     return IDBError();
185 }
186
187 IDBError MemoryIDBBackingStore::createIndex(const IDBResourceIdentifier& transactionIdentifier, const IDBIndexInfo& info)
188 {
189     LOG(IndexedDB, "MemoryIDBBackingStore::createIndex");
190
191     auto rawTransaction = m_transactions.get(transactionIdentifier);
192     ASSERT(rawTransaction);
193     ASSERT(rawTransaction->isVersionChange());
194
195     auto* objectStore = m_objectStoresByIdentifier.get(info.objectStoreIdentifier());
196     if (!objectStore)
197         return IDBError(IDBExceptionCode::ConstraintError);
198
199     return objectStore->createIndex(*rawTransaction, info);
200 }
201
202 void MemoryIDBBackingStore::removeObjectStoreForVersionChangeAbort(MemoryObjectStore& objectStore)
203 {
204     LOG(IndexedDB, "MemoryIDBBackingStore::removeObjectStoreForVersionChangeAbort");
205
206     ASSERT(m_objectStoresByIdentifier.contains(objectStore.info().identifier()));
207     ASSERT(m_objectStoresByIdentifier.get(objectStore.info().identifier()) == &objectStore);
208
209     unregisterObjectStore(objectStore);
210 }
211
212 void MemoryIDBBackingStore::restoreObjectStoreForVersionChangeAbort(std::unique_ptr<MemoryObjectStore>&& objectStore)
213 {
214     registerObjectStore(WTF::move(objectStore));
215 }
216
217 IDBError MemoryIDBBackingStore::keyExistsInObjectStore(const IDBResourceIdentifier&, uint64_t objectStoreIdentifier, const IDBKeyData& keyData, bool& keyExists)
218 {
219     LOG(IndexedDB, "MemoryIDBBackingStore::keyExistsInObjectStore");
220
221     ASSERT(objectStoreIdentifier);
222
223     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
224     RELEASE_ASSERT(objectStore);
225
226     keyExists = objectStore->containsRecord(keyData);
227     return IDBError();
228 }
229
230 IDBError MemoryIDBBackingStore::deleteRange(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData& range)
231 {
232     LOG(IndexedDB, "MemoryIDBBackingStore::deleteRange");
233
234     ASSERT(objectStoreIdentifier);
235
236     if (!m_transactions.contains(transactionIdentifier))
237         return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral("No backing store transaction found to delete from"));
238
239     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
240     if (!objectStore)
241         return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral("No backing store object store found"));
242
243     objectStore->deleteRange(range);
244     return IDBError();
245 }
246
247 IDBError MemoryIDBBackingStore::putRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData& keyData, const ThreadSafeDataBuffer& value)
248 {
249     LOG(IndexedDB, "MemoryIDBBackingStore::putRecord");
250
251     ASSERT(objectStoreIdentifier);
252
253     auto transaction = m_transactions.get(transactionIdentifier);
254     if (!transaction)
255         return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral("No backing store transaction found to put record"));
256
257     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
258     if (!objectStore)
259         return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral("No backing store object store found to put record"));
260
261     objectStore->putRecord(*transaction, keyData, value);
262     return IDBError();
263 }
264
265 IDBError MemoryIDBBackingStore::getRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData& keyRangeData, ThreadSafeDataBuffer& outValue)
266 {
267     LOG(IndexedDB, "MemoryIDBBackingStore::getRecord");
268
269     ASSERT(objectStoreIdentifier);
270
271     if (!m_transactions.contains(transactionIdentifier))
272         return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral("No backing store transaction found to get record"));
273
274     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
275     if (!objectStore)
276         return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral("No backing store object store found"));
277
278     outValue = objectStore->valueForKeyRange(keyRangeData);
279     return IDBError();
280 }
281
282 IDBError MemoryIDBBackingStore::getCount(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData& range, uint64_t& outCount)
283 {
284     LOG(IndexedDB, "MemoryIDBBackingStore::getCount");
285
286     ASSERT(objectStoreIdentifier);
287
288     if (!m_transactions.contains(transactionIdentifier))
289         return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral("No backing store transaction found to get count"));
290
291     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
292     if (!objectStore)
293         return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral("No backing store object store found"));
294
295     outCount = objectStore->countForKeyRange(range);
296     return IDBError();
297 }
298
299 IDBError MemoryIDBBackingStore::generateKeyNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t& keyNumber)
300 {
301     LOG(IndexedDB, "MemoryIDBBackingStore::generateKeyNumber");
302     ASSERT(objectStoreIdentifier);
303     ASSERT_UNUSED(transactionIdentifier, m_transactions.contains(transactionIdentifier));
304     ASSERT_UNUSED(transactionIdentifier, m_transactions.get(transactionIdentifier)->isWriting());
305
306     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
307     RELEASE_ASSERT(objectStore);
308
309     keyNumber = objectStore->currentKeyGeneratorValue();
310     objectStore->setKeyGeneratorValue(keyNumber + 1);
311
312     return IDBError();
313 }
314
315 void MemoryIDBBackingStore::registerObjectStore(std::unique_ptr<MemoryObjectStore>&& objectStore)
316 {
317     ASSERT(objectStore);
318     ASSERT(!m_objectStoresByIdentifier.contains(objectStore->info().identifier()));
319     ASSERT(!m_objectStoresByName.contains(objectStore->info().name()));
320
321     m_objectStoresByName.set(objectStore->info().name(), objectStore.get());
322     m_objectStoresByIdentifier.set(objectStore->info().identifier(), WTF::move(objectStore));
323 }
324
325 void MemoryIDBBackingStore::unregisterObjectStore(MemoryObjectStore& objectStore)
326 {
327     ASSERT(m_objectStoresByIdentifier.contains(objectStore.info().identifier()));
328     ASSERT(m_objectStoresByName.contains(objectStore.info().name()));
329
330     m_objectStoresByName.remove(objectStore.info().name());
331     m_objectStoresByIdentifier.remove(objectStore.info().identifier());
332 }
333
334 std::unique_ptr<MemoryObjectStore> MemoryIDBBackingStore::takeObjectStoreByName(const String& name)
335 {
336     auto rawObjectStore = m_objectStoresByName.take(name);
337     if (!rawObjectStore)
338         return nullptr;
339
340     auto objectStore = m_objectStoresByIdentifier.take(rawObjectStore->info().identifier());
341     ASSERT(objectStore);
342
343     return objectStore;
344 }
345
346 } // namespace IDBServer
347 } // namespace WebCore
348
349 #endif // ENABLE(INDEXED_DATABASE)