foundationdb/bindings/c/test/mako/utils.hpp

187 lines
5.7 KiB
C++
Raw Normal View History

/*
* utils.hpp
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2013-2022 Apple Inc. and the FoundationDB project authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef UTILS_HPP
#define UTILS_HPP
2019-05-31 00:01:22 +08:00
#pragma once
#include "mako.hpp"
#include <cassert>
#include <chrono>
#include <cstdint>
#include <type_traits>
#include <fmt/format.h>
namespace mako {
2019-05-31 00:01:22 +08:00
/* uniform-distribution random */
/* return a uniform random number between low and high, both inclusive */
int urand(int low, int high);
/* random string */
2022-03-03 20:33:58 +08:00
template <bool Clear = true, typename Char>
void randomString(std::basic_string<Char>& str, int len) {
2022-03-03 20:33:58 +08:00
if constexpr (Clear)
str.clear();
assert(len >= 0);
str.reserve(str.size() + static_cast<size_t>(len));
for (auto i = 0; i < len; i++) {
str.push_back('!' + urand(0, 'z' - '!')); /* generage a char from '!' to 'z' */
}
}
2019-05-31 00:01:22 +08:00
/* random numeric string */
2022-03-03 20:33:58 +08:00
template <bool Clear = true, typename Char>
void randomNumericString(std::basic_string<Char>& str, int len) {
2022-03-03 20:33:58 +08:00
if constexpr (Clear)
str.clear();
assert(len >= 0);
str.reserve(str.size() + static_cast<size_t>(len));
for (auto i = 0; i < len; i++) {
str.push_back('0' + urand(0, 9)); /* generage a char from '0' to '9' */
}
}
2019-05-31 00:01:22 +08:00
/* given the total number of rows to be inserted,
* the worker process index p_idx and the thread index t_idx (both 0-based),
* and the total number of processes, total_p, and threads, total_t,
* returns the first row number assigned to this partition.
*/
int insertBegin(int rows, int p_idx, int t_idx, int total_p, int total_t);
2019-05-31 00:01:22 +08:00
/* similar to insertBegin, insertEnd returns the last row numer */
int insertEnd(int rows, int p_idx, int t_idx, int total_p, int total_t);
2019-05-31 00:01:22 +08:00
/* devide a value equally among threads */
int computeThreadPortion(int val, int p_idx, int t_idx, int total_p, int total_t);
2019-05-31 00:01:22 +08:00
/* similar to insertBegin/end, computeThreadTps computes
2019-05-31 00:01:22 +08:00
* the per-thread target TPS for given configuration.
*/
#define computeThreadTps(val, p_idx, t_idx, total_p, total_t) computeThreadPortion(val, p_idx, t_idx, total_p, total_t)
2019-05-31 00:01:22 +08:00
/* similar to computeThreadTps,
* computeThreadIters computs the number of iterations.
2019-05-31 00:01:22 +08:00
*/
#define computeThreadIters(val, p_idx, t_idx, total_p, total_t) \
computeThreadPortion(val, p_idx, t_idx, total_p, total_t)
2019-05-31 00:01:22 +08:00
/* get the number of digits */
int digits(int num);
/* fill (str) with configured key prefix: i.e. non-numeric part
* (str) is appended with concat([padding], PREFIX)
*/
2022-03-03 20:33:58 +08:00
template <bool Clear = true, typename Char>
void genKeyPrefix(std::basic_string<Char>& str, std::string_view prefix, Arguments const& args) {
2022-03-03 20:33:58 +08:00
// concat('x' * padding_len, key_prefix)
if constexpr (Clear)
str.clear();
const auto padding_len =
args.prefixpadding ? (args.key_length - args.row_digits - static_cast<int>(prefix.size())) : 0;
assert(padding_len >= 0);
str.reserve(str.size() + padding_len + prefix.size());
fmt::format_to(std::back_inserter(str), "{0:x>{1}}{2}", "", padding_len, prefix);
}
2019-05-31 00:01:22 +08:00
/* generate a key for a given key number */
/* prefix is "mako" by default, prefixpadding = 1 means 'x' will be in front rather than trailing the keyname */
2022-03-03 20:33:58 +08:00
template <bool Clear = true, typename Char>
void genKey(std::basic_string<Char>& str, std::string_view prefix, Arguments const& args, int num) {
2022-03-03 20:33:58 +08:00
static_assert(sizeof(Char) == 1);
const auto pad_len = args.prefixpadding ? args.key_length - (static_cast<int>(prefix.size()) + args.row_digits) : 0;
assert(pad_len >= 0);
if constexpr (Clear)
str.clear();
str.reserve(str.size() + static_cast<size_t>(args.key_length));
fmt::format_to(std::back_inserter(str),
"{0:x>{1}}{2}{3:0{4}d}{5:x>{6}}",
"",
pad_len,
prefix,
num,
args.row_digits,
"",
args.key_length - pad_len - static_cast<int>(prefix.size()) - args.row_digits);
}
// invoke user-provided callable when object goes out of scope.
template <typename Func>
class ExitGuard {
2022-03-03 20:33:58 +08:00
std::decay_t<Func> fn;
public:
ExitGuard(Func&& fn) : fn(std::forward<Func>(fn)) {}
~ExitGuard() { fn(); }
};
// invoke user-provided callable when stack unwinds by exception.
template <typename Func>
class FailGuard {
2022-03-03 20:33:58 +08:00
std::decay_t<Func> fn;
public:
FailGuard(Func&& fn) : fn(std::forward<Func>(fn)) {}
~FailGuard() {
2022-03-03 20:33:58 +08:00
if (std::uncaught_exceptions()) {
fn();
}
}
};
// trace helpers
constexpr const int STATS_TITLE_WIDTH = 12;
constexpr const int STATS_FIELD_WIDTH = 12;
template <typename Value>
void putTitle(Value&& value) {
2022-03-03 20:33:58 +08:00
fmt::print("{0: <{1}} ", std::forward<Value>(value), STATS_TITLE_WIDTH);
}
template <typename Value>
void putTitleRight(Value&& value) {
2022-03-03 20:33:58 +08:00
fmt::print("{0: >{1}} ", std::forward<Value>(value), STATS_TITLE_WIDTH);
}
inline void putTitleBar() {
2022-03-03 20:33:58 +08:00
fmt::print("{0:=<{1}} ", "", STATS_TITLE_WIDTH);
}
template <typename Value>
void putField(Value&& value) {
2022-03-03 20:33:58 +08:00
fmt::print("{0: >{1}} ", std::forward<Value>(value), STATS_FIELD_WIDTH);
}
2019-05-31 00:01:22 +08:00
inline void putFieldBar() {
2022-03-03 20:33:58 +08:00
fmt::print("{0:=>{1}} ", "", STATS_FIELD_WIDTH);
}
template <typename Value>
void putFieldFloat(Value&& value, int precision) {
2022-03-03 20:33:58 +08:00
fmt::print("{0: >{1}.{2}f} ", std::forward<Value>(value), STATS_FIELD_WIDTH, precision);
}
} // namespace mako
#endif /* UTILS_HPP */