Compare commits

...

5 Commits

Author SHA1 Message Date
Jennifer Peshansky
e74d2910bb Merge branch 'master' into jenniferpeshansky/SERVER-70854 2022-11-03 16:13:20 +00:00
Jennifer Peshansky
280145e994 SERVER-70854 Make plan_cache_size_parameter generic 2022-11-03 16:11:08 +00:00
Jennifer Peshansky
df7136e2fa Remove unnecessary knob 2022-10-31 20:47:12 +00:00
Jennifer Peshansky
36d0612419 SERVER-70854 Code review comments 2022-10-31 20:43:33 +00:00
Jennifer Peshansky
4bd264e877 SERVER-70854 Create query knobs for telemetry project 2022-10-28 18:42:56 +00:00
14 changed files with 323 additions and 117 deletions

View File

@ -2540,6 +2540,7 @@ if wiredtiger:
'keypattern_test.cpp',
'keys_collection_document_test.cpp',
'logical_time_test.cpp',
'memory_parameter_test.cpp',
'mirroring_sampler_test.cpp',
'multi_key_path_tracker_test.cpp',
'namespace_string_test.cpp',
@ -2589,6 +2590,7 @@ if wiredtiger:
'$BUILD_DIR/mongo/db/change_stream_change_collection_manager',
'$BUILD_DIR/mongo/db/change_stream_serverless_helpers',
'$BUILD_DIR/mongo/db/change_streams_cluster_parameter',
'$BUILD_DIR/mongo/db/memory_parameters',
'$BUILD_DIR/mongo/db/mongohasher',
'$BUILD_DIR/mongo/db/ops/write_ops',
'$BUILD_DIR/mongo/db/pipeline/change_stream_expired_pre_image_remover',

View File

