Modern IDB: Make indexes actually index.
[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::addExistingObjectStore(MemoryObjectStore& objectStore)
90 {
91     LOG(IndexedDB, "MemoryBackingStoreTransaction::addExistingObjectStore");
92
93     ASSERT(isWriting());
94
95     ASSERT(!m_objectStores.contains(&objectStore));
96     m_objectStores.add(&objectStore);
97
98     objectStore.writeTransactionStarted(*this);
99
100     m_originalKeyGenerators.add(&objectStore, objectStore.currentKeyGeneratorValue());
101 }
102
103 void MemoryBackingStoreTransaction::objectStoreDeleted(std::unique_ptr<MemoryObjectStore> objectStore)
104 {
105     ASSERT(objectStore);
106     ASSERT(m_objectStores.contains(objectStore.get()));
107     m_objectStores.remove(objectStore.get());
108
109     auto addResult = m_deletedObjectStores.add(objectStore->info().name(), nullptr);
110     if (addResult.isNewEntry)
111         addResult.iterator->value = WTF::move(objectStore);
112 }
113
114 void MemoryBackingStoreTransaction::objectStoreCleared(MemoryObjectStore& objectStore, std::unique_ptr<KeyValueMap>&& keyValueMap)
115 {
116     ASSERT(m_objectStores.contains(&objectStore));
117
118     auto addResult = m_clearedKeyValueMaps.add(&objectStore, nullptr);
119
120     // If this object store has already been cleared during this transaction, we shouldn't remember this clearing.
121     if (!addResult.isNewEntry)
122         return;
123
124     addResult.iterator->value = WTF::move(keyValueMap);
125 }
126
127 void MemoryBackingStoreTransaction::indexCleared(MemoryIndex& index, std::unique_ptr<IndexValueStore>&& valueStore)
128 {
129     auto addResult = m_clearedIndexValueStores.add(&index, nullptr);
130
131     // If this index has already been cleared during this transaction, we shouldn't remember this clearing.
132     if (!addResult.isNewEntry)
133         return;
134
135     addResult.iterator->value = WTF::move(valueStore);
136 }
137
138 void MemoryBackingStoreTransaction::recordValueChanged(MemoryObjectStore& objectStore, const IDBKeyData& key, ThreadSafeDataBuffer* value)
139 {
140     ASSERT(m_objectStores.contains(&objectStore));
141
142     if (m_isAborting)
143         return;
144
145     // If this object store had been cleared during the transaction, no point in recording this
146     // individual key/value change as its entire key/value map will be restored upon abort.
147     if (m_clearedKeyValueMaps.contains(&objectStore))
148         return;
149
150     auto originalAddResult = m_originalValues.add(&objectStore, nullptr);
151     if (originalAddResult.isNewEntry)
152         originalAddResult.iterator->value = std::make_unique<KeyValueMap>();
153
154     auto* map = originalAddResult.iterator->value.get();
155
156     auto addResult = map->add(key, ThreadSafeDataBuffer());
157     if (!addResult.isNewEntry)
158         return;
159
160     if (value)
161         addResult.iterator->value = *value;
162 }
163
164 void MemoryBackingStoreTransaction::abort()
165 {
166     LOG(IndexedDB, "MemoryBackingStoreTransaction::abort()");
167
168     TemporaryChange<bool> change(m_isAborting, true);
169
170     // This loop moves the underlying unique_ptrs from out of the m_deleteObjectStores map,
171     // but the entries in the map still remain.
172     for (auto& objectStore : m_deletedObjectStores.values()) {
173         MemoryObjectStore* rawObjectStore = objectStore.get();
174         m_backingStore.restoreObjectStoreForVersionChangeAbort(WTF::move(objectStore));
175
176         ASSERT(!m_objectStores.contains(rawObjectStore));
177         m_objectStores.add(rawObjectStore);
178     }
179
180     // This clears the entries from the map.
181     m_deletedObjectStores.clear();
182
183     if (m_originalDatabaseInfo) {
184         ASSERT(m_info.mode() == IndexedDB::TransactionMode::VersionChange);
185         m_backingStore.setDatabaseInfo(*m_originalDatabaseInfo);
186     }
187
188     // Restore cleared index value stores before we re-insert values into object stores
189     // because inserting those values will regenerate the appropriate index values.
190     for (auto& iterator : m_clearedIndexValueStores)
191         iterator.key->replaceIndexValueStore(WTF::move(iterator.value));
192     m_clearedIndexValueStores.clear();
193     
194     for (auto objectStore : m_objectStores) {
195         ASSERT(m_originalKeyGenerators.contains(objectStore));
196         objectStore->setKeyGeneratorValue(m_originalKeyGenerators.get(objectStore));
197
198         auto clearedKeyValueMap = m_clearedKeyValueMaps.take(objectStore);
199         if (clearedKeyValueMap)
200             objectStore->replaceKeyValueStore(WTF::move(clearedKeyValueMap));
201
202         auto keyValueMap = m_originalValues.take(objectStore);
203         if (!keyValueMap)
204             continue;
205
206         for (auto entry : *keyValueMap) {
207             objectStore->deleteRecord(entry.key);
208             objectStore->addRecord(*this, entry.key, entry.value);
209         }
210     }
211
212     finish();
213
214     for (auto objectStore : m_versionChangeAddedObjectStores)
215         m_backingStore.removeObjectStoreForVersionChangeAbort(*objectStore);
216 }
217
218 void MemoryBackingStoreTransaction::commit()
219 {
220     LOG(IndexedDB, "MemoryBackingStoreTransaction::commit()");
221
222     finish();
223 }
224
225 void MemoryBackingStoreTransaction::finish()
226 {
227     m_inProgress = false;
228
229     if (!isWriting())
230         return;
231
232     for (auto& objectStore : m_objectStores)
233         objectStore->writeTransactionFinished(*this);
234     for (auto& objectStore : m_deletedObjectStores.values())
235         objectStore->writeTransactionFinished(*this);
236 }
237
238 } // namespace IDBServer
239 } // namespace WebCore
240
241 #endif // ENABLE(INDEXED_DATABASE)