]> git.proxmox.com Git - ceph.git/blame - ceph/src/rocksdb/monitoring/persistent_stats_history.cc
bump version to 18.2.4-pve3
[ceph.git] / ceph / src / rocksdb / monitoring / persistent_stats_history.cc
CommitLineData
f67539c2
TL
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// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
6// Use of this source code is governed by a BSD-style license that can be
7// found in the LICENSE file. See the AUTHORS file for names of contributors.
8
9#include "monitoring/persistent_stats_history.h"
10
11#include <cstring>
12#include <string>
13#include <utility>
1e59de90 14
f67539c2 15#include "db/db_impl/db_impl.h"
f67539c2
TL
16#include "util/string_util.h"
17
18namespace ROCKSDB_NAMESPACE {
19// 10 digit seconds timestamp => [Sep 9, 2001 ~ Nov 20, 2286]
20const int kNowSecondsStringLength = 10;
21const std::string kFormatVersionKeyString =
22 "__persistent_stats_format_version__";
23const std::string kCompatibleVersionKeyString =
24 "__persistent_stats_compatible_version__";
25// Every release maintains two versions numbers for persistents stats: Current
26// format version and compatible format version. Current format version
27// designates what type of encoding will be used when writing to stats CF;
28// compatible format version designates the minimum format version that
29// can decode the stats CF encoded using the current format version.
30const uint64_t kStatsCFCurrentFormatVersion = 1;
31const uint64_t kStatsCFCompatibleFormatVersion = 1;
32
33Status DecodePersistentStatsVersionNumber(DBImpl* db, StatsVersionKeyType type,
34 uint64_t* version_number) {
35 if (type >= StatsVersionKeyType::kKeyTypeMax) {
36 return Status::InvalidArgument("Invalid stats version key type provided");
37 }
38 std::string key;
39 if (type == StatsVersionKeyType::kFormatVersion) {
40 key = kFormatVersionKeyString;
41 } else if (type == StatsVersionKeyType::kCompatibleVersion) {
42 key = kCompatibleVersionKeyString;
43 }
44 ReadOptions options;
45 options.verify_checksums = true;
46 std::string result;
47 Status s = db->Get(options, db->PersistentStatsColumnFamily(), key, &result);
48 if (!s.ok() || result.empty()) {
49 return Status::NotFound("Persistent stats version key " + key +
50 " not found.");
51 }
52
53 // read version_number but do nothing in current version
54 *version_number = ParseUint64(result);
55 return Status::OK();
56}
57
58int EncodePersistentStatsKey(uint64_t now_seconds, const std::string& key,
59 int size, char* buf) {
60 char timestamp[kNowSecondsStringLength + 1];
61 // make time stamp string equal in length to allow sorting by time
62 snprintf(timestamp, sizeof(timestamp), "%010d",
63 static_cast<int>(now_seconds));
64 timestamp[kNowSecondsStringLength] = '\0';
65 return snprintf(buf, size, "%s#%s", timestamp, key.c_str());
66}
67
68void OptimizeForPersistentStats(ColumnFamilyOptions* cfo) {
69 cfo->write_buffer_size = 2 << 20;
70 cfo->target_file_size_base = 2 * 1048576;
71 cfo->max_bytes_for_level_base = 10 * 1048576;
72 cfo->soft_pending_compaction_bytes_limit = 256 * 1048576;
73 cfo->hard_pending_compaction_bytes_limit = 1073741824ul;
74 cfo->compression = kNoCompression;
75}
76
77PersistentStatsHistoryIterator::~PersistentStatsHistoryIterator() {}
78
79bool PersistentStatsHistoryIterator::Valid() const { return valid_; }
80
81Status PersistentStatsHistoryIterator::status() const { return status_; }
82
83void PersistentStatsHistoryIterator::Next() {
84 // increment start_time by 1 to avoid infinite loop
85 AdvanceIteratorByTime(GetStatsTime() + 1, end_time_);
86}
87
88uint64_t PersistentStatsHistoryIterator::GetStatsTime() const { return time_; }
89
90const std::map<std::string, uint64_t>&
91PersistentStatsHistoryIterator::GetStatsMap() const {
92 return stats_map_;
93}
94
95std::pair<uint64_t, std::string> parseKey(const Slice& key,
96 uint64_t start_time) {
97 std::pair<uint64_t, std::string> result;
98 std::string key_str = key.ToString();
99 std::string::size_type pos = key_str.find("#");
100 // TODO(Zhongyi): add counters to track parse failures?
101 if (pos == std::string::npos) {
1e59de90 102 result.first = std::numeric_limits<uint64_t>::max();
f67539c2
TL
103 result.second.clear();
104 } else {
105 uint64_t parsed_time = ParseUint64(key_str.substr(0, pos));
106 // skip entries with timestamp smaller than start_time
107 if (parsed_time < start_time) {
1e59de90 108 result.first = std::numeric_limits<uint64_t>::max();
f67539c2
TL
109 result.second = "";
110 } else {
111 result.first = parsed_time;
112 std::string key_resize = key_str.substr(pos + 1);
113 result.second = key_resize;
114 }
115 }
116 return result;
117}
118
119// advance the iterator to the next time between [start_time, end_time)
120// if success, update time_ and stats_map_ with new_time and stats_map
121void PersistentStatsHistoryIterator::AdvanceIteratorByTime(uint64_t start_time,
122 uint64_t end_time) {
123 // try to find next entry in stats_history_ map
124 if (db_impl_ != nullptr) {
125 ReadOptions ro;
126 Iterator* iter =
127 db_impl_->NewIterator(ro, db_impl_->PersistentStatsColumnFamily());
128
129 char timestamp[kNowSecondsStringLength + 1];
130 snprintf(timestamp, sizeof(timestamp), "%010d",
131 static_cast<int>(std::max(time_, start_time)));
132 timestamp[kNowSecondsStringLength] = '\0';
133
134 iter->Seek(timestamp);
135 // no more entries with timestamp >= start_time is found or version key
136 // is found to be incompatible
137 if (!iter->Valid()) {
138 valid_ = false;
139 delete iter;
140 return;
141 }
142 time_ = parseKey(iter->key(), start_time).first;
143 valid_ = true;
144 // check parsed time and invalid if it exceeds end_time
145 if (time_ > end_time) {
146 valid_ = false;
147 delete iter;
148 return;
149 }
150 // find all entries with timestamp equal to time_
151 std::map<std::string, uint64_t> new_stats_map;
152 std::pair<uint64_t, std::string> kv;
153 for (; iter->Valid(); iter->Next()) {
154 kv = parseKey(iter->key(), start_time);
155 if (kv.first != time_) {
156 break;
157 }
158 if (kv.second.compare(kFormatVersionKeyString) == 0) {
159 continue;
160 }
161 new_stats_map[kv.second] = ParseUint64(iter->value().ToString());
162 }
163 stats_map_.swap(new_stats_map);
164 delete iter;
165 } else {
166 valid_ = false;
167 }
168}
169
170} // namespace ROCKSDB_NAMESPACE