Modern IDB: autoIncrement support.
[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 %llu", 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 void MemoryIDBBackingStore::removeObjectStoreForVersionChangeAbort(MemoryObjectStore& objectStore)
165 {
166     LOG(IndexedDB, "MemoryIDBBackingStore::removeObjectStoreForVersionChangeAbort");
167
168     ASSERT(m_objectStoresByIdentifier.contains(objectStore.info().identifier()));
169     ASSERT(m_objectStoresByIdentifier.get(objectStore.info().identifier()) == &objectStore);
170
171     unregisterObjectStore(objectStore);
172 }
173
174 void MemoryIDBBackingStore::restoreObjectStoreForVersionChangeAbort(std::unique_ptr<MemoryObjectStore>&& objectStore)
175 {
176     registerObjectStore(WTF::move(objectStore));
177 }
178
179 IDBError MemoryIDBBackingStore::keyExistsInObjectStore(const IDBResourceIdentifier&, uint64_t objectStoreIdentifier, const IDBKeyData& keyData, bool& keyExists)
180 {
181     LOG(IndexedDB, "MemoryIDBBackingStore::keyExistsInObjectStore");
182
183     ASSERT(objectStoreIdentifier);
184
185     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
186     RELEASE_ASSERT(objectStore);
187
188     keyExists = objectStore->containsRecord(keyData);
189     return IDBError();
190 }
191
192 IDBError MemoryIDBBackingStore::deleteRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData& keyData)
193 {
194     LOG(IndexedDB, "MemoryIDBBackingStore::deleteRecord");
195
196     ASSERT(objectStoreIdentifier);
197
198     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
199     RELEASE_ASSERT(objectStore);
200     RELEASE_ASSERT(m_transactions.contains(transactionIdentifier));
201
202     objectStore->deleteRecord(keyData);
203     return IDBError();
204 }
205
206 IDBError MemoryIDBBackingStore::putRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData& keyData, const ThreadSafeDataBuffer& value)
207 {
208     LOG(IndexedDB, "MemoryIDBBackingStore::putRecord");
209
210     ASSERT(objectStoreIdentifier);
211
212     auto transaction = m_transactions.get(transactionIdentifier);
213     if (!transaction)
214         return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral("No backing store transaction found to put record"));
215
216     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
217     if (!objectStore)
218         return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral("No backing store object store found to put record"));
219
220     objectStore->putRecord(*transaction, keyData, value);
221     return IDBError();
222 }
223
224 IDBError MemoryIDBBackingStore::getRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData& keyData, ThreadSafeDataBuffer& outValue)
225 {
226     LOG(IndexedDB, "MemoryIDBBackingStore::getRecord");
227
228     ASSERT(objectStoreIdentifier);
229
230     if (!m_transactions.contains(transactionIdentifier))
231         return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral("No backing store transaction found to get record"));
232
233     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
234     if (!objectStore)
235         return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral("No backing store object store found"));
236
237     outValue = objectStore->valueForKey(keyData);
238     return IDBError();
239 }
240
241 IDBError MemoryIDBBackingStore::generateKeyNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t& keyNumber)
242 {
243     LOG(IndexedDB, "MemoryIDBBackingStore::generateKeyNumber");
244     ASSERT(objectStoreIdentifier);
245     ASSERT_UNUSED(transactionIdentifier, m_transactions.contains(transactionIdentifier));
246     ASSERT_UNUSED(transactionIdentifier, m_transactions.get(transactionIdentifier)->isWriting());
247
248     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
249     RELEASE_ASSERT(objectStore);
250
251     keyNumber = objectStore->currentKeyGeneratorValue();
252     objectStore->setKeyGeneratorValue(keyNumber + 1);
253
254     return IDBError();
255 }
256
257 void MemoryIDBBackingStore::registerObjectStore(std::unique_ptr<MemoryObjectStore>&& objectStore)
258 {
259     ASSERT(objectStore);
260     ASSERT(!m_objectStoresByIdentifier.contains(objectStore->info().identifier()));
261     ASSERT(!m_objectStoresByName.contains(objectStore->info().name()));
262
263     m_objectStoresByName.set(objectStore->info().name(), objectStore.get());
264     m_objectStoresByIdentifier.set(objectStore->info().identifier(), WTF::move(objectStore));
265 }
266
267 void MemoryIDBBackingStore::unregisterObjectStore(MemoryObjectStore& objectStore)
268 {
269     ASSERT(m_objectStoresByIdentifier.contains(objectStore.info().identifier()));
270     ASSERT(m_objectStoresByName.contains(objectStore.info().name()));
271
272     m_objectStoresByName.remove(objectStore.info().name());
273     m_objectStoresByIdentifier.remove(objectStore.info().identifier());
274 }
275
276 std::unique_ptr<MemoryObjectStore> MemoryIDBBackingStore::takeObjectStoreByName(const String& name)
277 {
278     auto rawObjectStore = m_objectStoresByName.take(name);
279     if (!rawObjectStore)
280         return nullptr;
281
282     auto objectStore = m_objectStoresByIdentifier.take(rawObjectStore->info().identifier());
283     ASSERT(objectStore);
284
285     return objectStore;
286 }
287
288 } // namespace IDBServer
289 } // namespace WebCore
290
291 #endif // ENABLE(INDEXED_DATABASE)