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_LEVELDB_LEVELDB_TRANSACTION_H_
6#define CONTENT_BROWSER_INDEXED_DB_LEVELDB_LEVELDB_TRANSACTION_H_
7
8#include <map>
9#include <set>
10#include <string>
11
12#include "base/gtest_prod_util.h"
13#include "base/memory/ref_counted.h"
14#include "base/memory/scoped_ptr.h"
15#include "base/strings/string_piece.h"
16#include "content/browser/indexed_db/leveldb/leveldb_comparator.h"
17#include "content/browser/indexed_db/leveldb/leveldb_database.h"
18#include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
19
20namespace content {
21
22class LevelDBWriteBatch;
23
24class CONTENT_EXPORT LevelDBTransaction
25    : public base::RefCounted<LevelDBTransaction> {
26 public:
27  void Put(const base::StringPiece& key, std::string* value);
28  void Remove(const base::StringPiece& key);
29  virtual leveldb::Status Get(const base::StringPiece& key,
30                              std::string* value,
31                              bool* found);
32  virtual leveldb::Status Commit();
33  void Rollback();
34
35  scoped_ptr<LevelDBIterator> CreateIterator();
36
37 protected:
38  virtual ~LevelDBTransaction();
39  explicit LevelDBTransaction(LevelDBDatabase* db);
40  friend class IndexedDBClassFactory;
41
42 private:
43  friend class base::RefCounted<LevelDBTransaction>;
44  FRIEND_TEST_ALL_PREFIXES(LevelDBDatabaseTest, Transaction);
45  FRIEND_TEST_ALL_PREFIXES(LevelDBDatabaseTest, TransactionCommitTest);
46  FRIEND_TEST_ALL_PREFIXES(LevelDBDatabaseTest, TransactionIterator);
47
48  struct Record {
49    Record();
50    ~Record();
51    std::string key;
52    std::string value;
53    bool deleted;
54  };
55
56  class Comparator {
57   public:
58    explicit Comparator(const LevelDBComparator* comparator)
59        : comparator_(comparator) {}
60    bool operator()(const base::StringPiece& a,
61                    const base::StringPiece& b) const {
62      return comparator_->Compare(a, b) < 0;
63    }
64
65   private:
66    const LevelDBComparator* comparator_;
67  };
68
69  typedef std::map<base::StringPiece, Record*, Comparator> DataType;
70
71  class DataIterator : public LevelDBIterator {
72   public:
73    static scoped_ptr<DataIterator> Create(LevelDBTransaction* transaction);
74    virtual ~DataIterator();
75
76    virtual bool IsValid() const OVERRIDE;
77    virtual leveldb::Status SeekToLast() OVERRIDE;
78    virtual leveldb::Status Seek(const base::StringPiece& slice) OVERRIDE;
79    virtual leveldb::Status Next() OVERRIDE;
80    virtual leveldb::Status Prev() OVERRIDE;
81    virtual base::StringPiece Key() const OVERRIDE;
82    virtual base::StringPiece Value() const OVERRIDE;
83    bool IsDeleted() const;
84
85   private:
86    explicit DataIterator(LevelDBTransaction* transaction);
87    DataType* data_;
88    DataType::iterator iterator_;
89
90    DISALLOW_COPY_AND_ASSIGN(DataIterator);
91  };
92
93  class TransactionIterator : public LevelDBIterator {
94   public:
95    virtual ~TransactionIterator();
96    static scoped_ptr<TransactionIterator> Create(
97        scoped_refptr<LevelDBTransaction> transaction);
98
99    virtual bool IsValid() const OVERRIDE;
100    virtual leveldb::Status SeekToLast() OVERRIDE;
101    virtual leveldb::Status Seek(const base::StringPiece& target) OVERRIDE;
102    virtual leveldb::Status Next() OVERRIDE;
103    virtual leveldb::Status Prev() OVERRIDE;
104    virtual base::StringPiece Key() const OVERRIDE;
105    virtual base::StringPiece Value() const OVERRIDE;
106    void DataChanged();
107
108   private:
109    enum Direction { FORWARD, REVERSE };
110
111    explicit TransactionIterator(scoped_refptr<LevelDBTransaction> transaction);
112    void HandleConflictsAndDeletes();
113    void SetCurrentIteratorToSmallestKey();
114    void SetCurrentIteratorToLargestKey();
115    void RefreshDataIterator() const;
116    bool DataIteratorIsLower() const;
117    bool DataIteratorIsHigher() const;
118
119    scoped_refptr<LevelDBTransaction> transaction_;
120    const LevelDBComparator* comparator_;
121    mutable scoped_ptr<DataIterator> data_iterator_;
122    scoped_ptr<LevelDBIterator> db_iterator_;
123    LevelDBIterator* current_;
124
125    Direction direction_;
126    mutable bool data_changed_;
127
128    DISALLOW_COPY_AND_ASSIGN(TransactionIterator);
129  };
130
131  void Set(const base::StringPiece& key, std::string* value, bool deleted);
132  void Clear();
133  void RegisterIterator(TransactionIterator* iterator);
134  void UnregisterIterator(TransactionIterator* iterator);
135  void NotifyIterators();
136
137  LevelDBDatabase* db_;
138  const LevelDBSnapshot snapshot_;
139  const LevelDBComparator* comparator_;
140  Comparator data_comparator_;
141  DataType data_;
142  bool finished_;
143  std::set<TransactionIterator*> iterators_;
144
145  DISALLOW_COPY_AND_ASSIGN(LevelDBTransaction);
146};
147
148// Reads go straight to the database, ignoring any writes cached in
149// write_batch_, and writes are write-through, without consolidation.
150class LevelDBDirectTransaction {
151 public:
152  static scoped_ptr<LevelDBDirectTransaction> Create(LevelDBDatabase* db);
153
154  ~LevelDBDirectTransaction();
155  void Put(const base::StringPiece& key, const std::string* value);
156  leveldb::Status Get(const base::StringPiece& key,
157                      std::string* value,
158                      bool* found);
159  void Remove(const base::StringPiece& key);
160  leveldb::Status Commit();
161
162 private:
163  explicit LevelDBDirectTransaction(LevelDBDatabase* db);
164
165  LevelDBDatabase* db_;
166  scoped_ptr<LevelDBWriteBatch> write_batch_;
167  bool finished_;
168
169  DISALLOW_COPY_AND_ASSIGN(LevelDBDirectTransaction);
170};
171
172}  // namespace content
173
174#endif  // CONTENT_BROWSER_INDEXED_DB_LEVELDB_LEVELDB_TRANSACTION_H_
175