// wiredtiger_util.h /** * Copyright (C) 2014 MongoDB Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * 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 * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * * 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 GNU Affero General 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 #include #include "mongo/base/disallow_copying.h" #include "mongo/base/status.h" #include "mongo/base/status_with.h" #include "mongo/bson/bsonobj.h" #include "mongo/db/namespace_string.h" #include "mongo/util/assert_util.h" namespace mongo { class BSONObjBuilder; class OperationContext; class WiredTigerConfigParser; class WiredTigerKVEngine; class WiredTigerSession; inline bool wt_keeptxnopen() { return false; } Status wtRCToStatus_slow(int retCode, const char* prefix); /** * converts wiredtiger return codes to mongodb statuses. */ inline Status wtRCToStatus(int retCode, const char* prefix = NULL) { if (MONGO_likely(retCode == 0)) return Status::OK(); return wtRCToStatus_slow(retCode, prefix); } #define invariantWTOK(expression) \ do { \ int _invariantWTOK_retCode = expression; \ if (MONGO_unlikely(_invariantWTOK_retCode != 0)) { \ invariantOKFailed( \ #expression, wtRCToStatus(_invariantWTOK_retCode), __FILE__, __LINE__); \ } \ } while (false) struct WiredTigerItem : public WT_ITEM { WiredTigerItem(const void* d, size_t s) { data = d; size = s; } WiredTigerItem(const std::string& str) { data = str.c_str(); size = str.size(); } // NOTE: do not call Get() on a temporary. // The pointer returned by Get() must not be allowed to live longer than *this. WT_ITEM* Get() { return this; } const WT_ITEM* Get() const { return this; } }; /** * Returns a WT_EVENT_HANDLER with MongoDB's default handlers. * The default handlers just log so it is recommended that you consider calling them even if * you are capturing the output. * * There is no default "close" handler. You only need to provide one if you need to call a * destructor. */ class WiredTigerEventHandler : private WT_EVENT_HANDLER { public: WiredTigerEventHandler(); WT_EVENT_HANDLER* getWtEventHandler(); bool wasStartupSuccessful() { return _startupSuccessful; } void setStartupSuccessful() { _startupSuccessful = true; } private: int suppressibleStartupErrorLog(WT_EVENT_HANDLER* handler, WT_SESSION* sesion, int errorCode, const char* message); bool _startupSuccessful = false; }; class WiredTigerUtil { MONGO_DISALLOW_COPYING(WiredTigerUtil); private: WiredTigerUtil(); public: /** * Fetch the type and source fields out of the colgroup metadata. 'tableUri' must be a * valid table: uri. */ static void fetchTypeAndSourceURI(OperationContext* opCtx, const std::string& tableUri, std::string* type, std::string* source); /** * Reads contents of table using URI and exports all keys to BSON as string elements. * Additional, adds 'uri' field to output document. */ static Status exportTableToBSON(WT_SESSION* s, const std::string& uri, const std::string& config, BSONObjBuilder* bob); /** * Appends information about the storage engine's currently available snapshots and the settings * that affect that window of maintained history. * * "snapshot-window-settings" : { * "cache pressure percentage threshold" : , * "current cache pressure percentage" : , * "max target available snapshots window size in seconds" : , * "target available snapshots window size in seconds" : , * "current available snapshots window size in seconds" : , * "latest majority snapshot timestamp available" : , * "oldest majority snapshot timestamp available" : * } */ static void appendSnapshotWindowSettings(WiredTigerKVEngine* engine, WiredTigerSession* session, BSONObjBuilder* bob); /** * Gets entire metadata string for collection/index at URI with the provided session. */ static StatusWith getMetadataRaw(WT_SESSION* session, StringData uri); /** * Gets entire metadata string for collection/index at URI. */ static StatusWith getMetadata(OperationContext* opCtx, StringData uri); /** * Reads app_metadata for collection/index at URI as a BSON document. */ static Status getApplicationMetadata(OperationContext* opCtx, StringData uri, BSONObjBuilder* bob); static StatusWith getApplicationMetadata(OperationContext* opCtx, StringData uri); /** * Validates formatVersion in application metadata for 'uri'. * Version must be numeric and be in the range [minimumVersion, maximumVersion]. * URI is used in error messages only. Returns actual version. */ static StatusWith checkApplicationMetadataFormatVersion(OperationContext* opCtx, StringData uri, int64_t minimumVersion, int64_t maximumVersion); /** * Validates the 'configString' specified as a collection or index creation option. */ static Status checkTableCreationOptions(const BSONElement& configElem); /** * Reads individual statistics using URI. * List of statistics keys WT_STAT_* can be found in wiredtiger.h. */ static StatusWith getStatisticsValue(WT_SESSION* session, const std::string& uri, const std::string& config, int statisticsKey); /** * Reads individual statistics using URI and casts to type ResultType. * Caps statistics value at max(ResultType) in case of overflow. */ template static StatusWith getStatisticsValueAs(WT_SESSION* session, const std::string& uri, const std::string& config, int statisticsKey); /** * Reads individual statistics using URI and casts to type ResultType. * Caps statistics value at 'maximumResultType'. */ template static StatusWith getStatisticsValueAs(WT_SESSION* session, const std::string& uri, const std::string& config, int statisticsKey, ResultType maximumResultType); static int64_t getIdentSize(WT_SESSION* s, const std::string& uri); /** * Return amount of memory to use for the WiredTiger cache based on either the startup * option chosen or the amount of available memory on the host. */ static size_t getCacheSizeMB(double requestedCacheSizeGB); class ErrorAccumulator : public WT_EVENT_HANDLER { public: ErrorAccumulator(std::vector* errors); private: static int onError(WT_EVENT_HANDLER* handler, WT_SESSION* session, int error, const char* message); using ErrorHandler = int (*)(WT_EVENT_HANDLER*, WT_SESSION*, int, const char*); std::vector* const _errors; const ErrorHandler _defaultErrorHandler; }; /** * Calls WT_SESSION::validate() on a side-session to ensure that your current transaction * isn't left in an invalid state. * * If errors is non-NULL, all error messages will be appended to the array. */ static int verifyTable(OperationContext* opCtx, const std::string& uri, std::vector* errors = NULL); static bool useTableLogging(NamespaceString ns, bool replEnabled); private: /** * Casts unsigned 64-bit statistics value to T. * If original value exceeds maximum value of T, return max(T). */ template static T _castStatisticsValue(uint64_t statisticsValue); /** * Casts unsigned 64-bit statistics value to T. * If original value exceeds 'maximumResultType', return 'maximumResultType'. */ template static T _castStatisticsValue(uint64_t statisticsValue, T maximumResultType); }; class WiredTigerConfigParser { MONGO_DISALLOW_COPYING(WiredTigerConfigParser); public: WiredTigerConfigParser(StringData config) { invariantWTOK( wiredtiger_config_parser_open(NULL, config.rawData(), config.size(), &_parser)); } WiredTigerConfigParser(const WT_CONFIG_ITEM& nested) { invariant(nested.type == WT_CONFIG_ITEM::WT_CONFIG_ITEM_STRUCT); invariantWTOK(wiredtiger_config_parser_open(NULL, nested.str, nested.len, &_parser)); } ~WiredTigerConfigParser() { invariantWTOK(_parser->close(_parser)); } int next(WT_CONFIG_ITEM* key, WT_CONFIG_ITEM* value) { return _parser->next(_parser, key, value); } int get(const char* key, WT_CONFIG_ITEM* value) { return _parser->get(_parser, key, value); } private: WT_CONFIG_PARSER* _parser; }; // static template StatusWith WiredTigerUtil::getStatisticsValueAs(WT_SESSION* session, const std::string& uri, const std::string& config, int statisticsKey) { return getStatisticsValueAs( session, uri, config, statisticsKey, std::numeric_limits::max()); } // static template StatusWith WiredTigerUtil::getStatisticsValueAs(WT_SESSION* session, const std::string& uri, const std::string& config, int statisticsKey, ResultType maximumResultType) { StatusWith result = getStatisticsValue(session, uri, config, statisticsKey); if (!result.isOK()) { return StatusWith(result.getStatus()); } return StatusWith( _castStatisticsValue(result.getValue(), maximumResultType)); } // static template ResultType WiredTigerUtil::_castStatisticsValue(uint64_t statisticsValue) { return _castStatisticsValue(statisticsValue, std::numeric_limits::max()); } // static template ResultType WiredTigerUtil::_castStatisticsValue(uint64_t statisticsValue, ResultType maximumResultType) { return statisticsValue > static_cast(maximumResultType) ? maximumResultType : static_cast(statisticsValue); } } // namespace mongo