Modern IDB: IDBObjectStore.deleteIndex() support.
[WebKit-https.git] / Source / WebCore / Modules / indexeddb / server / MemoryBackingStoreTransaction.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 "MemoryBackingStoreTransaction.h"
28
29 #if ENABLE(INDEXED_DATABASE)
30
31 #include "IDBKeyRangeData.h"
32 #include "IndexedDB.h"
33 #include "Logging.h"
34 #include "MemoryIDBBackingStore.h"
35 #include "MemoryObjectStore.h"
36 #include <wtf/TemporaryChange.h>
37
38 namespace WebCore {
39 namespace IDBServer {
40
41 std::unique_ptr<MemoryBackingStoreTransaction> MemoryBackingStoreTransaction::create(MemoryIDBBackingStore& backingStore, const IDBTransactionInfo& info)
42 {
43     return std::make_unique<MemoryBackingStoreTransaction>(backingStore, info);
44 }
45
46 MemoryBackingStoreTransaction::MemoryBackingStoreTransaction(MemoryIDBBackingStore& backingStore, const IDBTransactionInfo& info)
47     : m_backingStore(backingStore)
48     , m_info(info)
49 {
50     if (m_info.mode() == IndexedDB::TransactionMode::VersionChange)
51         m_originalDatabaseInfo = std::make_unique<IDBDatabaseInfo>(m_backingStore.getOrEstablishDatabaseInfo());
52 }
53
54 MemoryBackingStoreTransaction::~MemoryBackingStoreTransaction()
55 {
56     ASSERT(!m_inProgress);
57 }
58
59 void MemoryBackingStoreTransaction::addNewObjectStore(MemoryObjectStore& objectStore)
60 {
61     LOG(IndexedDB, "MemoryBackingStoreTransaction::addNewObjectStore()");
62
63     ASSERT(isVersionChange());
64     m_versionChangeAddedObjectStores.add(&objectStore);
65
66     addExistingObjectStore(objectStore);
67 }
68
69 void MemoryBackingStoreTransaction::addNewIndex(MemoryIndex& index)
70 {
71     LOG(IndexedDB, "MemoryBackingStoreTransaction::addNewIndex()");
72
73     ASSERT(isVersionChange());
74     m_versionChangeAddedIndexes.add(&index);
75
76     addExistingIndex(index);
77 }
78
79 void MemoryBackingStoreTransaction::addExistingIndex(MemoryIndex& index)
80 {
81     LOG(IndexedDB, "MemoryBackingStoreTransaction::addExistingIndex");
82
83     ASSERT(isWriting());
84
85     ASSERT(!m_indexes.contains(&index));
86     m_indexes.add(&index);
87 }
88
89 void MemoryBackingStoreTransaction::indexDeleted(std::unique_ptr<MemoryIndex> index)
90 {
91     ASSERT(index);
92     m_indexes.remove(index.get());
93
94     auto addResult = m_deletedIndexes.add(index->info().name(), nullptr);
95     if (addResult.isNewEntry)
96         addResult.iterator->value = WTF::move(index);
97 }
98
99 void MemoryBackingStoreTransaction::addExistingObjectStore(MemoryObjectStore& objectStore)
100 {
101     LOG(IndexedDB, "MemoryBackingStoreTransaction::addExistingObjectStore");
102
103     ASSERT(isWriting());
104
105     ASSERT(!m_objectStores.contains(&objectStore));
106     m_objectStores.add(&objectStore);
107
108     objectStore.writeTransactionStarted(*this);
109
110     m_originalKeyGenerators.add(&objectStore, objectStore.currentKeyGeneratorValue());
111 }
112
113 void MemoryBackingStoreTransaction::objectStoreDeleted(std::unique_ptr<MemoryObjectStore> objectStore)
114 {
115     ASSERT(objectStore);
116     ASSERT(m_objectStores.contains(objectStore.get()));
117     m_objectStores.remove(objectStore.get());
118
119     auto addResult = m_deletedObjectStores.add(objectStore->info().name(), nullptr);
120     if (addResult.isNewEntry)
121         addResult.iterator->value = WTF::move(objectStore);
122 }
123
124 void MemoryBackingStoreTransaction::objectStoreCleared(MemoryObjectStore& objectStore, std::unique_ptr<KeyValueMap>&& keyValueMap, std::unique_ptr<std::set<IDBKeyData>>&& orderedKeys)
125 {
126     ASSERT(m_objectStores.contains(&objectStore));
127
128     auto addResult = m_clearedKeyValueMaps.add(&objectStore, nullptr);
129
130     // If this object store has already been cleared during this transaction, we shouldn't remember this clearing.
131     if (!addResult.isNewEntry)
132         return;
133
134     addResult.iterator->value = WTF::move(keyValueMap);
135
136     ASSERT(!m_clearedOrderedKeys.contains(&objectStore));
137     m_clearedOrderedKeys.add(&objectStore, WTF::move(orderedKeys));
138 }
139
140 void MemoryBackingStoreTransaction::indexCleared(MemoryIndex& index, std::unique_ptr<IndexValueStore>&& valueStore)
141 {
142     auto addResult = m_clearedIndexValueStores.add(&index, nullptr);
143
144     // If this index has already been cleared during this transaction, we shouldn't remember this clearing.
145     if (!addResult.isNewEntry)
146         return;
147
148     addResult.iterator->value = WTF::move(valueStore);
149 }
150
151 void MemoryBackingStoreTransaction::recordValueChanged(MemoryObjectStore& objectStore, const IDBKeyData& key, ThreadSafeDataBuffer* value)
152 {
153     ASSERT(m_objectStores.contains(&objectStore));
154
155     if (m_isAborting)
156         return;
157
158     // If this object store had been cleared during the transaction, no point in recording this
159     // individual key/value change as its entire key/value map will be restored upon abort.
160     if (m_clearedKeyValueMaps.contains(&objectStore))
161         return;
162
163     auto originalAddResult = m_originalValues.add(&objectStore, nullptr);
164     if (originalAddResult.isNewEntry)
165         originalAddResult.iterator->value = std::make_unique<KeyValueMap>();
166
167     auto* map = originalAddResult.iterator->value.get();
168
169     auto addResult = map->add(key, ThreadSafeDataBuffer());
170     if (!addResult.isNewEntry)
171         return;
172
173     if (value)
174         addResult.iterator->value = *value;
175 }
176
177 void MemoryBackingStoreTransaction::abort()
178 {
179     LOG(IndexedDB, "MemoryBackingStoreTransaction::abort()");
180
181     TemporaryChange<bool> change(m_isAborting, true);
182
183     // This loop moves the underlying unique_ptrs from out of the m_deletedObjectStores map,
184     // but the entries in the map still remain.
185     for (auto& objectStore : m_deletedObjectStores.values()) {
186         MemoryObjectStore* rawObjectStore = objectStore.get();
187         m_backingStore.restoreObjectStoreForVersionChangeAbort(WTF::move(objectStore));
188
189         ASSERT(!m_objectStores.contains(rawObjectStore));
190         m_objectStores.add(rawObjectStore);
191     }
192
193     // This clears the entries from the map.
194     m_deletedObjectStores.clear();
195
196     if (m_originalDatabaseInfo) {
197         ASSERT(m_info.mode() == IndexedDB::TransactionMode::VersionChange);
198         m_backingStore.setDatabaseInfo(*m_originalDatabaseInfo);
199     }
200
201     // Restore cleared index value stores before we re-insert values into object stores
202     // because inserting those values will regenerate the appropriate index values.
203     for (auto& iterator : m_clearedIndexValueStores)
204         iterator.key->replaceIndexValueStore(WTF::move(iterator.value));
205     m_clearedIndexValueStores.clear();
206     
207     for (auto objectStore : m_objectStores) {
208         ASSERT(m_originalKeyGenerators.contains(objectStore));
209         objectStore->setKeyGeneratorValue(m_originalKeyGenerators.get(objectStore));
210
211         auto clearedKeyValueMap = m_clearedKeyValueMaps.take(objectStore);
212         if (clearedKeyValueMap) {
213             ASSERT(m_clearedOrderedKeys.contains(objectStore));
214             objectStore->replaceKeyValueStore(WTF::move(clearedKeyValueMap), m_clearedOrderedKeys.take(objectStore));
215         }
216
217         auto keyValueMap = m_originalValues.take(objectStore);
218         if (!keyValueMap)
219             continue;
220
221         for (auto entry : *keyValueMap) {
222             objectStore->deleteRecord(entry.key);
223             objectStore->addRecord(*this, entry.key, entry.value);
224         }
225     }
226
227     // This loop moves the underlying unique_ptrs from out of the m_deletedIndexes map,
228     // but the entries in the map still remain.
229     for (auto& index : m_deletedIndexes.values()) {
230         MemoryObjectStore& objectStore = index->objectStore();
231         objectStore.maybeRestoreDeletedIndex(WTF::move(index));
232     }
233
234     // This clears the entries from the map.
235     m_deletedIndexes.clear();
236
237     finish();
238
239     for (auto objectStore : m_versionChangeAddedObjectStores)
240         m_backingStore.removeObjectStoreForVersionChangeAbort(*objectStore);
241 }
242
243 void MemoryBackingStoreTransaction::commit()
244 {
245     LOG(IndexedDB, "MemoryBackingStoreTransaction::commit()");
246
247     finish();
248 }
249
250 void MemoryBackingStoreTransaction::finish()
251 {
252     m_inProgress = false;
253
254     if (!isWriting())
255         return;
256
257     for (auto& objectStore : m_objectStores)
258         objectStore->writeTransactionFinished(*this);
259     for (auto& objectStore : m_deletedObjectStores.values())
260         objectStore->writeTransactionFinished(*this);
261 }
262
263 } // namespace IDBServer
264 } // namespace WebCore
265
266 #endif // ENABLE(INDEXED_DATABASE)