1/*
2 * Copyright (C) 2010 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
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.
13 *
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.
24 */
25
26#ifndef IDBTransactionBackend_h
27#define IDBTransactionBackend_h
28
29#if ENABLE(INDEXED_DATABASE)
30
31#include "IDBDatabaseBackend.h"
32#include "IDBDatabaseError.h"
33#include "IDBOperation.h"
34#include "Timer.h"
35#include <wtf/Deque.h>
36#include <wtf/HashSet.h>
37#include <wtf/RefPtr.h>
38
39namespace WebCore {
40
41class IDBCursorBackend;
42class IDBDatabaseCallbacks;
43
44class IDBTransactionBackend : public RefCounted<IDBTransactionBackend> {
45public:
46    static PassRefPtr<IDBTransactionBackend> create(IDBDatabaseBackend*, int64_t transactionId, PassRefPtr<IDBDatabaseCallbacks>, const Vector<int64_t>& objectStoreIds, IndexedDB::TransactionMode);
47    ~IDBTransactionBackend();
48
49    void commit();
50    void abort();
51    void abort(PassRefPtr<IDBDatabaseError>);
52
53    void run();
54    IndexedDB::TransactionMode mode() const  { return m_mode; }
55    const HashSet<int64_t>& scope() const  { return m_objectStoreIds; }
56
57    void scheduleTask(PassRefPtr<IDBOperation> task, PassRefPtr<IDBSynchronousOperation> abortTask = nullptr) { scheduleTask(IDBDatabaseBackend::NormalTask, task, abortTask); }
58    void scheduleTask(IDBDatabaseBackend::TaskType, PassRefPtr<IDBOperation>, PassRefPtr<IDBSynchronousOperation> abortTask = nullptr);
59
60    void registerOpenCursor(IDBCursorBackend*);
61    void unregisterOpenCursor(IDBCursorBackend*);
62
63    void addPreemptiveEvent()  { m_pendingPreemptiveEvents++; }
64    void didCompletePreemptiveEvent()  { m_pendingPreemptiveEvents--; ASSERT(m_pendingPreemptiveEvents >= 0); }
65
66    IDBDatabaseBackend& database() const  { return *m_database; }
67
68    void scheduleCreateObjectStoreOperation(const IDBObjectStoreMetadata&);
69    void scheduleDeleteObjectStoreOperation(const IDBObjectStoreMetadata&);
70    void scheduleVersionChangeOperation(int64_t requestedVersion, PassRefPtr<IDBCallbacks>, PassRefPtr<IDBDatabaseCallbacks>, const IDBDatabaseMetadata&);
71    void scheduleCreateIndexOperation(int64_t objectStoreId, const IDBIndexMetadata&);
72    void scheduleDeleteIndexOperation(int64_t objectStoreId, const IDBIndexMetadata&);
73    void scheduleGetOperation(const IDBDatabaseMetadata&, int64_t objectStoreId, int64_t indexId, PassRefPtr<IDBKeyRange>, IndexedDB::CursorType, PassRefPtr<IDBCallbacks>);
74    void schedulePutOperation(const IDBObjectStoreMetadata&, PassRefPtr<SharedBuffer> value, PassRefPtr<IDBKey>, IDBDatabaseBackend::PutMode, PassRefPtr<IDBCallbacks>, const Vector<int64_t>& indexIds, const Vector<IndexKeys>&);
75    void scheduleSetIndexesReadyOperation(size_t indexCount);
76    void scheduleOpenCursorOperation(int64_t objectStoreId, int64_t indexId, PassRefPtr<IDBKeyRange>, IndexedDB::CursorDirection, IndexedDB::CursorType, IDBDatabaseBackend::TaskType, PassRefPtr<IDBCallbacks>);
77    void scheduleCountOperation(int64_t objectStoreId, int64_t indexId, PassRefPtr<IDBKeyRange>, PassRefPtr<IDBCallbacks>);
78    void scheduleDeleteRangeOperation(int64_t objectStoreId, PassRefPtr<IDBKeyRange>, PassRefPtr<IDBCallbacks>);
79    void scheduleClearObjectStoreOperation(int64_t objectStoreId, PassRefPtr<IDBCallbacks>);
80
81    int64_t id() const { return m_id; }
82
83private:
84    IDBTransactionBackend(IDBDatabaseBackend*, int64_t id, PassRefPtr<IDBDatabaseCallbacks>, const HashSet<int64_t>& objectStoreIds, IndexedDB::TransactionMode);
85
86    enum State {
87        Unopened, // Backing store transaction not yet created.
88        Unused, // Backing store transaction created, but no tasks yet.
89        StartPending, // Enqueued tasks, but backing store transaction not yet started.
90        Running, // Backing store transaction started but not yet finished.
91        Finished, // Either aborted or committed.
92    };
93
94    void start();
95
96    bool isTaskQueueEmpty() const;
97    bool hasPendingTasks() const;
98
99    void taskTimerFired(Timer<IDBTransactionBackend>&);
100    void closeOpenCursors();
101
102    const HashSet<int64_t> m_objectStoreIds;
103    const IndexedDB::TransactionMode m_mode;
104
105    State m_state;
106    bool m_commitPending;
107    RefPtr<IDBDatabaseCallbacks> m_callbacks;
108    RefPtr<IDBDatabaseBackend> m_database;
109
110    typedef Deque<RefPtr<IDBOperation>> TaskQueue;
111    TaskQueue m_taskQueue;
112    TaskQueue m_preemptiveTaskQueue;
113    Deque<RefPtr<IDBSynchronousOperation>> m_abortTaskQueue;
114
115    // FIXME: delete the timer once we have threads instead.
116    Timer<IDBTransactionBackend> m_taskTimer;
117    int m_pendingPreemptiveEvents;
118
119    HashSet<IDBCursorBackend*> m_openCursors;
120
121    int64_t m_id;
122};
123
124} // namespace WebCore
125
126#endif // ENABLE(INDEXED_DATABASE)
127
128#endif // IDBTransactionBackend_h
129