1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
content / browser / indexed_db / indexed_db_leveldb_operations.h [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_LEVELDB_OPERATIONS_H_
#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_LEVELDB_OPERATIONS_H_
#include <memory>
#include <string>
#include <string_view>
#include "base/files/file_path.h"
#include "base/time/time.h"
#include "components/services/storage/indexed_db/transactional_leveldb/leveldb_write_batch.h"
#include "content/browser/indexed_db/indexed_db_data_loss_info.h"
#include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
#include "content/browser/indexed_db/status.h"
#include "content/common/content_export.h"
#include "third_party/blink/public/common/indexeddb/indexeddb_key_path.h"
#include "third_party/leveldatabase/src/include/leveldb/comparator.h"
// Contains common operations for LevelDBTransactions and/or LevelDBDatabases.
namespace storage {
struct BucketLocator;
} // namespace storage
namespace content::indexed_db {
class TransactionalLevelDBDatabase;
class TransactionalLevelDBIterator;
class TransactionalLevelDBTransaction;
class LevelDBDirectTransaction;
base::FilePath ComputeCorruptionFileName(
const storage::BucketLocator& bucket_locator);
// If a corruption file for the given `storage_key` at the given |path_base|
// exists it is deleted, and the message is returned. If the file does not
// exist, or if there is an error parsing the message, then this method returns
// an empty string (and deletes the file).
std::string CONTENT_EXPORT
ReadCorruptionInfo(const base::FilePath& path_base,
const storage::BucketLocator& bucket_locator);
// Was able to use LevelDB to read the data w/o error, but the data read was not
// in the expected format.
Status CONTENT_EXPORT InternalInconsistencyStatus();
Status InvalidDBKeyStatus();
Status IOErrorStatus();
template <typename Transaction>
Status PutValue(Transaction* transaction,
std::string_view key,
std::string* value) {
return Status(transaction->Put(key, value));
}
// This function must be declared as 'inline' to avoid duplicate symbols.
template <>
inline Status PutValue(LevelDBWriteBatch* write_batch,
std::string_view key,
std::string* value) {
write_batch->Put(key, std::string_view(*value));
return Status::OK();
}
// Note - this uses DecodeInt, which is a 'dumb' varint decoder. See DecodeInt.
template <typename DBOrTransaction>
Status GetInt(DBOrTransaction* db,
std::string_view key,
int64_t* found_int,
bool* found) {
std::string result;
Status s(db->Get(key, &result, found));
if (!s.ok())
return s;
if (!*found)
return Status::OK();
std::string_view slice(result);
if (DecodeInt(&slice, found_int) && slice.empty())
return s;
return InternalInconsistencyStatus();
}
[[nodiscard]] Status PutBool(TransactionalLevelDBTransaction* transaction,
std::string_view key,
bool value);
// Note - this uses EncodeInt, which is a 'dumb' varint encoder. See EncodeInt.
template <typename TransactionOrWriteBatch>
[[nodiscard]] Status PutInt(TransactionOrWriteBatch* transaction_or_write_batch,
std::string_view key,
int64_t value) {
DCHECK_GE(value, 0);
std::string buffer;
EncodeInt(value, &buffer);
return PutValue(transaction_or_write_batch, key, &buffer);
}
template <typename DBOrTransaction>
[[nodiscard]] Status GetVarInt(DBOrTransaction* db,
std::string_view key,
int64_t* found_int,
bool* found);
template <typename TransactionOrWriteBatch>
[[nodiscard]] Status PutVarInt(TransactionOrWriteBatch* transaction,
std::string_view key,
int64_t value);
template <typename DBOrTransaction>
[[nodiscard]] Status GetString(DBOrTransaction* db,
std::string_view key,
std::u16string* found_string,
bool* found);
[[nodiscard]] Status PutString(TransactionalLevelDBTransaction* transaction,
std::string_view key,
const std::u16string& value);
[[nodiscard]] Status PutIDBKeyPath(TransactionalLevelDBTransaction* transaction,
std::string_view key,
const blink::IndexedDBKeyPath& value);
template <typename DBOrTransaction>
[[nodiscard]] Status GetMaxObjectStoreId(DBOrTransaction* db,
int64_t database_id,
int64_t* max_object_store_id);
[[nodiscard]] Status SetMaxObjectStoreId(
TransactionalLevelDBTransaction* transaction,
int64_t database_id,
int64_t object_store_id);
[[nodiscard]] Status GetNewVersionNumber(
TransactionalLevelDBTransaction* transaction,
int64_t database_id,
int64_t object_store_id,
int64_t* new_version_number);
[[nodiscard]] Status SetMaxIndexId(TransactionalLevelDBTransaction* transaction,
int64_t database_id,
int64_t object_store_id,
int64_t index_id);
[[nodiscard]] Status VersionExists(TransactionalLevelDBTransaction* transaction,
int64_t database_id,
int64_t object_store_id,
int64_t version,
const std::string& encoded_primary_key,
bool* exists);
template <typename Transaction>
[[nodiscard]] Status GetNewDatabaseId(Transaction* transaction,
int64_t* new_id);
[[nodiscard]] bool CheckObjectStoreAndMetaDataType(
const TransactionalLevelDBIterator* it,
const std::string& stop_key,
int64_t object_store_id,
int64_t meta_data_type);
[[nodiscard]] bool CheckIndexAndMetaDataKey(
const TransactionalLevelDBIterator* it,
const std::string& stop_key,
int64_t index_id,
unsigned char meta_data_type);
[[nodiscard]] bool FindGreatestKeyLessThanOrEqual(
TransactionalLevelDBTransaction* transaction,
const std::string& target,
std::string* found_key,
Status* s);
[[nodiscard]] bool GetBlobNumberGeneratorCurrentNumber(
LevelDBDirectTransaction* leveldb_transaction,
int64_t database_id,
int64_t* blob_number_generator_current_number);
[[nodiscard]] bool UpdateBlobNumberGeneratorCurrentNumber(
LevelDBDirectTransaction* leveldb_transaction,
int64_t database_id,
int64_t blob_number_generator_current_number);
// Maximum time delays for tombstone sweeping and compaction tasks, throttled on
// global and per-bucket frequencies, triggered by backing store close.
static constexpr base::TimeDelta kMaxGlobalSweepDelay = base::Hours(1);
static constexpr base::TimeDelta kMaxBucketSweepDelay = base::Days(3);
static constexpr base::TimeDelta kMaxGlobalCompactionDelay = base::Hours(1);
static constexpr base::TimeDelta kMaxBucketCompactionDelay = base::Days(3);
// Get or update the earliest tombstone sweeping and compaction times, using
// global and per-bucket delays.
base::Time GetEarliestSweepTime(TransactionalLevelDBDatabase* db);
Status UpdateEarliestSweepTime(LevelDBDirectTransaction* txn);
base::Time GetEarliestCompactionTime(TransactionalLevelDBDatabase* db);
Status UpdateEarliestCompactionTime(LevelDBDirectTransaction* txn);
// Initialize global times for compaction and tombstone sweeping.
void InitializeGlobalSweepAndCompactionTimes();
// Forcibly reset global times for compaction and tombstone sweeping for tests.
CONTENT_EXPORT void ResetGlobalSweepAndCompactionTimesForTest();
CONTENT_EXPORT const leveldb::Comparator* GetDefaultLevelDBComparator();
} // namespace content::indexed_db
#endif // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_LEVELDB_OPERATIONS_H_