/**
* Copyright (C) 2018 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 "mongo/base/disallow_copying.h"
#include "mongo/db/catalog/database.h"
#include "mongo/db/s/sharding_migration_critical_section.h"
#include "mongo/s/database_version_gen.h"
namespace mongo {
class MovePrimarySourceManager;
class OperationContext;
/**
* Synchronizes access to this shard server's cached database version for Database.
*/
class DatabaseShardingState {
MONGO_DISALLOW_COPYING(DatabaseShardingState);
public:
static const Database::Decoration get;
DatabaseShardingState();
~DatabaseShardingState() = default;
/**
* Methods to control the databases's critical section. Must be called with the database X lock
* held.
*/
void enterCriticalSectionCatchUpPhase(OperationContext* opCtx);
void enterCriticalSectionCommitPhase(OperationContext* opCtx);
void exitCriticalSection(OperationContext* opCtx,
boost::optional newDbVersion);
auto getCriticalSectionSignal(ShardingMigrationCriticalSection::Operation op) const {
return _critSec.getSignal(op);
}
/**
* Returns this shard server's cached dbVersion, if one is cached.
*
* Invariants that the caller holds the DBLock in X or IS.
*/
boost::optional getDbVersion(OperationContext* opCtx) const;
/**
* Sets this shard server's cached dbVersion to newVersion.
*
* Invariants that the caller holds the DBLock in X mode.
*/
void setDbVersion(OperationContext* opCtx, boost::optional newVersion);
/**
* If _critSecSignal is non-null, always throws StaleDbVersion.
* Otherwise, if there is a client dbVersion on the OperationContext, compares it with this
* shard server's cached dbVersion and throws StaleDbVersion if they do not match.
*/
void checkDbVersion(OperationContext* opCtx) const;
/**
* Returns the active movePrimary source manager, if one is available.
*/
MovePrimarySourceManager* getMovePrimarySourceManager();
/**
* Attaches a movePrimary source manager to this database's sharding state. Must be called with
* the database lock in X mode. May not be called if there is a movePrimary source manager
* already installed. Must be followed by a call to clearMovePrimarySourceManager.
*/
void setMovePrimarySourceManager(OperationContext* opCtx, MovePrimarySourceManager* sourceMgr);
/**
* Removes a movePrimary source manager from this database's sharding state. Must be called with
* with the database lock in X mode. May not be called if there isn't a movePrimary source
* manager installed already through a previous call to setMovePrimarySourceManager.
*/
void clearMovePrimarySourceManager(OperationContext* opCtx);
private:
// Modifying the state below requires holding the DBLock in X mode; holding the DBLock in any
// mode is acceptable for reading it. (Note: accessing this class at all requires holding the
// DBLock in some mode, since it requires having a pointer to the Database).
ShardingMigrationCriticalSection _critSec;
// This shard server's cached dbVersion. If boost::none, indicates this shard server does not
// know the dbVersion.
boost::optional _dbVersion = boost::none;
// If this database is serving as a source shard for a movePrimary, the source manager will be
// non-null. To write this value, there needs to be X-lock on the database in order to
// synchronize with other callers which will read the source manager.
//
// NOTE: The source manager is not owned by this class.
MovePrimarySourceManager* _sourceMgr{nullptr};
};
} // namespace mongo