2 * Copyright (C) 2010 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "IDBCursorBackend.h"
29 #if ENABLE(INDEXED_DATABASE)
31 #include "IDBBackingStoreInterface.h"
32 #include "IDBCallbacks.h"
33 #include "IDBDatabaseBackendImpl.h"
34 #include "IDBDatabaseCallbacks.h"
35 #include "IDBDatabaseError.h"
36 #include "IDBDatabaseException.h"
37 #include "IDBKeyRange.h"
38 #include "IDBOperation.h"
40 #include "SharedBuffer.h"
44 class IDBCursorBackend::CursorIterationOperation : public IDBOperation {
46 static PassOwnPtr<IDBOperation> create(PassRefPtr<IDBCursorBackend> cursor, PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks)
48 return adoptPtr(new CursorIterationOperation(cursor, key, callbacks));
50 virtual void perform() OVERRIDE FINAL;
52 CursorIterationOperation(PassRefPtr<IDBCursorBackend> cursor, PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks)
55 , m_callbacks(callbacks)
59 RefPtr<IDBCursorBackend> m_cursor;
61 RefPtr<IDBCallbacks> m_callbacks;
64 class IDBCursorBackend::CursorAdvanceOperation : public IDBOperation {
66 static PassOwnPtr<IDBOperation> create(PassRefPtr<IDBCursorBackend> cursor, unsigned long count, PassRefPtr<IDBCallbacks> callbacks)
68 return adoptPtr(new CursorAdvanceOperation(cursor, count, callbacks));
70 virtual void perform() OVERRIDE FINAL;
72 CursorAdvanceOperation(PassRefPtr<IDBCursorBackend> cursor, unsigned long count, PassRefPtr<IDBCallbacks> callbacks)
75 , m_callbacks(callbacks)
79 RefPtr<IDBCursorBackend> m_cursor;
80 unsigned long m_count;
81 RefPtr<IDBCallbacks> m_callbacks;
84 class IDBCursorBackend::CursorPrefetchIterationOperation : public IDBOperation {
86 static PassOwnPtr<IDBOperation> create(PassRefPtr<IDBCursorBackend> cursor, int numberToFetch, PassRefPtr<IDBCallbacks> callbacks)
88 return adoptPtr(new CursorPrefetchIterationOperation(cursor, numberToFetch, callbacks));
90 virtual void perform() OVERRIDE FINAL;
92 CursorPrefetchIterationOperation(PassRefPtr<IDBCursorBackend> cursor, int numberToFetch, PassRefPtr<IDBCallbacks> callbacks)
94 , m_numberToFetch(numberToFetch)
95 , m_callbacks(callbacks)
99 RefPtr<IDBCursorBackend> m_cursor;
101 RefPtr<IDBCallbacks> m_callbacks;
104 IDBCursorBackend::IDBCursorBackend(PassRefPtr<IDBBackingStoreCursorInterface> cursor, IndexedDB::CursorType cursorType, IDBDatabaseBackendInterface::TaskType taskType, IDBTransactionBackend* transaction, int64_t objectStoreId)
105 : m_taskType(taskType)
106 , m_cursorType(cursorType)
107 , m_database(&(transaction->database()))
108 , m_transaction(transaction)
109 , m_objectStoreId(objectStoreId)
113 m_transaction->registerOpenCursor(this);
116 IDBCursorBackend::~IDBCursorBackend()
118 m_transaction->unregisterOpenCursor(this);
122 void IDBCursorBackend::continueFunction(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> prpCallbacks, ExceptionCode&)
124 LOG(StorageAPI, "IDBCursorBackend::continue");
125 RefPtr<IDBCallbacks> callbacks = prpCallbacks;
126 m_transaction->scheduleTask(m_taskType, CursorIterationOperation::create(this, key, callbacks));
129 void IDBCursorBackend::advance(unsigned long count, PassRefPtr<IDBCallbacks> prpCallbacks, ExceptionCode&)
131 LOG(StorageAPI, "IDBCursorBackend::advance");
132 RefPtr<IDBCallbacks> callbacks = prpCallbacks;
133 m_transaction->scheduleTask(CursorAdvanceOperation::create(this, count, callbacks));
136 void IDBCursorBackend::CursorAdvanceOperation::perform()
138 LOG(StorageAPI, "CursorAdvanceOperation");
139 if (!m_cursor->m_cursor || !m_cursor->m_cursor->advance(m_count)) {
140 m_cursor->m_cursor = 0;
141 m_callbacks->onSuccess(static_cast<SharedBuffer*>(0));
145 m_callbacks->onSuccess(m_cursor->key(), m_cursor->primaryKey(), m_cursor->value());
148 void IDBCursorBackend::CursorIterationOperation::perform()
150 LOG(StorageAPI, "CursorIterationOperation");
151 if (!m_cursor->m_cursor || !m_cursor->m_cursor->continueFunction(m_key.get())) {
152 m_cursor->m_cursor = 0;
153 m_callbacks->onSuccess(static_cast<SharedBuffer*>(0));
157 m_callbacks->onSuccess(m_cursor->key(), m_cursor->primaryKey(), m_cursor->value());
160 void IDBCursorBackend::deleteFunction(PassRefPtr<IDBCallbacks> prpCallbacks, ExceptionCode&)
162 LOG(StorageAPI, "IDBCursorBackend::delete");
163 ASSERT(m_transaction->mode() != IndexedDB::TransactionReadOnly);
164 RefPtr<IDBKeyRange> keyRange = IDBKeyRange::create(m_cursor->primaryKey());
165 m_database->deleteRange(m_transaction.get()->id(), m_objectStoreId, keyRange.release(), prpCallbacks);
168 void IDBCursorBackend::prefetchContinue(int numberToFetch, PassRefPtr<IDBCallbacks> prpCallbacks, ExceptionCode&)
170 LOG(StorageAPI, "IDBCursorBackend::prefetchContinue");
171 RefPtr<IDBCallbacks> callbacks = prpCallbacks;
172 m_transaction->scheduleTask(m_taskType, CursorPrefetchIterationOperation::create(this, numberToFetch, callbacks));
175 void IDBCursorBackend::CursorPrefetchIterationOperation::perform()
177 LOG(StorageAPI, "CursorPrefetchIterationOperation");
179 Vector<RefPtr<IDBKey>> foundKeys;
180 Vector<RefPtr<IDBKey>> foundPrimaryKeys;
181 Vector<RefPtr<SharedBuffer>> foundValues;
183 if (m_cursor->m_cursor)
184 m_cursor->m_savedCursor = m_cursor->m_cursor->clone();
186 const size_t maxSizeEstimate = 10 * 1024 * 1024;
187 size_t sizeEstimate = 0;
189 for (int i = 0; i < m_numberToFetch; ++i) {
190 if (!m_cursor->m_cursor || !m_cursor->m_cursor->continueFunction(0)) {
191 m_cursor->m_cursor = 0;
195 foundKeys.append(m_cursor->m_cursor->key());
196 foundPrimaryKeys.append(m_cursor->m_cursor->primaryKey());
198 switch (m_cursor->m_cursorType) {
199 case IndexedDB::CursorKeyOnly:
200 foundValues.append(SharedBuffer::create());
202 case IndexedDB::CursorKeyAndValue:
203 sizeEstimate += m_cursor->m_cursor->value()->size();
204 foundValues.append(m_cursor->m_cursor->value());
207 ASSERT_NOT_REACHED();
209 sizeEstimate += m_cursor->m_cursor->key()->sizeEstimate();
210 sizeEstimate += m_cursor->m_cursor->primaryKey()->sizeEstimate();
212 if (sizeEstimate > maxSizeEstimate)
216 if (!foundKeys.size()) {
217 m_callbacks->onSuccess(static_cast<SharedBuffer*>(0));
221 m_callbacks->onSuccessWithPrefetch(foundKeys, foundPrimaryKeys, foundValues);
224 void IDBCursorBackend::prefetchReset(int usedPrefetches, int)
226 LOG(StorageAPI, "IDBCursorBackend::prefetchReset");
227 m_cursor = m_savedCursor;
233 for (int i = 0; i < usedPrefetches; ++i) {
234 bool ok = m_cursor->continueFunction();
235 ASSERT_UNUSED(ok, ok);
240 void IDBCursorBackend::close()
242 LOG(StorageAPI, "IDBCursorBackend::close");
245 m_savedCursor.clear();
248 } // namespace WebCore
250 #endif // ENABLE(INDEXED_DATABASE)