summaryrefslogtreecommitdiff
path: root/src/mongo/db/storage/wiredtiger/wiredtiger_stats_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/storage/wiredtiger/wiredtiger_stats_test.cpp')
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_stats_test.cpp345
1 files changed, 0 insertions, 345 deletions
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_stats_test.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_stats_test.cpp
deleted file mode 100644
index de55e539056..00000000000
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_stats_test.cpp
+++ /dev/null
@@ -1,345 +0,0 @@
-/**
- * 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.
- */
-
-#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kWiredTiger
-
-#include "mongo/db/storage/wiredtiger/wiredtiger_stats.h"
-#include "mongo/db/storage/wiredtiger/wiredtiger_util.h"
-#include "mongo/logv2/log.h"
-#include "mongo/unittest/log_test.h"
-#include "mongo/unittest/temp_dir.h"
-#include "mongo/unittest/unittest.h"
-#include <memory>
-
-namespace mongo {
-namespace {
-
-#define ASSERT_WT_OK(result) ASSERT_EQ(result, 0) << wiredtiger_strerror(result)
-
-class WiredTigerStatsTest : public unittest::Test {
-protected:
- void setUp() override {
- openConnectionAndCreateSession();
- // Prepare data to be read by tests. Reading data written within the same transaction does
- // not count towards bytes read into cache.
-
- // Tests in the fixture do up to _maxReads reads.
- for (int64_t i = 0; i < _kMaxReads; ++i) {
- // Make the write big enough to span different pages.
- writeAtKey(std::string(20000, 'a'), i);
- }
-
- // Closing the connection will ensure that tests actually have to read into cache.
- closeConnection();
- openConnectionAndCreateSession();
- }
-
- void tearDown() override {
- closeConnection();
- }
-
- void openConnectionAndCreateSession() {
- ASSERT_WT_OK(
- wiredtiger_open(_path.path().c_str(), nullptr, "create,statistics=(fast),", &_conn));
- ASSERT_WT_OK(_conn->open_session(_conn, nullptr, "isolation=snapshot", &_session));
- ASSERT_WT_OK(_session->create(
- _session, _uri.c_str(), "type=file,key_format=q,value_format=u,log=(enabled=false)"));
- }
-
- void closeConnection() {
- ASSERT_EQ(_conn->close(_conn, nullptr), 0);
- }
-
- /**
- * Writes some data using WT. Causes the bytesWritten stat to be incremented, and may also
- * increment timeWritingMicros.
- */
- void write() {
- writeAtKey(std::string(_writeKey + 1, 'a'), _writeKey);
- ++_writeKey;
- }
-
- /**
- * Writes the specified data using WT. Causes the bytesWritten stat to be incremented, and may
- * also increment timeWritingMicros.
- */
- void write(const std::string& data) {
- writeAtKey(data, _writeKey);
- ++_writeKey;
- }
-
- /**
- * Writes at the specified key to WT.
- */
- void writeAtKey(const std::string& data, int64_t key) {
- ASSERT_WT_OK(_session->begin_transaction(_session, nullptr));
-
- WT_CURSOR* cursor;
- ASSERT_WT_OK(_session->open_cursor(_session, _uri.c_str(), nullptr, nullptr, &cursor));
-
- cursor->set_key(cursor, key);
-
- WT_ITEM item{data.data(), data.size()};
- cursor->set_value(cursor, &item);
-
- ASSERT_WT_OK(cursor->insert(cursor));
- ASSERT_WT_OK(cursor->close(cursor));
- ASSERT_WT_OK(_session->commit_transaction(_session, nullptr));
-
- // Without a checkpoint, an operation is not guaranteed to write to disk.
- ASSERT_WT_OK(_session->checkpoint(_session, nullptr));
- }
-
- /**
- * Reads at the specified key from WT.
- */
- void readAtKey(int64_t key) {
- ASSERT_WT_OK(_session->begin_transaction(_session, nullptr));
-
- WT_CURSOR* cursor;
- ASSERT_WT_OK(_session->open_cursor(_session, _uri.c_str(), nullptr, nullptr, &cursor));
-
- cursor->set_key(cursor, key);
- ASSERT_WT_OK(cursor->search(cursor));
-
- WT_ITEM value;
- ASSERT_WT_OK(cursor->get_value(cursor, &value));
-
- ASSERT_WT_OK(cursor->close(cursor));
- ASSERT_WT_OK(_session->commit_transaction(_session, nullptr));
- }
-
- /**
- * Reads fixture data from WT. Causes the bytesRead stat to be incremented. May also cause
- * timeReadingMicros to be incremented, but not always. This function can only be called up to
- * _kMaxReads times within a test.
- */
- void read() {
- ASSERT_LT(_readKey, _kMaxReads);
- readAtKey(_readKey++);
- }
-
- /**
- * Reads data written by the test from WT. Causes the bytesRead stat to be incremented. May
- * also cause timeReadingMicros to be incremented, but not always.
- */
- void readTestWrites() {
- for (int64_t i = _kMaxReads; i < _writeKey; i++) {
- readAtKey(i);
- }
- }
-
- unittest::TempDir _path{"wiredtiger_operation_stats_test"};
- std::string _uri{"table:wiredtiger_operation_stats_test"};
- WT_CONNECTION* _conn;
- WT_SESSION* _session;
- /* Number of reads the fixture will prepare in setUp(), consequently max amount of times read()
- * can be called in a test. */
- static constexpr int64_t _kMaxReads = 2;
- /* Next key to be used by read(), must be initialized at 0. */
- int64_t _readKey = 0;
- /* Next key to be used by write(), must be initialized >= _kMaxReads. */
- int64_t _writeKey = _kMaxReads;
-};
-
-TEST_F(WiredTigerStatsTest, EmptySession) {
- // Increase log component verbosity for WiredTiger
- auto verbosityGuard = unittest::MinimumLoggedSeverityGuard{logv2::LogComponent::kWiredTiger,
- logv2::LogSeverity::Debug(5)};
- auto verboseConfig = WiredTigerUtil::generateWTVerboseConfiguration();
- ASSERT_OK(wtRCToStatus(_conn->reconfigure(_conn, verboseConfig.c_str()), nullptr));
-
- // Read and write statistics should be empty. Check "data" field does not exist. "wait" fields
- // such as the schemaLock might have some value.
- auto statsBson = WiredTigerStats{_session}.toBSON();
-
- {
- BSONObjBuilder bob;
- ASSERT_OK(WiredTigerUtil::exportTableToBSON(_session, "statistics:", "", &bob));
- LOGV2(9032000, "Connection statistics", "stats"_attr = bob.obj());
- }
-
- ASSERT_FALSE(statsBson.hasField("data")) << statsBson;
-}
-
-TEST_F(WiredTigerStatsTest, SessionWithWrite) {
- write();
-
- auto statsObj = WiredTigerStats{_session}.toBSON();
- auto dataSection = statsObj["data"];
- ASSERT_EQ(dataSection.type(), BSONType::Object) << statsObj;
-
- ASSERT(dataSection["bytesWritten"]) << statsObj;
- for (auto&& [name, value] : dataSection.Obj()) {
- ASSERT_EQ(value.type(), BSONType::NumberLong) << statsObj;
- ASSERT_GT(value.numberLong(), 0) << statsObj;
- }
-}
-
-TEST_F(WiredTigerStatsTest, SessionWithRead) {
- read();
-
- auto statsObj = WiredTigerStats{_session}.toBSON();
-
- auto dataSection = statsObj["data"];
- ASSERT_EQ(dataSection.type(), BSONType::Object) << statsObj;
-
- ASSERT(dataSection["bytesRead"]) << statsObj;
- for (auto&& [name, value] : dataSection.Obj()) {
- ASSERT_EQ(value.type(), BSONType::NumberLong) << statsObj;
- ASSERT_GT(value.numberLong(), 0) << statsObj;
- }
-}
-
-TEST_F(WiredTigerStatsTest, SessionWithLargeWriteAndLargeRead) {
- auto remaining = static_cast<int64_t>(std::numeric_limits<uint32_t>::max()) + 1;
- while (remaining > 0) {
- std::string data(1024 * 1024, 'a');
- remaining -= data.size();
- write(data);
- }
-
- auto statsObj = WiredTigerStats{_session}.toBSON();
- ASSERT_GT(statsObj["data"]["bytesWritten"].numberLong(), std::numeric_limits<uint32_t>::max())
- << statsObj;
-
- // Closing the connection will ensure that tests actually have to read into cache.
- closeConnection();
- openConnectionAndCreateSession();
-
- readTestWrites();
-
- statsObj = WiredTigerStats{_session}.toBSON();
- ASSERT_GT(statsObj["data"]["bytesRead"].numberLong(), std::numeric_limits<uint32_t>::max())
- << statsObj;
-}
-
-TEST_F(WiredTigerStatsTest, OperationsAddToSessionStats) {
- std::vector<std::unique_ptr<WiredTigerStats>> operationStats;
-
- write();
- WiredTigerStats firstWrite(_session);
- operationStats.push_back(std::make_unique<WiredTigerStats>(firstWrite - WiredTigerStats{}));
- read();
- WiredTigerStats firstRead(_session);
- operationStats.push_back(std::make_unique<WiredTigerStats>(firstRead - firstWrite));
- write();
- WiredTigerStats secondWrite(_session);
- operationStats.push_back(std::make_unique<WiredTigerStats>(secondWrite - firstRead));
- read();
- WiredTigerStats secondRead(_session);
- operationStats.push_back(std::make_unique<WiredTigerStats>(secondRead - secondWrite));
-
- const WiredTigerStats& fetchedSessionStats = secondRead;
-
- long long bytesWritten = 0;
- long long timeWritingMicros = 0;
- long long bytesRead = 0;
- long long timeReadingMicros = 0;
-
- WiredTigerStats addedSessionStats;
-
- for (auto&& op : operationStats) {
- auto statsObj = op->toBSON();
-
- bytesWritten += statsObj["data"]["bytesWritten"].numberLong();
- timeWritingMicros += statsObj["data"]["timeWritingMicros"].numberLong();
- bytesRead += statsObj["data"]["bytesRead"].numberLong();
- timeReadingMicros += statsObj["data"]["timeReadingMicros"].numberLong();
-
- addedSessionStats += *op;
- }
-
- auto addedObj = addedSessionStats.toBSON();
- auto dataSection = addedObj["data"];
- ASSERT_EQ(dataSection.type(), BSONType::Object) << addedObj;
- ASSERT_EQ(dataSection["bytesWritten"].numberLong(), bytesWritten) << addedObj;
- ASSERT_EQ(dataSection["timeWritingMicros"].numberLong(), timeWritingMicros) << addedObj;
- ASSERT_EQ(dataSection["bytesRead"].numberLong(), bytesRead) << addedObj;
- ASSERT_EQ(dataSection["timeReadingMicros"].numberLong(), timeReadingMicros) << addedObj;
-
- auto fetchedObj = fetchedSessionStats.toBSON();
- auto fetchedDataSection = fetchedObj["data"];
- ASSERT_EQ(fetchedDataSection.type(), BSONType::Object) << fetchedObj;
- ASSERT_EQ(fetchedDataSection["bytesWritten"].numberLong(), bytesWritten) << fetchedObj;
- ASSERT_EQ(fetchedDataSection["timeWritingMicros"].numberLong(), timeWritingMicros)
- << fetchedObj;
- ASSERT_EQ(fetchedDataSection["bytesRead"].numberLong(), bytesRead) << fetchedObj;
- ASSERT_EQ(fetchedDataSection["timeReadingMicros"].numberLong(), timeReadingMicros)
- << fetchedObj;
-}
-
-TEST_F(WiredTigerStatsTest, OperationsSubtractToZero) {
- std::vector<std::unique_ptr<WiredTigerStats>> operationStats;
-
- write();
- WiredTigerStats firstWrite(_session);
- operationStats.push_back(std::make_unique<WiredTigerStats>(firstWrite - WiredTigerStats{}));
- read();
- WiredTigerStats firstRead(_session);
- operationStats.push_back(std::make_unique<WiredTigerStats>(firstRead - firstWrite));
- write();
- WiredTigerStats secondWrite(_session);
- operationStats.push_back(std::make_unique<WiredTigerStats>(secondWrite - firstRead));
- read();
- WiredTigerStats secondRead(_session);
- operationStats.push_back(std::make_unique<WiredTigerStats>(secondRead - secondWrite));
-
- WiredTigerStats& fetchedSessionStats = secondRead;
-
- // Assert fetchedSessionStats was not zero before checking subtract results in it being zero.
- // We ignore the time statistics as those might still be 0 from time to time.
- auto preSubtractObj = fetchedSessionStats.toBSON();
- auto preSubtract = preSubtractObj["data"];
- ASSERT_EQ(preSubtract.type(), BSONType::Object) << preSubtractObj;
- ASSERT_GT(preSubtract["bytesWritten"].numberLong(), 0) << preSubtractObj;
- ASSERT_GT(preSubtract["bytesRead"].numberLong(), 0) << preSubtractObj;
-
- for (auto&& op : operationStats) {
- fetchedSessionStats -= *op;
- }
-
- auto subtractedObj = fetchedSessionStats.toBSON();
- ASSERT_BSONOBJ_EQ(subtractedObj, BSONObj{});
-}
-
-TEST_F(WiredTigerStatsTest, Clone) {
- write();
-
- WiredTigerStats stats{_session};
- auto clone = stats.clone();
-
- ASSERT_BSONOBJ_EQ(stats.toBSON(), clone->toBSON());
-
- stats += *clone;
- ASSERT_BSONOBJ_NE(stats.toBSON(), clone->toBSON());
-}
-
-} // namespace
-} // namespace mongo