File: cleanup_scheduler.h

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (159 lines) | stat: -rw-r--r-- 5,967 bytes parent folder | download | duplicates (5)
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
// Copyright 2025 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_INSTANCE_LEVELDB_CLEANUP_SCHEDULER_H_
#define CONTENT_BROWSER_INDEXED_DB_INSTANCE_LEVELDB_CLEANUP_SCHEDULER_H_

#include <memory>

#include "base/feature_list.h"
#include "base/memory/raw_ptr.h"
#include "base/timer/timer.h"
#include "content/browser/indexed_db/status.h"
#include "content/common/content_export.h"

namespace blink {
struct IndexedDBDatabaseMetadata;
}  // namespace blink

namespace leveldb {
class DB;
}  // namespace leveldb

namespace content::indexed_db::level_db {

CONTENT_EXPORT BASE_DECLARE_FEATURE(kIdbInSessionDbCleanup);

class LevelDbTombstoneSweeper;

// Sweeps the IndexedDB LevelDB database looking for index tombstones, followed
// by a round of DB compaction. Sweeping is broken into phases so as to not
// impact ongoing transactions. Please check `Phase` description for more
// information. Also sets the last run time of the tombstone sweeper after a
// successful run. Ref: crbug.com/374691835
class CONTENT_EXPORT LevelDBCleanupScheduler {
 public:
  // These values are persisted to logs. Entries should not be renumbered and
  // numeric values should never be reused.
  // `kRunScheduled` is the state when the `running_state_` has been set. When
  // `RunCleanupTask` is called, the scheduler will start the tombstone sweeper.
  // `kTombstoneSweeper` is the state when the tombstone sweeper is running.
  // The tombstone sweeper runs in rounds so this state can last multiple task
  // rounds.
  // `kDatabaseCompaction` is set when the tombstone sweeper completes and the
  // next time the `RunCleanupTask` gets called, the DB compaction task is run.
  // `kLoggingAndCleanup` is set when the DB compaction task completes and the
  // next time logging operations are carried followed by resetting the state.
  // LINT.IfChange(Phase)
  enum class Phase {
    kRunScheduled = 0,
    kTombstoneSweeper = 1,
    kDatabaseCompaction = 2,
    kLoggingAndCleanup = 3,
    kMaxValue = kLoggingAndCleanup,
  };
  // LINT.ThenChange(//tools/metrics/histograms/metadata/storage/enums.xml:LevelDBCleanupSchedulerPhase)

  // Abstraction of backing store calls which are required
  // by the scheduler.
  class Delegate {
   public:
    // This function updates the next run timestamp for the
    // tombstone sweeper in the database metadata.
    // Virtual for testing.
    // Returns `true`  if the update was successful.
    virtual bool UpdateEarliestSweepTime() = 0;
    // This function updates the next run timestamp for the
    // level db compaction in the database metadata.
    // Virtual for testing.
    // Returns `true` if the update was successful.
    virtual bool UpdateEarliestCompactionTime() = 0;
    virtual Status GetCompleteMetadata(
        std::vector<std::unique_ptr<blink::IndexedDBDatabaseMetadata>>*
            output) = 0;
  };

  struct RunningState {
    RunningState();
    RunningState(const RunningState&) = delete;
    RunningState& operator=(const RunningState&) = delete;
    ~RunningState();

    std::vector<std::unique_ptr<blink::IndexedDBDatabaseMetadata>>
        metadata_vector;
    std::unique_ptr<LevelDbTombstoneSweeper> tombstone_sweeper;

    base::TimeDelta tombstone_sweeper_duration;
    base::TimeDelta db_compaction_duration;

    // The timer for running the cleanup tasks. Can be scheduled for either
    // `kDeferTimeOnNoTransactions` when there are not active transactions
    // or `kDeferTimeAfterLastTransaction` when there are active
    // transactions.
    base::RetainingOneShotTimer clean_up_scheduling_timer_;

    Phase cleanup_phase = Phase::kRunScheduled;
    int postpone_count = 0;
  };

  // `database` and `backing_store` must outlive this instance.
  LevelDBCleanupScheduler(leveldb::DB* database, Delegate* backing_store);

  LevelDBCleanupScheduler(const LevelDBCleanupScheduler&) = delete;
  LevelDBCleanupScheduler& operator=(const LevelDBCleanupScheduler&) = delete;

  virtual ~LevelDBCleanupScheduler();

  // Initializes the running state if a certain amount of time has passed
  // since the last run. This is invoked during transaction completion when
  // enough number of tombstones are encountered by the cursor.
  void Initialize();

  const std::optional<RunningState>& GetRunningStateForTesting() const {
    return running_state_;
  }

  // Postpones any scheduled task unless `kMaximumTimeBetweenRuns` has passed.
  void OnTransactionStart();

  // Schedules a cleanup task if `running_state_` is set and there are no other
  // active transactions.
  void OnTransactionComplete();

  // To avoid interrupting active usage, defer runs until there has been no
  // activity for a few seconds.
  static constexpr base::TimeDelta kDeferTimeAfterLastTransaction =
      base::Seconds(4);
  static constexpr base::TimeDelta kDeferTimeOnNoTransactions =
      base::Seconds(0.4);

 private:
  // Starts the timer for the cleanup tasks.
  void ScheduleNextCleanupTask(const base::TimeDelta& defer_time);

  // Logs the histograms for the current clean up tasks, resets the running
  // state and marks the last run time.
  void LogAndResetState();

  // Orchestrates the clean up tasks. Decides if we need to schedule a sweeper
  // run or DB compaction run or log and reset the scheduler state.
  void RunCleanupTask();

  bool RunTombstoneSweeper();

  // The actual DB reference inside `TransactionalLevelDBDatabase` owned by
  // `BackingStore`. It's instantiated before the scheduler and hence also
  // destroyed after the scheduler.
  const raw_ptr<leveldb::DB> database_;

  const raw_ptr<Delegate> delegate_;

  base::TimeTicks last_run_;
  std::optional<RunningState> running_state_;
  int active_transactions_count_ = 0;
};

}  // namespace content::indexed_db::level_db

#endif  // CONTENT_BROWSER_INDEXED_DB_INSTANCE_LEVELDB_CLEANUP_SCHEDULER_H_