Changeset 125728 in webkit
- Timestamp:
- Aug 15, 2012 5:50:52 PM (12 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 27 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r125727 r125728 1 2012-08-15 Alec Flett <alecflett@chromium.org> 2 3 IndexedDB: generate index keys for existing data in createIndex in front end 4 https://bugs.webkit.org/show_bug.cgi?id=91125 5 6 Reviewed by Tony Chang. 7 8 The transaction should be aborted when existing data in an 9 objectStore causes uniqueness errors during index creation. 10 11 * storage/indexeddb/lazy-index-population-expected.txt: Added. 12 * storage/indexeddb/lazy-index-population.html: Added. 13 1 14 2012-08-15 Hayato Ito <hayato@chromium.org> 2 15 -
trunk/LayoutTests/storage/indexeddb/index-multientry-expected.txt
r120967 r125728 98 98 This should fail the uniqueness constraint on the index, and fail: 99 99 transaction.objectStore('store-unique').put({x: [5, 2], y: 'c'}, 'should fail') 100 Request failed, as expected ( DataError)100 Request failed, as expected (ConstraintError) 101 101 Transaction aborted as expected 102 102 -
trunk/LayoutTests/storage/indexeddb/index-unique-expected.txt
r120114 r125728 22 22 addMoreDataFailed(): 23 23 event.preventDefault() 24 PASS event.target.errorCode is IDBDatabaseException. DATA_ERR25 PASS event.target.error.name is ' DataError'24 PASS event.target.errorCode is IDBDatabaseException.CONSTRAINT_ERR 25 PASS event.target.error.name is 'ConstraintError' 26 26 transaction.objectStore('store').put({x: 0}, 'foo') 27 27 changeDataSuccess(): -
trunk/LayoutTests/storage/indexeddb/objectstore-basics-expected.txt
r124859 r125728 97 97 event.target.source.add({x: 'foo'}, 'zzz') 98 98 addAgainFailure(): 99 PASS event.target.errorCode is IDBDatabaseException. DATA_ERR100 PASS event.target.error.name is ' DataError'99 PASS event.target.errorCode is IDBDatabaseException.CONSTRAINT_ERR 100 PASS event.target.error.name is 'ConstraintError' 101 101 event.preventDefault() 102 102 db.transaction(['storeName'], 'readwrite') -
trunk/LayoutTests/storage/indexeddb/objectstore-basics-workers-expected.txt
r124859 r125728 98 98 [Worker] event.target.source.add({x: 'foo'}, 'zzz') 99 99 [Worker] addAgainFailure(): 100 PASS [Worker] event.target.errorCode is IDBDatabaseException. DATA_ERR101 PASS [Worker] event.target.error.name is ' DataError'100 PASS [Worker] event.target.errorCode is IDBDatabaseException.CONSTRAINT_ERR 101 PASS [Worker] event.target.error.name is 'ConstraintError' 102 102 [Worker] event.preventDefault() 103 103 [Worker] db.transaction(['storeName'], 'readwrite') -
trunk/LayoutTests/storage/indexeddb/resources/index-unique.js
r120114 r125728 66 66 evalAndLog("event.preventDefault()"); 67 67 68 shouldBe("event.target.errorCode", "IDBDatabaseException. DATA_ERR");69 shouldBe("event.target.error.name", "' DataError'");68 shouldBe("event.target.errorCode", "IDBDatabaseException.CONSTRAINT_ERR"); 69 shouldBe("event.target.error.name", "'ConstraintError'"); 70 70 71 71 // Update the 'foo' entry in object store, changing the value of x. -
trunk/LayoutTests/storage/indexeddb/resources/objectstore-basics.js
r124859 r125728 176 176 event = evt; 177 177 debug("addAgainFailure():"); 178 shouldBe("event.target.errorCode", "IDBDatabaseException. DATA_ERR");179 shouldBe("event.target.error.name", "' DataError'");178 shouldBe("event.target.errorCode", "IDBDatabaseException.CONSTRAINT_ERR"); 179 shouldBe("event.target.error.name", "'ConstraintError'"); 180 180 181 181 evalAndLog("event.preventDefault()"); -
trunk/Source/WebCore/ChangeLog
r125727 r125728 1 2012-08-15 Alec Flett <alecflett@chromium.org> 2 3 IndexedDB: generate index keys for existing data in createIndex in front end 4 https://bugs.webkit.org/show_bug.cgi?id=91125 5 6 Reviewed by Tony Chang. 7 8 Make createIndex() do index key generation in the frontend, rather 9 than the backend. When an index is created, the frontend uses the 10 cursor API to iterate through the values in the backend to 11 generate keys, sending them back to the backend using 12 IDBObjectStore::setIndexKeys() 13 14 This confines all key injection/extraction to the frontend. 15 16 The new test verifies the implemented behavior with respect to 17 error handling in degenerate uses of put(), though that behavior 18 is still in discussion as the spec is vague on the proper error 19 behavior. 20 21 Test: storage/indexeddb/lazy-index-population.html 22 23 * Modules/indexeddb/IDBCursorBackendImpl.cpp: Make sure that the 24 TaskType propagates throught the cursor and all subsequent 25 continue() calls. 26 (WebCore::IDBCursorBackendImpl::IDBCursorBackendImpl): 27 (WebCore::IDBCursorBackendImpl::continueFunction): 28 (WebCore::IDBCursorBackendImpl::prefetchContinue): 29 * Modules/indexeddb/IDBCursorBackendImpl.h: 30 (WebCore::IDBCursorBackendImpl::create): 31 (IDBCursorBackendImpl): 32 * Modules/indexeddb/IDBObjectStore.cpp: Add an IndexPopulator 33 class to run a cursor from the frontend. 34 (WebCore): 35 (WebCore::IDBObjectStore::createIndex): 36 (WebCore::IDBObjectStore::openCursor): 37 * Modules/indexeddb/IDBObjectStore.h: 38 (WebCore::IDBObjectStore::openCursor): 39 (IDBObjectStore): 40 (WebCore::IDBObjectStore::createIndex): 41 * Modules/indexeddb/IDBObjectStore.idl: Pass along ScriptContext 42 so that openCursor can be called from createIndex. 43 * Modules/indexeddb/IDBObjectStoreBackendImpl.cpp: 44 (WebCore): 45 (WebCore::makeIndexWriters): 46 (WebCore::IDBObjectStoreBackendImpl::setIndexKeys): 47 (WebCore::IDBObjectStoreBackendImpl::setIndexesReady): 48 (WebCore::IDBObjectStoreBackendImpl::setIndexesReadyInternal): 49 (WebCore::IDBObjectStoreBackendImpl::putInternal): 50 (WebCore::IDBObjectStoreBackendImpl::deleteInternal): 51 (WebCore::IDBObjectStoreBackendImpl::createIndexInternal): 52 (WebCore::IDBObjectStoreBackendImpl::openCursor): 53 (WebCore::IDBObjectStoreBackendImpl::openCursorInternal): 54 * Modules/indexeddb/IDBObjectStoreBackendImpl.h: 55 (IDBObjectStoreBackendImpl): 56 (WebCore::IDBObjectStoreBackendImpl::iterIndexesBegin): 57 (WebCore::IDBObjectStoreBackendImpl::iterIndexesEnd): 58 (WebCore::IDBObjectStoreBackendImpl::backingStore): 59 (WebCore::IDBObjectStoreBackendImpl::databaseId): 60 * Modules/indexeddb/IDBObjectStoreBackendInterface.h: 61 * Modules/indexeddb/IDBRequest.cpp: 62 Allow requests to keep their own TaskType, to give certain 63 requests priority over others. 64 (WebCore::IDBRequest::create): 65 (WebCore): 66 (WebCore::IDBRequest::IDBRequest): 67 (WebCore::IDBRequest::abort): 68 * Modules/indexeddb/IDBRequest.h: 69 (IDBRequest): 70 (WebCore::IDBRequest::taskType): 71 * Modules/indexeddb/IDBTransactionBackendImpl.cpp: 72 Introduce a second, higher priority event queue, m_preemptiveTaskQueue, 73 which takes priority over the regular task queue. 74 (WebCore::IDBTransactionBackendImpl::IDBTransactionBackendImpl): 75 (WebCore::IDBTransactionBackendImpl::scheduleTask): 76 (WebCore::IDBTransactionBackendImpl::isTaskQueueEmpty): 77 (WebCore): 78 (WebCore::IDBTransactionBackendImpl::commit): 79 (WebCore::IDBTransactionBackendImpl::taskTimerFired): 80 (WebCore::IDBTransactionBackendImpl::taskEventTimerFired): 81 * Modules/indexeddb/IDBTransactionBackendImpl.h: 82 (WebCore::IDBTransactionBackendImpl::scheduleTask): 83 (IDBTransactionBackendImpl): 84 (WebCore::IDBTransactionBackendImpl::addEarlyEvent): 85 (WebCore::IDBTransactionBackendImpl::didCompleteEarlyEvent): 86 * Modules/indexeddb/IDBVersionChangeRequest.cpp: 87 (WebCore::IDBVersionChangeRequest::IDBVersionChangeRequest): 88 1 89 2012-08-15 Hayato Ito <hayato@chromium.org> 2 90 -
trunk/Source/WebCore/Modules/indexeddb/IDBCursorBackendImpl.cpp
r125568 r125728 43 43 namespace WebCore { 44 44 45 IDBCursorBackendImpl::IDBCursorBackendImpl(PassRefPtr<IDBBackingStore::Cursor> cursor, CursorType cursorType, IDBTransactionBackendI mpl* transaction, IDBObjectStoreBackendImpl* objectStore)45 IDBCursorBackendImpl::IDBCursorBackendImpl(PassRefPtr<IDBBackingStore::Cursor> cursor, CursorType cursorType, IDBTransactionBackendInterface::TaskType taskType, IDBTransactionBackendImpl* transaction, IDBObjectStoreBackendImpl* objectStore) 46 46 : m_cursor(cursor) 47 , m_taskType(taskType) 47 48 , m_cursorType(cursorType) 48 49 , m_transaction(transaction) … … 66 67 { 67 68 IDB_TRACE("IDBCursorBackendImpl::continue"); 68 RefPtr<IDBKey> key = prpKey; 69 70 if (!m_transaction->scheduleTask(createCallbackTask(&IDBCursorBackendImpl::continueFunctionInternal, this, key, prpCallbacks))) 69 70 if (!m_transaction->scheduleTask(m_taskType, createCallbackTask(&IDBCursorBackendImpl::continueFunctionInternal, this, prpKey, prpCallbacks))) 71 71 ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR; 72 72 } … … 127 127 { 128 128 IDB_TRACE("IDBCursorBackendImpl::prefetchContinue"); 129 if (!m_transaction->scheduleTask( createCallbackTask(&IDBCursorBackendImpl::prefetchContinueInternal, this, numberToFetch, prpCallbacks)))129 if (!m_transaction->scheduleTask(m_taskType, createCallbackTask(&IDBCursorBackendImpl::prefetchContinueInternal, this, numberToFetch, prpCallbacks))) 130 130 ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR; 131 131 } -
trunk/Source/WebCore/Modules/indexeddb/IDBCursorBackendImpl.h
r125568 r125728 50 50 static PassRefPtr<IDBCursorBackendImpl> create(PassRefPtr<IDBBackingStore::Cursor> cursor, CursorType cursorType, IDBTransactionBackendImpl* transaction, IDBObjectStoreBackendImpl* objectStore) 51 51 { 52 return adoptRef(new IDBCursorBackendImpl(cursor, cursorType, transaction, objectStore)); 52 return adoptRef(new IDBCursorBackendImpl(cursor, cursorType, IDBTransactionBackendInterface::NormalTask, transaction, objectStore)); 53 } 54 static PassRefPtr<IDBCursorBackendImpl> create(PassRefPtr<IDBBackingStore::Cursor> cursor, CursorType cursorType, IDBTransactionBackendInterface::TaskType taskType, IDBTransactionBackendImpl* transaction, IDBObjectStoreBackendImpl* objectStore) 55 { 56 return adoptRef(new IDBCursorBackendImpl(cursor, cursorType, taskType, transaction, objectStore)); 53 57 } 54 58 virtual ~IDBCursorBackendImpl(); … … 68 72 69 73 private: 70 IDBCursorBackendImpl(PassRefPtr<IDBBackingStore::Cursor>, CursorType, IDBTransactionBackendI mpl*, IDBObjectStoreBackendImpl*);74 IDBCursorBackendImpl(PassRefPtr<IDBBackingStore::Cursor>, CursorType, IDBTransactionBackendInterface::TaskType, IDBTransactionBackendImpl*, IDBObjectStoreBackendImpl*); 71 75 72 76 static void advanceInternal(ScriptExecutionContext*, PassRefPtr<IDBCursorBackendImpl>, unsigned long, PassRefPtr<IDBCallbacks>); … … 76 80 RefPtr<IDBBackingStore::Cursor> m_cursor; 77 81 RefPtr<IDBBackingStore::Cursor> m_savedCursor; 82 IDBTransactionBackendInterface::TaskType m_taskType; 78 83 CursorType m_cursorType; 79 84 RefPtr<IDBTransactionBackendImpl> m_transaction; -
trunk/Source/WebCore/Modules/indexeddb/IDBObjectStore.cpp
r123843 r125728 33 33 #include "IDBBindingUtilities.h" 34 34 #include "IDBCursorBackendInterface.h" 35 #include "IDBCursorWithValue.h" 35 36 #include "IDBDatabase.h" 36 37 #include "IDBDatabaseException.h" … … 283 284 } 284 285 285 PassRefPtr<IDBIndex> IDBObjectStore::createIndex(const String& name, const String& keyPath, const Dictionary& options, ExceptionCode& ec) 286 { 287 return createIndex(name, IDBKeyPath(keyPath), options, ec); 288 } 289 290 PassRefPtr<IDBIndex> IDBObjectStore::createIndex(const String& name, PassRefPtr<DOMStringList> keyPath, const Dictionary& options, ExceptionCode& ec) 291 { 292 return createIndex(name, IDBKeyPath(*keyPath), options, ec); 293 } 294 295 296 PassRefPtr<IDBIndex> IDBObjectStore::createIndex(const String& name, const IDBKeyPath& keyPath, const Dictionary& options, ExceptionCode& ec) 286 namespace { 287 // This class creates the index keys for a given index by extracting 288 // them from the SerializedScriptValue, for all the existing values in 289 // the objectStore. It only needs to be kept alive by virtue of being 290 // a listener on an IDBRequest object, in the same way that JavaScript 291 // cursor success handlers are kept alive. 292 class IndexPopulator : public EventListener { 293 public: 294 static PassRefPtr<IndexPopulator> create(PassRefPtr<IDBObjectStoreBackendInterface> backend, PassRefPtr<IDBTransactionBackendInterface> transaction, PassRefPtr<IDBRequest> request, const IDBIndexMetadata& indexMetadata) 295 { 296 return adoptRef(new IndexPopulator(backend, transaction, indexMetadata)); 297 } 298 299 virtual bool operator==(const EventListener& other) 300 { 301 return this == &other; 302 } 303 304 private: 305 IndexPopulator(PassRefPtr<IDBObjectStoreBackendInterface> backend, 306 PassRefPtr<IDBTransactionBackendInterface> transaction, 307 const IDBIndexMetadata& indexMetadata) 308 : EventListener(CPPEventListenerType) 309 , m_objectStoreBackend(backend) 310 , m_transaction(transaction) 311 , m_indexMetadata(indexMetadata) 312 { 313 } 314 315 virtual void handleEvent(ScriptExecutionContext*, Event* event) 316 { 317 ASSERT(event->type() == eventNames().successEvent); 318 EventTarget* target = event->target(); 319 IDBRequest* request = static_cast<IDBRequest*>(target); 320 321 ExceptionCode ec = 0; 322 RefPtr<IDBAny> cursorAny = request->result(ec); 323 ASSERT(!ec); 324 RefPtr<IDBCursorWithValue> cursor; 325 if (cursorAny->type() == IDBAny::IDBCursorWithValueType) 326 cursor = cursorAny->idbCursorWithValue(); 327 328 Vector<String, 1> indexNames; 329 indexNames.append(m_indexMetadata.name); 330 if (cursor) { 331 cursor->continueFunction(ec); 332 ASSERT(!ec); 333 334 RefPtr<IDBKey> primaryKey = cursor->primaryKey(); 335 RefPtr<IDBAny> valueAny = cursor->value(); 336 337 ASSERT(valueAny->type() == IDBAny::SerializedScriptValueType); 338 RefPtr<SerializedScriptValue> value = valueAny->serializedScriptValue(); 339 340 IDBObjectStore::IndexKeys indexKeys; 341 generateIndexKeysForValue(m_indexMetadata, value, &indexKeys); 342 343 Vector<IDBObjectStore::IndexKeys, 1> indexKeysList; 344 indexKeysList.append(indexKeys); 345 346 m_objectStoreBackend->setIndexKeys(primaryKey, indexNames, indexKeysList, m_transaction.get()); 347 348 } else { 349 // Now that we are done indexing, tell the backend to go 350 // back to processing tasks of type NormalTask. 351 m_objectStoreBackend->setIndexesReady(indexNames, m_transaction.get()); 352 m_objectStoreBackend.clear(); 353 m_transaction.clear(); 354 } 355 356 } 357 358 RefPtr<IDBObjectStoreBackendInterface> m_objectStoreBackend; 359 RefPtr<IDBTransactionBackendInterface> m_transaction; 360 IDBIndexMetadata m_indexMetadata; 361 }; 362 } 363 364 PassRefPtr<IDBIndex> IDBObjectStore::createIndex(ScriptExecutionContext* context, const String& name, const String& keyPath, const Dictionary& options, ExceptionCode& ec) 365 { 366 return createIndex(context, name, IDBKeyPath(keyPath), options, ec); 367 } 368 369 PassRefPtr<IDBIndex> IDBObjectStore::createIndex(ScriptExecutionContext* context, const String& name, PassRefPtr<DOMStringList> keyPath, const Dictionary& options, ExceptionCode& ec) 370 { 371 return createIndex(context, name, IDBKeyPath(*keyPath), options, ec); 372 } 373 374 375 PassRefPtr<IDBIndex> IDBObjectStore::createIndex(ScriptExecutionContext* context, const String& name, const IDBKeyPath& keyPath, const Dictionary& options, ExceptionCode& ec) 297 376 { 298 377 IDB_TRACE("IDBObjectStore::createIndex"); … … 338 417 m_indexMap.set(name, index); 339 418 m_metadata.indexes.set(name, metadata); 419 420 ASSERT(!ec); 421 if (ec) 422 return 0; 423 424 RefPtr<IDBRequest> indexRequest = openCursor(context, static_cast<IDBKeyRange*>(0), IDBCursor::directionNext(), IDBTransactionBackendInterface::PreemptiveTask, ec); 425 ASSERT(!ec); 426 if (ec) 427 return 0; 428 429 // This is kept alive by being the success handler of the request, which is in turn kept alive by the owning transaction. 430 RefPtr<IndexPopulator> indexPopulator = IndexPopulator::create(m_backend, m_transaction->backend(), indexRequest, metadata); 431 indexRequest->setOnsuccess(indexPopulator); 340 432 341 433 return index.release(); … … 399 491 } 400 492 401 PassRefPtr<IDBRequest> IDBObjectStore::openCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> range, const String& directionString, ExceptionCode& ec)493 PassRefPtr<IDBRequest> IDBObjectStore::openCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> range, const String& directionString, IDBTransactionBackendInterface::TaskType taskType, ExceptionCode& ec) 402 494 { 403 495 IDB_TRACE("IDBObjectStore::openCursor"); … … 416 508 RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get()); 417 509 request->setCursorDetails(IDBCursorBackendInterface::ObjectStoreCursor, direction); 418 m_backend->openCursor(range, direction, request, m_transaction->backend(), ec);510 m_backend->openCursor(range, direction, request, taskType, m_transaction->backend(), ec); 419 511 if (ec) { 420 512 request->markEarlyDeath(); -
trunk/Source/WebCore/Modules/indexeddb/IDBObjectStore.h
r123843 r125728 69 69 PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, ExceptionCode& ec) { return openCursor(context, keyRange, IDBCursor::directionNext(), ec); } 70 70 PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext* context, PassRefPtr<IDBKey> key, ExceptionCode& ec) { return openCursor(context, key, IDBCursor::directionNext(), ec); } 71 PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> range, const String& direction, ExceptionCode& ec) { return openCursor(context, range, direction, IDBTransactionBackendInterface::NormalTask, ec); } 72 PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext*, PassRefPtr<IDBKeyRange>, const String& direction, IDBTransactionBackendInterface::TaskType, ExceptionCode&); 73 PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext*, PassRefPtr<IDBKey>, const String& direction, ExceptionCode&); 74 PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext*, PassRefPtr<IDBKeyRange>, unsigned short direction, ExceptionCode&); 75 PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext*, PassRefPtr<IDBKey>, unsigned short direction, ExceptionCode&); 71 76 72 77 PassRefPtr<IDBRequest> get(ScriptExecutionContext*, PassRefPtr<IDBKey>, ExceptionCode&); … … 79 84 80 85 // FIXME: Try to modify the code generator so this duplication is unneeded. 81 PassRefPtr<IDBIndex> createIndex( const String& name, const String& keyPath, const Dictionary&, ExceptionCode&);82 PassRefPtr<IDBIndex> createIndex( const String& name, const String& keyPath, ExceptionCode& ec) { return createIndex(name, keyPath, Dictionary(), ec); }83 PassRefPtr<IDBIndex> createIndex( const String& name, PassRefPtr<DOMStringList> keyPath, const Dictionary&, ExceptionCode&);84 PassRefPtr<IDBIndex> createIndex( const String& name, PassRefPtr<DOMStringList> keyPath, ExceptionCode& ec) { return createIndex(name, keyPath, Dictionary(), ec); }85 PassRefPtr<IDBIndex> createIndex( const String&, const IDBKeyPath&, const Dictionary&, ExceptionCode&);86 PassRefPtr<IDBIndex> createIndex(ScriptExecutionContext*, const String& name, const String& keyPath, const Dictionary&, ExceptionCode&); 87 PassRefPtr<IDBIndex> createIndex(ScriptExecutionContext* context, const String& name, const String& keyPath, ExceptionCode& ec) { return createIndex(context, name, keyPath, Dictionary(), ec); } 88 PassRefPtr<IDBIndex> createIndex(ScriptExecutionContext*, const String& name, PassRefPtr<DOMStringList> keyPath, const Dictionary&, ExceptionCode&); 89 PassRefPtr<IDBIndex> createIndex(ScriptExecutionContext* context, const String& name, PassRefPtr<DOMStringList> keyPath, ExceptionCode& ec) { return createIndex(context, name, keyPath, Dictionary(), ec); } 90 PassRefPtr<IDBIndex> createIndex(ScriptExecutionContext*, const String&, const IDBKeyPath&, const Dictionary&, ExceptionCode&); 86 91 87 92 PassRefPtr<IDBIndex> index(const String& name, ExceptionCode&); 88 93 void deleteIndex(const String& name, ExceptionCode&); 89 94 90 PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext*, PassRefPtr<IDBKeyRange>, const String& direction, ExceptionCode&);91 PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext*, PassRefPtr<IDBKey>, const String& direction, ExceptionCode&);92 PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext*, PassRefPtr<IDBKeyRange>, unsigned short direction, ExceptionCode&);93 PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext*, PassRefPtr<IDBKey>, unsigned short direction, ExceptionCode&);94 95 PassRefPtr<IDBRequest> count(ScriptExecutionContext* context, ExceptionCode& ec) { return count(context, static_cast<IDBKeyRange*>(0), ec); } 95 96 PassRefPtr<IDBRequest> count(ScriptExecutionContext*, PassRefPtr<IDBKeyRange>, ExceptionCode&); -
trunk/Source/WebCore/Modules/indexeddb/IDBObjectStore.idl
r122775 r125728 60 60 raises (IDBDatabaseException); 61 61 62 IDBIndex createIndex(in DOMString name, in DOMString[] keyPath, in [Optional] Dictionary options)62 [CallWith=ScriptExecutionContext] IDBIndex createIndex(in DOMString name, in DOMString[] keyPath, in [Optional] Dictionary options) 63 63 raises (IDBDatabaseException); 64 IDBIndex createIndex(in DOMString name, in DOMString keyPath, in [Optional] Dictionary options)64 [CallWith=ScriptExecutionContext] IDBIndex createIndex(in DOMString name, in DOMString keyPath, in [Optional] Dictionary options) 65 65 raises (IDBDatabaseException); 66 66 IDBIndex index(in DOMString name) -
trunk/Source/WebCore/Modules/indexeddb/IDBObjectStoreBackendImpl.cpp
r125627 r125728 155 155 { } 156 156 157 // FIXME: remove this once createIndex() generates these in the renderer.158 void generateIndexKeysForValue(SerializedScriptValue* objectValue)159 {160 m_indexKeys.clear();161 162 RefPtr<IDBKey> indexKey = fetchKeyFromKeyPath(objectValue);163 164 if (!indexKey)165 return;166 167 if (!m_indexMetadata.multiEntry || indexKey->type() != IDBKey::ArrayType) {168 if (!indexKey->isValid())169 return;170 171 m_indexKeys.append(indexKey);172 } else {173 ASSERT(m_indexMetadata.multiEntry);174 ASSERT(indexKey->type() == IDBKey::ArrayType);175 indexKey = IDBKey::createMultiEntryArray(indexKey->array());176 177 for (size_t i = 0; i < indexKey->array().size(); ++i)178 m_indexKeys.append(indexKey->array()[i]);179 }180 }181 182 157 bool verifyIndexKeys(IDBBackingStore& backingStore, 183 158 int64_t databaseId, int64_t objectStoreId, int64_t indexId, … … 246 221 } 247 222 223 static bool makeIndexWriters(IDBObjectStoreBackendImpl* objectStore, PassRefPtr<IDBKey> primaryKey, bool keyWasGenerated, const Vector<String> indexNames, const Vector<IDBObjectStoreBackendInterface::IndexKeys>& indexKeys, Vector<OwnPtr<IndexWriter> >* indexWriters, String* errorMessage) 224 { 225 ASSERT(indexNames.size() == indexKeys.size()); 226 227 HashMap<String, IDBObjectStoreBackendInterface::IndexKeys> indexKeyMap; 228 for (size_t i = 0; i < indexNames.size(); i++) 229 indexKeyMap.add(indexNames[i], indexKeys[i]); 230 231 for (IDBObjectStoreBackendImpl::IndexMap::iterator it = objectStore->iterIndexesBegin(); it != objectStore->iterIndexesEnd(); ++it) { 232 233 const RefPtr<IDBIndexBackendImpl>& index = it->second; 234 if (!index->hasValidId()) 235 continue; // The index object has been created, but does not exist in the database yet. 236 237 IDBObjectStoreBackendInterface::IndexKeys keys = indexKeyMap.get(it->first); 238 // If the objectStore is using autoIncrement, then any indexes with an identical keyPath need to also use the primary (generated) key as a key. 239 if (keyWasGenerated) { 240 const IDBKeyPath& indexKeyPath = index->keyPath(); 241 if (indexKeyPath == objectStore->keyPath()) 242 keys.append(primaryKey); 243 } 244 245 OwnPtr<IndexWriter> indexWriter(adoptPtr(new IndexWriter(index->metadata(), keys))); 246 if (!indexWriter->verifyIndexKeys(*objectStore->backingStore(), 247 objectStore->databaseId(), 248 objectStore->id(), 249 index->id(), primaryKey.get(), errorMessage)) { 250 return false; 251 } 252 253 indexWriters->append(indexWriter.release()); 254 } 255 256 return true; 257 } 258 259 void IDBObjectStoreBackendImpl::setIndexKeys(PassRefPtr<IDBKey> prpPrimaryKey, const Vector<String>& indexNames, const Vector<IndexKeys>& indexKeys, IDBTransactionBackendInterface* transaction) 260 { 261 IDB_TRACE("IDBObjectStoreBackendImpl::setIndexKeys"); 262 RefPtr<IDBKey> primaryKey = prpPrimaryKey; 263 264 // FIXME: This method could be asynchronous, but we need to evaluate if it's worth the extra complexity. 265 RefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> recordIdentifier = backingStore()->createInvalidRecordIdentifier(); 266 if (!backingStore()->keyExistsInObjectStore(databaseId(), id(), *primaryKey, recordIdentifier.get())) { 267 transaction->abort(); 268 return; 269 } 270 271 Vector<OwnPtr<IndexWriter> > indexWriters; 272 String errorMessage; 273 if (!makeIndexWriters(this, primaryKey, false, indexNames, indexKeys, &indexWriters, &errorMessage)) { 274 // FIXME: Need to deal with errorMessage here. makeIndexWriters only fails on uniqueness constraint errors. 275 transaction->abort(); 276 return; 277 } 278 279 for (size_t i = 0; i < indexWriters.size(); ++i) { 280 IndexWriter* indexWriter = indexWriters[i].get(); 281 if (!indexWriter->writeIndexKeys(recordIdentifier.get(), 282 *backingStore(), 283 databaseId(), 284 m_id, 285 m_indexes.get(indexWriter->indexName())->id())) { 286 transaction->abort(); 287 return; 288 } 289 } 290 } 291 292 void IDBObjectStoreBackendImpl::setIndexesReady(const Vector<String>& indexNames, IDBTransactionBackendInterface* transactionInterface) 293 { 294 IDB_TRACE("IDBObjectStoreBackendImpl::setIndexesReady"); 295 RefPtr<IDBObjectStoreBackendImpl> objectStore = this; 296 297 OwnPtr<Vector<String> > names = adoptPtr(new Vector<String>(indexNames)); 298 RefPtr<IDBTransactionBackendImpl> transaction = IDBTransactionBackendImpl::from(transactionInterface); 299 300 if (!transaction->scheduleTask( 301 IDBTransactionBackendInterface::PreemptiveTask, 302 createCallbackTask(&IDBObjectStoreBackendImpl::setIndexesReadyInternal, objectStore, names.release(), transaction))) 303 ASSERT_NOT_REACHED(); 304 } 305 306 void IDBObjectStoreBackendImpl::setIndexesReadyInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassOwnPtr<Vector<String> > popIndexNames, PassRefPtr<IDBTransactionBackendImpl> transaction) 307 { 308 IDB_TRACE("IDBObjectStoreBackendImpl::setIndexesReadyInternal"); 309 OwnPtr<Vector<String> > indexNames = popIndexNames; 310 for (size_t i = 0; i < indexNames->size(); ++i) 311 transaction->didCompletePreemptiveEvent(); 312 transaction->didCompleteTaskEvents(); 313 } 314 248 315 void IDBObjectStoreBackendImpl::putInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBKey> prpKey, PutMode putMode, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBTransactionBackendImpl> transaction, PassOwnPtr<Vector<String> > popIndexNames, PassOwnPtr<Vector<IndexKeys> > popIndexKeys) 249 316 { … … 277 344 278 345 Vector<OwnPtr<IndexWriter> > indexWriters; 279 HashMap<String, IndexKeys> indexKeyMap; 280 for (size_t i = 0; i < indexNames->size(); ++i) { 281 IndexKeys keys = indexKeys->at(i); 282 283 // If the objectStore is using autoIncrement, then any indexes with an identical keyPath need to also use the primary (generated) key as a key. 284 if (keyWasGenerated) { 285 const IDBKeyPath& indexKeyPath = objectStore->m_indexes.get(indexNames->at(i))->keyPath(); 286 if (indexKeyPath == objectStore->keyPath()) 287 keys.append(key); 288 } 289 290 indexKeyMap.add(indexNames->at(i), keys); 291 } 292 293 for (IndexMap::iterator it = objectStore->m_indexes.begin(); it != objectStore->m_indexes.end(); ++it) { 294 295 const RefPtr<IDBIndexBackendImpl>& index = it->second; 296 if (!index->hasValidId()) 297 continue; // The index object has been created, but does not exist in the database yet. 298 299 OwnPtr<IndexWriter> indexWriter; 300 indexWriter = adoptPtr(new IndexWriter(index->metadata(), indexKeyMap.get(it->first))); 301 302 String errorMessage; 303 if (!indexWriter->verifyIndexKeys(*objectStore->backingStore(), 304 objectStore->databaseId(), 305 objectStore->id(), 306 index->id(), key.get(), &errorMessage)) { 307 callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, errorMessage)); 308 return; 309 } 310 311 indexWriters.append(indexWriter.release()); 346 String errorMessage; 347 if (!makeIndexWriters(objectStore.get(), key, keyWasGenerated, *indexNames, *indexKeys, &indexWriters, &errorMessage)) { 348 callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::CONSTRAINT_ERR, errorMessage)); 349 return; 312 350 } 313 351 … … 366 404 recordIdentifier = backingStoreCursor->objectStoreRecordIdentifier(); 367 405 368 for (I ndexMap::iterator it = objectStore->m_indexes.begin(); it != objectStore->m_indexes.end(); ++it) {406 for (IDBObjectStoreBackendImpl::IndexMap::iterator it = objectStore->m_indexes.begin(); it != objectStore->m_indexes.end(); ++it) { 369 407 if (!it->second->hasValidId()) 370 408 continue; // The index object has been created, but does not exist in the database yet. … … 404 442 } 405 443 406 namespace {407 class PopulateIndexCallback : public IDBBackingStore::ObjectStoreRecordCallback {408 public:409 PopulateIndexCallback(IDBBackingStore& backingStore, const IDBIndexMetadata& indexMetadata, int64_t databaseId, int64_t objectStoreId, int64_t indexId)410 : m_backingStore(backingStore)411 , m_databaseId(databaseId)412 , m_objectStoreId(objectStoreId)413 , m_indexId(indexId)414 , m_writer(indexMetadata)415 {416 }417 418 virtual bool callback(const IDBBackingStore::ObjectStoreRecordIdentifier* recordIdentifier, const String& value)419 {420 RefPtr<SerializedScriptValue> objectValue = SerializedScriptValue::createFromWire(value);421 m_writer.generateIndexKeysForValue(objectValue.get());422 if (!m_writer.verifyIndexKeys(m_backingStore, m_databaseId, m_objectStoreId, m_indexId))423 return false;424 return m_writer.writeIndexKeys(recordIdentifier, m_backingStore, m_databaseId, m_objectStoreId, m_indexId);425 }426 427 private:428 IDBBackingStore& m_backingStore;429 int64_t m_databaseId;430 int64_t m_objectStoreId;431 int64_t m_indexId;432 IndexWriter m_writer;433 };434 }435 436 bool IDBObjectStoreBackendImpl::populateIndex(IDBBackingStore& backingStore, int64_t databaseId, int64_t objectStoreId, PassRefPtr<IDBIndexBackendImpl> index)437 {438 PopulateIndexCallback callback(backingStore, index->metadata(), databaseId, objectStoreId, index->id());439 if (!backingStore.forEachObjectStoreRecord(databaseId, objectStoreId, callback))440 return false;441 return true;442 }443 444 444 PassRefPtr<IDBIndexBackendInterface> IDBObjectStoreBackendImpl::createIndex(const String& name, const IDBKeyPath& keyPath, bool unique, bool multiEntry, IDBTransactionBackendInterface* transactionPtr, ExceptionCode& ec) 445 445 { … … 473 473 474 474 index->setId(id); 475 476 if (!populateIndex(*objectStore->backingStore(), objectStore->databaseId(), objectStore->m_id, index)) {477 transaction->abort();478 return;479 }480 475 481 476 transaction->didCompleteTaskEvents(); … … 516 511 } 517 512 518 void IDBObjectStoreBackendImpl::openCursor(PassRefPtr<IDBKeyRange> prpRange, unsigned short direction, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transactionPtr, ExceptionCode& ec) 513 void IDBObjectStoreBackendImpl::openCursor(PassRefPtr<IDBKeyRange> prpRange, unsigned short tmpDirection, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface* transactionPtr, ExceptionCode& ec) 514 { 515 IDBCursor::Direction direction = static_cast<IDBCursor::Direction>(tmpDirection); 516 openCursor(prpRange, direction, prpCallbacks, IDBTransactionBackendInterface::NormalTask, transactionPtr, ec); 517 } 518 519 void IDBObjectStoreBackendImpl::openCursor(PassRefPtr<IDBKeyRange> prpRange, IDBCursor::Direction direction, PassRefPtr<IDBCallbacks> prpCallbacks, IDBTransactionBackendInterface::TaskType taskType, IDBTransactionBackendInterface* transactionPtr, ExceptionCode& ec) 519 520 { 520 521 IDB_TRACE("IDBObjectStoreBackendImpl::openCursor"); … … 524 525 RefPtr<IDBTransactionBackendImpl> transaction = IDBTransactionBackendImpl::from(transactionPtr); 525 526 if (!transaction->scheduleTask( 526 createCallbackTask(&IDBObjectStoreBackendImpl::openCursorInternal, objectStore, range, direction, callbacks, t ransaction))) {527 ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR; 528 } 529 } 530 531 void IDBObjectStoreBackendImpl::openCursorInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBKeyRange> range, unsigned short tmpDirection, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBTransactionBackendImpl> transaction)527 createCallbackTask(&IDBObjectStoreBackendImpl::openCursorInternal, objectStore, range, direction, callbacks, taskType, transaction))) { 528 ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR; 529 } 530 } 531 532 void IDBObjectStoreBackendImpl::openCursorInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBKeyRange> range, IDBCursor::Direction direction, PassRefPtr<IDBCallbacks> callbacks, IDBTransactionBackendInterface::TaskType taskType, PassRefPtr<IDBTransactionBackendImpl> transaction) 532 533 { 533 534 IDB_TRACE("IDBObjectStoreBackendImpl::openCursorInternal"); 534 IDBCursor::Direction direction = static_cast<IDBCursor::Direction>(tmpDirection);535 535 536 536 RefPtr<IDBBackingStore::Cursor> backingStoreCursor = objectStore->backingStore()->openObjectStoreCursor(objectStore->databaseId(), objectStore->id(), range.get(), direction); 537 // The frontend has begun indexing, so this pauses the transaction 538 // until the indexing is complete. This can't happen any earlier 539 // because we don't want to switch to early mode in case multiple 540 // indexes are being created in a row, with put()'s in between. 541 if (taskType == IDBTransactionBackendInterface::PreemptiveTask) 542 transaction->addPreemptiveEvent(); 537 543 if (!backingStoreCursor) { 538 544 callbacks->onSuccess(SerializedScriptValue::nullValue()); … … 540 546 } 541 547 542 RefPtr<IDBCursorBackendImpl> cursor = IDBCursorBackendImpl::create(backingStoreCursor.release(), IDBCursorBackendInterface::ObjectStoreCursor, t ransaction.get(), objectStore.get());548 RefPtr<IDBCursorBackendImpl> cursor = IDBCursorBackendImpl::create(backingStoreCursor.release(), IDBCursorBackendInterface::ObjectStoreCursor, taskType, transaction.get(), objectStore.get()); 543 549 callbacks->onSuccess(cursor, cursor->key(), cursor->primaryKey(), cursor->value()); 544 550 } -
trunk/Source/WebCore/Modules/indexeddb/IDBObjectStoreBackendImpl.h
r123843 r125728 27 27 #define IDBObjectStoreBackendImpl_h 28 28 29 #include "IDBBackingStore.h" 29 30 #include "IDBDatabaseBackendImpl.h" 30 31 #include "IDBKeyPath.h" … … 57 58 virtual ~IDBObjectStoreBackendImpl(); 58 59 60 typedef HashMap<String, RefPtr<IDBIndexBackendImpl> > IndexMap; 61 59 62 static const int64_t InvalidId = 0; 60 63 int64_t id() const … … 72 75 73 76 virtual PassRefPtr<IDBIndexBackendInterface> createIndex(const String& name, const IDBKeyPath&, bool unique, bool multiEntry, IDBTransactionBackendInterface*, ExceptionCode&); 77 virtual void setIndexKeys(PassRefPtr<IDBKey> prpPrimaryKey, const Vector<String>&, const Vector<IndexKeys>& , IDBTransactionBackendInterface*); 78 virtual void setIndexesReady(const Vector<String>&, IDBTransactionBackendInterface*); 74 79 virtual PassRefPtr<IDBIndexBackendInterface> index(const String& name, ExceptionCode&); 75 80 virtual void deleteIndex(const String& name, IDBTransactionBackendInterface*, ExceptionCode&); 76 81 82 // FIXME: Remove this version of openCursor when TaskType is plumbed through chromium. 77 83 virtual void openCursor(PassRefPtr<IDBKeyRange> range, unsigned short direction, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*, ExceptionCode&); 84 virtual void openCursor(PassRefPtr<IDBKeyRange>, IDBCursor::Direction, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface::TaskType, IDBTransactionBackendInterface*, ExceptionCode&); 78 85 virtual void count(PassRefPtr<IDBKeyRange>, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*, ExceptionCode&); 79 86 80 87 static bool populateIndex(IDBBackingStore&, int64_t databaseId, int64_t objectStoreId, PassRefPtr<IDBIndexBackendImpl>); 88 89 const IndexMap::iterator iterIndexesBegin() { return m_indexes.begin(); }; 90 const IndexMap::iterator iterIndexesEnd() { return m_indexes.end(); }; 81 91 82 92 IDBObjectStoreMetadata metadata() const; … … 84 94 const IDBKeyPath& keyPath() const { return m_keyPath; } 85 95 const bool& autoIncrement() const { return m_autoIncrement; } 86 96 97 PassRefPtr<IDBBackingStore> backingStore() const { return m_database->backingStore(); } 98 int64_t databaseId() const { return m_database->id(); } 99 87 100 private: 88 101 IDBObjectStoreBackendImpl(const IDBDatabaseBackendImpl*, int64_t databaseId, const String& name, const IDBKeyPath&, bool autoIncrement); … … 96 109 static void putInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<SerializedScriptValue>, PassRefPtr<IDBKey>, PutMode, PassRefPtr<IDBCallbacks>, PassRefPtr<IDBTransactionBackendImpl>, PassOwnPtr<Vector<String> > popIndexNames, PassOwnPtr<Vector<IndexKeys> >); 97 110 static void deleteInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBKeyRange>, PassRefPtr<IDBCallbacks>); 111 static void setIndexesReadyInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassOwnPtr<Vector<String> > popIndexNames, PassRefPtr<IDBTransactionBackendImpl>); 98 112 static void clearInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBCallbacks>); 99 113 static void createIndexInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBIndexBackendImpl>, PassRefPtr<IDBTransactionBackendImpl>); 100 114 static void deleteIndexInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBIndexBackendImpl>, PassRefPtr<IDBTransactionBackendImpl>); 101 static void openCursorInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBKeyRange>, unsigned short direction, PassRefPtr<IDBCallbacks>, PassRefPtr<IDBTransactionBackendImpl>);115 static void openCursorInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBKeyRange>, IDBCursor::Direction, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface::TaskType, PassRefPtr<IDBTransactionBackendImpl>); 102 116 static void countInternal(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBKeyRange>, PassRefPtr<IDBCallbacks>); 103 117 … … 105 119 static void removeIndexFromMap(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBIndexBackendImpl>); 106 120 static void addIndexToMap(ScriptExecutionContext*, PassRefPtr<IDBObjectStoreBackendImpl>, PassRefPtr<IDBIndexBackendImpl>); 107 108 PassRefPtr<IDBBackingStore> backingStore() const { return m_database->backingStore(); }109 int64_t databaseId() const { return m_database->id(); }110 121 111 122 const IDBDatabaseBackendImpl* m_database; … … 115 126 bool m_autoIncrement; 116 127 117 typedef HashMap<String, RefPtr<IDBIndexBackendImpl> > IndexMap;118 128 IndexMap m_indexes; 119 129 }; -
trunk/Source/WebCore/Modules/indexeddb/IDBObjectStoreBackendInterface.h
r123843 r125728 27 27 #define IDBObjectStoreBackendInterface_h 28 28 29 #include "IDBCursor.h" 29 30 #include "PlatformString.h" 30 31 #include <wtf/Threading.h> … … 64 65 65 66 virtual PassRefPtr<IDBIndexBackendInterface> createIndex(const String& name, const IDBKeyPath&, bool unique, bool multiEntry, IDBTransactionBackendInterface*, ExceptionCode&) = 0; 67 virtual void setIndexKeys(PassRefPtr<IDBKey> prpPrimaryKey, const Vector<String>&, const Vector<IndexKeys>&, IDBTransactionBackendInterface*) = 0; 68 virtual void setIndexesReady(const Vector<String>&, IDBTransactionBackendInterface*) = 0; 66 69 virtual PassRefPtr<IDBIndexBackendInterface> index(const String& name, ExceptionCode&) = 0; 67 70 virtual void deleteIndex(const String& name, IDBTransactionBackendInterface*, ExceptionCode&) = 0; 68 71 72 // FIXME: Remove this version of openCursor when TaskType is plumbed through chromium. 69 73 virtual void openCursor(PassRefPtr<IDBKeyRange>, unsigned short direction, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*, ExceptionCode&) = 0; 74 virtual void openCursor(PassRefPtr<IDBKeyRange>, IDBCursor::Direction, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface::TaskType, IDBTransactionBackendInterface*, ExceptionCode&) = 0; 70 75 virtual void count(PassRefPtr<IDBKeyRange>, PassRefPtr<IDBCallbacks>, IDBTransactionBackendInterface*, ExceptionCode&) = 0; 71 76 }; -
trunk/Source/WebCore/Modules/indexeddb/IDBRequest.cpp
r125713 r125728 47 47 PassRefPtr<IDBRequest> IDBRequest::create(ScriptExecutionContext* context, PassRefPtr<IDBAny> source, IDBTransaction* transaction) 48 48 { 49 RefPtr<IDBRequest> request(adoptRef(new IDBRequest(context, source, transaction)));49 RefPtr<IDBRequest> request(adoptRef(new IDBRequest(context, source, IDBTransactionBackendInterface::NormalTask, transaction))); 50 50 request->suspendIfNeeded(); 51 51 return request.release(); 52 52 } 53 53 54 IDBRequest::IDBRequest(ScriptExecutionContext* context, PassRefPtr<IDBAny> source, IDBTransaction* transaction) 54 PassRefPtr<IDBRequest> IDBRequest::create(ScriptExecutionContext* context, PassRefPtr<IDBAny> source, IDBTransactionBackendInterface::TaskType taskType, IDBTransaction* transaction) 55 { 56 RefPtr<IDBRequest> request(adoptRef(new IDBRequest(context, source, taskType, transaction))); 57 request->suspendIfNeeded(); 58 return request.release(); 59 } 60 61 IDBRequest::IDBRequest(ScriptExecutionContext* context, PassRefPtr<IDBAny> source, IDBTransactionBackendInterface::TaskType taskType, IDBTransaction* transaction) 55 62 : ActiveDOMObject(context, this) 56 63 , m_errorCode(0) 57 64 , m_source(source) 65 , m_taskType(taskType) 58 66 , m_transaction(transaction) 59 67 , m_readyState(PENDING) -
trunk/Source/WebCore/Modules/indexeddb/IDBRequest.h
r125568 r125728 53 53 public: 54 54 static PassRefPtr<IDBRequest> create(ScriptExecutionContext*, PassRefPtr<IDBAny> source, IDBTransaction*); 55 static PassRefPtr<IDBRequest> create(ScriptExecutionContext*, PassRefPtr<IDBAny> source, IDBTransactionBackendInterface::TaskType, IDBTransaction*); 55 56 virtual ~IDBRequest(); 56 57 … … 106 107 using ThreadSafeRefCounted<IDBCallbacks>::deref; 107 108 109 IDBTransactionBackendInterface::TaskType taskType() { return m_taskType; } 110 108 111 protected: 109 IDBRequest(ScriptExecutionContext*, PassRefPtr<IDBAny> source, IDBTransaction *);112 IDBRequest(ScriptExecutionContext*, PassRefPtr<IDBAny> source, IDBTransactionBackendInterface::TaskType, IDBTransaction*); 110 113 void enqueueEvent(PassRefPtr<Event>); 111 114 bool shouldEnqueueEvent() const; … … 127 130 128 131 RefPtr<IDBAny> m_source; 132 const IDBTransactionBackendInterface::TaskType m_taskType; 129 133 RefPtr<IDBTransaction> m_transaction; 130 134 -
trunk/Source/WebCore/Modules/indexeddb/IDBTransactionBackendImpl.cpp
r124675 r125728 52 52 , m_taskTimer(this, &IDBTransactionBackendImpl::taskTimerFired) 53 53 , m_taskEventTimer(this, &IDBTransactionBackendImpl::taskEventTimerFired) 54 , m_pendingPreemptiveEvents(0) 54 55 , m_pendingEvents(0) 55 56 { … … 90 91 } 91 92 92 bool IDBTransactionBackendImpl::scheduleTask( PassOwnPtr<ScriptExecutionContext::Task> task, PassOwnPtr<ScriptExecutionContext::Task> abortTask)93 bool IDBTransactionBackendImpl::scheduleTask(TaskType type, PassOwnPtr<ScriptExecutionContext::Task> task, PassOwnPtr<ScriptExecutionContext::Task> abortTask) 93 94 { 94 95 if (m_state == Finished) 95 96 return false; 96 97 97 m_taskQueue.append(task); 98 if (type == NormalTask) 99 m_taskQueue.append(task); 100 else 101 m_preemptiveTaskQueue.append(task); 102 98 103 if (abortTask) 99 104 m_abortTaskQueue.prepend(abortTask); … … 148 153 149 154 m_database = 0; 155 } 156 157 bool IDBTransactionBackendImpl::isTaskQueueEmpty() const 158 { 159 return m_preemptiveTaskQueue.isEmpty() && m_taskQueue.isEmpty(); 150 160 } 151 161 … … 204 214 RefPtr<IDBTransactionBackendImpl> self(this); 205 215 ASSERT(m_state == Unused || m_state == Running); 206 ASSERT( m_taskQueue.isEmpty());216 ASSERT(isTaskQueueEmpty()); 207 217 208 218 bool unused = m_state == Unused; … … 236 246 { 237 247 IDB_TRACE("IDBTransactionBackendImpl::taskTimerFired"); 238 ASSERT(! m_taskQueue.isEmpty());248 ASSERT(!isTaskQueueEmpty()); 239 249 240 250 if (m_state == StartPending) { … … 243 253 } 244 254 245 TaskQueue queue; 246 queue.swap(m_taskQueue); 247 while (!queue.isEmpty() && m_state != Finished) { 255 // Just process a single event here, in case the event itself 256 // changes which queue should be processed next. 257 TaskQueue& taskQueue = m_pendingPreemptiveEvents ? m_preemptiveTaskQueue : m_taskQueue; 258 if (!taskQueue.isEmpty() && m_state != Finished) { 248 259 ASSERT(m_state == Running); 249 OwnPtr<ScriptExecutionContext::Task> task( queue.first().release());250 queue.removeFirst();260 OwnPtr<ScriptExecutionContext::Task> task(taskQueue.first().release()); 261 taskQueue.removeFirst(); 251 262 m_pendingEvents++; 252 263 task->performTask(0); … … 259 270 ASSERT(m_state == Running); 260 271 261 if (!m_pendingEvents && m_taskQueue.isEmpty()) {272 if (!m_pendingEvents && isTaskQueueEmpty()) { 262 273 // The last task event has completed and the task 263 274 // queue is empty. Commit the transaction. … … 269 280 // the task queue is non-empty and the timer is inactive. 270 281 // We can therfore schedule the timer again. 271 if (! m_taskQueue.isEmpty() && !m_taskTimer.isActive())282 if (!isTaskQueueEmpty() && !m_taskTimer.isActive()) 272 283 m_taskTimer.startOneShot(0); 273 284 } -
trunk/Source/WebCore/Modules/indexeddb/IDBTransactionBackendImpl.h
r123276 r125728 59 59 void run(); 60 60 unsigned short mode() const { return m_mode; } 61 bool scheduleTask(PassOwnPtr<ScriptExecutionContext::Task>, PassOwnPtr<ScriptExecutionContext::Task> abortTask = nullptr); 61 bool scheduleTask(PassOwnPtr<ScriptExecutionContext::Task> task, PassOwnPtr<ScriptExecutionContext::Task> abortTask = nullptr) { return scheduleTask(NormalTask, task, abortTask); } 62 bool scheduleTask(TaskType, PassOwnPtr<ScriptExecutionContext::Task>, PassOwnPtr<ScriptExecutionContext::Task> abortTask = nullptr); 62 63 void registerOpenCursor(IDBCursorBackendImpl*); 63 64 void unregisterOpenCursor(IDBCursorBackendImpl*); 64 65 void addPendingEvents(int); 66 void addPreemptiveEvent() { m_pendingPreemptiveEvents++; } 67 void didCompletePreemptiveEvent() { m_pendingPreemptiveEvents--; ASSERT(m_pendingPreemptiveEvents >= 0); } 65 68 66 69 private: … … 77 80 void commit(); 78 81 82 bool isTaskQueueEmpty() const; 83 79 84 void taskTimerFired(Timer<IDBTransactionBackendImpl>*); 80 85 void taskEventTimerFired(Timer<IDBTransactionBackendImpl>*); … … 90 95 typedef Deque<OwnPtr<ScriptExecutionContext::Task> > TaskQueue; 91 96 TaskQueue m_taskQueue; 97 TaskQueue m_preemptiveTaskQueue; 92 98 TaskQueue m_abortTaskQueue; 93 99 … … 97 103 Timer<IDBTransactionBackendImpl> m_taskTimer; 98 104 Timer<IDBTransactionBackendImpl> m_taskEventTimer; 105 int m_pendingPreemptiveEvents; 99 106 int m_pendingEvents; 100 107 -
trunk/Source/WebCore/Modules/indexeddb/IDBVersionChangeRequest.cpp
r125231 r125728 43 43 44 44 IDBVersionChangeRequest::IDBVersionChangeRequest(ScriptExecutionContext* context, PassRefPtr<IDBAny> source, const String& version) 45 : IDBRequest(context, source, 0)45 : IDBRequest(context, source, IDBTransactionBackendInterface::NormalTask, 0) 46 46 , m_version(version) 47 47 { -
trunk/Source/WebKit/chromium/ChangeLog
r125716 r125728 1 2012-08-15 Alec Flett <alecflett@chromium.org> 2 3 IndexedDB: generate index keys for existing data in createIndex in front end 4 https://bugs.webkit.org/show_bug.cgi?id=91125 5 6 Reviewed by Tony Chang. 7 8 Add Chromium API methods to let the renderer process tell the 9 browser process about indexing progress. 10 11 * public/WebIDBObjectStore.h: 12 (WebKit::WebIDBObjectStore::openCursor): 13 * src/IDBObjectStoreBackendProxy.cpp: 14 (WebKit::IDBObjectStoreBackendProxy::setIndexKeys): 15 (WebKit): 16 (WebKit::IDBObjectStoreBackendProxy::setIndexesReady): 17 (WebKit::IDBObjectStoreBackendProxy::openCursor): 18 * src/IDBObjectStoreBackendProxy.h: 19 (IDBObjectStoreBackendProxy): 20 * src/WebIDBObjectStoreImpl.cpp: 21 (WebKit::WebIDBObjectStoreImpl::setIndexKeys): 22 (WebKit): 23 (WebKit::WebIDBObjectStoreImpl::setIndexesReady): 24 (WebKit::WebIDBObjectStoreImpl::openCursor): 25 * src/WebIDBObjectStoreImpl.h: 26 (WebIDBObjectStoreImpl): 27 1 28 2012-08-15 Bruno de Oliveira Abinader <bruno.abinader@basyskom.com> 2 29 -
trunk/Source/WebKit/chromium/public/WebIDBObjectStore.h
r125084 r125728 74 74 virtual void deleteIndex(const WebString& name, const WebIDBTransaction&, WebExceptionCode&) { WEBKIT_ASSERT_NOT_REACHED(); } 75 75 // FIXME: Remove this version of openCursor when TaskType is plumbed through chromium. 76 virtual void openCursor(const WebIDBKeyRange&, unsigned short direction, WebIDBCallbacks*, const WebIDBTransaction&, WebExceptionCode&) { WEBKIT_ASSERT_NOT_REACHED(); } 76 virtual void openCursor(const WebIDBKeyRange& range, unsigned short direction, WebIDBCallbacks* callbacks, const WebIDBTransaction& transaction, WebExceptionCode& ec) 77 { 78 openCursor(range, static_cast<WebIDBCursor::Direction>(direction), callbacks, WebIDBTransaction::NormalTask, transaction, ec); 79 } 77 80 virtual void openCursor(const WebIDBKeyRange&, WebIDBCursor::Direction direction, WebIDBCallbacks*, WebIDBTransaction::TaskType, const WebIDBTransaction&, WebExceptionCode&) { WEBKIT_ASSERT_NOT_REACHED(); } 78 81 virtual void count(const WebIDBKeyRange&, WebIDBCallbacks*, const WebIDBTransaction&, WebExceptionCode&) { WEBKIT_ASSERT_NOT_REACHED(); } -
trunk/Source/WebKit/chromium/src/IDBObjectStoreBackendProxy.cpp
r123843 r125728 78 78 } 79 79 80 void IDBObjectStoreBackendProxy::setIndexKeys(PassRefPtr<IDBKey> prpPrimaryKey, const Vector<String>& indexNames, const Vector<IndexKeys>& indexKeys, IDBTransactionBackendInterface* transaction) 81 { 82 // The transaction pointer is guaranteed to be a pointer to a proxy object as, in the renderer, 83 // all implementations of IDB interfaces are proxy objects. 84 IDBTransactionBackendProxy* transactionProxy = static_cast<IDBTransactionBackendProxy*>(transaction); 85 WebVector<WebString> webIndexNames(indexNames); 86 WebVector<IndexKeys> webIndexKeys(indexKeys); 87 m_webIDBObjectStore->setIndexKeys(prpPrimaryKey, webIndexNames, webIndexKeys, *transactionProxy->getWebIDBTransaction()); 88 } 89 80 90 void IDBObjectStoreBackendProxy::deleteFunction(PassRefPtr<IDBKeyRange> keyRange, PassRefPtr<IDBCallbacks> callbacks, IDBTransactionBackendInterface* transaction, ExceptionCode& ec) 81 91 { … … 105 115 } 106 116 117 void IDBObjectStoreBackendProxy::setIndexesReady(const Vector<String>& indexNames, IDBTransactionBackendInterface* transaction) 118 { 119 // The transaction pointer is guaranteed to be a pointer to a proxy object as, in the renderer, 120 // all implementations of IDB interfaces are proxy objects. 121 IDBTransactionBackendProxy* transactionProxy = static_cast<IDBTransactionBackendProxy*>(transaction); 122 m_webIDBObjectStore->setIndexesReady(indexNames, *transactionProxy->getWebIDBTransaction()); 123 } 124 107 125 PassRefPtr<IDBIndexBackendInterface> IDBObjectStoreBackendProxy::index(const String& name, ExceptionCode& ec) 108 126 { … … 126 144 // all implementations of IDB interfaces are proxy objects. 127 145 IDBTransactionBackendProxy* transactionProxy = static_cast<IDBTransactionBackendProxy*>(transaction); 128 m_webIDBObjectStore->openCursor(range, direction, new WebIDBCallbacksImpl(callbacks), *transactionProxy->getWebIDBTransaction(), ec); 146 m_webIDBObjectStore->openCursor(range, static_cast<WebIDBCursor::Direction>(direction), new WebIDBCallbacksImpl(callbacks), *transactionProxy->getWebIDBTransaction(), ec); 147 } 148 149 void IDBObjectStoreBackendProxy::openCursor(PassRefPtr<IDBKeyRange> range, IDBCursor::Direction direction, PassRefPtr<IDBCallbacks> callbacks, IDBTransactionBackendInterface::TaskType taskType, IDBTransactionBackendInterface* transaction, ExceptionCode& ec) 150 { 151 // The transaction pointer is guaranteed to be a pointer to a proxy object as, in the renderer, 152 // all implementations of IDB interfaces are proxy objects. 153 IDBTransactionBackendProxy* transactionProxy = static_cast<IDBTransactionBackendProxy*>(transaction); 154 m_webIDBObjectStore->openCursor(range, static_cast<WebIDBCursor::Direction>(direction), new WebIDBCallbacksImpl(callbacks), static_cast<WebIDBTransaction::TaskType>(taskType), *transactionProxy->getWebIDBTransaction(), ec); 129 155 } 130 156 -
trunk/Source/WebKit/chromium/src/IDBObjectStoreBackendProxy.h
r123843 r125728 50 50 51 51 PassRefPtr<WebCore::IDBIndexBackendInterface> createIndex(const String& name, const WebCore::IDBKeyPath&, bool unique, bool multiEntry, WebCore::IDBTransactionBackendInterface*, WebCore::ExceptionCode&); 52 virtual void setIndexKeys(PassRefPtr<WebCore::IDBKey> prpPrimaryKey, const WTF::Vector<WTF::String>&, const WTF::Vector<IndexKeys>&, WebCore::IDBTransactionBackendInterface*); 53 virtual void setIndexesReady(const Vector<String>&, WebCore::IDBTransactionBackendInterface*); 54 52 55 PassRefPtr<WebCore::IDBIndexBackendInterface> index(const String& name, WebCore::ExceptionCode&); 53 56 void deleteIndex(const String& name, WebCore::IDBTransactionBackendInterface*, WebCore::ExceptionCode&); 54 57 58 // FIXME: Remove this version of openCursor when TaskType is plumbed through chromium. 55 59 virtual void openCursor(PassRefPtr<WebCore::IDBKeyRange>, unsigned short direction, PassRefPtr<WebCore::IDBCallbacks>, WebCore::IDBTransactionBackendInterface*, WebCore::ExceptionCode&); 60 virtual void openCursor(PassRefPtr<WebCore::IDBKeyRange>, WebCore::IDBCursor::Direction, PassRefPtr<WebCore::IDBCallbacks>, WebCore::IDBTransactionBackendInterface::TaskType, WebCore::IDBTransactionBackendInterface*, WebCore::ExceptionCode&); 56 61 virtual void count(PassRefPtr<WebCore::IDBKeyRange>, PassRefPtr<WebCore::IDBCallbacks>, WebCore::IDBTransactionBackendInterface*, WebCore::ExceptionCode&); 57 62 -
trunk/Source/WebKit/chromium/src/WebIDBObjectStoreImpl.cpp
r125211 r125728 76 76 } 77 77 78 void WebIDBObjectStoreImpl::setIndexKeys(const WebIDBKey& primaryKey, const WebVector<WebString>& webIndexNames, const WebVector<WebIndexKeys>& webIndexKeys, const WebIDBTransaction& transaction) 79 { 80 ASSERT(webIndexNames.size() == webIndexKeys.size()); 81 Vector<String> indexNames(webIndexNames.size()); 82 Vector<IDBObjectStoreBackendInterface::IndexKeys> indexKeys(webIndexKeys.size()); 83 84 for (size_t i = 0; i < webIndexNames.size(); ++i) { 85 indexNames[i] = webIndexNames[i]; 86 Vector<RefPtr<IDBKey> > indexKeyList(webIndexKeys[i].size()); 87 for (size_t j = 0; j < webIndexKeys[i].size(); ++j) 88 indexKeyList[j] = webIndexKeys[i][j]; 89 indexKeys[i] = indexKeyList; 90 } 91 m_objectStore->setIndexKeys(primaryKey, indexNames, indexKeys, transaction.getIDBTransactionBackendInterface()); 92 } 93 94 void WebIDBObjectStoreImpl::setIndexesReady(const WebVector<WebString>& webIndexNames, const WebIDBTransaction& transaction) 95 { 96 Vector<String> indexNames(webIndexNames.size()); 97 for (size_t i = 0; i < webIndexNames.size(); ++i) 98 indexNames[i] = webIndexNames[i]; 99 m_objectStore->setIndexesReady(indexNames, transaction.getIDBTransactionBackendInterface()); 100 } 101 78 102 void WebIDBObjectStoreImpl::deleteFunction(const WebIDBKeyRange& keyRange, WebIDBCallbacks* callbacks, const WebIDBTransaction& transaction, WebExceptionCode& ec) 79 103 { … … 107 131 } 108 132 109 void WebIDBObjectStoreImpl::openCursor(const WebIDBKeyRange& keyRange, WebIDBCursor::Direction direction, WebIDBCallbacks* callbacks, WebIDBTransaction::TaskType , const WebIDBTransaction& transaction, WebExceptionCode& ec)133 void WebIDBObjectStoreImpl::openCursor(const WebIDBKeyRange& keyRange, WebIDBCursor::Direction direction, WebIDBCallbacks* callbacks, WebIDBTransaction::TaskType taskType, const WebIDBTransaction& transaction, WebExceptionCode& ec) 110 134 { 111 // FIXME: Pass along TaskType when the API becomes available. 112 m_objectStore->openCursor(keyRange, direction, IDBCallbacksProxy::create(adoptPtr(callbacks)), transaction.getIDBTransactionBackendInterface(), ec); 135 m_objectStore->openCursor(keyRange, static_cast<IDBCursor::Direction>(direction), IDBCallbacksProxy::create(adoptPtr(callbacks)), static_cast<IDBTransactionBackendInterface::TaskType>(taskType), transaction.getIDBTransactionBackendInterface(), ec); 113 136 } 114 137 -
trunk/Source/WebKit/chromium/src/WebIDBObjectStoreImpl.h
r125211 r125728 47 47 48 48 void get(const WebIDBKeyRange&, WebIDBCallbacks*, const WebIDBTransaction&, WebExceptionCode&); 49 void putWithIndexKeys(const WebSerializedScriptValue&, const WebIDBKey&, PutMode, WebIDBCallbacks*, const WebIDBTransaction&, const WebVector<WebString>& indexNames, const WebVector<WebIndexKeys>&, WebExceptionCode&); 49 void putWithIndexKeys(const WebSerializedScriptValue&, const WebIDBKey&, PutMode, WebIDBCallbacks*, const WebIDBTransaction&, const WebVector<WebString>&, const WebVector<WebIndexKeys>&, WebExceptionCode&); 50 void setIndexKeys(const WebIDBKey&, const WebVector<WebString>& indexNames, const WebVector<WebIndexKeys>&, const WebIDBTransaction&); 51 void setIndexesReady(const WebVector<WebString>&, const WebIDBTransaction&); 50 52 void deleteFunction(const WebIDBKeyRange&, WebIDBCallbacks*, const WebIDBTransaction&, WebExceptionCode&); 51 53 void clear(WebIDBCallbacks*, const WebIDBTransaction&, WebExceptionCode&);
Note: See TracChangeset
for help on using the changeset viewer.