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