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_