2
* Copyright (C) 2011 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 "IDBDatabaseBackendImpl.h"
29
#if ENABLE(INDEXED_DATABASE)
31
#include "CrossThreadTask.h"
32
#include "IDBBackingStore.h"
33
#include "IDBDatabaseException.h"
34
#include "IDBFactoryBackendImpl.h"
35
#include "IDBObjectStoreBackendImpl.h"
36
#include "IDBTransactionBackendImpl.h"
37
#include "IDBTransactionCoordinator.h"
41
class IDBDatabaseBackendImpl::PendingOpenCall {
43
static PassOwnPtr<PendingOpenCall> create(PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBDatabaseCallbacks> databaseCallbacks)
45
return adoptPtr(new PendingOpenCall(callbacks, databaseCallbacks));
47
PassRefPtr<IDBCallbacks> callbacks() { return m_callbacks; }
48
PassRefPtr<IDBDatabaseCallbacks> databaseCallbacks() { return m_databaseCallbacks; }
51
PendingOpenCall(PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBDatabaseCallbacks> databaseCallbacks)
52
: m_callbacks(callbacks)
53
, m_databaseCallbacks(databaseCallbacks)
57
RefPtr<IDBCallbacks> m_callbacks;
58
RefPtr<IDBDatabaseCallbacks> m_databaseCallbacks;
61
class IDBDatabaseBackendImpl::PendingOpenWithVersionCall {
63
static PassOwnPtr<PendingOpenWithVersionCall> create(PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBDatabaseCallbacks> databaseCallbacks, int64_t version)
65
return adoptPtr(new PendingOpenWithVersionCall(callbacks, databaseCallbacks, version));
67
PassRefPtr<IDBCallbacks> callbacks() { return m_callbacks; }
68
PassRefPtr<IDBDatabaseCallbacks> databaseCallbacks() { return m_databaseCallbacks; }
69
int64_t version() { return m_version; }
72
PendingOpenWithVersionCall(PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBDatabaseCallbacks> databaseCallbacks, int64_t version)
73
: m_callbacks(callbacks)
74
, m_databaseCallbacks(databaseCallbacks)
78
RefPtr<IDBCallbacks> m_callbacks;
79
RefPtr<IDBDatabaseCallbacks> m_databaseCallbacks;
83
class IDBDatabaseBackendImpl::PendingDeleteCall {
85
static PassOwnPtr<PendingDeleteCall> create(PassRefPtr<IDBCallbacks> callbacks)
87
return adoptPtr(new PendingDeleteCall(callbacks));
89
PassRefPtr<IDBCallbacks> callbacks() { return m_callbacks; }
92
PendingDeleteCall(PassRefPtr<IDBCallbacks> callbacks)
93
: m_callbacks(callbacks)
96
RefPtr<IDBCallbacks> m_callbacks;
99
PassRefPtr<IDBDatabaseBackendImpl> IDBDatabaseBackendImpl::create(const String& name, IDBBackingStore* database, IDBFactoryBackendImpl* factory, const String& uniqueIdentifier)
101
RefPtr<IDBDatabaseBackendImpl> backend = adoptRef(new IDBDatabaseBackendImpl(name, database, factory, uniqueIdentifier));
102
if (!backend->openInternal())
104
return backend.release();
108
const char* NoStringVersion = "";
111
IDBDatabaseBackendImpl::IDBDatabaseBackendImpl(const String& name, IDBBackingStore* backingStore, IDBFactoryBackendImpl* factory, const String& uniqueIdentifier)
112
: m_backingStore(backingStore)
113
, m_metadata(name, InvalidId, NoStringVersion, IDBDatabaseMetadata::NoIntVersion, InvalidId)
114
, m_identifier(uniqueIdentifier)
116
, m_transactionCoordinator(IDBTransactionCoordinator::create())
117
, m_closingConnection(false)
119
ASSERT(!m_metadata.name.isNull());
122
bool IDBDatabaseBackendImpl::openInternal()
124
bool success = m_backingStore->getIDBDatabaseMetaData(m_metadata.name, &m_metadata);
125
ASSERT_WITH_MESSAGE(success == (m_metadata.id != InvalidId), "success = %s, m_id = %lld", success ? "true" : "false", static_cast<long long>(m_metadata.id));
130
return m_backingStore->createIDBDatabaseMetaData(m_metadata.name, m_metadata.version, m_metadata.intVersion, m_metadata.id);
133
IDBDatabaseBackendImpl::~IDBDatabaseBackendImpl()
137
PassRefPtr<IDBBackingStore> IDBDatabaseBackendImpl::backingStore() const
139
return m_backingStore;
142
IDBDatabaseMetadata IDBDatabaseBackendImpl::metadata() const
144
// FIXME: Figure out a way to keep m_metadata.objectStores.get(N).indexes up to date rather than regenerating this every time.
145
IDBDatabaseMetadata metadata(m_metadata);
146
for (ObjectStoreMap::const_iterator it = m_objectStores.begin(); it != m_objectStores.end(); ++it)
147
metadata.objectStores.set(it->value->id(), it->value->metadata());
151
PassRefPtr<IDBObjectStoreBackendInterface> IDBDatabaseBackendImpl::createObjectStore(int64_t id, const String& name, const IDBKeyPath& keyPath, bool autoIncrement, IDBTransactionBackendInterface* transactionPtr, ExceptionCode& ec)
153
ASSERT(!m_objectStores.contains(id));
155
RefPtr<IDBObjectStoreBackendImpl> objectStore = IDBObjectStoreBackendImpl::create(this, IDBObjectStoreMetadata(name, id, keyPath, autoIncrement, IDBObjectStoreBackendInterface::MinimumIndexId));
156
ASSERT(objectStore->name() == name);
158
RefPtr<IDBTransactionBackendImpl> transaction = IDBTransactionBackendImpl::from(transactionPtr);
159
ASSERT(transaction->mode() == IDBTransaction::VERSION_CHANGE);
161
// FIXME: Fix edge cases around transaction aborts that prevent this from just being ASSERT(id == m_metadata.maxObjectStoreId + 1)
162
ASSERT(id > m_metadata.maxObjectStoreId);
163
m_metadata.maxObjectStoreId = id;
165
RefPtr<IDBDatabaseBackendImpl> database = this;
166
if (!transaction->scheduleTask(
167
createCallbackTask(&IDBDatabaseBackendImpl::createObjectStoreInternal, database, objectStore, transaction),
168
createCallbackTask(&IDBDatabaseBackendImpl::removeObjectStoreFromMap, database, objectStore))) {
169
ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
173
m_objectStores.set(id, objectStore);
174
return objectStore.release();
177
void IDBDatabaseBackendImpl::createObjectStoreInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl> database, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBTransactionBackendImpl> transaction)
179
if (!database->m_backingStore->createObjectStore(transaction->backingStoreTransaction(), database->id(), objectStore->id(), objectStore->name(), objectStore->keyPath(), objectStore->autoIncrement())) {
180
transaction->abort();
185
PassRefPtr<IDBObjectStoreBackendImpl> IDBDatabaseBackendImpl::objectStore(int64_t id)
187
return m_objectStores.get(id);
190
void IDBDatabaseBackendImpl::deleteObjectStore(int64_t id, IDBTransactionBackendInterface* transactionPtr, ExceptionCode& ec)
192
ASSERT(m_objectStores.contains(id));
194
RefPtr<IDBDatabaseBackendImpl> database = this;
195
RefPtr<IDBObjectStoreBackendImpl> objectStore = m_objectStores.get(id);
196
RefPtr<IDBTransactionBackendImpl> transaction = IDBTransactionBackendImpl::from(transactionPtr);
197
ASSERT(transaction->mode() == IDBTransaction::VERSION_CHANGE);
199
if (!transaction->scheduleTask(
200
createCallbackTask(&IDBDatabaseBackendImpl::deleteObjectStoreInternal, database, objectStore, transaction),
201
createCallbackTask(&IDBDatabaseBackendImpl::addObjectStoreToMap, database, objectStore))) {
202
ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
205
m_objectStores.remove(id);
208
void IDBDatabaseBackendImpl::deleteObjectStoreInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl> database, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBTransactionBackendImpl> transaction)
210
database->m_backingStore->deleteObjectStore(transaction->backingStoreTransaction(), database->id(), objectStore->id());
213
void IDBDatabaseBackendImpl::setIntVersionInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl> database, int64_t version, PassRefPtr<IDBCallbacks> prpCallbacks, PassRefPtr<IDBDatabaseCallbacks> databaseCallbacks, PassRefPtr<IDBTransactionBackendImpl> transaction)
215
RefPtr<IDBCallbacks> callbacks(prpCallbacks);
216
int64_t databaseId = database->id();
217
int64_t oldVersion = database->m_metadata.intVersion;
218
ASSERT(version > oldVersion);
219
database->m_metadata.intVersion = version;
220
if (!database->m_backingStore->updateIDBDatabaseIntVersion(transaction->backingStoreTransaction(), databaseId, database->m_metadata.intVersion)) {
221
RefPtr<IDBDatabaseError> error = IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Error writing data to stable storage.");
222
callbacks->onError(error);
223
transaction->abort(error);
226
ASSERT(!database->m_pendingSecondHalfOpenWithVersion);
227
database->m_pendingSecondHalfOpenWithVersion = PendingOpenWithVersionCall::create(callbacks, databaseCallbacks, version);
228
callbacks->onUpgradeNeeded(oldVersion, transaction, database);
231
void IDBDatabaseBackendImpl::transactionStarted(PassRefPtr<IDBTransactionBackendImpl> prpTransaction)
233
RefPtr<IDBTransactionBackendImpl> transaction = prpTransaction;
234
if (transaction->mode() == IDBTransaction::VERSION_CHANGE) {
235
ASSERT(!m_runningVersionChangeTransaction);
236
m_runningVersionChangeTransaction = transaction;
240
void IDBDatabaseBackendImpl::transactionFinished(PassRefPtr<IDBTransactionBackendImpl> prpTransaction)
242
RefPtr<IDBTransactionBackendImpl> transaction = prpTransaction;
243
ASSERT(m_transactions.contains(transaction.get()));
244
m_transactions.remove(transaction.get());
245
if (transaction->mode() == IDBTransaction::VERSION_CHANGE) {
246
ASSERT(transaction.get() == m_runningVersionChangeTransaction.get());
247
m_runningVersionChangeTransaction.clear();
251
void IDBDatabaseBackendImpl::transactionFinishedAndAbortFired(PassRefPtr<IDBTransactionBackendImpl> prpTransaction)
253
RefPtr<IDBTransactionBackendImpl> transaction = prpTransaction;
254
if (transaction->mode() == IDBTransaction::VERSION_CHANGE) {
255
// If this was an open-with-version call, there will be a "second
256
// half" open call waiting for us in processPendingCalls.
257
// FIXME: When we no longer support setVersion, assert such a thing.
258
if (m_pendingSecondHalfOpenWithVersion) {
259
m_pendingSecondHalfOpenWithVersion->callbacks()->onError(IDBDatabaseError::create(IDBDatabaseException::IDB_ABORT_ERR, "Version change transaction was aborted in upgradeneeded event handler."));
260
m_pendingSecondHalfOpenWithVersion.release();
262
processPendingCalls();
266
void IDBDatabaseBackendImpl::transactionFinishedAndCompleteFired(PassRefPtr<IDBTransactionBackendImpl> prpTransaction)
268
RefPtr<IDBTransactionBackendImpl> transaction = prpTransaction;
269
if (transaction->mode() == IDBTransaction::VERSION_CHANGE)
270
processPendingCalls();
273
size_t IDBDatabaseBackendImpl::connectionCount()
275
// This does not include pending open calls, as those should not block version changes and deletes.
276
return m_databaseCallbacksSet.size();
279
void IDBDatabaseBackendImpl::processPendingCalls()
281
if (m_pendingSecondHalfOpenWithVersion) {
282
ASSERT(m_pendingSecondHalfOpenWithVersion->version() == m_metadata.intVersion);
283
ASSERT(m_metadata.id != InvalidId);
284
m_pendingSecondHalfOpenWithVersion->callbacks()->onSuccess(this);
285
m_pendingSecondHalfOpenWithVersion.release();
286
// Fall through when complete, as pending deletes may be (partially) unblocked.
289
// Note that this check is only an optimization to reduce queue-churn and
290
// not necessary for correctness; deleteDatabase and openConnection will
291
// requeue their calls if this condition is true.
292
if (m_runningVersionChangeTransaction)
295
// Pending calls may be requeued.
296
Deque<OwnPtr<PendingDeleteCall> > pendingDeleteCalls;
297
m_pendingDeleteCalls.swap(pendingDeleteCalls);
298
while (!pendingDeleteCalls.isEmpty()) {
299
OwnPtr<PendingDeleteCall> pendingDeleteCall = pendingDeleteCalls.takeFirst();
300
deleteDatabase(pendingDeleteCall->callbacks());
303
// This check is also not really needed, openConnection would just requeue its calls.
304
if (m_runningVersionChangeTransaction || !m_pendingDeleteCalls.isEmpty())
307
Deque<OwnPtr<PendingOpenWithVersionCall> > pendingOpenWithVersionCalls;
308
m_pendingOpenWithVersionCalls.swap(pendingOpenWithVersionCalls);
309
while (!pendingOpenWithVersionCalls.isEmpty()) {
310
OwnPtr<PendingOpenWithVersionCall> pendingOpenWithVersionCall = pendingOpenWithVersionCalls.takeFirst();
311
openConnectionWithVersion(pendingOpenWithVersionCall->callbacks(), pendingOpenWithVersionCall->databaseCallbacks(), pendingOpenWithVersionCall->version());
314
// Open calls can be requeued if an openWithVersion call started a version
315
// change transaction.
316
Deque<OwnPtr<PendingOpenCall> > pendingOpenCalls;
317
m_pendingOpenCalls.swap(pendingOpenCalls);
318
while (!pendingOpenCalls.isEmpty()) {
319
OwnPtr<PendingOpenCall> pendingOpenCall = pendingOpenCalls.takeFirst();
320
openConnection(pendingOpenCall->callbacks(), pendingOpenCall->databaseCallbacks());
324
// FIXME: Remove this as part of https://bugs.webkit.org/show_bug.cgi?id=102733.
325
PassRefPtr<IDBTransactionBackendInterface> IDBDatabaseBackendImpl::transaction(const Vector<int64_t>& objectStoreIds, unsigned short mode)
327
return createTransaction(0, objectStoreIds, mode);
330
PassRefPtr<IDBTransactionBackendInterface> IDBDatabaseBackendImpl::createTransaction(int64_t transactionId, const Vector<int64_t>& objectStoreIds, unsigned short mode)
332
RefPtr<IDBTransactionBackendImpl> transaction = IDBTransactionBackendImpl::create(transactionId, objectStoreIds, mode, this);
333
m_transactions.add(transaction.get());
334
return transaction.release();
337
void IDBDatabaseBackendImpl::openConnection(PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBDatabaseCallbacks> databaseCallbacks)
339
ASSERT(m_backingStore.get());
340
if (!m_pendingDeleteCalls.isEmpty() || m_runningVersionChangeTransaction) {
341
m_pendingOpenCalls.append(PendingOpenCall::create(callbacks, databaseCallbacks));
344
if (m_metadata.id == InvalidId && !openInternal()) {
345
callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Internal error."));
348
if (m_metadata.version == NoStringVersion && m_metadata.intVersion == IDBDatabaseMetadata::NoIntVersion) {
349
// Spec says: If no version is specified and no database exists, set
350
// database version to 1. We infer that the database didn't exist from
351
// its lack of either type of version.
352
openConnectionWithVersion(callbacks, databaseCallbacks, 1);
355
m_databaseCallbacksSet.add(RefPtr<IDBDatabaseCallbacks>(databaseCallbacks));
356
callbacks->onSuccess(this);
359
void IDBDatabaseBackendImpl::runIntVersionChangeTransaction(int64_t requestedVersion, PassRefPtr<IDBCallbacks> prpCallbacks, PassRefPtr<IDBDatabaseCallbacks> prpDatabaseCallbacks)
361
RefPtr<IDBCallbacks> callbacks = prpCallbacks;
362
RefPtr<IDBDatabaseCallbacks> databaseCallbacks = prpDatabaseCallbacks;
364
for (DatabaseCallbacksSet::const_iterator it = m_databaseCallbacksSet.begin(); it != m_databaseCallbacksSet.end(); ++it) {
365
// Front end ensures the event is not fired at connections that have closePending set.
366
if (*it != databaseCallbacks)
367
(*it)->onVersionChange(m_metadata.intVersion, requestedVersion);
369
// The spec dictates we wait until all the version change events are
370
// delivered and then check m_databaseCallbacks.empty() before proceeding
371
// or firing a blocked event, but instead we should be consistent with how
372
// the old setVersion (incorrectly) did it.
373
// FIXME: Remove the call to onBlocked and instead wait until the frontend
374
// tells us that all the blocked events have been delivered. See
375
// https://bugs.webkit.org/show_bug.cgi?id=71130
376
if (connectionCount())
377
callbacks->onBlocked(m_metadata.intVersion);
378
// FIXME: Add test for m_runningVersionChangeTransaction.
379
if (m_runningVersionChangeTransaction || connectionCount()) {
380
m_pendingOpenWithVersionCalls.append(PendingOpenWithVersionCall::create(callbacks, databaseCallbacks, requestedVersion));
384
Vector<int64_t> objectStoreIds;
385
RefPtr<IDBTransactionBackendInterface> transactionInterface = transaction(objectStoreIds, IDBTransaction::VERSION_CHANGE);
386
RefPtr<IDBTransactionBackendImpl> transaction = IDBTransactionBackendImpl::from(transactionInterface.get());
388
RefPtr<IDBDatabaseBackendImpl> database = this;
389
OwnPtr<ScriptExecutionContext::Task> intVersionTask = createCallbackTask(&IDBDatabaseBackendImpl::setIntVersionInternal, database, requestedVersion, callbacks, databaseCallbacks, transaction);
390
OwnPtr<ScriptExecutionContext::Task> resetVersionOnAbortTask = createCallbackTask(&IDBDatabaseBackendImpl::resetVersion, database, m_metadata.version, m_metadata.intVersion);
391
if (!transaction->scheduleTask(intVersionTask.release(), resetVersionOnAbortTask.release())) {
392
ASSERT_NOT_REACHED();
394
ASSERT(!m_pendingSecondHalfOpenWithVersion);
395
m_databaseCallbacksSet.add(databaseCallbacks);
398
void IDBDatabaseBackendImpl::openConnectionWithVersion(PassRefPtr<IDBCallbacks> prpCallbacks, PassRefPtr<IDBDatabaseCallbacks> prpDatabaseCallbacks, int64_t version)
400
RefPtr<IDBCallbacks> callbacks = prpCallbacks;
401
RefPtr<IDBDatabaseCallbacks> databaseCallbacks = prpDatabaseCallbacks;
402
if (!m_pendingDeleteCalls.isEmpty() || m_runningVersionChangeTransaction) {
403
m_pendingOpenWithVersionCalls.append(PendingOpenWithVersionCall::create(callbacks, databaseCallbacks, version));
406
if (m_metadata.id == InvalidId) {
408
ASSERT(m_metadata.intVersion == IDBDatabaseMetadata::NoIntVersion);
410
callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Internal error."));
414
if (version > m_metadata.intVersion) {
415
runIntVersionChangeTransaction(version, callbacks, databaseCallbacks);
418
if (version < m_metadata.intVersion) {
419
callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::VER_ERR, String::format("The requested version (%lld) is less than the existing version (%lld).", static_cast<long long>(version), static_cast<long long>(m_metadata.intVersion))));
422
ASSERT(version == m_metadata.intVersion);
423
m_databaseCallbacksSet.add(databaseCallbacks);
424
callbacks->onSuccess(this);
427
void IDBDatabaseBackendImpl::deleteDatabase(PassRefPtr<IDBCallbacks> prpCallbacks)
429
if (m_runningVersionChangeTransaction) {
430
m_pendingDeleteCalls.append(PendingDeleteCall::create(prpCallbacks));
433
RefPtr<IDBCallbacks> callbacks = prpCallbacks;
434
for (DatabaseCallbacksSet::const_iterator it = m_databaseCallbacksSet.begin(); it != m_databaseCallbacksSet.end(); ++it) {
435
// Front end ensures the event is not fired at connections that have closePending set.
436
(*it)->onVersionChange(NoStringVersion);
438
// FIXME: Only fire onBlocked if there are open connections after the
439
// VersionChangeEvents are received, not just set up to fire.
440
// https://bugs.webkit.org/show_bug.cgi?id=71130
441
if (connectionCount()) {
442
m_pendingDeleteCalls.append(PendingDeleteCall::create(callbacks));
443
callbacks->onBlocked();
446
ASSERT(m_backingStore);
447
if (!m_backingStore->deleteDatabase(m_metadata.name)) {
448
callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Internal error."));
451
m_metadata.version = NoStringVersion;
452
m_metadata.id = InvalidId;
453
m_metadata.intVersion = IDBDatabaseMetadata::NoIntVersion;
454
m_objectStores.clear();
455
callbacks->onSuccess();
458
void IDBDatabaseBackendImpl::close(PassRefPtr<IDBDatabaseCallbacks> prpCallbacks)
460
RefPtr<IDBDatabaseCallbacks> callbacks = prpCallbacks;
461
ASSERT(m_databaseCallbacksSet.contains(callbacks));
463
m_databaseCallbacksSet.remove(callbacks);
464
if (m_pendingSecondHalfOpenWithVersion && m_pendingSecondHalfOpenWithVersion->databaseCallbacks() == callbacks) {
465
m_pendingSecondHalfOpenWithVersion->callbacks()->onError(IDBDatabaseError::create(IDBDatabaseException::IDB_ABORT_ERR, "The connection was closed."));
466
m_pendingSecondHalfOpenWithVersion.release();
469
if (connectionCount() > 1)
472
// processPendingCalls allows the inspector to process a pending open call
473
// and call close, reentering IDBDatabaseBackendImpl::close. Then the
474
// backend would be removed both by the inspector closing its connection, and
475
// by the connection that first called close.
476
// To avoid that situation, don't proceed in case of reentrancy.
477
if (m_closingConnection)
479
m_closingConnection = true;
480
processPendingCalls();
482
// FIXME: Add a test for the m_pendingOpenCalls and m_pendingOpenWithVersionCalls cases below.
483
if (!connectionCount() && !m_pendingOpenCalls.size() && !m_pendingOpenWithVersionCalls.size() && !m_pendingDeleteCalls.size()) {
484
TransactionSet transactions(m_transactions);
485
for (TransactionSet::const_iterator it = transactions.begin(); it != transactions.end(); ++it)
488
ASSERT(m_transactions.isEmpty());
490
m_backingStore.clear();
491
// This check should only be false in tests.
493
m_factory->removeIDBDatabaseBackend(m_identifier);
495
m_closingConnection = false;
498
void IDBDatabaseBackendImpl::loadObjectStores()
501
Vector<String> names;
502
Vector<IDBKeyPath> keyPaths;
503
Vector<bool> autoIncrementFlags;
504
Vector<int64_t> maxIndexIds;
505
Vector<IDBObjectStoreMetadata> objectStores = m_backingStore->getObjectStores(m_metadata.id);
507
for (size_t i = 0; i < objectStores.size(); i++)
508
m_objectStores.set(objectStores[i].id, IDBObjectStoreBackendImpl::create(this, objectStores[i]));
511
void IDBDatabaseBackendImpl::removeObjectStoreFromMap(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl> database, PassRefPtr<IDBObjectStoreBackendImpl> prpObjectStore)
513
RefPtr<IDBObjectStoreBackendImpl> objectStore = prpObjectStore;
514
ASSERT(database->m_objectStores.contains(objectStore->id()));
515
database->m_objectStores.remove(objectStore->id());
518
void IDBDatabaseBackendImpl::addObjectStoreToMap(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl> database, PassRefPtr<IDBObjectStoreBackendImpl> objectStore)
520
RefPtr<IDBObjectStoreBackendImpl> objectStorePtr = objectStore;
521
ASSERT(!database->m_objectStores.contains(objectStorePtr->id()));
522
database->m_objectStores.set(objectStorePtr->id(), objectStorePtr);
525
void IDBDatabaseBackendImpl::resetVersion(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl> database, const String& previousVersion, int64_t previousIntVersion)
527
database->m_metadata.version = previousVersion;
528
database->m_metadata.intVersion = previousIntVersion;
531
} // namespace WebCore
533
#endif // ENABLE(INDEXED_DATABASE)