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 COMPONENTS_SERVICES_STORAGE_INDEXED_DB_TRANSACTIONAL_LEVELDB_TRANSACTIONAL_LEVELDB_DATABASE_H_
6 #define COMPONENTS_SERVICES_STORAGE_INDEXED_DB_TRANSACTIONAL_LEVELDB_TRANSACTIONAL_LEVELDB_DATABASE_H_
7 
8 #include <memory>
9 #include <string>
10 
11 #include "base/containers/flat_set.h"
12 #include "base/containers/mru_cache.h"
13 #include "base/files/file_path.h"
14 #include "base/gtest_prod_util.h"
15 #include "base/macros.h"
16 #include "base/memory/weak_ptr.h"
17 #include "base/sequenced_task_runner.h"
18 #include "base/strings/string_piece.h"
19 #include "base/time/clock.h"
20 #include "base/trace_event/memory_dump_provider.h"
21 #include "components/services/storage/indexed_db/leveldb/leveldb_state.h"
22 #include "third_party/leveldatabase/src/include/leveldb/options.h"
23 #include "third_party/leveldatabase/src/include/leveldb/status.h"
24 
25 namespace leveldb {
26 class DB;
27 class Env;
28 class Snapshot;
29 }  // namespace leveldb
30 
31 namespace content {
32 class TransactionalLevelDBDatabase;
33 class TransactionalLevelDBFactory;
34 class TransactionalLevelDBIterator;
35 class TransactionalLevelDBTransaction;
36 class LevelDBScopes;
37 class LevelDBWriteBatch;
38 
39 // This class manages the acquisition and release of a leveldb snapshot.
40 class LevelDBSnapshot {
41  public:
42   explicit LevelDBSnapshot(TransactionalLevelDBDatabase* db);
43   ~LevelDBSnapshot();
44 
snapshot()45   const leveldb::Snapshot* snapshot() const { return snapshot_; }
46 
47  private:
48   leveldb::DB* db_;
49   const leveldb::Snapshot* snapshot_;
50 
51   DISALLOW_COPY_AND_ASSIGN(LevelDBSnapshot);
52 };
53 
54 class TransactionalLevelDBDatabase
55     : public base::trace_event::MemoryDumpProvider {
56  public:
57   // Necessary because every iterator hangs onto leveldb blocks which can be
58   // large. See https://crbug/696055.
59   static const size_t kDefaultMaxOpenIteratorsPerDatabase = 50;
60 
61   ~TransactionalLevelDBDatabase() override;
62 
63   leveldb::Status Put(const base::StringPiece& key, std::string* value);
64   leveldb::Status Remove(const base::StringPiece& key);
65   virtual leveldb::Status Get(const base::StringPiece& key,
66                               std::string* value,
67                               bool* found);
68   virtual leveldb::Status Write(LevelDBWriteBatch* write_batch);
69 
70   // This iterator will stay up-to-date with changes made to this database
71   // object (as in, automatically reload when values are modified), but not
72   // from any transactions.
73   // LevelDBIterator must not outlive the LevelDBDatabase.
74   // Note: Use DefaultReadOptions() and then adjust any values afterwards.
75   std::unique_ptr<TransactionalLevelDBIterator> CreateIterator(
76       leveldb::ReadOptions options);
77 
78   void Compact(const base::StringPiece& start, const base::StringPiece& stop);
79   void CompactAll();
80 
81   leveldb::ReadOptions DefaultReadOptions();
82 
83   // base::trace_event::MemoryDumpProvider implementation.
84   bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
85                     base::trace_event::ProcessMemoryDump* pmd) override;
86 
leveldb_state()87   LevelDBState* leveldb_state() { return level_db_state_.get(); }
db()88   leveldb::DB* db() { return level_db_state_->db(); }
env()89   leveldb::Env* env() { return level_db_state_->in_memory_env(); }
scopes()90   LevelDBScopes* scopes() { return scopes_.get(); }
LastModified()91   base::Time LastModified() const { return last_modified_; }
92 
class_factory()93   TransactionalLevelDBFactory* class_factory() const { return class_factory_; }
94 
95   void SetClockForTesting(std::unique_ptr<base::Clock> clock);
96 
97  private:
98   friend class DefaultTransactionalLevelDBFactory;
99   friend class LevelDBSnapshot;
100   friend class TransactionalLevelDBIterator;
101   friend class TransactionalLevelDBTransaction;
102   friend class LevelDBTestDatabase;
103   FRIEND_TEST_ALL_PREFIXES(IndexedDBTest, DeleteFailsIfDirectoryLocked);
104   class IteratorNotifier;
105 
106   // |max_open_cursors| cannot be 0.
107   // All calls to this class should be done on |task_runner|.
108   TransactionalLevelDBDatabase(
109       scoped_refptr<LevelDBState> level_db_state,
110       std::unique_ptr<LevelDBScopes> leveldb_scopes,
111       TransactionalLevelDBFactory* factory,
112       scoped_refptr<base::SequencedTaskRunner> task_runner,
113       size_t max_open_iterators);
114 
115   void EvictAllIterators();
116 
117   void OnIteratorUsed(TransactionalLevelDBIterator* iterator);
118   void OnIteratorLoaded(TransactionalLevelDBIterator* iterator);
119   void OnIteratorEvicted(TransactionalLevelDBIterator* iterator);
120   void OnIteratorDestroyed(TransactionalLevelDBIterator* iterator);
121 
122   void CloseDatabase();
123 
124   // This iterator will stay up-to-date with changes from this |txn| (as
125   // in, automatically reload when values are modified), but not any other
126   // transactions or the database.
127   // LevelDBIterator must not outlive the LevelDBDatabase.
128   // Note: Use DefaultReadOptions() and then adjust any values afterwards.
129   std::unique_ptr<TransactionalLevelDBIterator> CreateIterator(
130       base::WeakPtr<TransactionalLevelDBTransaction> txn,
131       leveldb::ReadOptions options);
132 
133   scoped_refptr<LevelDBState> level_db_state_;
134   std::unique_ptr<LevelDBScopes> scopes_;
135   TransactionalLevelDBFactory* class_factory_;
136   base::Time last_modified_;
137   std::unique_ptr<base::Clock> clock_;
138 
139   // Contains all iterators created by this database directly through
140   // |CreateIterator| WITHOUT a transaction. Iterators created with a
141   // transaction will not be added to this list. Raw pointers are safe here
142   // because the destructor of TransactionalLevelDBIterator removes itself from
143   // its associated database. |db_only_loaded_iterators_| have loaded
144   // leveldb::Iterators, and |db_only_evicted_iterators_| have had their
145   // leveldb::Iterator evicted. It is performant to have
146   // |db_only_loaded_iterators_| as a flat_set, as the iterator pooling feature
147   // of TransactionalLevelDBDatabase ensures a maximum number of
148   // kDefaultMaxOpenIteratorsPerDatabase loaded iterators.
149   base::flat_set<TransactionalLevelDBIterator*> db_only_loaded_iterators_;
150   std::set<TransactionalLevelDBIterator*> db_only_evicted_iterators_;
151   bool is_evicting_all_loaded_iterators_ = false;
152 
153   struct DetachIteratorOnDestruct {
154     DetachIteratorOnDestruct() = default;
155     explicit DetachIteratorOnDestruct(TransactionalLevelDBIterator* it);
156     DetachIteratorOnDestruct(DetachIteratorOnDestruct&& that);
157     ~DetachIteratorOnDestruct();
158 
159     TransactionalLevelDBIterator* it = nullptr;
160 
161     DISALLOW_COPY_AND_ASSIGN(DetachIteratorOnDestruct);
162   };
163   // Despite the type name, this object uses LRU eviction. Raw pointers are safe
164   // here because the destructor of TransactionalLevelDBIterator removes itself
165   // from its associated database.
166   base::HashingMRUCache<TransactionalLevelDBIterator*, DetachIteratorOnDestruct>
167       iterator_lru_;
168 
169   // Recorded for UMA reporting.
170   uint32_t num_iterators_ = 0;
171   uint32_t max_iterators_ = 0;
172 
173   base::WeakPtrFactory<TransactionalLevelDBDatabase>
174       weak_factory_for_iterators_{this};
175 };
176 
177 }  // namespace content
178 
179 #endif  // COMPONENTS_SERVICES_STORAGE_INDEXED_DB_TRANSACTIONAL_LEVELDB_TRANSACTIONAL_LEVELDB_DATABASE_H_
180