summaryrefslogtreecommitdiff
path: root/Source/WebCore/Modules/indexeddb/server/MemoryIndex.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/Modules/indexeddb/server/MemoryIndex.cpp
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebCore/Modules/indexeddb/server/MemoryIndex.cpp')
-rw-r--r--Source/WebCore/Modules/indexeddb/server/MemoryIndex.cpp277
1 files changed, 277 insertions, 0 deletions
diff --git a/Source/WebCore/Modules/indexeddb/server/MemoryIndex.cpp b/Source/WebCore/Modules/indexeddb/server/MemoryIndex.cpp
new file mode 100644
index 000000000..e92d26801
--- /dev/null
+++ b/Source/WebCore/Modules/indexeddb/server/MemoryIndex.cpp
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "MemoryIndex.h"
+
+#if ENABLE(INDEXED_DATABASE)
+
+#include "IDBError.h"
+#include "IDBGetAllResult.h"
+#include "IDBGetResult.h"
+#include "IDBKeyRangeData.h"
+#include "IndexKey.h"
+#include "Logging.h"
+#include "MemoryBackingStoreTransaction.h"
+#include "MemoryIndexCursor.h"
+#include "MemoryObjectStore.h"
+#include "ThreadSafeDataBuffer.h"
+
+namespace WebCore {
+namespace IDBServer {
+
+Ref<MemoryIndex> MemoryIndex::create(const IDBIndexInfo& info, MemoryObjectStore& objectStore)
+{
+ return adoptRef(*new MemoryIndex(info, objectStore));
+}
+
+MemoryIndex::MemoryIndex(const IDBIndexInfo& info, MemoryObjectStore& objectStore)
+ : m_info(info)
+ , m_objectStore(objectStore)
+{
+}
+
+MemoryIndex::~MemoryIndex()
+{
+}
+
+void MemoryIndex::cursorDidBecomeClean(MemoryIndexCursor& cursor)
+{
+ m_cleanCursors.add(&cursor);
+}
+
+void MemoryIndex::cursorDidBecomeDirty(MemoryIndexCursor& cursor)
+{
+ m_cleanCursors.remove(&cursor);
+}
+
+void MemoryIndex::objectStoreCleared()
+{
+ auto transaction = m_objectStore.writeTransaction();
+ ASSERT(transaction);
+
+ transaction->indexCleared(*this, WTFMove(m_records));
+
+ notifyCursorsOfAllRecordsChanged();
+}
+
+void MemoryIndex::notifyCursorsOfValueChange(const IDBKeyData& indexKey, const IDBKeyData& primaryKey)
+{
+ Vector<MemoryIndexCursor*> cursors;
+ copyToVector(m_cleanCursors, cursors);
+ for (auto* cursor : cursors)
+ cursor->indexValueChanged(indexKey, primaryKey);
+}
+
+void MemoryIndex::notifyCursorsOfAllRecordsChanged()
+{
+ Vector<MemoryIndexCursor*> cursors;
+ copyToVector(m_cleanCursors, cursors);
+ for (auto* cursor : cursors)
+ cursor->indexRecordsAllChanged();
+
+ ASSERT(m_cleanCursors.isEmpty());
+}
+
+void MemoryIndex::clearIndexValueStore()
+{
+ ASSERT(m_objectStore.writeTransaction());
+ ASSERT(m_objectStore.writeTransaction()->isAborting());
+
+ m_records = nullptr;
+}
+
+void MemoryIndex::replaceIndexValueStore(std::unique_ptr<IndexValueStore>&& valueStore)
+{
+ ASSERT(m_objectStore.writeTransaction());
+ ASSERT(m_objectStore.writeTransaction()->isAborting());
+
+ m_records = WTFMove(valueStore);
+}
+
+IDBGetResult MemoryIndex::getResultForKeyRange(IndexedDB::IndexRecordType type, const IDBKeyRangeData& range) const
+{
+ LOG(IndexedDB, "MemoryIndex::getResultForKeyRange - %s", range.loggingString().utf8().data());
+
+ if (!m_records)
+ return { };
+
+ IDBKeyData keyToLookFor;
+ if (range.isExactlyOneKey())
+ keyToLookFor = range.lowerKey;
+ else
+ keyToLookFor = m_records->lowestKeyWithRecordInRange(range);
+
+ if (keyToLookFor.isNull())
+ return { };
+
+ const IDBKeyData* keyValue = m_records->lowestValueForKey(keyToLookFor);
+
+ if (!keyValue)
+ return { };
+
+ return type == IndexedDB::IndexRecordType::Key ? IDBGetResult(*keyValue) : IDBGetResult(m_objectStore.valueForKeyRange(*keyValue));
+}
+
+uint64_t MemoryIndex::countForKeyRange(const IDBKeyRangeData& inRange)
+{
+ LOG(IndexedDB, "MemoryIndex::countForKeyRange");
+
+ if (!m_records)
+ return 0;
+
+ uint64_t count = 0;
+ IDBKeyRangeData range = inRange;
+ while (true) {
+ auto key = m_records->lowestKeyWithRecordInRange(range);
+ if (key.isNull())
+ break;
+
+ count += m_records->countForKey(key);
+
+ range.lowerKey = key;
+ range.lowerOpen = true;
+ }
+
+ return count;
+}
+
+void MemoryIndex::getAllRecords(const IDBKeyRangeData& keyRangeData, std::optional<uint32_t> count, IndexedDB::GetAllType type, IDBGetAllResult& result) const
+{
+ LOG(IndexedDB, "MemoryIndex::getAllRecords");
+
+ result = { type };
+
+ if (!m_records)
+ return;
+
+ uint32_t targetCount;
+ if (count && count.value())
+ targetCount = count.value();
+ else
+ targetCount = std::numeric_limits<uint32_t>::max();
+
+ IDBKeyRangeData range = keyRangeData;
+ uint32_t currentCount = 0;
+ while (currentCount < targetCount) {
+ auto key = m_records->lowestKeyWithRecordInRange(range);
+ if (key.isNull())
+ return;
+
+ range.lowerKey = key;
+ range.lowerOpen = true;
+
+ auto allValues = m_records->allValuesForKey(key, targetCount - currentCount);
+ for (auto& keyValue : allValues) {
+ if (type == IndexedDB::GetAllType::Keys) {
+ IDBKeyData keyCopy { keyValue };
+ result.addKey(WTFMove(keyCopy));
+ } else
+ result.addValue(m_objectStore.valueForKeyRange(keyValue));
+ }
+
+ currentCount += allValues.size();
+ }
+}
+
+
+IDBError MemoryIndex::putIndexKey(const IDBKeyData& valueKey, const IndexKey& indexKey)
+{
+ LOG(IndexedDB, "MemoryIndex::provisionalPutIndexKey");
+
+ if (!m_records) {
+ m_records = std::make_unique<IndexValueStore>(m_info.unique());
+ notifyCursorsOfAllRecordsChanged();
+ }
+
+ if (!m_info.multiEntry()) {
+ IDBKeyData key = indexKey.asOneKey();
+ IDBError result = m_records->addRecord(key, valueKey);
+ notifyCursorsOfValueChange(key, valueKey);
+ return result;
+ }
+
+ Vector<IDBKeyData> keys = indexKey.multiEntry();
+
+ if (m_info.unique()) {
+ for (auto& key : keys) {
+ if (m_records->contains(key))
+ return IDBError(IDBDatabaseException::ConstraintError);
+ }
+ }
+
+ for (auto& key : keys) {
+ auto error = m_records->addRecord(key, valueKey);
+ ASSERT_UNUSED(error, error.isNull());
+ notifyCursorsOfValueChange(key, valueKey);
+ }
+
+ return { };
+}
+
+void MemoryIndex::removeRecord(const IDBKeyData& valueKey, const IndexKey& indexKey)
+{
+ LOG(IndexedDB, "MemoryIndex::removeRecord");
+
+ ASSERT(m_records);
+
+ if (!m_info.multiEntry()) {
+ IDBKeyData key = indexKey.asOneKey();
+ m_records->removeRecord(key, valueKey);
+ notifyCursorsOfValueChange(key, valueKey);
+ return;
+ }
+
+ Vector<IDBKeyData> keys = indexKey.multiEntry();
+ for (auto& key : keys) {
+ m_records->removeRecord(key, valueKey);
+ notifyCursorsOfValueChange(key, valueKey);
+ }
+}
+
+void MemoryIndex::removeEntriesWithValueKey(const IDBKeyData& valueKey)
+{
+ LOG(IndexedDB, "MemoryIndex::removeEntriesWithValueKey");
+
+ if (!m_records)
+ return;
+
+ m_records->removeEntriesWithValueKey(*this, valueKey);
+}
+
+MemoryIndexCursor* MemoryIndex::maybeOpenCursor(const IDBCursorInfo& info)
+{
+ auto result = m_cursors.add(info.identifier(), nullptr);
+ if (!result.isNewEntry)
+ return nullptr;
+
+ result.iterator->value = std::make_unique<MemoryIndexCursor>(*this, info);
+ return result.iterator->value.get();
+}
+
+} // namespace IDBServer
+} // namespace WebCore
+
+#endif // ENABLE(INDEXED_DATABASE)