Replace WTF::move with WTFMove
[WebKit-https.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 #include "UniqueIDBDatabase.h"
39
40 #include <wtf/NeverDestroyed.h>
41
42 using namespace JSC;
43
44 namespace WebCore {
45 namespace IDBServer {
46
47 std::unique_ptr<MemoryObjectStore> MemoryObjectStore::create(const IDBObjectStoreInfo& info)
48 {
49     return std::make_unique<MemoryObjectStore>(info);
50 }
51
52 MemoryObjectStore::MemoryObjectStore(const IDBObjectStoreInfo& info)
53     : m_info(info)
54 {
55 }
56
57 MemoryObjectStore::~MemoryObjectStore()
58 {
59     m_writeTransaction = nullptr;
60 }
61
62 MemoryIndex* MemoryObjectStore::indexForIdentifier(uint64_t identifier)
63 {
64     ASSERT(identifier);
65     return m_indexesByIdentifier.get(identifier);
66 }
67
68 void MemoryObjectStore::writeTransactionStarted(MemoryBackingStoreTransaction& transaction)
69 {
70     LOG(IndexedDB, "MemoryObjectStore::writeTransactionStarted");
71
72     ASSERT(!m_writeTransaction);
73     m_writeTransaction = &transaction;
74 }
75
76 void MemoryObjectStore::writeTransactionFinished(MemoryBackingStoreTransaction& transaction)
77 {
78     LOG(IndexedDB, "MemoryObjectStore::writeTransactionFinished");
79
80     ASSERT_UNUSED(transaction, m_writeTransaction == &transaction);
81     m_writeTransaction = nullptr;
82 }
83
84 IDBError MemoryObjectStore::createIndex(MemoryBackingStoreTransaction& transaction, const IDBIndexInfo& info)
85 {
86     LOG(IndexedDB, "MemoryObjectStore::createIndex");
87
88     if (!m_writeTransaction || !m_writeTransaction->isVersionChange() || m_writeTransaction != &transaction)
89         return IDBError(IDBDatabaseException::ConstraintError);
90
91     ASSERT(!m_indexesByIdentifier.contains(info.identifier()));
92     auto index = MemoryIndex::create(info, *this);
93
94     // If there was an error populating the new index, then the current records in the object store violate its contraints
95     auto error = populateIndexWithExistingRecords(*index);
96     if (!error.isNull())
97         return error;
98
99     m_info.addExistingIndex(info);
100     transaction.addNewIndex(*index);
101     registerIndex(WTFMove(index));
102
103     return { };
104 }
105
106 void MemoryObjectStore::maybeRestoreDeletedIndex(std::unique_ptr<MemoryIndex> index)
107 {
108     LOG(IndexedDB, "MemoryObjectStore::maybeRestoreDeletedIndex");
109
110     ASSERT(index);
111
112     if (m_info.hasIndex(index->info().name()))
113         return;
114
115     m_info.addExistingIndex(index->info());
116
117     ASSERT(!m_indexesByIdentifier.contains(index->info().identifier()));
118     index->clearIndexValueStore();
119     auto error = populateIndexWithExistingRecords(*index);
120
121     // Since this index was installed in the object store before this transaction started,
122     // assuming things were in a valid state then, we should definitely be able to successfully
123     // repopulate the index with the object store's pre-transaction records.
124     ASSERT_UNUSED(error, error.isNull());
125
126     registerIndex(WTFMove(index));
127 }
128
129 std::unique_ptr<MemoryIndex> MemoryObjectStore::takeIndexByName(const String& name)
130 {
131     auto rawIndex = m_indexesByName.take(name);
132     if (!rawIndex)
133         return nullptr;
134
135     auto index = m_indexesByIdentifier.take(rawIndex->info().identifier());
136     ASSERT(index);
137
138     return index;
139 }
140
141 IDBError MemoryObjectStore::deleteIndex(MemoryBackingStoreTransaction& transaction, const String& indexName)
142 {
143     LOG(IndexedDB, "MemoryObjectStore::deleteIndex");
144
145     if (!m_writeTransaction || !m_writeTransaction->isVersionChange() || m_writeTransaction != &transaction)
146         return IDBError(IDBDatabaseException::ConstraintError);
147     
148     auto index = takeIndexByName(indexName);
149     ASSERT(index);
150     if (!index)
151         return IDBError(IDBDatabaseException::ConstraintError);
152
153     m_info.deleteIndex(indexName);
154     transaction.indexDeleted(WTFMove(index));
155
156     return { };
157 }
158
159 bool MemoryObjectStore::containsRecord(const IDBKeyData& key)
160 {
161     if (!m_keyValueStore)
162         return false;
163
164     return m_keyValueStore->contains(key);
165 }
166
167 void MemoryObjectStore::clear()
168 {
169     LOG(IndexedDB, "MemoryObjectStore::clear");
170     ASSERT(m_writeTransaction);
171
172     m_writeTransaction->objectStoreCleared(*this, WTFMove(m_keyValueStore), WTFMove(m_orderedKeys));
173     for (auto& index : m_indexesByIdentifier.values())
174         index->objectStoreCleared();
175
176     for (auto& cursor : m_cursors.values())
177         cursor->objectStoreCleared();
178 }
179
180 void MemoryObjectStore::replaceKeyValueStore(std::unique_ptr<KeyValueMap>&& store, std::unique_ptr<std::set<IDBKeyData>>&& orderedKeys)
181 {
182     ASSERT(m_writeTransaction);
183     ASSERT(m_writeTransaction->isAborting());
184
185     m_keyValueStore = WTFMove(store);
186     m_orderedKeys = WTFMove(orderedKeys);
187 }
188
189 void MemoryObjectStore::deleteRecord(const IDBKeyData& key)
190 {
191     LOG(IndexedDB, "MemoryObjectStore::deleteRecord");
192
193     ASSERT(m_writeTransaction);
194
195     if (!m_keyValueStore) {
196         m_writeTransaction->recordValueChanged(*this, key, nullptr);
197         return;
198     }
199
200     ASSERT(m_orderedKeys);
201
202     auto iterator = m_keyValueStore->find(key);
203     if (iterator == m_keyValueStore->end()) {
204         m_writeTransaction->recordValueChanged(*this, key, nullptr);
205         return;
206     }
207
208     m_writeTransaction->recordValueChanged(*this, key, &iterator->value);
209     m_keyValueStore->remove(iterator);
210     m_orderedKeys->erase(key);
211
212     updateIndexesForDeleteRecord(key);
213     updateCursorsForDeleteRecord(key);
214 }
215
216 void MemoryObjectStore::deleteRange(const IDBKeyRangeData& inputRange)
217 {
218     LOG(IndexedDB, "MemoryObjectStore::deleteRange");
219
220     ASSERT(m_writeTransaction);
221
222     if (inputRange.isExactlyOneKey()) {
223         deleteRecord(inputRange.lowerKey);
224         return;
225     }
226
227     IDBKeyRangeData range = inputRange;
228     while (true) {
229         auto key = lowestKeyWithRecordInRange(range);
230         if (key.isNull())
231             break;
232
233         deleteRecord(key);
234
235         range.lowerKey = key;
236         range.lowerOpen = true;
237     }
238 }
239
240 IDBError MemoryObjectStore::addRecord(MemoryBackingStoreTransaction& transaction, const IDBKeyData& keyData, const ThreadSafeDataBuffer& value)
241 {
242     LOG(IndexedDB, "MemoryObjectStore::addRecord");
243
244     ASSERT(m_writeTransaction);
245     ASSERT_UNUSED(transaction, m_writeTransaction == &transaction);
246     ASSERT(!m_keyValueStore || !m_keyValueStore->contains(keyData));
247     ASSERT(!m_orderedKeys || m_orderedKeys->find(keyData) == m_orderedKeys->end());
248
249     if (!m_keyValueStore) {
250         ASSERT(!m_orderedKeys);
251         m_keyValueStore = std::make_unique<KeyValueMap>();
252         m_orderedKeys = std::make_unique<std::set<IDBKeyData>>();
253     }
254
255     auto mapResult = m_keyValueStore->set(keyData, value);
256     ASSERT(mapResult.isNewEntry);
257     auto listResult = m_orderedKeys->insert(keyData);
258     ASSERT(listResult.second);
259
260     // If there was an error indexing this addition, then revert it.
261     auto error = updateIndexesForPutRecord(keyData, value);
262     if (!error.isNull()) {
263         m_keyValueStore->remove(mapResult.iterator);
264         m_orderedKeys->erase(listResult.first);
265     } else
266         updateCursorsForPutRecord(listResult.first);
267
268     return error;
269 }
270
271 void MemoryObjectStore::updateCursorsForPutRecord(std::set<IDBKeyData>::iterator iterator)
272 {
273     for (auto& cursor : m_cursors.values())
274         cursor->keyAdded(iterator);
275 }
276
277 void MemoryObjectStore::updateCursorsForDeleteRecord(const IDBKeyData& key)
278 {
279     for (auto& cursor : m_cursors.values())
280         cursor->keyDeleted(key);
281 }
282
283 void MemoryObjectStore::updateIndexesForDeleteRecord(const IDBKeyData& value)
284 {
285     for (auto* index : m_indexesByName.values())
286         index->removeEntriesWithValueKey(value);
287 }
288
289 IDBError MemoryObjectStore::updateIndexesForPutRecord(const IDBKeyData& key, const ThreadSafeDataBuffer& value)
290 {
291     JSLockHolder locker(UniqueIDBDatabase::databaseThreadVM());
292
293     auto jsValue = idbValueDataToJSValue(UniqueIDBDatabase::databaseThreadExecState(), value);
294     if (jsValue.isUndefinedOrNull())
295         return { };
296
297     IDBError error;
298     Vector<std::pair<MemoryIndex*, IndexKey>> changedIndexRecords;
299
300     for (auto* index : m_indexesByName.values()) {
301         IndexKey indexKey;
302         generateIndexKeyForValue(UniqueIDBDatabase::databaseThreadExecState(), index->info(), jsValue, indexKey);
303
304         if (indexKey.isNull())
305             continue;
306
307         error = index->putIndexKey(key, indexKey);
308         if (!error.isNull())
309             break;
310
311         changedIndexRecords.append(std::make_pair(index, indexKey));
312     }
313
314     // If any of the index puts failed, revert all of the ones that went through.
315     if (!error.isNull()) {
316         for (auto& record : changedIndexRecords)
317             record.first->removeRecord(key, record.second);
318     }
319
320     return error;
321 }
322
323 IDBError MemoryObjectStore::populateIndexWithExistingRecords(MemoryIndex& index)
324 {
325     if (!m_keyValueStore)
326         return { };
327
328     JSLockHolder locker(UniqueIDBDatabase::databaseThreadVM());
329
330     for (auto iterator : *m_keyValueStore) {
331         auto jsValue = idbValueDataToJSValue(UniqueIDBDatabase::databaseThreadExecState(), iterator.value);
332         if (jsValue.isUndefinedOrNull())
333             return { };
334
335         IndexKey indexKey;
336         generateIndexKeyForValue(UniqueIDBDatabase::databaseThreadExecState(), index.info(), jsValue, indexKey);
337
338         if (indexKey.isNull())
339             continue;
340
341         IDBError error = index.putIndexKey(iterator.key, indexKey);
342         if (!error.isNull())
343             return error;
344     }
345
346     return { };
347 }
348
349 uint64_t MemoryObjectStore::countForKeyRange(uint64_t indexIdentifier, const IDBKeyRangeData& inRange) const
350 {
351     LOG(IndexedDB, "MemoryObjectStore::countForKeyRange");
352
353     if (indexIdentifier) {
354         auto* index = m_indexesByIdentifier.get(indexIdentifier);
355         ASSERT(index);
356         return index->countForKeyRange(inRange);
357     }
358
359     if (!m_keyValueStore)
360         return 0;
361
362     uint64_t count = 0;
363     IDBKeyRangeData range = inRange;
364     while (true) {
365         auto key = lowestKeyWithRecordInRange(range);
366         if (key.isNull())
367             break;
368
369         ++count;
370         range.lowerKey = key;
371         range.lowerOpen = true;
372     }
373
374     return count;
375 }
376
377 ThreadSafeDataBuffer MemoryObjectStore::valueForKey(const IDBKeyData& key) const
378 {
379     if (!m_keyValueStore)
380         return { };
381
382     return m_keyValueStore->get(key);
383 }
384
385 ThreadSafeDataBuffer MemoryObjectStore::valueForKeyRange(const IDBKeyRangeData& keyRangeData) const
386 {
387     LOG(IndexedDB, "MemoryObjectStore::valueForKey");
388
389     IDBKeyData key = lowestKeyWithRecordInRange(keyRangeData);
390     if (key.isNull())
391         return ThreadSafeDataBuffer();
392
393     ASSERT(m_keyValueStore);
394     return m_keyValueStore->get(key);
395 }
396
397 IDBGetResult MemoryObjectStore::indexValueForKeyRange(uint64_t indexIdentifier, IndexedDB::IndexRecordType recordType, const IDBKeyRangeData& range) const
398 {
399     LOG(IndexedDB, "MemoryObjectStore::indexValueForKeyRange");
400
401     auto* index = m_indexesByIdentifier.get(indexIdentifier);
402     ASSERT(index);
403     return index->getResultForKeyRange(recordType, range);
404 }
405
406 IDBKeyData MemoryObjectStore::lowestKeyWithRecordInRange(const IDBKeyRangeData& keyRangeData) const
407 {
408     if (!m_keyValueStore)
409         return { };
410
411     if (keyRangeData.isExactlyOneKey() && m_keyValueStore->contains(keyRangeData.lowerKey))
412         return keyRangeData.lowerKey;
413
414     ASSERT(m_orderedKeys);
415
416     auto lowestInRange = m_orderedKeys->lower_bound(keyRangeData.lowerKey);
417
418     if (lowestInRange == m_orderedKeys->end())
419         return { };
420
421     if (keyRangeData.lowerOpen && *lowestInRange == keyRangeData.lowerKey)
422         ++lowestInRange;
423
424     if (lowestInRange == m_orderedKeys->end())
425         return { };
426
427     if (!keyRangeData.upperKey.isNull()) {
428         if (lowestInRange->compare(keyRangeData.upperKey) > 0)
429             return { };
430         if (keyRangeData.upperOpen && *lowestInRange == keyRangeData.upperKey)
431             return { };
432     }
433
434     return *lowestInRange;
435 }
436
437 void MemoryObjectStore::registerIndex(std::unique_ptr<MemoryIndex>&& index)
438 {
439     ASSERT(index);
440     ASSERT(!m_indexesByIdentifier.contains(index->info().identifier()));
441     ASSERT(!m_indexesByName.contains(index->info().name()));
442
443     m_indexesByName.set(index->info().name(), index.get());
444     m_indexesByIdentifier.set(index->info().identifier(), WTFMove(index));
445 }
446
447 void MemoryObjectStore::unregisterIndex(MemoryIndex& index)
448 {
449     ASSERT(m_indexesByIdentifier.contains(index.info().identifier()));
450     ASSERT(m_indexesByName.contains(index.info().name()));
451
452     m_indexesByName.remove(index.info().name());
453     m_indexesByIdentifier.remove(index.info().identifier());
454 }
455
456 MemoryObjectStoreCursor* MemoryObjectStore::maybeOpenCursor(const IDBCursorInfo& info)
457 {
458     auto result = m_cursors.add(info.identifier(), nullptr);
459     if (!result.isNewEntry)
460         return nullptr;
461
462     result.iterator->value = std::make_unique<MemoryObjectStoreCursor>(*this, info);
463     return result.iterator->value.get();
464 }
465
466 } // namespace IDBServer
467 } // namespace WebCore
468
469 #endif // ENABLE(INDEXED_DATABASE)