Coverage Report

Created: 2026-11-12 08:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/rocksdb/db/db_impl/db_impl_experimental.cc
Line
Count
Source
1
//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2
//  This source code is licensed under both the GPLv2 (found in the
3
//  COPYING file in the root directory) and Apache 2.0 License
4
//  (found in the LICENSE.Apache file in the root directory).
5
//
6
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
7
// Use of this source code is governed by a BSD-style license that can be
8
// found in the LICENSE file. See the AUTHORS file for names of contributors.
9
10
#include <cinttypes>
11
#include <vector>
12
13
#include "db/column_family.h"
14
#include "db/db_impl/db_impl.h"
15
#include "db/job_context.h"
16
#include "db/version_set.h"
17
#include "logging/logging.h"
18
#include "rocksdb/status.h"
19
#include "util/cast_util.h"
20
21
namespace ROCKSDB_NAMESPACE {
22
23
Status DBImpl::SuggestCompactRange(ColumnFamilyHandle* column_family,
24
0
                                   const Slice* begin, const Slice* end) {
25
0
  auto cfh = static_cast_with_check<ColumnFamilyHandleImpl>(column_family);
26
0
  auto cfd = cfh->cfd();
27
0
  InternalKey start_key;
28
0
  InternalKey end_key;
29
0
  if (begin != nullptr) {
30
0
    start_key.SetMinPossibleForUserKey(*begin);
31
0
  }
32
0
  if (end != nullptr) {
33
0
    end_key.SetMaxPossibleForUserKey(*end);
34
0
  }
35
0
  {
36
0
    InstrumentedMutexLock l(&mutex_);
37
0
    auto vstorage = cfd->current()->storage_info();
38
0
    for (int level = 0; level < vstorage->num_non_empty_levels() - 1; ++level) {
39
0
      std::vector<FileMetaData*> inputs;
40
0
      vstorage->GetOverlappingInputs(
41
0
          level, begin == nullptr ? nullptr : &start_key,
42
0
          end == nullptr ? nullptr : &end_key, &inputs);
43
0
      for (auto f : inputs) {
44
0
        f->marked_for_compaction = true;
45
0
      }
46
0
    }
47
    // Since we have some more files to compact, we should also recompute
48
    // compaction score
49
0
    vstorage->ComputeCompactionScore(cfd->ioptions(),
50
0
                                     cfd->GetLatestMutableCFOptions(),
51
0
                                     cfd->GetFullHistoryTsLow());
52
0
    EnqueuePendingCompaction(cfd);
53
0
    MaybeScheduleFlushOrCompaction();
54
0
  }
55
0
  return Status::OK();
56
0
}
57
58
0
Status DBImpl::PromoteL0(ColumnFamilyHandle* column_family, int target_level) {
59
0
  assert(column_family);
60
61
0
  if (target_level < 1) {
62
0
    ROCKS_LOG_INFO(immutable_db_options_.info_log,
63
0
                   "PromoteL0 FAILED. Invalid target level %d\n", target_level);
64
0
    return Status::InvalidArgument("Invalid target level");
65
0
  }
66
  // TODO: plumb Env::IOActivity, Env::IOPriority
67
0
  const ReadOptions read_options;
68
0
  const WriteOptions write_options;
69
70
0
  Status status;
71
0
  VersionEdit edit;
72
0
  JobContext job_context(next_job_id_.fetch_add(1), true);
73
0
  {
74
0
    InstrumentedMutexLock l(&mutex_);
75
0
    auto* cfd = static_cast<ColumnFamilyHandleImpl*>(column_family)->cfd();
76
0
    const auto* vstorage = cfd->current()->storage_info();
77
78
0
    if (target_level >= vstorage->num_levels()) {
79
0
      ROCKS_LOG_INFO(immutable_db_options_.info_log,
80
0
                     "PromoteL0 FAILED. Target level %d does not exist\n",
81
0
                     target_level);
82
0
      job_context.Clean();
83
0
      status = Status::InvalidArgument("Target level does not exist");
84
0
      return status;
85
0
    }
86
87
    // Sort L0 files by range.
88
0
    const InternalKeyComparator* icmp = &cfd->internal_comparator();
89
0
    auto l0_files = vstorage->LevelFiles(0);
90
0
    std::sort(l0_files.begin(), l0_files.end(),
91
0
              [icmp](FileMetaData* f1, FileMetaData* f2) {
92
0
                return icmp->Compare(f1->largest, f2->largest) < 0;
93
0
              });
94
95
    // Check that no L0 file is being compacted and that they have
96
    // non-overlapping ranges.
97
0
    for (size_t i = 0; i < l0_files.size(); ++i) {
98
0
      auto f = l0_files[i];
99
0
      if (f->being_compacted) {
100
0
        ROCKS_LOG_INFO(immutable_db_options_.info_log,
101
0
                       "PromoteL0 FAILED. File %" PRIu64 " being compacted\n",
102
0
                       f->fd.GetNumber());
103
0
        job_context.Clean();
104
0
        status =
105
0
            Status::InvalidArgument("PromoteL0 called during L0 compaction");
106
0
        return status;
107
0
      }
108
109
0
      if (i == 0) {
110
0
        continue;
111
0
      }
112
0
      auto prev_f = l0_files[i - 1];
113
0
      if (icmp->Compare(prev_f->largest, f->smallest) >= 0) {
114
0
        ROCKS_LOG_INFO(immutable_db_options_.info_log,
115
0
                       "PromoteL0 FAILED. Files %" PRIu64 " and %" PRIu64
116
0
                       " have overlapping ranges\n",
117
0
                       prev_f->fd.GetNumber(), f->fd.GetNumber());
118
0
        job_context.Clean();
119
0
        status = Status::InvalidArgument("L0 has overlapping files");
120
0
        return status;
121
0
      }
122
0
    }
123
124
    // Check that all levels up to target_level are empty.
125
0
    for (int level = 1; level <= target_level; ++level) {
126
0
      if (vstorage->NumLevelFiles(level) > 0) {
127
0
        ROCKS_LOG_INFO(immutable_db_options_.info_log,
128
0
                       "PromoteL0 FAILED. Level %d not empty\n", level);
129
0
        job_context.Clean();
130
0
        status = Status::InvalidArgument(
131
0
            "All levels up to target_level "
132
0
            "must be empty");
133
0
        return status;
134
0
      }
135
0
    }
136
137
0
    edit.SetColumnFamily(cfd->GetID());
138
0
    for (const auto& f : l0_files) {
139
0
      edit.DeleteFile(0, f->fd.GetNumber());
140
0
      edit.AddExistingFile(target_level, *f, kProvenanceMovedBetweenLevels);
141
0
    }
142
143
0
    status = versions_->LogAndApply(cfd, read_options, write_options, &edit,
144
0
                                    &mutex_, directories_.GetDbDir());
145
0
    if (status.ok()) {
146
0
      InstallSuperVersionAndScheduleWork(
147
0
          cfd, job_context.superversion_contexts.data(),
148
0
          /*defer_snapshot_refresh=*/false);
149
0
    }
150
0
  }  // lock released here
151
0
  LogFlush(immutable_db_options_.info_log);
152
0
  job_context.Clean();
153
154
0
  return status;
155
0
}
156
157
}  // namespace ROCKSDB_NAMESPACE