Modern IDB: Memory indexes aren't deleted when their owning memory object stores...
[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 = WTFMove(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     objectStore->deleteAllIndexes(*this);
120
121     auto addResult = m_deletedObjectStores.add(objectStore->info().name(), nullptr);
122     if (addResult.isNewEntry)
123         addResult.iterator->value = WTFMove(objectStore);
124 }
125
126 void MemoryBackingStoreTransaction::objectStoreCleared(MemoryObjectStore& objectStore, std::unique_ptr<KeyValueMap>&& keyValueMap, std::unique_ptr<std::set<IDBKeyData>>&& orderedKeys)
127 {
128     ASSERT(m_objectStores.contains(&objectStore));
129
130     auto addResult = m_clearedKeyValueMaps.add(&objectStore, nullptr);
131
132     // If this object store has already been cleared during this transaction, we shouldn't remember this clearing.
133     if (!addResult.isNewEntry)
134         return;
135
136     addResult.iterator->value = WTFMove(keyValueMap);
137
138     ASSERT(!m_clearedOrderedKeys.contains(&objectStore));
139     m_clearedOrderedKeys.add(&objectStore, WTFMove(orderedKeys));
140 }
141
142 void MemoryBackingStoreTransaction::indexCleared(MemoryIndex& index, std::unique_ptr<IndexValueStore>&& valueStore)
143 {
144     auto addResult = m_clearedIndexValueStores.add(&index, nullptr);
145
146     // If this index has already been cleared during this transaction, we shouldn't remember this clearing.
147     if (!addResult.isNewEntry)
148         return;
149
150     addResult.iterator->value = WTFMove(valueStore);
151 }
152
153 void MemoryBackingStoreTransaction::recordValueChanged(MemoryObjectStore& objectStore, const IDBKeyData& key, ThreadSafeDataBuffer* value)
154 {
155     ASSERT(m_objectStores.contains(&objectStore));
156
157     if (m_isAborting)
158         return;
159
160     // If this object store had been cleared during the transaction, no point in recording this
161     // individual key/value change as its entire key/value map will be restored upon abort.
162     if (m_clearedKeyValueMaps.contains(&objectStore))
163         return;
164
165     auto originalAddResult = m_originalValues.add(&objectStore, nullptr);
166     if (originalAddResult.isNewEntry)
167         originalAddResult.iterator->value = std::make_unique<KeyValueMap>();
168
169     auto* map = originalAddResult.iterator->value.get();
170
171     auto addResult = map->add(key, ThreadSafeDataBuffer());
172     if (!addResult.isNewEntry)
173         return;
174
175     if (value)
176         addResult.iterator->value = *value;
177 }
178
179 void MemoryBackingStoreTransaction::abort()
180 {
181     LOG(IndexedDB, "MemoryBackingStoreTransaction::abort()");
182
183     TemporaryChange<bool> change(m_isAborting, true);
184
185     // This loop moves the underlying unique_ptrs from out of the m_deletedObjectStores map,
186     // but the entries in the map still remain.
187     for (auto& objectStore : m_deletedObjectStores.values()) {
188         MemoryObjectStore* rawObjectStore = objectStore.get();
189         m_backingStore.restoreObjectStoreForVersionChangeAbort(WTFMove(objectStore));
190
191         ASSERT(!m_objectStores.contains(rawObjectStore));
192         m_objectStores.add(rawObjectStore);
193     }
194
195     // This clears the entries from the map.
196     m_deletedObjectStores.clear();
197
198     if (m_originalDatabaseInfo) {
199         ASSERT(m_info.mode() == IndexedDB::TransactionMode::VersionChange);
200         m_backingStore.setDatabaseInfo(*m_originalDatabaseInfo);
201     }
202
203     // Restore cleared index value stores before we re-insert values into object stores
204     // because inserting those values will regenerate the appropriate index values.
205     for (auto& iterator : m_clearedIndexValueStores)
206         iterator.key->replaceIndexValueStore(WTFMove(iterator.value));
207     m_clearedIndexValueStores.clear();
208     
209     for (auto objectStore : m_objectStores) {
210         ASSERT(m_originalKeyGenerators.contains(objectStore));
211         objectStore->setKeyGeneratorValue(m_originalKeyGenerators.get(objectStore));
212
213         auto clearedKeyValueMap = m_clearedKeyValueMaps.take(objectStore);
214         if (clearedKeyValueMap) {
215             ASSERT(m_clearedOrderedKeys.contains(objectStore));
216             objectStore->replaceKeyValueStore(WTFMove(clearedKeyValueMap), m_clearedOrderedKeys.take(objectStore));
217         }
218
219         auto keyValueMap = m_originalValues.take(objectStore);
220         if (!keyValueMap)
221             continue;
222
223         for (auto entry : *keyValueMap) {
224             objectStore->deleteRecord(entry.key);
225             objectStore->addRecord(*this, entry.key, entry.value);
226         }
227     }
228
229     // This loop moves the underlying unique_ptrs from out of the m_deletedIndexes map,
230     // but the entries in the map still remain.
231     for (auto& index : m_deletedIndexes.values()) {
232         MemoryObjectStore& objectStore = index->objectStore();
233         objectStore.maybeRestoreDeletedIndex(WTFMove(index));
234     }
235
236     // This clears the entries from the map.
237     m_deletedIndexes.clear();
238
239     finish();
240
241     for (auto objectStore : m_versionChangeAddedObjectStores)
242         m_backingStore.removeObjectStoreForVersionChangeAbort(*objectStore);
243 }
244
245 void MemoryBackingStoreTransaction::commit()
246 {
247     LOG(IndexedDB, "MemoryBackingStoreTransaction::commit()");
248
249     finish();
250 }
251
252 void MemoryBackingStoreTransaction::finish()
253 {
254     m_inProgress = false;
255
256     if (!isWriting())
257         return;
258
259     for (auto& objectStore : m_objectStores)
260         objectStore->writeTransactionFinished(*this);
261     for (auto& objectStore : m_deletedObjectStores.values())
262         objectStore->writeTransactionFinished(*this);
263 }
264
265 } // namespace IDBServer
266 } // namespace WebCore
267
268 #endif // ENABLE(INDEXED_DATABASE)