summaryrefslogtreecommitdiffstats
path: root/WebCore/storage/Database.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/storage/Database.cpp')
-rw-r--r--WebCore/storage/Database.cpp80
1 files changed, 48 insertions, 32 deletions
diff --git a/WebCore/storage/Database.cpp b/WebCore/storage/Database.cpp
index 5aaa26f..29dec26 100644
--- a/WebCore/storage/Database.cpp
+++ b/WebCore/storage/Database.cpp
@@ -149,11 +149,12 @@ PassRefPtr<Database> Database::openDatabase(Document* document, const String& na
Database::Database(Document* document, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize)
: m_transactionInProgress(false)
+ , m_isTransactionQueueEnabled(true)
, m_document(document)
, m_name(name.crossThreadString())
, m_guid(0)
- , m_expectedVersion(expectedVersion)
- , m_displayName(displayName)
+ , m_expectedVersion(expectedVersion.crossThreadString())
+ , m_displayName(displayName.crossThreadString())
, m_estimatedSize(estimatedSize)
, m_deleted(false)
, m_stopped(false)
@@ -190,6 +191,11 @@ Database::Database(Document* document, const String& name, const String& expecte
m_document->addOpenDatabase(this);
}
+static void derefDocument(void* document)
+{
+ static_cast<Document*>(document)->deref();
+}
+
Database::~Database()
{
if (m_document->databaseThread())
@@ -197,6 +203,9 @@ Database::~Database()
DatabaseTracker::tracker().removeOpenDatabase(this);
m_document->removeOpenDatabase(this);
+
+ // Deref m_document on the main thread.
+ callOnMainThread(derefDocument, m_document.release().releaseRef());
}
bool Database::openAndVerifyVersion(ExceptionCode& e)
@@ -205,15 +214,14 @@ bool Database::openAndVerifyVersion(ExceptionCode& e)
return false;
m_databaseAuthorizer = DatabaseAuthorizer::create();
- RefPtr<DatabaseOpenTask> task = DatabaseOpenTask::create(this);
+ bool success = false;
+ DatabaseTaskSynchronizer synchronizer;
+ OwnPtr<DatabaseOpenTask> task = DatabaseOpenTask::create(this, &synchronizer, e, success);
- task->lockForSynchronousScheduling();
- m_document->databaseThread()->scheduleImmediateTask(task);
- task->waitForSynchronousCompletion();
+ m_document->databaseThread()->scheduleImmediateTask(task.release());
+ synchronizer.waitForTaskCompletion();
- ASSERT(task->isComplete());
- e = task->exceptionCode();
- return task->openSuccessful();
+ return success;
}
@@ -318,11 +326,11 @@ void Database::markAsDeletedAndClose()
m_document->databaseThread()->unscheduleDatabaseTasks(this);
- RefPtr<DatabaseCloseTask> task = DatabaseCloseTask::create(this);
+ DatabaseTaskSynchronizer synchronizer;
+ OwnPtr<DatabaseCloseTask> task = DatabaseCloseTask::create(this, &synchronizer);
- task->lockForSynchronousScheduling();
- m_document->databaseThread()->scheduleImmediateTask(task);
- task->waitForSynchronousCompletion();
+ m_document->databaseThread()->scheduleImmediateTask(task.release());
+ synchronizer.waitForTaskCompletion();
}
void Database::close()
@@ -362,7 +370,7 @@ void Database::stop()
{
MutexLocker locker(m_transactionInProgressMutex);
- m_transactionQueue.kill();
+ m_isTransactionQueueEnabled = false;
m_transactionInProgress = false;
}
}
@@ -497,15 +505,13 @@ bool Database::performOpenAndVerify(ExceptionCode& e)
currentVersion = "";
}
- // FIXME: For now, the spec says that if the database has no version, it is valid for any "Expected version" string. That seems silly and I think it should be
- // changed, and here's where we would change it
- if (m_expectedVersion.length()) {
- if (currentVersion.length() && m_expectedVersion != currentVersion) {
- LOG(StorageAPI, "page expects version %s from database %s, which actually has version name %s - openDatabase() call will fail", m_expectedVersion.ascii().data(),
- databaseDebugName().ascii().data(), currentVersion.ascii().data());
- e = INVALID_STATE_ERR;
- return false;
- }
+ // If the expected version isn't the empty string, ensure that the current database version we have matches that version. Otherwise, set an exception.
+ // If the expected version is the empty string, then we always return with whatever version of the database we have.
+ if (m_expectedVersion.length() && m_expectedVersion != currentVersion) {
+ LOG(StorageAPI, "page expects version %s from database %s, which actually has version name %s - openDatabase() call will fail", m_expectedVersion.ascii().data(),
+ databaseDebugName().ascii().data(), currentVersion.ascii().data());
+ e = INVALID_STATE_ERR;
+ return false;
}
return true;
@@ -534,8 +540,14 @@ void Database::scheduleTransaction()
{
ASSERT(!m_transactionInProgressMutex.tryLock()); // Locked by caller.
RefPtr<SQLTransaction> transaction;
- if (m_transactionQueue.tryGetMessage(transaction) && m_document->databaseThread()) {
- RefPtr<DatabaseTransactionTask> task = DatabaseTransactionTask::create(transaction);
+
+ if (m_isTransactionQueueEnabled && !m_transactionQueue.isEmpty()) {
+ transaction = m_transactionQueue.first();
+ m_transactionQueue.removeFirst();
+ }
+
+ if (transaction && m_document->databaseThread()) {
+ OwnPtr<DatabaseTransactionTask> task = DatabaseTransactionTask::create(transaction);
LOG(StorageAPI, "Scheduling DatabaseTransactionTask %p for transaction %p\n", task.get(), task->transaction());
m_transactionInProgress = true;
m_document->databaseThread()->scheduleTask(task.release());
@@ -548,7 +560,7 @@ void Database::scheduleTransactionStep(SQLTransaction* transaction, bool immedia
if (!m_document->databaseThread())
return;
- RefPtr<DatabaseTransactionTask> task = DatabaseTransactionTask::create(transaction);
+ OwnPtr<DatabaseTransactionTask> task = DatabaseTransactionTask::create(transaction);
LOG(StorageAPI, "Scheduling DatabaseTransactionTask %p for the transaction step\n", task.get());
if (immediately)
m_document->databaseThread()->scheduleImmediateTask(task.release());
@@ -618,15 +630,19 @@ void Database::deliverPendingCallback(void* context)
Vector<String> Database::tableNames()
{
+ // FIXME: Not using threadsafeCopy on these strings looks ok since threads take strict turns
+ // in dealing with them. However, if the code changes, this may not be true anymore.
+ Vector<String> result;
if (!m_document->databaseThread())
- return Vector<String>();
- RefPtr<DatabaseTableNamesTask> task = DatabaseTableNamesTask::create(this);
+ return result;
+
+ DatabaseTaskSynchronizer synchronizer;
+ OwnPtr<DatabaseTableNamesTask> task = DatabaseTableNamesTask::create(this, &synchronizer, result);
- task->lockForSynchronousScheduling();
- m_document->databaseThread()->scheduleImmediateTask(task);
- task->waitForSynchronousCompletion();
+ m_document->databaseThread()->scheduleImmediateTask(task.release());
+ synchronizer.waitForTaskCompletion();
- return task->tableNames();
+ return result;
}
void Database::setExpectedVersion(const String& version)