Home | History | Annotate | Download | only in indexed_db
      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 
     27 namespace content {
     28 
     29 class LevelDBComparator;
     30 class LevelDBDatabase;
     31 
     32 class 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 
     42 class 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