7eca09319d2019cdf3d778bced8472fa32f3c866
[WebKit.git] / Source / WebCore / Modules / indexeddb / server / MemoryObjectStore.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. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "MemoryObjectStore.h"
28
29 #if ENABLE(INDEXED_DATABASE)
30
31 #include "IDBBindingUtilities.h"
32 #include "IDBDatabaseException.h"
33 #include "IDBError.h"
34 #include "IDBKeyRangeData.h"
35 #include "IndexKey.h"
36 #include "Logging.h"
37 #include "MemoryBackingStoreTransaction.h"
38
39 #include <wtf/NeverDestroyed.h>
40
41 using namespace JSC;
42
43 namespace WebCore {
44 namespace IDBServer {
45
46 std::unique_ptr<MemoryObjectStore> MemoryObjectStore::create(const IDBObjectStoreInfo& info)
47 {
48     return std::make_unique<MemoryObjectStore>(info);
49 }
50
51 MemoryObjectStore::MemoryObjectStore(const IDBObjectStoreInfo& info)
52     : m_info(info)
53 {
54 }
55
56 MemoryObjectStore::~MemoryObjectStore()
57 {
58     ASSERT(!m_writeTransaction);
59 }
60
61 void MemoryObjectStore::writeTransactionStarted(MemoryBackingStoreTransaction& transaction)
62 {
63     LOG(IndexedDB, "MemoryObjectStore::writeTransactionStarted");
64
65     ASSERT(!m_writeTransaction);
66     m_writeTransaction = &transaction;
67 }
68
69 void MemoryObjectStore::writeTransactionFinished(MemoryBackingStoreTransaction& transaction)
70 {
71     LOG(IndexedDB, "MemoryObjectStore::writeTransactionFinished");
72
73     ASSERT_UNUSED(transaction, m_writeTransaction == &transaction);
74     m_writeTransaction = nullptr;
75 }
76
77 IDBError MemoryObjectStore::createIndex(MemoryBackingStoreTransaction& transaction, const IDBIndexInfo& info)
78 {
79     LOG(IndexedDB, "MemoryObjectStore::createIndex");
80
81     if (!m_writeTransaction || !m_writeTransaction->isVersionChange() || m_writeTransaction != &transaction)
82         return IDBError(IDBExceptionCode::ConstraintError);
83
84     ASSERT(!m_indexesByIdentifier.contains(info.identifier()));
85     auto index = MemoryIndex::create(info, *this);
86
87     m_info.addExistingIndex(info);
88
89     transaction.addNewIndex(*index);
90     registerIndex(WTF::move(index));
91
92     return { };
93 }
94
95 bool MemoryObjectStore::containsRecord(const IDBKeyData& key)
96 {
97     if (!m_keyValueStore)
98         return false;
99
100     return m_keyValueStore->contains(key);
101 }
102
103 void MemoryObjectStore::clear()
104 {
105     LOG(IndexedDB, "MemoryObjectStore::clear");
106     ASSERT(m_writeTransaction);
107
108     m_writeTransaction->objectStoreCleared(*this, WTF::move(m_keyValueStore), WTF::move(m_orderedKeys));
109     for (auto& index : m_indexesByIdentifier.values())
110         index->objectStoreCleared();
111
112     for (auto& cursor : m_cursors.values())
113         cursor->objectStoreCleared();
114 }
115
116 void MemoryObjectStore::replaceKeyValueStore(std::unique_ptr<KeyValueMap>&& store, std::unique_ptr<std::set<IDBKeyData>>&& orderedKeys)
117 {
118     ASSERT(m_writeTransaction);
119     ASSERT(m_writeTransaction->isAborting());
120
121     m_keyValueStore = WTF::move(store);
122     m_orderedKeys = WTF::move(orderedKeys);
123 }
124
125 void MemoryObjectStore::deleteRecord(const IDBKeyData& key)
126 {
127     LOG(IndexedDB, "MemoryObjectStore::deleteRecord");
128
129     ASSERT(m_writeTransaction);
130
131     if (!m_keyValueStore) {
132         m_writeTransaction->recordValueChanged(*this, key, nullptr);
133         return;
134     }
135
136     ASSERT(m_orderedKeys);
137
138     auto iterator = m_keyValueStore->find(key);
139     if (iterator == m_keyValueStore->end()) {
140         m_writeTransaction->recordValueChanged(*this, key, nullptr);
141         return;
142     }
143
144     m_writeTransaction->recordValueChanged(*this, key, &iterator->value);
145     m_keyValueStore->remove(iterator);
146     m_orderedKeys->erase(key);
147
148     updateIndexesForDeleteRecord(key);
149     updateCursorsForDeleteRecord(key);
150 }
151
152 void MemoryObjectStore::deleteRange(const IDBKeyRangeData& inputRange)
153 {
154     LOG(IndexedDB, "MemoryObjectStore::deleteRange");
155
156     ASSERT(m_writeTransaction);
157
158     if (inputRange.isExactlyOneKey()) {
159         deleteRecord(inputRange.lowerKey);
160         return;
161     }
162
163     IDBKeyRangeData range = inputRange;
164     while (true) {
165         auto key = lowestKeyWithRecordInRange(range);
166         if (key.isNull())
167             break;
168
169         deleteRecord(key);
170
171         range.lowerKey = key;
172         range.lowerOpen = true;
173     }
174 }
175
176 IDBError MemoryObjectStore::addRecord(MemoryBackingStoreTransaction& transaction, const IDBKeyData& keyData, const ThreadSafeDataBuffer& value)
177 {
178     LOG(IndexedDB, "MemoryObjectStore::addRecord");
179
180     ASSERT(m_writeTransaction);
181     ASSERT_UNUSED(transaction, m_writeTransaction == &transaction);
182     ASSERT(!m_keyValueStore || !m_keyValueStore->contains(keyData));
183     ASSERT(!m_orderedKeys || m_orderedKeys->find(keyData) == m_orderedKeys->end());
184
185     if (!m_keyValueStore) {
186         ASSERT(!m_orderedKeys);
187         m_keyValueStore = std::make_unique<KeyValueMap>();
188         m_orderedKeys = std::make_unique<std::set<IDBKeyData>>();
189     }
190
191     auto mapResult = m_keyValueStore->set(keyData, value);
192     ASSERT(mapResult.isNewEntry);
193     auto listResult = m_orderedKeys->insert(keyData);
194     ASSERT(listResult.second);
195
196     // If there was an error indexing this addition, then revert it.
197     auto error = updateIndexesForPutRecord(keyData, value);
198     if (!error.isNull()) {
199         m_keyValueStore->remove(mapResult.iterator);
200         m_orderedKeys->erase(listResult.first);
201     } else
202         updateCursorsForPutRecord(listResult.first);
203
204     return error;
205 }
206
207 static VM& indexVM()
208 {
209     ASSERT(!isMainThread());
210     static NeverDestroyed<RefPtr<VM>> vm = VM::create();
211     return *vm.get();
212 }
213
214 static ExecState& indexGlobalExec()
215 {
216     ASSERT(!isMainThread());
217     static NeverDestroyed<Strong<JSGlobalObject>> globalObject;
218     static bool initialized = false;
219     if (!initialized) {
220         globalObject.get().set(indexVM(), JSGlobalObject::create(indexVM(), JSGlobalObject::createStructure(indexVM(), jsNull())));
221         initialized = true;
222     }
223
224     RELEASE_ASSERT(globalObject.get()->globalExec());
225     return *globalObject.get()->globalExec();
226 }
227
228 void MemoryObjectStore::updateCursorsForPutRecord(std::set<IDBKeyData>::iterator iterator)
229 {
230     for (auto& cursor : m_cursors.values())
231         cursor->keyAdded(iterator);
232 }
233
234 void MemoryObjectStore::updateCursorsForDeleteRecord(const IDBKeyData& key)
235 {
236     for (auto& cursor : m_cursors.values())
237         cursor->keyDeleted(key);
238 }
239
240 void MemoryObjectStore::updateIndexesForDeleteRecord(const IDBKeyData& value)
241 {
242     for (auto* index : m_indexesByName.values())
243         index->removeEntriesWithValueKey(value);
244 }
245
246 IDBError MemoryObjectStore::updateIndexesForPutRecord(const IDBKeyData& key, const ThreadSafeDataBuffer& value)
247 {
248     JSLockHolder locker(indexVM());
249
250     auto jsValue = idbValueDataToJSValue(indexGlobalExec(), value);
251     if (jsValue.isUndefinedOrNull())
252         return { };
253
254     IDBError error;
255     Vector<std::pair<MemoryIndex*, IndexKey>> changedIndexRecords;
256
257     for (auto* index : m_indexesByName.values()) {
258         IndexKey indexKey;
259         generateIndexKeyForValue(indexGlobalExec(), index->info(), jsValue, indexKey);
260
261         if (indexKey.isNull())
262             continue;
263
264         error = index->putIndexKey(key, indexKey);
265         if (!error.isNull())
266             break;
267
268         changedIndexRecords.append(std::make_pair(index, indexKey));
269     }
270
271     // If any of the index puts failed, revert all of the ones that went through.
272     if (!error.isNull()) {
273         for (auto& record : changedIndexRecords)
274             record.first->removeRecord(key, record.second);
275     }
276
277     return error;
278 }
279
280 uint64_t MemoryObjectStore::countForKeyRange(uint64_t indexIdentifier, const IDBKeyRangeData& inRange) const
281 {
282     LOG(IndexedDB, "MemoryObjectStore::countForKeyRange");
283
284     if (indexIdentifier) {
285         auto* index = m_indexesByIdentifier.get(indexIdentifier);
286         ASSERT(index);
287         return index->countForKeyRange(inRange);
288     }
289
290     if (!m_keyValueStore)
291         return 0;
292
293     uint64_t count = 0;
294     IDBKeyRangeData range = inRange;
295     while (true) {
296         auto key = lowestKeyWithRecordInRange(range);
297         if (key.isNull())
298             break;
299
300         ++count;
301         range.lowerKey = key;
302         range.lowerOpen = true;
303     }
304
305     return count;
306 }
307
308 ThreadSafeDataBuffer MemoryObjectStore::valueForKeyRange(const IDBKeyRangeData& keyRangeData) const
309 {
310     LOG(IndexedDB, "MemoryObjectStore::valueForKey");
311
312     IDBKeyData key = lowestKeyWithRecordInRange(keyRangeData);
313     if (key.isNull())
314         return ThreadSafeDataBuffer();
315
316     ASSERT(m_keyValueStore);
317     return m_keyValueStore->get(key);
318 }
319
320 IDBGetResult MemoryObjectStore::indexValueForKeyRange(uint64_t indexIdentifier, IndexedDB::IndexRecordType recordType, const IDBKeyRangeData& range) const
321 {
322     LOG(IndexedDB, "MemoryObjectStore::indexValueForKeyRange");
323
324     auto* index = m_indexesByIdentifier.get(indexIdentifier);
325     ASSERT(index);
326     return index->getResultForKeyRange(recordType, range);
327 }
328
329 IDBKeyData MemoryObjectStore::lowestKeyWithRecordInRange(const IDBKeyRangeData& keyRangeData) const
330 {
331     if (!m_keyValueStore)
332         return { };
333
334     if (keyRangeData.isExactlyOneKey() && m_keyValueStore->contains(keyRangeData.lowerKey))
335         return keyRangeData.lowerKey;
336
337     ASSERT(m_orderedKeys);
338
339     auto lowestInRange = m_orderedKeys->lower_bound(keyRangeData.lowerKey);
340
341     if (lowestInRange == m_orderedKeys->end())
342         return { };
343
344     if (keyRangeData.lowerOpen && *lowestInRange == keyRangeData.lowerKey)
345         ++lowestInRange;
346
347     if (lowestInRange == m_orderedKeys->end())
348         return { };
349
350     if (!keyRangeData.upperKey.isNull()) {
351         if (lowestInRange->compare(keyRangeData.upperKey) > 0)
352             return { };
353         if (keyRangeData.upperOpen && *lowestInRange == keyRangeData.upperKey)
354             return { };
355     }
356
357     return *lowestInRange;
358 }
359
360 void MemoryObjectStore::registerIndex(std::unique_ptr<MemoryIndex>&& index)
361 {
362     ASSERT(index);
363     ASSERT(!m_indexesByIdentifier.contains(index->info().identifier()));
364     ASSERT(!m_indexesByName.contains(index->info().name()));
365
366     m_indexesByName.set(index->info().name(), index.get());
367     m_indexesByIdentifier.set(index->info().identifier(), WTF::move(index));
368 }
369
370 void MemoryObjectStore::unregisterIndex(MemoryIndex& index)
371 {
372     ASSERT(m_indexesByIdentifier.contains(index.info().identifier()));
373     ASSERT(m_indexesByName.contains(index.info().name()));
374
375     m_indexesByName.remove(index.info().name());
376     m_indexesByIdentifier.remove(index.info().identifier());
377 }
378
379 MemoryObjectStoreCursor* MemoryObjectStore::maybeOpenCursor(const IDBCursorInfo& info)
380 {
381     auto result = m_cursors.add(info.identifier(), nullptr);
382     if (!result.isNewEntry)
383         return nullptr;
384
385     result.iterator->value = MemoryObjectStoreCursor::create(*this, info);
386     return result.iterator->value.get();
387 }
388
389 } // namespace IDBServer
390 } // namespace WebCore
391
392 #endif // ENABLE(INDEXED_DATABASE)