22a6ae8a5c8dc61477e2a56402658ecc732c8d7d
[WebKit-https.git] / Source / WebCore / Modules / indexeddb / server / MemoryIndex.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 "MemoryIndex.h"
28
29 #if ENABLE(INDEXED_DATABASE)
30
31 #include "IDBError.h"
32 #include "IDBGetAllResult.h"
33 #include "IDBGetResult.h"
34 #include "IDBKeyRangeData.h"
35 #include "IndexKey.h"
36 #include "Logging.h"
37 #include "MemoryBackingStoreTransaction.h"
38 #include "MemoryIndexCursor.h"
39 #include "MemoryObjectStore.h"
40 #include "ThreadSafeDataBuffer.h"
41
42 namespace WebCore {
43 namespace IDBServer {
44
45 Ref<MemoryIndex> MemoryIndex::create(const IDBIndexInfo& info, MemoryObjectStore& objectStore)
46 {
47     return adoptRef(*new MemoryIndex(info, objectStore));
48 }
49
50 MemoryIndex::MemoryIndex(const IDBIndexInfo& info, MemoryObjectStore& objectStore)
51     : m_info(info)
52     , m_objectStore(objectStore)
53 {
54 }
55
56 MemoryIndex::~MemoryIndex() = default;
57
58 void MemoryIndex::cursorDidBecomeClean(MemoryIndexCursor& cursor)
59 {
60     m_cleanCursors.add(&cursor);
61 }
62
63 void MemoryIndex::cursorDidBecomeDirty(MemoryIndexCursor& cursor)
64 {
65     m_cleanCursors.remove(&cursor);
66 }
67
68 void MemoryIndex::objectStoreCleared()
69 {
70     auto transaction = m_objectStore.writeTransaction();
71     ASSERT(transaction);
72
73     transaction->indexCleared(*this, WTFMove(m_records));
74
75     notifyCursorsOfAllRecordsChanged();
76 }
77
78 void MemoryIndex::notifyCursorsOfValueChange(const IDBKeyData& indexKey, const IDBKeyData& primaryKey)
79 {
80     for (auto* cursor : copyToVector(m_cleanCursors))
81         cursor->indexValueChanged(indexKey, primaryKey);
82 }
83
84 void MemoryIndex::notifyCursorsOfAllRecordsChanged()
85 {
86     for (auto* cursor : copyToVector(m_cleanCursors))
87         cursor->indexRecordsAllChanged();
88
89     ASSERT(m_cleanCursors.isEmpty());
90 }
91
92 void MemoryIndex::clearIndexValueStore()
93 {
94     ASSERT(m_objectStore.writeTransaction());
95     ASSERT(m_objectStore.writeTransaction()->isAborting());
96
97     m_records = nullptr;
98 }
99
100 void MemoryIndex::replaceIndexValueStore(std::unique_ptr<IndexValueStore>&& valueStore)
101 {
102     ASSERT(m_objectStore.writeTransaction());
103     ASSERT(m_objectStore.writeTransaction()->isAborting());
104
105     m_records = WTFMove(valueStore);
106 }
107
108 IDBGetResult MemoryIndex::getResultForKeyRange(IndexedDB::IndexRecordType type, const IDBKeyRangeData& range) const
109 {
110     LOG(IndexedDB, "MemoryIndex::getResultForKeyRange - %s", range.loggingString().utf8().data());
111
112     if (!m_records)
113         return { };
114
115     IDBKeyData keyToLookFor;
116     if (range.isExactlyOneKey())
117         keyToLookFor = range.lowerKey;
118     else
119         keyToLookFor = m_records->lowestKeyWithRecordInRange(range);
120
121     if (keyToLookFor.isNull())
122         return { };
123
124     const IDBKeyData* keyValue = m_records->lowestValueForKey(keyToLookFor);
125
126     if (!keyValue)
127         return { };
128
129     return type == IndexedDB::IndexRecordType::Key ? IDBGetResult(*keyValue) : IDBGetResult(m_objectStore.valueForKeyRange(*keyValue));
130 }
131
132 uint64_t MemoryIndex::countForKeyRange(const IDBKeyRangeData& inRange)
133 {
134     LOG(IndexedDB, "MemoryIndex::countForKeyRange");
135
136     if (!m_records)
137         return 0;
138
139     uint64_t count = 0;
140     IDBKeyRangeData range = inRange;
141     while (true) {
142         auto key = m_records->lowestKeyWithRecordInRange(range);
143         if (key.isNull())
144             break;
145
146         count += m_records->countForKey(key);
147
148         range.lowerKey = key;
149         range.lowerOpen = true;
150     }
151
152     return count;
153 }
154
155 void MemoryIndex::getAllRecords(const IDBKeyRangeData& keyRangeData, Optional<uint32_t> count, IndexedDB::GetAllType type, IDBGetAllResult& result) const
156 {
157     LOG(IndexedDB, "MemoryIndex::getAllRecords");
158
159     result = { type };
160
161     if (!m_records)
162         return;
163
164     uint32_t targetCount;
165     if (count && count.value())
166         targetCount = count.value();
167     else
168         targetCount = std::numeric_limits<uint32_t>::max();
169
170     IDBKeyRangeData range = keyRangeData;
171     uint32_t currentCount = 0;
172     while (currentCount < targetCount) {
173         auto key = m_records->lowestKeyWithRecordInRange(range);
174         if (key.isNull())
175             return;
176
177         range.lowerKey = key;
178         range.lowerOpen = true;
179
180         auto allValues = m_records->allValuesForKey(key, targetCount - currentCount);
181         for (auto& keyValue : allValues) {
182             if (type == IndexedDB::GetAllType::Keys) {
183                 IDBKeyData keyCopy { keyValue };
184                 result.addKey(WTFMove(keyCopy));
185             } else
186                 result.addValue(m_objectStore.valueForKeyRange(keyValue));
187         }
188
189         currentCount += allValues.size();
190     }
191 }
192
193
194 IDBError MemoryIndex::putIndexKey(const IDBKeyData& valueKey, const IndexKey& indexKey)
195 {
196     LOG(IndexedDB, "MemoryIndex::provisionalPutIndexKey");
197
198     if (!m_records) {
199         m_records = std::make_unique<IndexValueStore>(m_info.unique());
200         notifyCursorsOfAllRecordsChanged();
201     }
202
203     if (!m_info.multiEntry()) {
204         IDBKeyData key = indexKey.asOneKey();
205         IDBError result = m_records->addRecord(key, valueKey);
206         notifyCursorsOfValueChange(key, valueKey);
207         return result;
208     }
209
210     Vector<IDBKeyData> keys = indexKey.multiEntry();
211
212     if (m_info.unique()) {
213         for (auto& key : keys) {
214             if (m_records->contains(key))
215                 return IDBError(ConstraintError);
216         }
217     }
218
219     for (auto& key : keys) {
220         auto error = m_records->addRecord(key, valueKey);
221         ASSERT_UNUSED(error, error.isNull());
222         notifyCursorsOfValueChange(key, valueKey);
223     }
224
225     return IDBError { };
226 }
227
228 void MemoryIndex::removeRecord(const IDBKeyData& valueKey, const IndexKey& indexKey)
229 {
230     LOG(IndexedDB, "MemoryIndex::removeRecord");
231
232     ASSERT(m_records);
233
234     if (!m_info.multiEntry()) {
235         IDBKeyData key = indexKey.asOneKey();
236         m_records->removeRecord(key, valueKey);
237         notifyCursorsOfValueChange(key, valueKey);
238         return;
239     }
240
241     Vector<IDBKeyData> keys = indexKey.multiEntry();
242     for (auto& key : keys) {
243         m_records->removeRecord(key, valueKey);
244         notifyCursorsOfValueChange(key, valueKey);
245     }
246 }
247
248 void MemoryIndex::removeEntriesWithValueKey(const IDBKeyData& valueKey)
249 {
250     LOG(IndexedDB, "MemoryIndex::removeEntriesWithValueKey");
251
252     if (!m_records)
253         return;
254
255     m_records->removeEntriesWithValueKey(*this, valueKey);
256 }
257
258 MemoryIndexCursor* MemoryIndex::maybeOpenCursor(const IDBCursorInfo& info)
259 {
260     auto result = m_cursors.add(info.identifier(), nullptr);
261     if (!result.isNewEntry)
262         return nullptr;
263
264     result.iterator->value = std::make_unique<MemoryIndexCursor>(*this, info);
265     return result.iterator->value.get();
266 }
267
268 } // namespace IDBServer
269 } // namespace WebCore
270
271 #endif // ENABLE(INDEXED_DATABASE)