@ -100,6 +100,7 @@ env.Library(
LIBDEPS=[
"$BUILD_DIR/mongo/base",
"$BUILD_DIR/mongo/db/exec/sbe/query_sbe",
'$BUILD_DIR/mongo/util/memory_util',
"canonical_query",
],
)
@ -257,14 +258,15 @@ env.Library(
source=[
'ce_mode_parameter.cpp',
'framework_control.cpp',
'plan_cache_size_parameter.cpp',
'query_feature_flags.idl',
'query_knobs.idl',
'sbe_plan_cache_on_parameter_change.cpp',
'telemetry_util.cpp',
],
LIBDEPS_PRIVATE=[
'$BUILD_DIR/mongo/db/server_base',
'$BUILD_DIR/mongo/db/service_context',
'$BUILD_DIR/mongo/util/memory_util',
'$BUILD_DIR/mongo/util/pcre_wrapper',
],
)
@ -372,7 +374,6 @@ env.CppUnitTest(
'map_reduce_output_format_test.cpp',
"parsed_distinct_test.cpp",
"plan_cache_indexability_test.cpp",
"plan_cache_size_parameter_test.cpp",
"plan_cache_key_info_test.cpp",
"plan_cache_test.cpp",
"plan_ranker_test.cpp",
@ -412,6 +413,7 @@ env.CppUnitTest(
"$BUILD_DIR/mongo/db/catalog/collection_crud",
"$BUILD_DIR/mongo/db/concurrency/lock_manager",
"$BUILD_DIR/mongo/db/exec/sbe/sbe_plan_stage_test",
"$BUILD_DIR/mongo/db/memory_parameters",
"$BUILD_DIR/mongo/db/multitenancy",
"$BUILD_DIR/mongo/db/pipeline/aggregation_request_helper",
"$BUILD_DIR/mongo/db/pipeline/document_source_mock",

View File

@ -1,79 +0,0 @@
/**
* Copyright (C) 2021-present MongoDB, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Server Side Public License, version 1,
* as published by MongoDB, Inc.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Server Side Public License for more details.
*
* You should have received a copy of the Server Side Public License
* along with this program. If not, see
* <http://www.mongodb.com/licensing/server-side-public-license>.
*
* As a special exception, the copyright holders give permission to link the
* code of portions of this program with the OpenSSL library under certain
* conditions as described in each individual source file and distribute
* linked combinations including the program with the OpenSSL library. You
* must comply with the Server Side Public License in all respects for
* all of the code used other than as permitted herein. If you modify file(s)
* with this exception, you may extend this exception to your version of the
* file(s), but you are not obligated to do so. If you do not wish to do so,
* delete this exception statement from your version. If you delete this
* exception statement from all source files in the program, then also delete
* it in the license file.
*/
#include "mongo/db/query/plan_cache_size_parameter.h"
#include "mongo/unittest/unittest.h"
namespace mongo::plan_cache_util {
bool operator==(const PlanCacheSizeParameter& lhs, const PlanCacheSizeParameter& rhs) {
constexpr double kEpsilon = 1e-10;
return std::abs(lhs.size - rhs.size) < kEpsilon && lhs.units == rhs.units;
}
TEST(PlanCacheParameterTest, ParseUnitStringPercent) {
ASSERT_TRUE(PlanCacheSizeUnits::kPercent == parseUnitString("%"));
}
TEST(PlanCacheParameterTest, ParseUnitStringMB) {
ASSERT_TRUE(PlanCacheSizeUnits::kMB == parseUnitString("MB"));
ASSERT_TRUE(PlanCacheSizeUnits::kMB == parseUnitString("mb"));
ASSERT_TRUE(PlanCacheSizeUnits::kMB == parseUnitString("mB"));
ASSERT_TRUE(PlanCacheSizeUnits::kMB == parseUnitString("Mb"));
}
TEST(PlanCacheParameterTest, ParseUnitStringGB) {
ASSERT_TRUE(PlanCacheSizeUnits::kGB == parseUnitString("GB"));
ASSERT_TRUE(PlanCacheSizeUnits::kGB == parseUnitString("gb"));
ASSERT_TRUE(PlanCacheSizeUnits::kGB == parseUnitString("gB"));
ASSERT_TRUE(PlanCacheSizeUnits::kGB == parseUnitString("Gb"));
}
TEST(PlanCacheParameterTest, ParseUnitStringIncorrectValue) {
ASSERT_NOT_OK(parseUnitString("").getStatus());
ASSERT_NOT_OK(parseUnitString(" ").getStatus());
ASSERT_NOT_OK(parseUnitString("KB").getStatus());
}
TEST(PlanCacheParameterTest, ParsePlanCacheSizeParameter) {
ASSERT_TRUE((PlanCacheSizeParameter{10.0, PlanCacheSizeUnits::kPercent}) ==
PlanCacheSizeParameter::parse("10%"));
ASSERT_TRUE((PlanCacheSizeParameter{300.0, PlanCacheSizeUnits::kMB}) ==
PlanCacheSizeParameter::parse("300MB"));
ASSERT_TRUE((PlanCacheSizeParameter{4.0, PlanCacheSizeUnits::kGB}) ==
PlanCacheSizeParameter::parse("4GB"));
ASSERT_TRUE((PlanCacheSizeParameter{5.1, PlanCacheSizeUnits::kPercent}) ==
PlanCacheSizeParameter::parse(" 5.1%"));
ASSERT_TRUE((PlanCacheSizeParameter{11.1, PlanCacheSizeUnits::kMB}) ==
PlanCacheSizeParameter::parse("11.1 mb"));
ASSERT_TRUE((PlanCacheSizeParameter{12.1, PlanCacheSizeUnits::kGB}) ==
PlanCacheSizeParameter::parse(" 12.1 Gb "));
}
} // namespace mongo::plan_cache_util

View File

@ -30,8 +30,9 @@ global:
cpp_namespace: "mongo"
cpp_includes:
- "mongo/db/query/ce_mode_parameter.h"
- "mongo/db/query/plan_cache_size_parameter.h"
- "mongo/util/memory_util.h"
- "mongo/db/query/sbe_plan_cache_on_parameter_change.h"
- "mongo/db/query/telemetry_util.h"
- "mongo/platform/atomic_proxy.h"
- "mongo/platform/atomic_word.h"
@ -938,6 +939,30 @@ server_parameters:
default:
expr: false
internalQueryConfigureTelemetrySamplingRate:
description: "The maximum number of queries per second that are sampled for query telemetry.
If the rate of queries goes above this number, then rate limiting will kick in, and any
further queries will not be sampled. The default is INT_MAX, effectively meaning that all
queries will be sampled. This can be set to 0 to turn telemetry off completely."
set_at: [ startup, runtime ]
cpp_varname: "queryTelemetrySamplingRate"
cpp_vartype: AtomicWord<int>
default: 2147483647
internalQueryConfigureTelemetryCacheSize:
description: "The maximum amount of memory that the system will allocate for the query telemetry
cache. This will accept values in either of the following formats:
1. <number>% indicates a percentage of the physical memory available to the process. E.g.: 15%.
2. <number>(MB|GB), indicates the amount of memory in MB or GB. E.g.: 1.5GB, 100MB.
The default value is 5%, which means 5% of the physical memory available to the process."
set_at: [ startup, runtime ]
cpp_varname: "queryTelemetryCacheSize"
cpp_vartype: synchronized_value<std::string>
default: "5%"
on_update: telemetry_util::onTelemetryCacheSizeUpdate
validator:
callback: telemetry_util::validateTelemetryCacheSize
internalQueryDisableExclusionProjectionFastPath:
description: "If true, then ExclusionProjectionExecutor won't use fast path implementation. This
is needed to pass generational fuzzers that are sensitive to field order and other corner cases

View File

@ -30,9 +30,9 @@
#include "mongo/db/query/sbe_plan_cache.h"
#include "mongo/db/query/plan_cache_size_parameter.h"
#include "mongo/db/server_options.h"
#include "mongo/logv2/log.h"
#include "mongo/util/memory_util.h"
#include "mongo/util/processinfo.h"
#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kQuery
@ -44,19 +44,19 @@ namespace {
const auto sbePlanCacheDecoration =
ServiceContext::declareDecoration<std::unique_ptr<sbe::PlanCache>>();
size_t convertToSizeInBytes(const plan_cache_util::PlanCacheSizeParameter& param) {
size_t convertToSizeInBytes(const memory_util::MemorySize& param) {
constexpr size_t kBytesInMB = 1024 * 1024;
constexpr size_t kMBytesInGB = 1024;
double sizeInMB = param.size;
switch (param.units) {
case plan_cache_util::PlanCacheSizeUnits::kPercent:
case memory_util::MemoryUnits::kPercent:
sizeInMB *= ProcessInfo::getMemSizeMB() / 100.0;
break;
case plan_cache_util::PlanCacheSizeUnits::kMB:
case memory_util::MemoryUnits::kMB:
break;
case plan_cache_util::PlanCacheSizeUnits::kGB:
case memory_util::MemoryUnits::kGB:
sizeInMB *= kMBytesInGB;
break;
}
@ -75,8 +75,7 @@ size_t capPlanCacheSize(size_t planCacheSize) {
constexpr size_t kMaximumPlanCacheSize = 500 * kBytesInGB;
// Maximum size of the plan cache expressed as a share of the memory available to the process.
const plan_cache_util::PlanCacheSizeParameter limitToProcessSize{
25, plan_cache_util::PlanCacheSizeUnits::kPercent};
const memory_util::MemorySize limitToProcessSize{25, memory_util::MemoryUnits::kPercent};
const size_t limitToProcessSizeInBytes = convertToSizeInBytes(limitToProcessSize);
// The size will be capped by the minimum of the two values defined above.
@ -93,7 +92,7 @@ size_t capPlanCacheSize(size_t planCacheSize) {
return planCacheSize;
}
size_t getPlanCacheSizeInBytes(const plan_cache_util::PlanCacheSizeParameter& param) {
size_t getPlanCacheSizeInBytes(const memory_util::MemorySize& param) {
size_t planCacheSize = convertToSizeInBytes(param);
uassert(5968001,
"Cache size must be at least 1KB * number of cores",
@ -103,8 +102,7 @@ size_t getPlanCacheSizeInBytes(const plan_cache_util::PlanCacheSizeParameter& pa
class PlanCacheOnParamChangeUpdaterImpl final : public plan_cache_util::OnParamChangeUpdater {
public:
void updateCacheSize(ServiceContext* serviceCtx,
plan_cache_util::PlanCacheSizeParameter parameter) final {
void updateCacheSize(ServiceContext* serviceCtx, memory_util::MemorySize parameter) final {
if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) {
auto size = getPlanCacheSizeInBytes(parameter);
auto& globalPlanCache = sbePlanCacheDecoration(serviceCtx);
@ -126,7 +124,7 @@ ServiceContext::ConstructorActionRegisterer planCacheRegisterer{
std::make_unique<PlanCacheOnParamChangeUpdaterImpl>();
if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) {
auto status = plan_cache_util::PlanCacheSizeParameter::parse(planCacheSize.get());
auto status = memory_util::MemorySize::parse(planCacheSize.get());
uassertStatusOK(status);
auto size = getPlanCacheSizeInBytes(status.getValue());

View File

@ -56,7 +56,7 @@ Status clearSbeCacheOnParameterChangeHelper() {
}
Status onPlanCacheSizeUpdate(const std::string& str) {
auto newSize = PlanCacheSizeParameter::parse(str);
auto newSize = memory_util::MemorySize::parse(str);
if (!newSize.isOK()) {
return newSize.getStatus();
}
@ -73,7 +73,7 @@ Status onPlanCacheSizeUpdate(const std::string& str) {
}
Status validatePlanCacheSize(const std::string& str, const boost::optional<TenantId>&) {
return PlanCacheSizeParameter::parse(str).getStatus();
return memory_util::MemorySize::parse(str).getStatus();
}
const Decorable<ServiceContext>::Decoration<std::unique_ptr<OnParamChangeUpdater>>

View File

@ -32,8 +32,8 @@
#include <string>
#include "mongo/base/status.h"
#include "mongo/db/query/plan_cache_size_parameter.h"
#include "mongo/db/service_context.h"
#include "mongo/util/memory_util.h"
namespace mongo::plan_cache_util {
@ -70,11 +70,12 @@ public:
virtual ~OnParamChangeUpdater() = default;
/**
* Resizes the SBE plan cache decorating 'serviceCtx' to the new size given by 'parameter'. If
* Resizes the SBE plan cache decorating 'serviceCtx' to the new size given by 'memorySize'. If
* the new cache size is smaller than the old, cache entries are evicted in order to ensure the
* cache fits within the new size bound.
*/
virtual void updateCacheSize(ServiceContext* serviceCtx, PlanCacheSizeParameter parameter) = 0;
virtual void updateCacheSize(ServiceContext* serviceCtx,
memory_util::MemorySize memorySize) = 0;
/**
* Deletes all plans from the SBE plan cache decorating 'serviceCtx'.

View File

@ -0,0 +1,52 @@
/**
* Copyright (C) 2022-present MongoDB, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Server Side Public License, version 1,
* as published by MongoDB, Inc.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Server Side Public License for more details.
*
* You should have received a copy of the Server Side Public License
* along with this program. If not, see
* <http://www.mongodb.com/licensing/server-side-public-license>.
*
* As a special exception, the copyright holders give permission to link the
* code of portions of this program with the OpenSSL library under certain
* conditions as described in each individual source file and distribute
* linked combinations including the program with the OpenSSL library. You
* must comply with the Server Side Public License in all respects for
* all of the code used other than as permitted herein. If you modify file(s)
* with this exception, you may extend this exception to your version of the
* file(s), but you are not obligated to do so. If you do not wish to do so,
* delete this exception statement from your version. If you delete this
* exception statement from all source files in the program, then also delete
* it in the license file.
*/
#include "mongo/db/query/telemetry_util.h"
#include "mongo/util/memory_util.h"
namespace mongo {
namespace telemetry_util {
Status onTelemetryCacheSizeUpdate(const std::string& str) {
auto newSize = memory_util::MemorySize::parse(str);
if (!newSize.isOK()) {
return newSize.getStatus();
}
// TODO update telemetry cache size wherever it is stored
return Status::OK();
}
Status validateTelemetryCacheSize(const std::string& str, const boost::optional<TenantId>&) {
return memory_util::MemorySize::parse(str).getStatus();
}
} // namespace telemetry_util
} // namespace mongo

View File

@ -0,0 +1,50 @@
/**
* Copyright (C) 2022-present MongoDB, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Server Side Public License, version 1,
* as published by MongoDB, Inc.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Server Side Public License for more details.
*
* You should have received a copy of the Server Side Public License
* along with this program. If not, see
* <http://www.mongodb.com/licensing/server-side-public-license>.
*
* As a special exception, the copyright holders give permission to link the
* code of portions of this program with the OpenSSL library under certain
* conditions as described in each individual source file and distribute
* linked combinations including the program with the OpenSSL library. You
* must comply with the Server Side Public License in all respects for
* all of the code used other than as permitted herein. If you modify file(s)
* with this exception, you may extend this exception to your version of the
* file(s), but you are not obligated to do so. If you do not wish to do so,
* delete this exception statement from your version. If you delete this
* exception statement from all source files in the program, then also delete
* it in the license file.
*/
#pragma once
#include "mongo/base/status.h"
#include "mongo/db/service_context.h"
namespace mongo {
namespace telemetry_util {
/**
* Callback called on a change of telemetryCacheSize parameter.
*/
Status onTelemetryCacheSizeUpdate(const std::string& str);
/**
* Callback called on validation of telemetryCacheSize parameter.
*/
Status validateTelemetryCacheSize(const std::string& str, const boost::optional<TenantId>&);
} // namespace telemetry_util
} // namespace mongo

View File

@ -614,6 +614,17 @@ env.Library(
],
)
env.Library(
target='memory_util',
source=[
'memory_util.cpp',
],
LIBDEPS=[
'pcre_wrapper',
],
)
env.Benchmark(
target='hash_table_bm',
source='hash_table_bm.cpp',
@ -748,6 +759,7 @@ icuEnv.CppUnitTest(
'lru_cache_test.cpp',
'md5_test.cpp',
'md5main.cpp',
'memory_util_test.cpp',
'optional_util_test.cpp',
'out_of_line_executor_test.cpp',
'overloaded_visitor_test.cpp',
@ -795,6 +807,7 @@ icuEnv.CppUnitTest(
'icu',
'latch_analyzer' if get_option('use-diagnostic-latches') == 'on' else [],
'md5',
'memory_util',
'pcre_util',
'pcre_wrapper',
'periodic_runner_impl',

View File

@ -27,30 +27,29 @@
* it in the license file.
*/
#include "mongo/db/query/plan_cache_size_parameter.h"
#include "mongo/util/memory_util.h"
#include "mongo/db/query/query_knobs_gen.h"
#include "mongo/util/pcre.h"
namespace mongo::plan_cache_util {
namespace mongo::memory_util {
StatusWith<PlanCacheSizeUnits> parseUnitString(const std::string& strUnit) {
StatusWith<MemoryUnits> parseUnitString(const std::string& strUnit) {
if (strUnit.empty()) {
return Status(ErrorCodes::Error{6007010}, "Unit value cannot be empty");
}
if (strUnit[0] == '%') {
return PlanCacheSizeUnits::kPercent;
return MemoryUnits::kPercent;
} else if (strUnit[0] == 'M' || strUnit[0] == 'm') {
return PlanCacheSizeUnits::kMB;
return MemoryUnits::kMB;
} else if (strUnit[0] == 'G' || strUnit[0] == 'g') {
return PlanCacheSizeUnits::kGB;
return MemoryUnits::kGB;
}
return Status(ErrorCodes::Error{6007011}, "Incorrect unit value");
}
StatusWith<PlanCacheSizeParameter> PlanCacheSizeParameter::parse(const std::string& str) {
StatusWith<MemorySize> MemorySize::parse(const std::string& str) {
// Looks for a floating point number with followed by a unit suffix (MB, GB, %).
static auto& re = *new pcre::Regex(R"re((?i)^\s*(\d+\.?\d*)\s*(MB|GB|%)\s*$)re");
auto m = re.matchView(str);
@ -65,7 +64,7 @@ StatusWith<PlanCacheSizeParameter> PlanCacheSizeParameter::parse(const std::stri
return statusWithUnit.getStatus();
}
return PlanCacheSizeParameter{size, statusWithUnit.getValue()};
return MemorySize{size, statusWithUnit.getValue()};
}
} // namespace mongo::plan_cache_util
} // namespace mongo::memory_util

View File

@ -0,0 +1,70 @@
/**
* Copyright (C) 2021-present MongoDB, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Server Side Public License, version 1,
* as published by MongoDB, Inc.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Server Side Public License for more details.
*
* You should have received a copy of the Server Side Public License
* along with this program. If not, see
* <http://www.mongodb.com/licensing/server-side-public-license>.
*
* As a special exception, the copyright holders give permission to link the
* code of portions of this program with the OpenSSL library under certain
* conditions as described in each individual source file and distribute
* linked combinations including the program with the OpenSSL library. You
* must comply with the Server Side Public License in all respects for
* all of the code used other than as permitted herein. If you modify file(s)
* with this exception, you may extend this exception to your version of the
* file(s), but you are not obligated to do so. If you do not wish to do so,
* delete this exception statement from your version. If you delete this
* exception statement from all source files in the program, then also delete
* it in the license file.
*/
#include "mongo/util/memory_util.h"
#include "mongo/util/pcre.h"
namespace mongo::memory_util {
StatusWith<MemoryUnits> parseUnitString(const std::string& strUnit) {
if (strUnit.empty()) {
return Status(ErrorCodes::Error{6007010}, "Unit value cannot be empty");
}
if (strUnit[0] == '%') {
return MemoryUnits::kPercent;
} else if (strUnit[0] == 'M' || strUnit[0] == 'm') {
return MemoryUnits::kMB;
} else if (strUnit[0] == 'G' || strUnit[0] == 'g') {
return MemoryUnits::kGB;
}
return Status(ErrorCodes::Error{6007011}, "Incorrect unit value");
}
StatusWith<MemorySize> MemorySize::parse(const std::string& str) {
// Looks for a floating point number with followed by a unit suffix (MB, GB, %).
static auto& re = *new pcre::Regex(R"re((?i)^\s*(\d+\.?\d*)\s*(MB|GB|%)\s*$)re");
auto m = re.matchView(str);
if (!m) {
return {ErrorCodes::Error{6007012}, "Unable to parse plan cache size string"};
}
double size = std::stod(std::string{m[1]});
std::string strUnit{m[2]};
auto statusWithUnit = parseUnitString(strUnit);
if (!statusWithUnit.isOK()) {
return statusWithUnit.getStatus();
}
return MemorySize{size, statusWithUnit.getValue()};
}
} // namespace mongo::memory_util

View File

@ -33,27 +33,27 @@
#include "mongo/base/status_with.h"
namespace mongo::plan_cache_util {
namespace mongo::memory_util {
/**
* Defines units of planCacheSize parameter.
* Defines units of memory consumption.
*/
enum class PlanCacheSizeUnits {
enum class MemoryUnits {
kPercent,
kMB,
kGB,
};
StatusWith<PlanCacheSizeUnits> parseUnitString(const std::string& strUnit);
StatusWith<MemoryUnits> parseUnitString(const std::string& strUnit);
/**
* Represents parsed planCacheSize parameter.
* Represents parsed memory size parameter.
*/
struct PlanCacheSizeParameter {
static StatusWith<PlanCacheSizeParameter> parse(const std::string& str);
struct MemorySize {
static StatusWith<MemorySize> parse(const std::string& str);
const double size;
const PlanCacheSizeUnits units;
const MemoryUnits units;
};
} // namespace mongo::plan_cache_util
} // namespace mongo::memory_util

View File

@ -0,0 +1,73 @@
/**
* Copyright (C) 2021-present MongoDB, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Server Side Public License, version 1,
* as published by MongoDB, Inc.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Server Side Public License for more details.
*
* You should have received a copy of the Server Side Public License
* along with this program. If not, see
* <http://www.mongodb.com/licensing/server-side-public-license>.
*
* As a special exception, the copyright holders give permission to link the
* code of portions of this program with the OpenSSL library under certain
* conditions as described in each individual source file and distribute
* linked combinations including the program with the OpenSSL library. You
* must comply with the Server Side Public License in all respects for
* all of the code used other than as permitted herein. If you modify file(s)
* with this exception, you may extend this exception to your version of the
* file(s), but you are not obligated to do so. If you do not wish to do so,
* delete this exception statement from your version. If you delete this
* exception statement from all source files in the program, then also delete
* it in the license file.
*/
#include "mongo/util/memory_util.h"
#include "mongo/unittest/unittest.h"
namespace mongo::memory_util {
bool operator==(const MemorySize& lhs, const MemorySize& rhs) {
constexpr double kEpsilon = 1e-10;
return std::abs(lhs.size - rhs.size) < kEpsilon && lhs.units == rhs.units;
}
TEST(MemorySizeTest, ParseUnitStringPercent) {
ASSERT_TRUE(MemoryUnits::kPercent == parseUnitString("%"));
}
TEST(MemorySizeTest, ParseUnitStringMB) {
ASSERT_TRUE(MemoryUnits::kMB == parseUnitString("MB"));
ASSERT_TRUE(MemoryUnits::kMB == parseUnitString("mb"));
ASSERT_TRUE(MemoryUnits::kMB == parseUnitString("mB"));
ASSERT_TRUE(MemoryUnits::kMB == parseUnitString("Mb"));
}
TEST(MemorySizeTest, ParseUnitStringGB) {
ASSERT_TRUE(MemoryUnits::kGB == parseUnitString("GB"));
ASSERT_TRUE(MemoryUnits::kGB == parseUnitString("gb"));
ASSERT_TRUE(MemoryUnits::kGB == parseUnitString("gB"));
ASSERT_TRUE(MemoryUnits::kGB == parseUnitString("Gb"));
}
TEST(MemorySizeTest, ParseUnitStringIncorrectValue) {
ASSERT_NOT_OK(parseUnitString("").getStatus());
ASSERT_NOT_OK(parseUnitString(" ").getStatus());
ASSERT_NOT_OK(parseUnitString("KB").getStatus());
}
TEST(MemorySizeTest, ParseMemorySize) {
ASSERT_TRUE((MemorySize{10.0, MemoryUnits::kPercent}) == MemorySize::parse("10%"));
ASSERT_TRUE((MemorySize{300.0, MemoryUnits::kMB}) == MemorySize::parse("300MB"));
ASSERT_TRUE((MemorySize{4.0, MemoryUnits::kGB}) == MemorySize::parse("4GB"));
ASSERT_TRUE((MemorySize{5.1, MemoryUnits::kPercent}) == MemorySize::parse(" 5.1%"));
ASSERT_TRUE((MemorySize{11.1, MemoryUnits::kMB}) == MemorySize::parse("11.1 mb"));
ASSERT_TRUE((MemorySize{12.1, MemoryUnits::kGB}) == MemorySize::parse(" 12.1 Gb "));
}
} // namespace mongo::memory_util