indexed_db_backing_store.h revision 0f1bc08d4cfcc34181b0b5cbf065c40f687bf740
1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_BACKING_STORE_H_
6#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_BACKING_STORE_H_
7
8#include <string>
9#include <vector>
10
11#include "base/basictypes.h"
12#include "base/files/file_path.h"
13#include "base/memory/ref_counted.h"
14#include "base/memory/scoped_ptr.h"
15#include "base/timer/timer.h"
16#include "content/browser/indexed_db/indexed_db.h"
17#include "content/browser/indexed_db/indexed_db_metadata.h"
18#include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
19#include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
20#include "content/common/content_export.h"
21#include "content/common/indexed_db/indexed_db_key.h"
22#include "content/common/indexed_db/indexed_db_key_path.h"
23#include "content/common/indexed_db/indexed_db_key_range.h"
24#include "third_party/WebKit/public/platform/WebIDBCallbacks.h"
25#include "third_party/leveldatabase/src/include/leveldb/status.h"
26#include "url/gurl.h"
27
28namespace content {
29
30class LevelDBComparator;
31class LevelDBDatabase;
32
33class LevelDBFactory {
34 public:
35  virtual ~LevelDBFactory() {}
36  virtual leveldb::Status OpenLevelDB(const base::FilePath& file_name,
37                                      const LevelDBComparator* comparator,
38                                      scoped_ptr<LevelDBDatabase>* db,
39                                      bool* is_disk_full) = 0;
40  virtual bool DestroyLevelDB(const base::FilePath& file_name) = 0;
41};
42
43class CONTENT_EXPORT IndexedDBBackingStore
44    : public base::RefCounted<IndexedDBBackingStore> {
45 public:
46  class CONTENT_EXPORT Transaction;
47
48  const GURL& origin_url() const { return origin_url_; }
49  base::OneShotTimer<IndexedDBBackingStore>* close_timer() {
50    return &close_timer_;
51  }
52
53  static scoped_refptr<IndexedDBBackingStore> Open(
54      const GURL& origin_url,
55      const base::FilePath& path_base,
56      WebKit::WebIDBCallbacks::DataLoss* data_loss,
57      std::string* data_loss_message,
58      bool* disk_full);
59
60  static scoped_refptr<IndexedDBBackingStore> Open(
61      const GURL& origin_url,
62      const base::FilePath& path_base,
63      WebKit::WebIDBCallbacks::DataLoss* data_loss,
64      std::string* data_loss_message,
65      bool* disk_full,
66      LevelDBFactory* factory);
67  static scoped_refptr<IndexedDBBackingStore> OpenInMemory(
68      const GURL& origin_url);
69  static scoped_refptr<IndexedDBBackingStore> OpenInMemory(
70      const GURL& origin_url,
71      LevelDBFactory* factory);
72
73  virtual std::vector<string16> GetDatabaseNames();
74  virtual bool GetIDBDatabaseMetaData(const string16& name,
75                                      IndexedDBDatabaseMetadata* metadata,
76                                      bool* success) WARN_UNUSED_RESULT;
77  virtual bool CreateIDBDatabaseMetaData(const string16& name,
78                                         const string16& version,
79                                         int64 int_version,
80                                         int64* row_id);
81  virtual bool UpdateIDBDatabaseMetaData(
82      IndexedDBBackingStore::Transaction* transaction,
83      int64 row_id,
84      const string16& version);
85  virtual bool UpdateIDBDatabaseIntVersion(
86      IndexedDBBackingStore::Transaction* transaction,
87      int64 row_id,
88      int64 int_version);
89  virtual bool DeleteDatabase(const string16& name);
90
91  bool GetObjectStores(int64 database_id,
92                       IndexedDBDatabaseMetadata::ObjectStoreMap* map)
93      WARN_UNUSED_RESULT;
94  virtual bool CreateObjectStore(
95      IndexedDBBackingStore::Transaction* transaction,
96      int64 database_id,
97      int64 object_store_id,
98      const string16& name,
99      const IndexedDBKeyPath& key_path,
100      bool auto_increment);
101  virtual bool DeleteObjectStore(
102      IndexedDBBackingStore::Transaction* transaction,
103      int64 database_id,
104      int64 object_store_id) WARN_UNUSED_RESULT;
105
106  class CONTENT_EXPORT RecordIdentifier {
107   public:
108    RecordIdentifier(const std::string& primary_key, int64 version);
109    RecordIdentifier();
110    ~RecordIdentifier();
111
112    const std::string& primary_key() const { return primary_key_; }
113    int64 version() const { return version_; }
114    void Reset(const std::string& primary_key, int64 version) {
115      primary_key_ = primary_key;
116      version_ = version;
117    }
118
119   private:
120    // TODO(jsbell): Make it more clear that this is the *encoded* version of
121    // the key.
122    std::string primary_key_;
123    int64 version_;
124    DISALLOW_COPY_AND_ASSIGN(RecordIdentifier);
125  };
126
127  virtual bool GetRecord(IndexedDBBackingStore::Transaction* transaction,
128                         int64 database_id,
129                         int64 object_store_id,
130                         const IndexedDBKey& key,
131                         std::string* record) WARN_UNUSED_RESULT;
132  virtual bool PutRecord(IndexedDBBackingStore::Transaction* transaction,
133                         int64 database_id,
134                         int64 object_store_id,
135                         const IndexedDBKey& key,
136                         const std::string& value,
137                         RecordIdentifier* record) WARN_UNUSED_RESULT;
138  virtual bool ClearObjectStore(IndexedDBBackingStore::Transaction* transaction,
139                                int64 database_id,
140                                int64 object_store_id) WARN_UNUSED_RESULT;
141  virtual bool DeleteRecord(IndexedDBBackingStore::Transaction* transaction,
142                            int64 database_id,
143                            int64 object_store_id,
144                            const RecordIdentifier& record) WARN_UNUSED_RESULT;
145  virtual bool GetKeyGeneratorCurrentNumber(
146      IndexedDBBackingStore::Transaction* transaction,
147      int64 database_id,
148      int64 object_store_id,
149      int64* current_number) WARN_UNUSED_RESULT;
150  virtual bool MaybeUpdateKeyGeneratorCurrentNumber(
151      IndexedDBBackingStore::Transaction* transaction,
152      int64 database_id,
153      int64 object_store_id,
154      int64 new_state,
155      bool check_current) WARN_UNUSED_RESULT;
156  virtual bool KeyExistsInObjectStore(
157      IndexedDBBackingStore::Transaction* transaction,
158      int64 database_id,
159      int64 object_store_id,
160      const IndexedDBKey& key,
161      RecordIdentifier* found_record_identifier,
162      bool* found) WARN_UNUSED_RESULT;
163
164  virtual bool CreateIndex(IndexedDBBackingStore::Transaction* transaction,
165                           int64 database_id,
166                           int64 object_store_id,
167                           int64 index_id,
168                           const string16& name,
169                           const IndexedDBKeyPath& key_path,
170                           bool is_unique,
171                           bool is_multi_entry) WARN_UNUSED_RESULT;
172  virtual bool DeleteIndex(IndexedDBBackingStore::Transaction* transaction,
173                           int64 database_id,
174                           int64 object_store_id,
175                           int64 index_id) WARN_UNUSED_RESULT;
176  virtual bool PutIndexDataForRecord(
177      IndexedDBBackingStore::Transaction* transaction,
178      int64 database_id,
179      int64 object_store_id,
180      int64 index_id,
181      const IndexedDBKey& key,
182      const RecordIdentifier& record) WARN_UNUSED_RESULT;
183  virtual bool GetPrimaryKeyViaIndex(
184      IndexedDBBackingStore::Transaction* transaction,
185      int64 database_id,
186      int64 object_store_id,
187      int64 index_id,
188      const IndexedDBKey& key,
189      scoped_ptr<IndexedDBKey>* primary_key) WARN_UNUSED_RESULT;
190  virtual bool KeyExistsInIndex(IndexedDBBackingStore::Transaction* transaction,
191                                int64 database_id,
192                                int64 object_store_id,
193                                int64 index_id,
194                                const IndexedDBKey& key,
195                                scoped_ptr<IndexedDBKey>* found_primary_key,
196                                bool* exists) WARN_UNUSED_RESULT;
197
198  class Cursor {
199   public:
200    virtual ~Cursor();
201
202    enum IteratorState {
203      READY = 0,
204      SEEK
205    };
206
207    struct CursorOptions {
208      CursorOptions();
209      ~CursorOptions();
210      int64 database_id;
211      int64 object_store_id;
212      int64 index_id;
213      std::string low_key;
214      bool low_open;
215      std::string high_key;
216      bool high_open;
217      bool forward;
218      bool unique;
219    };
220
221    const IndexedDBKey& key() const { return *current_key_; }
222    bool Continue() { return Continue(NULL, SEEK); }
223    bool Continue(const IndexedDBKey* key, IteratorState state);
224    bool Advance(uint32 count);
225    bool FirstSeek();
226
227    virtual Cursor* Clone() = 0;
228    virtual const IndexedDBKey& primary_key() const;
229    virtual std::string* Value() = 0;
230    virtual const RecordIdentifier& record_identifier() const;
231    virtual bool LoadCurrentRow() = 0;
232
233   protected:
234    Cursor(LevelDBTransaction* transaction,
235           const CursorOptions& cursor_options);
236    explicit Cursor(const IndexedDBBackingStore::Cursor* other);
237
238    virtual std::string EncodeKey(const IndexedDBKey& key) = 0;
239
240    bool IsPastBounds() const;
241    bool HaveEnteredRange() const;
242
243    LevelDBTransaction* transaction_;
244    const CursorOptions cursor_options_;
245    scoped_ptr<LevelDBIterator> iterator_;
246    scoped_ptr<IndexedDBKey> current_key_;
247    IndexedDBBackingStore::RecordIdentifier record_identifier_;
248  };
249
250  virtual scoped_ptr<Cursor> OpenObjectStoreKeyCursor(
251      IndexedDBBackingStore::Transaction* transaction,
252      int64 database_id,
253      int64 object_store_id,
254      const IndexedDBKeyRange& key_range,
255      indexed_db::CursorDirection);
256  virtual scoped_ptr<Cursor> OpenObjectStoreCursor(
257      IndexedDBBackingStore::Transaction* transaction,
258      int64 database_id,
259      int64 object_store_id,
260      const IndexedDBKeyRange& key_range,
261      indexed_db::CursorDirection);
262  virtual scoped_ptr<Cursor> OpenIndexKeyCursor(
263      IndexedDBBackingStore::Transaction* transaction,
264      int64 database_id,
265      int64 object_store_id,
266      int64 index_id,
267      const IndexedDBKeyRange& key_range,
268      indexed_db::CursorDirection);
269  virtual scoped_ptr<Cursor> OpenIndexCursor(
270      IndexedDBBackingStore::Transaction* transaction,
271      int64 database_id,
272      int64 object_store_id,
273      int64 index_id,
274      const IndexedDBKeyRange& key_range,
275      indexed_db::CursorDirection);
276
277  class Transaction {
278   public:
279    explicit Transaction(IndexedDBBackingStore* backing_store);
280    ~Transaction();
281    void Begin();
282    bool Commit();
283    void Rollback();
284    void Reset() {
285      backing_store_ = NULL;
286      transaction_ = NULL;
287    }
288
289    LevelDBTransaction* transaction() { return transaction_; }
290
291   private:
292    IndexedDBBackingStore* backing_store_;
293    scoped_refptr<LevelDBTransaction> transaction_;
294  };
295
296 protected:
297  IndexedDBBackingStore(const GURL& origin_url,
298                        scoped_ptr<LevelDBDatabase> db,
299                        scoped_ptr<LevelDBComparator> comparator);
300  virtual ~IndexedDBBackingStore();
301  friend class base::RefCounted<IndexedDBBackingStore>;
302
303 private:
304  static scoped_refptr<IndexedDBBackingStore> Create(
305      const GURL& origin_url,
306      scoped_ptr<LevelDBDatabase> db,
307      scoped_ptr<LevelDBComparator> comparator);
308
309  bool FindKeyInIndex(IndexedDBBackingStore::Transaction* transaction,
310                      int64 database_id,
311                      int64 object_store_id,
312                      int64 index_id,
313                      const IndexedDBKey& key,
314                      std::string* found_encoded_primary_key,
315                      bool* found);
316  bool GetIndexes(int64 database_id,
317                  int64 object_store_id,
318                  IndexedDBObjectStoreMetadata::IndexMap* map)
319      WARN_UNUSED_RESULT;
320
321  const GURL origin_url_;
322
323  // The origin identifier is a key prefix unique to the origin used in the
324  // leveldb backing store to partition data by origin. It is a normalized
325  // version of the origin URL with a versioning suffix appended, e.g.
326  // "http_localhost_81@1" Since only one origin is stored per backing store
327  // this is redundant but necessary for backwards compatibility; the suffix
328  // provides for future flexibility.
329  const std::string origin_identifier_;
330
331  scoped_ptr<LevelDBDatabase> db_;
332  scoped_ptr<LevelDBComparator> comparator_;
333  base::OneShotTimer<IndexedDBBackingStore> close_timer_;
334};
335
336}  // namespace content
337
338#endif  // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_BACKING_STORE_H_
339