IDBTransactionBackendOperations.cpp [plain text]
#include "config.h"
#include "IDBTransactionBackendOperations.h"
#include "IDBCursorBackend.h"
#include "IDBDatabaseCallbacks.h"
#include "IDBKeyRange.h"
#include "IDBRecordIdentifier.h"
#include "IDBServerConnection.h"
#include "Logging.h"
#include <wtf/text/CString.h>
#if ENABLE(INDEXED_DATABASE)
#define STANDARD_DATABASE_ERROR_CALLBACK std::function<void(PassRefPtr<IDBDatabaseError>)> operationCallback = \
[operation, completionCallback](PassRefPtr<IDBDatabaseError> error) { \
if (error) \
operation->m_transaction->abort(error); \
completionCallback(); \
};
namespace WebCore {
void CreateObjectStoreOperation::perform(std::function<void()> completionCallback)
{
LOG(StorageAPI, "CreateObjectStoreOperation");
RefPtr<CreateObjectStoreOperation> operation(this);
STANDARD_DATABASE_ERROR_CALLBACK;
m_transaction->database().serverConnection().createObjectStore(*m_transaction, *this, operationCallback);
}
void CreateIndexOperation::perform(std::function<void()> completionCallback)
{
LOG(StorageAPI, "CreateIndexOperation");
RefPtr<CreateIndexOperation> operation(this);
STANDARD_DATABASE_ERROR_CALLBACK;
m_transaction->database().serverConnection().createIndex(*m_transaction, *this, operationCallback);
}
void CreateIndexAbortOperation::perform()
{
LOG(StorageAPI, "CreateIndexAbortOperation");
m_transaction->database().removeIndex(m_objectStoreID, m_indexID);
}
void DeleteIndexOperation::perform(std::function<void()> completionCallback)
{
LOG(StorageAPI, "DeleteIndexOperation");
RefPtr<DeleteIndexOperation> operation(this);
STANDARD_DATABASE_ERROR_CALLBACK;
m_transaction->database().serverConnection().deleteIndex(*m_transaction, *this, operationCallback);
}
void DeleteIndexAbortOperation::perform()
{
LOG(StorageAPI, "DeleteIndexAbortOperation");
m_transaction->database().addIndex(m_objectStoreID, m_indexMetadata, IDBIndexMetadata::InvalidId);
}
void GetOperation::perform(std::function<void()> completionCallback)
{
LOG(StorageAPI, "GetOperation");
RefPtr<GetOperation> operation(this);
STANDARD_DATABASE_ERROR_CALLBACK;
m_transaction->database().serverConnection().get(*m_transaction, *this, [this, operation, operationCallback](const IDBGetResult& result, PassRefPtr<IDBDatabaseError> prpError) {
RefPtr<IDBDatabaseError> error = prpError;
if (error)
m_callbacks->onError(error);
else {
if (!result.valueBuffer) {
if (result.keyData.isNull)
m_callbacks->onSuccess();
else
m_callbacks->onSuccess(result.keyData.maybeCreateIDBKey());
} else {
if (!result.keyData.isNull)
m_callbacks->onSuccess(result.valueBuffer, result.keyData.maybeCreateIDBKey(), result.keyPath);
else
m_callbacks->onSuccess(result.valueBuffer.get());
}
}
operationCallback(error.release());
});
}
void PutOperation::perform(std::function<void()> completionCallback)
{
LOG(StorageAPI, "PutOperation");
ASSERT(m_transaction->mode() != IndexedDB::TransactionMode::ReadOnly);
ASSERT(m_indexIDs.size() == m_indexKeys.size());
m_transaction->database().serverConnection().put(*m_transaction, *this, [this, completionCallback](PassRefPtr<IDBKey> key, PassRefPtr<IDBDatabaseError> prpError) {
RefPtr<IDBDatabaseError> error = prpError;
if (key) {
ASSERT(!error);
m_callbacks->onSuccess(key);
} else {
ASSERT(error);
m_callbacks->onError(error);
}
completionCallback();
});
}
void SetIndexesReadyOperation::perform(std::function<void()> completionCallback)
{
LOG(StorageAPI, "SetIndexesReadyOperation");
for (size_t i = 0; i < m_indexCount; ++i)
m_transaction->didCompletePreemptiveEvent();
callOnMainThread(completionCallback);
}
void OpenCursorOperation::perform(std::function<void()> completionCallback)
{
LOG(StorageAPI, "OpenCursorOperation");
RefPtr<OpenCursorOperation> operation(this);
auto callback = [this, operation, completionCallback](int64_t cursorID, PassRefPtr<IDBKey> key, PassRefPtr<IDBKey> primaryKey, PassRefPtr<SharedBuffer> valueBuffer, PassRefPtr<IDBDatabaseError> error) {
if (error) {
m_callbacks->onError(error);
} else if (!key) {
m_callbacks->onSuccess(static_cast<SharedBuffer*>(nullptr));
} else {
RefPtr<IDBCursorBackend> cursor = IDBCursorBackend::create(cursorID, m_cursorType, m_taskType, *m_transaction, m_objectStoreID);
cursor->updateCursorData(key.get(), primaryKey.get(), valueBuffer.get());
m_callbacks->onSuccess(cursor.release());
}
completionCallback();
};
m_transaction->database().serverConnection().openCursor(*m_transaction, *this, callback);
}
void CountOperation::perform(std::function<void()> completionCallback)
{
LOG(StorageAPI, "CountOperation");
RefPtr<CountOperation> operation(this);
auto callback = [this, operation, completionCallback](int64_t count, PassRefPtr<IDBDatabaseError>) {
m_callbacks->onSuccess(count);
completionCallback();
};
m_transaction->database().serverConnection().count(*m_transaction, *this, callback);
}
void DeleteRangeOperation::perform(std::function<void()> completionCallback)
{
LOG(StorageAPI, "DeleteRangeOperation");
RefPtr<DeleteRangeOperation> operation(this);
auto callback = [this, operation, completionCallback](PassRefPtr<IDBDatabaseError> error) {
if (error)
m_callbacks->onError(error);
else
m_callbacks->onSuccess();
completionCallback();
};
m_transaction->database().serverConnection().deleteRange(*m_transaction, *this, callback);
}
void ClearObjectStoreOperation::perform(std::function<void()> completionCallback)
{
LOG(StorageAPI, "ClearObjectStoreOperation");
RefPtr<ClearObjectStoreOperation> operation(this);
auto clearCallback = [this, operation, completionCallback](PassRefPtr<IDBDatabaseError> prpError) {
RefPtr<IDBDatabaseError> error = prpError;
if (error) {
m_callbacks->onError(error);
m_transaction->abort(error.release());
} else
m_callbacks->onSuccess();
completionCallback();
};
m_transaction->database().serverConnection().clearObjectStore(*m_transaction, *this, clearCallback);
}
void DeleteObjectStoreOperation::perform(std::function<void()> completionCallback)
{
LOG(StorageAPI, "DeleteObjectStoreOperation");
RefPtr<DeleteObjectStoreOperation> operation(this);
STANDARD_DATABASE_ERROR_CALLBACK;
m_transaction->database().serverConnection().deleteObjectStore(*m_transaction, *this, operationCallback);
}
void IDBDatabaseBackend::VersionChangeOperation::perform(std::function<void()> completionCallback)
{
LOG(StorageAPI, "VersionChangeOperation");
uint64_t oldVersion = m_transaction->database().metadata().version;
if (oldVersion == IDBDatabaseMetadata::NoIntVersion)
oldVersion = 0;
RefPtr<IDBDatabaseBackend::VersionChangeOperation> operation(this);
ASSERT(static_cast<uint64_t>(m_version) > oldVersion);
std::function<void(PassRefPtr<IDBDatabaseError>)> operationCallback = [oldVersion, operation, this, completionCallback](PassRefPtr<IDBDatabaseError> prpError) {
RefPtr<IDBDatabaseError> error = prpError;
if (error) {
m_callbacks->onError(error);
m_transaction->abort(error);
} else {
ASSERT(!m_transaction->database().hasPendingSecondHalfOpen());
m_transaction->database().setCurrentVersion(m_version);
m_transaction->database().setPendingSecondHalfOpen(std::make_unique<IDBPendingOpenCall>(*m_callbacks, *m_databaseCallbacks, m_transaction->id(), m_version));
m_callbacks->onUpgradeNeeded(oldVersion, &m_transaction->database(), m_transaction->database().metadata());
}
completionCallback();
};
m_transaction->database().serverConnection().changeDatabaseVersion(*m_transaction, *this, operationCallback);
}
void CreateObjectStoreAbortOperation::perform()
{
LOG(StorageAPI, "CreateObjectStoreAbortOperation");
m_transaction->database().removeObjectStore(m_objectStoreID);
}
void DeleteObjectStoreAbortOperation::perform()
{
LOG(StorageAPI, "DeleteObjectStoreAbortOperation");
m_transaction->database().addObjectStore(m_objectStoreMetadata, IDBObjectStoreMetadata::InvalidId);
}
void IDBDatabaseBackend::VersionChangeAbortOperation::perform()
{
LOG(StorageAPI, "VersionChangeAbortOperation");
m_transaction->database().setCurrentVersion(m_previousIntVersion);
}
}
#endif // ENABLE(INDEXED_DATABASE)