1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file.
4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#ifndef CONTENT_BROWSER_INDEXED_DB_LEVELDB_LEVELDB_TRANSACTION_H_
6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#define CONTENT_BROWSER_INDEXED_DB_LEVELDB_LEVELDB_TRANSACTION_H_
7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
8d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include <map>
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <set>
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <string>
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/gtest_prod_util.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/memory/ref_counted.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/strings/string_piece.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/leveldb/leveldb_comparator.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/leveldb/leveldb_database.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace content {
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class LevelDBWriteBatch;
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class CONTENT_EXPORT LevelDBTransaction
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : public base::RefCounted<LevelDBTransaction> {
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  void Put(const base::StringPiece& key, std::string* value);
297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  void Remove(const base::StringPiece& key);
306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  virtual leveldb::Status Get(const base::StringPiece& key,
316d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                              std::string* value,
326d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                              bool* found);
336d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  virtual leveldb::Status Commit();
34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void Rollback();
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<LevelDBIterator> CreateIterator();
37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
386d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) protected:
39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual ~LevelDBTransaction();
40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  explicit LevelDBTransaction(LevelDBDatabase* db);
41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  friend class IndexedDBClassFactory;
426d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
436d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) private:
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  friend class base::RefCounted<LevelDBTransaction>;
45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(LevelDBDatabaseTest, Transaction);
46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(LevelDBDatabaseTest, TransactionCommitTest);
47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(LevelDBDatabaseTest, TransactionIterator);
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
49d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  struct Record {
50d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    Record();
51d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ~Record();
527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    std::string key;
537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    std::string value;
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool deleted;
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  };
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
57d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  class Comparator {
58d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)   public:
59d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    explicit Comparator(const LevelDBComparator* comparator)
60d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        : comparator_(comparator) {}
61d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    bool operator()(const base::StringPiece& a,
62d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                    const base::StringPiece& b) const {
63d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return comparator_->Compare(a, b) < 0;
64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
66d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)   private:
67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const LevelDBComparator* comparator_;
68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  };
69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
70d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  typedef std::map<base::StringPiece, Record*, Comparator> DataType;
71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
72d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  class DataIterator : public LevelDBIterator {
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)   public:
74d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    static scoped_ptr<DataIterator> Create(LevelDBTransaction* transaction);
75d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    virtual ~DataIterator();
76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    virtual bool IsValid() const OVERRIDE;
780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    virtual leveldb::Status SeekToLast() OVERRIDE;
790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    virtual leveldb::Status Seek(const base::StringPiece& slice) OVERRIDE;
800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    virtual leveldb::Status Next() OVERRIDE;
810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    virtual leveldb::Status Prev() OVERRIDE;
827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    virtual base::StringPiece Key() const OVERRIDE;
837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    virtual base::StringPiece Value() const OVERRIDE;
84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool IsDeleted() const;
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)   private:
87d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    explicit DataIterator(LevelDBTransaction* transaction);
88d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    DataType* data_;
89d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    DataType::iterator iterator_;
90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    DISALLOW_COPY_AND_ASSIGN(DataIterator);
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  };
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  class TransactionIterator : public LevelDBIterator {
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)   public:
96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    virtual ~TransactionIterator();
97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    static scoped_ptr<TransactionIterator> Create(
98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        scoped_refptr<LevelDBTransaction> transaction);
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    virtual bool IsValid() const OVERRIDE;
1010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    virtual leveldb::Status SeekToLast() OVERRIDE;
1020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    virtual leveldb::Status Seek(const base::StringPiece& target) OVERRIDE;
1030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    virtual leveldb::Status Next() OVERRIDE;
1040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    virtual leveldb::Status Prev() OVERRIDE;
1057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    virtual base::StringPiece Key() const OVERRIDE;
1067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    virtual base::StringPiece Value() const OVERRIDE;
107d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    void DataChanged();
108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)   private:
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    explicit TransactionIterator(scoped_refptr<LevelDBTransaction> transaction);
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    void HandleConflictsAndDeletes();
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    void SetCurrentIteratorToSmallestKey();
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    void SetCurrentIteratorToLargestKey();
114d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    void RefreshDataIterator() const;
115d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    bool DataIteratorIsLower() const;
116d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    bool DataIteratorIsHigher() const;
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_refptr<LevelDBTransaction> transaction_;
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const LevelDBComparator* comparator_;
120d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    mutable scoped_ptr<DataIterator> data_iterator_;
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<LevelDBIterator> db_iterator_;
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    LevelDBIterator* current_;
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    enum Direction {
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      FORWARD,
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      REVERSE
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    };
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    Direction direction_;
129d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    mutable bool data_changed_;
130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    DISALLOW_COPY_AND_ASSIGN(TransactionIterator);
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  };
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  void Set(const base::StringPiece& key, std::string* value, bool deleted);
135d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  void Clear();
136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void RegisterIterator(TransactionIterator* iterator);
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void UnregisterIterator(TransactionIterator* iterator);
138d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  void NotifyIterators();
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  LevelDBDatabase* db_;
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const LevelDBSnapshot snapshot_;
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const LevelDBComparator* comparator_;
143d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  Comparator data_comparator_;
144d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DataType data_;
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool finished_;
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::set<TransactionIterator*> iterators_;
147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(LevelDBTransaction);
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Reads go straight to the database, ignoring any writes cached in
152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// write_batch_, and writes are write-through, without consolidation.
153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class LevelDBDirectTransaction {
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  static scoped_ptr<LevelDBDirectTransaction> Create(LevelDBDatabase* db);
156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ~LevelDBDirectTransaction();
158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void Put(const base::StringPiece& key, const std::string* value);
159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status Get(const base::StringPiece& key,
160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                      std::string* value,
161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                      bool* found);
1627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  void Remove(const base::StringPiece& key);
163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status Commit();
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  explicit LevelDBDirectTransaction(LevelDBDatabase* db);
167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  LevelDBDatabase* db_;
169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<LevelDBWriteBatch> write_batch_;
170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool finished_;
171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(LevelDBDirectTransaction);
173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace content
176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif  // CONTENT_BROWSER_INDEXED_DB_LEVELDB_LEVELDB_TRANSACTION_H_
178