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