1/*
2 * Copyright (C) 2011 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 IDBBackingStore_h
27#define IDBBackingStore_h
28
29#if ENABLE(INDEXED_DATABASE)
30
31#include "IDBKey.h"
32#include "IDBMetadata.h"
33#include "IndexedDB.h"
34#include "LevelDBTransaction.h"
35#include <wtf/OwnPtr.h>
36#include <wtf/RefCounted.h>
37#include <wtf/WeakPtr.h>
38
39namespace WebCore {
40
41class LevelDBComparator;
42class LevelDBDatabase;
43class LevelDBTransaction;
44class IDBKey;
45class IDBKeyRange;
46class SecurityOrigin;
47class SharedBuffer;
48
49class LevelDBFactory {
50public:
51    virtual PassOwnPtr<LevelDBDatabase> openLevelDB(const String& fileName, const LevelDBComparator*) = 0;
52    virtual bool destroyLevelDB(const String& fileName) = 0;
53};
54
55class IDBBackingStore : public RefCounted<IDBBackingStore> {
56public:
57    class Transaction;
58
59    virtual ~IDBBackingStore();
60    static PassRefPtr<IDBBackingStore> open(SecurityOrigin*, const String& pathBase, const String& fileIdentifier);
61    static PassRefPtr<IDBBackingStore> open(SecurityOrigin*, const String& pathBase, const String& fileIdentifier, LevelDBFactory*);
62    static PassRefPtr<IDBBackingStore> openInMemory(SecurityOrigin*, const String& identifier);
63    static PassRefPtr<IDBBackingStore> openInMemory(SecurityOrigin*, const String& identifier, LevelDBFactory*);
64    WeakPtr<IDBBackingStore> createWeakPtr() { return m_weakFactory.createWeakPtr(); }
65
66    virtual Vector<String> getDatabaseNames();
67    virtual bool getIDBDatabaseMetaData(const String& name, IDBDatabaseMetadata*, bool& success) WARN_UNUSED_RETURN;
68    virtual bool createIDBDatabaseMetaData(const String& name, const String& version, int64_t intVersion, int64_t& rowId);
69    virtual bool updateIDBDatabaseMetaData(IDBBackingStore::Transaction*, int64_t rowId, const String& version);
70    virtual bool updateIDBDatabaseIntVersion(IDBBackingStore::Transaction*, int64_t rowId, int64_t intVersion);
71    virtual bool deleteDatabase(const String& name);
72
73    bool getObjectStores(int64_t databaseId, IDBDatabaseMetadata::ObjectStoreMap*) WARN_UNUSED_RETURN;
74    virtual bool createObjectStore(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, const String& name, const IDBKeyPath&, bool autoIncrement);
75    virtual bool deleteObjectStore(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId) WARN_UNUSED_RETURN;
76
77    class RecordIdentifier {
78        WTF_MAKE_NONCOPYABLE(RecordIdentifier);
79    public:
80        RecordIdentifier(const Vector<char>& primaryKey, int64_t version) : m_primaryKey(primaryKey), m_version(version) { ASSERT(!primaryKey.isEmpty()); }
81        RecordIdentifier() : m_primaryKey(), m_version(-1) { }
82
83        const Vector<char> primaryKey() const { return m_primaryKey; }
84        int64_t version() const { return m_version; }
85        void reset(const Vector<char>& primaryKey, int64_t version) { m_primaryKey = primaryKey; m_version = version; }
86
87    private:
88        Vector<char> m_primaryKey; // FIXME: Make it more clear that this is the *encoded* version of the key.
89        int64_t m_version;
90    };
91
92    virtual bool getRecord(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, const IDBKey&, Vector<char>& record) WARN_UNUSED_RETURN;
93    virtual bool putRecord(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, const IDBKey&, PassRefPtr<SharedBuffer> value, RecordIdentifier*) WARN_UNUSED_RETURN;
94    virtual bool clearObjectStore(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId) WARN_UNUSED_RETURN;
95    virtual bool deleteRecord(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, const RecordIdentifier&) WARN_UNUSED_RETURN;
96    virtual bool getKeyGeneratorCurrentNumber(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t& currentNumber) WARN_UNUSED_RETURN;
97    virtual bool maybeUpdateKeyGeneratorCurrentNumber(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t newState, bool checkCurrent) WARN_UNUSED_RETURN;
98    virtual bool keyExistsInObjectStore(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, const IDBKey&, RecordIdentifier* foundRecordIdentifier, bool& found) WARN_UNUSED_RETURN;
99
100    virtual bool createIndex(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const String& name, const IDBKeyPath&, bool isUnique, bool isMultiEntry) WARN_UNUSED_RETURN;
101    virtual bool deleteIndex(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t indexId) WARN_UNUSED_RETURN;
102    virtual bool putIndexDataForRecord(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey&, const RecordIdentifier&) WARN_UNUSED_RETURN;
103    virtual bool getPrimaryKeyViaIndex(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey&, RefPtr<IDBKey>& primaryKey) WARN_UNUSED_RETURN;
104    virtual bool keyExistsInIndex(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& indexKey, RefPtr<IDBKey>& foundPrimaryKey, bool& exists) WARN_UNUSED_RETURN;
105
106    class Cursor : public RefCounted<Cursor> {
107    public:
108        enum IteratorState {
109            Ready = 0,
110            Seek
111        };
112
113        struct CursorOptions {
114            int64_t databaseId;
115            int64_t objectStoreId;
116            int64_t indexId;
117            Vector<char> lowKey;
118            bool lowOpen;
119            Vector<char> highKey;
120            bool highOpen;
121            bool forward;
122            bool unique;
123        };
124
125        PassRefPtr<IDBKey> key() const { return m_currentKey; }
126        bool continueFunction(const IDBKey* = 0, IteratorState = Seek);
127        bool advance(unsigned long);
128        bool firstSeek();
129
130        virtual PassRefPtr<Cursor> clone() = 0;
131        virtual PassRefPtr<IDBKey> primaryKey() const { return m_currentKey; }
132        virtual PassRefPtr<SharedBuffer> value() const = 0;
133        virtual const RecordIdentifier& recordIdentifier() const { return m_recordIdentifier; }
134        virtual ~Cursor() { }
135        virtual bool loadCurrentRow() = 0;
136
137    protected:
138        Cursor(LevelDBTransaction* transaction, const CursorOptions& cursorOptions)
139            : m_transaction(transaction)
140            , m_cursorOptions(cursorOptions)
141        {
142        }
143        explicit Cursor(const IDBBackingStore::Cursor* other);
144
145        virtual Vector<char> encodeKey(const IDBKey&) = 0;
146
147        bool isPastBounds() const;
148        bool haveEnteredRange() const;
149
150        LevelDBTransaction* m_transaction;
151        const CursorOptions m_cursorOptions;
152        OwnPtr<LevelDBIterator> m_iterator;
153        RefPtr<IDBKey> m_currentKey;
154        IDBBackingStore::RecordIdentifier m_recordIdentifier;
155    };
156
157    virtual PassRefPtr<Cursor> openObjectStoreKeyCursor(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, const IDBKeyRange*, IndexedDB::CursorDirection);
158    virtual PassRefPtr<Cursor> openObjectStoreCursor(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, const IDBKeyRange*, IndexedDB::CursorDirection);
159    virtual PassRefPtr<Cursor> openIndexKeyCursor(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange*, IndexedDB::CursorDirection);
160    virtual PassRefPtr<Cursor> openIndexCursor(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange*, IndexedDB::CursorDirection);
161
162    class Transaction {
163    public:
164        explicit Transaction(IDBBackingStore*);
165        void begin();
166        bool commit();
167        void rollback();
168        void reset() { m_backingStore = 0; m_transaction = 0; }
169
170        static LevelDBTransaction* levelDBTransactionFrom(Transaction* transaction)
171        {
172            return static_cast<Transaction*>(transaction)->m_transaction.get();
173        }
174
175    private:
176        IDBBackingStore* m_backingStore;
177        RefPtr<LevelDBTransaction> m_transaction;
178    };
179
180protected:
181    IDBBackingStore(const String& identifier, PassOwnPtr<LevelDBDatabase>, PassOwnPtr<LevelDBComparator>);
182
183    // Should only used for mocking.
184    IDBBackingStore();
185
186private:
187    static PassRefPtr<IDBBackingStore> create(const String& identifier, PassOwnPtr<LevelDBDatabase>, PassOwnPtr<LevelDBComparator>);
188
189    bool findKeyInIndex(IDBBackingStore::Transaction*, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey&, Vector<char>& foundEncodedPrimaryKey, bool& found);
190    bool getIndexes(int64_t databaseId, int64_t objectStoreId, IDBObjectStoreMetadata::IndexMap*) WARN_UNUSED_RETURN;
191
192    String m_identifier;
193
194    OwnPtr<LevelDBDatabase> m_db;
195    OwnPtr<LevelDBComparator> m_comparator;
196    WeakPtrFactory<IDBBackingStore> m_weakFactory;
197};
198
199} // namespace WebCore
200
201#endif // ENABLE(INDEXED_DATABASE)
202
203#endif // IDBBackingStore_h
204