summaryrefslogtreecommitdiff
path: root/src/mongo/s
diff options
context:
space:
mode:
authorDaniel Alabi <alabidan@gmail.com>2015-07-02 15:07:02 -0400
committerDaniel Alabi <alabidan@gmail.com>2015-07-06 16:38:34 -0400
commit57d9fb54686971d60d0ec8d01afa944dd6ca3730 (patch)
tree20d384201caa616faabe3d71d1ca97a9656b8fee /src/mongo/s
parent53b6e275061c50769467924ac0737d585e667edd (diff)
downloadmongo-57d9fb54686971d60d0ec8d01afa944dd6ca3730.tar.gz
SERVER-19272 ActionLogType should do its validation and handle setting balancing details
Diffstat (limited to 'src/mongo/s')
-rw-r--r--src/mongo/s/balance.cpp51
-rw-r--r--src/mongo/s/catalog/replset/catalog_manager_replica_set_log_action_test.cpp8
-rw-r--r--src/mongo/s/catalog/type_actionlog.cpp183
-rw-r--r--src/mongo/s/catalog/type_actionlog.h189
4 files changed, 155 insertions, 276 deletions
diff --git a/src/mongo/s/balance.cpp b/src/mongo/s/balance.cpp
index e172b588afc..4086a13cb76 100644
--- a/src/mongo/s/balance.cpp
+++ b/src/mongo/s/balance.cpp
@@ -208,46 +208,6 @@ void Balancer::_ping(bool waiting) {
NULL);
}
-/*
-* Builds the details object for the actionlog.
-* Current formats for detail are:
-* Success: {
-* "candidateChunks" : ,
-* "chunksMoved" : ,
-* "executionTimeMillis" : ,
-* "errorOccured" : false
-* }
-* Failure: {
-* "executionTimeMillis" : ,
-* "errmsg" : ,
-* "errorOccured" : true
-* }
-* @param didError, did this round end in an error?
-* @param executionTime, the time this round took to run
-* @param candidateChunks, the number of chunks identified to be moved
-* @param chunksMoved, the number of chunks moved
-* @param errmsg, the error message for this round
-*/
-
-static BSONObj _buildDetails(bool didError,
- int executionTime,
- int candidateChunks,
- int chunksMoved,
- const std::string& errmsg) {
- BSONObjBuilder builder;
- builder.append("executionTimeMillis", executionTime);
- builder.append("errorOccured", didError);
-
- if (didError) {
- builder.append("errmsg", errmsg);
- } else {
- builder.append("candidateChunks", candidateChunks);
- builder.append("chunksMoved", chunksMoved);
- }
-
- return builder.obj();
-}
-
bool Balancer::_checkOIDs() {
vector<ShardId> all;
grid.shardRegistry()->getAllShardIds(&all);
@@ -597,11 +557,10 @@ void Balancer::run() {
_moveChunks(candidateChunks, writeConcern.get(), waitForDelete);
}
- actionLog.setDetails(_buildDetails(false,
- balanceRoundTimer.millis(),
- static_cast<int>(candidateChunks.size()),
- _balancedLastTime,
- ""));
+ actionLog.setDetails(boost::none,
+ balanceRoundTimer.millis(),
+ static_cast<int>(candidateChunks.size()),
+ _balancedLastTime);
actionLog.setTime(jsTime());
grid.catalogManager()->logAction(actionLog);
@@ -620,7 +579,7 @@ void Balancer::run() {
LOG(1) << "*** End of balancing round";
// This round failed, tell the world!
- actionLog.setDetails(_buildDetails(true, balanceRoundTimer.millis(), 0, 0, e.what()));
+ actionLog.setDetails(string(e.what()), balanceRoundTimer.millis(), 0, 0);
actionLog.setTime(jsTime());
grid.catalogManager()->logAction(actionLog);
diff --git a/src/mongo/s/catalog/replset/catalog_manager_replica_set_log_action_test.cpp b/src/mongo/s/catalog/replset/catalog_manager_replica_set_log_action_test.cpp
index 77e3e0ada10..87ed6feed18 100644
--- a/src/mongo/s/catalog/replset/catalog_manager_replica_set_log_action_test.cpp
+++ b/src/mongo/s/catalog/replset/catalog_manager_replica_set_log_action_test.cpp
@@ -78,8 +78,9 @@ public:
ASSERT_EQUALS(1U, inserts.size());
BSONObj insert = inserts.front();
- ActionLogType actualActionLog;
- ASSERT_TRUE(actualActionLog.parseBSON(insert, &errmsg));
+ auto actualActionLogRes = ActionLogType::fromBSON(insert);
+ ASSERT_OK(actualActionLogRes.getStatus());
+ const ActionLogType& actualActionLog = actualActionLogRes.getValue();
ASSERT_EQUALS(expectedActionLog.toBSON(), actualActionLog.toBSON());
@@ -98,6 +99,7 @@ TEST_F(LogActionTest, LogActionNoRetryAfterSuccessfulCreate) {
expectedActionLog.setServer("server1");
expectedActionLog.setTime(network()->now());
expectedActionLog.setWhat("moved a chunk");
+ expectedActionLog.setDetails(boost::none, 0, 1, 1);
auto future =
launchAsync([this, &expectedActionLog] { catalogManager()->logAction(expectedActionLog); });
@@ -125,6 +127,7 @@ TEST_F(LogActionTest, LogActionNoRetryCreateIfAlreadyExists) {
expectedActionLog.setServer("server1");
expectedActionLog.setTime(network()->now());
expectedActionLog.setWhat("moved a chunk");
+ expectedActionLog.setDetails(boost::none, 0, 1, 1);
auto future =
launchAsync([this, &expectedActionLog] { catalogManager()->logAction(expectedActionLog); });
@@ -155,6 +158,7 @@ TEST_F(LogActionTest, LogActionCreateFailure) {
expectedActionLog.setServer("server1");
expectedActionLog.setTime(network()->now());
expectedActionLog.setWhat("moved a chunk");
+ expectedActionLog.setDetails(boost::none, 0, 1, 1);
auto future =
launchAsync([this, &expectedActionLog] { catalogManager()->logAction(expectedActionLog); });
diff --git a/src/mongo/s/catalog/type_actionlog.cpp b/src/mongo/s/catalog/type_actionlog.cpp
index 1cefd2774dc..b4f6db43fc1 100644
--- a/src/mongo/s/catalog/type_actionlog.cpp
+++ b/src/mongo/s/catalog/type_actionlog.cpp
@@ -25,17 +25,20 @@
* delete this exception statement from all source files in the program,
* then also delete it in the license file.
*/
+
+#include "mongo/platform/basic.h"
+
#include "mongo/s/catalog/type_actionlog.h"
-#include "mongo/db/field_parser.h"
+#include "mongo/base/status_with.h"
+#include "mongo/bson/bsonobj.h"
+#include "mongo/bson/bsonobjbuilder.h"
+#include "mongo/bson/util/bson_extract.h"
+#include "mongo/util/assert_util.h"
#include "mongo/util/mongoutils/str.h"
namespace mongo {
-using std::string;
-
-using mongo::str::stream;
-
const std::string ActionLogType::ConfigNS = "config.actionlog";
const BSONField<std::string> ActionLogType::server("server");
@@ -43,118 +46,114 @@ const BSONField<std::string> ActionLogType::what("what");
const BSONField<Date_t> ActionLogType::time("time");
const BSONField<BSONObj> ActionLogType::details("details");
-ActionLogType::ActionLogType() {
- clear();
-}
+StatusWith<ActionLogType> ActionLogType::fromBSON(const BSONObj& source) {
+ ActionLogType actionLog;
+
+ {
+ std::string actionLogServer;
+ Status status = bsonExtractStringField(source, server.name(), &actionLogServer);
+ if (!status.isOK())
+ return status;
+ actionLog._server = actionLogServer;
+ }
+
+ {
+ BSONElement actionLogTimeElem;
+ Status status = bsonExtractTypedField(source, time.name(), Date, &actionLogTimeElem);
+ if (!status.isOK())
+ return status;
+ actionLog._time = actionLogTimeElem.date();
+ }
-ActionLogType::~ActionLogType() {}
+ {
+ std::string actionLogWhat;
+ Status status = bsonExtractStringField(source, what.name(), &actionLogWhat);
+ if (!status.isOK())
+ return status;
+ actionLog._what = actionLogWhat;
+ }
-bool ActionLogType::isValid(std::string* errMsg) const {
- std::string dummy;
- if (errMsg == NULL) {
- errMsg = &dummy;
+ {
+ BSONElement actionLogDetailsElem;
+ Status status =
+ bsonExtractTypedField(source, details.name(), Object, &actionLogDetailsElem);
+ if (!status.isOK())
+ return status;
+ actionLog._details = actionLogDetailsElem.Obj().getOwned();
}
- // All the mandatory fields must be present.
- if (!_isServerSet) {
- *errMsg = stream() << "missing " << server.name() << " field";
- return false;
+ return actionLog;
+}
+
+Status ActionLogType::validate() const {
+ if (!_server.is_initialized() || _server->empty()) {
+ return {ErrorCodes::NoSuchKey, str::stream() << "missing " << server.name() << " field"};
}
- if (!_isTimeSet) {
- *errMsg = stream() << "missing " << time.name() << " field";
- return false;
+
+ if (!_what.is_initialized() || _what->empty()) {
+ return {ErrorCodes::NoSuchKey, str::stream() << "missing " << what.name() << " field"};
}
- if (!_isWhatSet) {
- *errMsg = stream() << "missing " << what.name() << " field";
- return false;
+
+ if (!_time.is_initialized()) {
+ return {ErrorCodes::NoSuchKey, str::stream() << "missing " << time.name() << " field"};
}
- if (!_isDetailsSet) {
- *errMsg = stream() << "missing " << details.name() << " field";
- return false;
+
+ if (!_details.is_initialized() || _details->isEmpty()) {
+ return {ErrorCodes::NoSuchKey, str::stream() << "missing " << details.name() << " field"};
}
- return true;
+ return Status::OK();
}
BSONObj ActionLogType::toBSON() const {
BSONObjBuilder builder;
- if (_isServerSet)
- builder.append(server(), _server);
- if (_isTimeSet)
- builder.append(time(), _time);
- if (_isWhatSet)
- builder.append(what(), _what);
- if (_isDetailsSet)
- builder.append(details(), _details);
+ if (_server)
+ builder.append(server.name(), getServer());
+ if (_what)
+ builder.append(what.name(), getWhat());
+ if (_time)
+ builder.append(time.name(), getTime());
+ if (_details)
+ builder.append(details.name(), _details.get());
return builder.obj();
}
-bool ActionLogType::parseBSON(const BSONObj& source, string* errMsg) {
- clear();
-
- std::string dummy;
- if (!errMsg)
- errMsg = &dummy;
-
- FieldParser::FieldState fieldState;
-
- fieldState = FieldParser::extract(source, server, &_server, errMsg);
- if (fieldState == FieldParser::FIELD_INVALID)
- return false;
- _isServerSet = fieldState == FieldParser::FIELD_SET;
-
- fieldState = FieldParser::extract(source, time, &_time, errMsg);
- if (fieldState == FieldParser::FIELD_INVALID)
- return false;
- _isTimeSet = fieldState == FieldParser::FIELD_SET;
-
- fieldState = FieldParser::extract(source, what, &_what, errMsg);
- if (fieldState == FieldParser::FIELD_INVALID)
- return false;
- _isWhatSet = fieldState == FieldParser::FIELD_SET;
-
- fieldState = FieldParser::extract(source, details, &_details, errMsg);
- if (fieldState == FieldParser::FIELD_INVALID)
- return false;
- _isDetailsSet = fieldState == FieldParser::FIELD_SET;
-
- return true;
+std::string ActionLogType::toString() const {
+ return toBSON().toString();
}
-void ActionLogType::clear() {
- _server.clear();
- _isServerSet = false;
-
- _what.clear();
- _isWhatSet = false;
-
- _time = Date_t();
- _isTimeSet = false;
-
- _details = BSONObj();
- _isDetailsSet = false;
+void ActionLogType::setServer(const std::string& server) {
+ invariant(!server.empty());
+ _server = server;
}
-void ActionLogType::cloneTo(ActionLogType* other) const {
- other->clear();
-
- other->_server = _server;
- other->_isServerSet = _isServerSet;
-
- other->_what = _what;
- other->_isWhatSet = _isWhatSet;
-
- other->_time = _time;
- other->_isTimeSet = _isTimeSet;
+void ActionLogType::setWhat(const std::string& what) {
+ invariant(!what.empty());
+ _what = what;
+}
- other->_details = _details;
- other->_isDetailsSet = _isDetailsSet;
+void ActionLogType::setTime(const Date_t& time) {
+ _time = time;
}
-std::string ActionLogType::toString() const {
- return toBSON().toString();
+void ActionLogType::setDetails(const boost::optional<std::string>& errMsg,
+ int executionTime,
+ int candidateChunks,
+ int chunksMoved) {
+ BSONObjBuilder builder;
+ builder.append("executionTimeMillis", executionTime);
+ builder.append("errorOccured", errMsg.is_initialized());
+
+ if (errMsg) {
+ builder.append("errmsg", errMsg.get());
+ } else {
+ builder.append("candidateChunks", candidateChunks);
+ builder.append("chunksMoved", chunksMoved);
+ }
+
+ _details = builder.obj();
}
} // namespace mongo
diff --git a/src/mongo/s/catalog/type_actionlog.h b/src/mongo/s/catalog/type_actionlog.h
index b7ff387a823..d13f21466da 100644
--- a/src/mongo/s/catalog/type_actionlog.h
+++ b/src/mongo/s/catalog/type_actionlog.h
@@ -28,11 +28,11 @@
#pragma once
+#include <boost/optional.hpp>
#include <string>
-#include "mongo/base/disallow_copying.h"
-#include "mongo/base/string_data.h"
#include "mongo/db/jsobj.h"
+#include "mongo/util/time_support.h"
namespace mongo {
@@ -40,31 +40,9 @@ namespace mongo {
* This class represents the layout and contents of documents contained in the
* config.actionlog collection. All manipulation of documents coming from that
* collection should be done with this class.
- *
- * Usage Example:
- *
- * // Contact the config. 'conn' has been obtained before.
- * DBClientBase* conn;
- * BSONObj query = QUERY(ActionLogType::exampleField("exampleFieldName"));
- * exampleDoc = conn->findOne(ActionLogType::ConfigNS, query);
- *
- * // Process the response.
- * ActionLogType exampleType;
- * std::string errMsg;
- * if (!exampleType.parseBSON(exampleDoc, &errMsg) || !exampleType.isValid(&errMsg)) {
- * // Can't use 'exampleType'. Take action.
- * }
- * // use 'exampleType'
- *
*/
class ActionLogType {
- MONGO_DISALLOW_COPYING(ActionLogType);
-
public:
- //
- // schema declarations
- //
-
// Name of the actionlog collection in the config server.
static const std::string ConfigNS;
@@ -81,139 +59,78 @@ public:
static const BSONField<long long> executionTimeMicros;
static const BSONField<std::string> errmsg;
-
- //
- // actionlog type methods
- //
-
- ActionLogType();
- ~ActionLogType();
-
- /**
- * Returns true if all the mandatory fields are present and have valid
- * representations. Otherwise returns false and fills in the optional 'errMsg' string.
- */
- bool isValid(std::string* errMsg) const;
-
- /**
- * Returns the BSON representation of the entry.
- */
- BSONObj toBSON() const;
-
- void buildDetails();
-
/**
- * Clears and populates the internal state using the 'source' BSON object if the
- * latter contains valid values. Otherwise sets errMsg and returns false.
+ * Constructs a new ActionLogType object from BSON.
+ * Also does validation of the contents.
*/
- bool parseBSON(const BSONObj& source, std::string* errMsg);
+ static StatusWith<ActionLogType> fromBSON(const BSONObj& source);
/**
- * Clears the internal state.
+ * Returns OK if all fiels have been set. Otherwise, returns NoSuchKey
+ * and information about the first field that is missing.
*/
- void clear();
+ Status validate() const;
/**
- * Copies all the fields present in 'this' to 'other'.
+ * Returns the BSON representation of the entry.
*/
- void cloneTo(ActionLogType* other) const;
+ BSONObj toBSON() const;
/**
* Returns a std::string representation of the current internal state.
*/
std::string toString() const;
- //
- // individual field accessors
- //
-
- void setServer(StringData server) {
- _server = server.toString();
- _isServerSet = true;
- }
-
- void unsetServer() {
- _isServerSet = false;
- }
-
- bool isServerSet() const {
- return _isServerSet;
- }
-
- // Calling get*() methods when the member is not set results in undefined behavior
const std::string& getServer() const {
- dassert(_isServerSet);
- return _what;
- }
-
- void setWhat(StringData what) {
- _what = what.toString();
- _isWhatSet = true;
- }
-
- void unsetWhat() {
- _isWhatSet = false;
- }
-
- bool isWhatSet() const {
- return _isWhatSet;
+ return _server.get();
}
+ void setServer(const std::string& server);
- // Calling get*() methods when the member is not set results in undefined behavior
const std::string& getWhat() const {
- dassert(_isWhatSet);
- return _what;
- }
-
- void setTime(const Date_t time) {
- _time = time;
- _isTimeSet = true;
- }
-
- void unsetTime() {
- _isTimeSet = false;
- }
-
- bool isTimeSet() const {
- return _isTimeSet;
- }
-
- // Calling get*() methods when the member is not set results in undefined behavior
- const Date_t getTime() const {
- dassert(_isTimeSet);
- return _time;
- }
-
- void setDetails(const BSONObj& details) {
- _details = details.getOwned();
- _isDetailsSet = true;
- }
-
- void unsetDetails() {
- _isDetailsSet = false;
- }
-
- bool isDetailsSet() const {
- return _isDetailsSet;
- }
-
- // Calling get*() methods when the member is not set results in undefined behavior
- const BSONObj getDetails() const {
- dassert(_isDetailsSet);
- return _details;
- }
+ return _what.get();
+ }
+ void setWhat(const std::string& what);
+
+ const Date_t& getTime() const {
+ return _time.get();
+ }
+ void setTime(const Date_t& time);
+
+ /*
+ * Builds the details object for the actionlog.
+ * Current formats for detail are:
+ * Success: {
+ * "candidateChunks" : ,
+ * "chunksMoved" : ,
+ * "executionTimeMillis" : ,
+ * "errorOccured" : false
+ * }
+ * Failure: {
+ * "executionTimeMillis" : ,
+ * "errmsg" : ,
+ * "errorOccured" : true
+ * }
+ * @param errMsg: set if a balancer round resulted in an error
+ * @param executionTime: the time this round took to run
+ * @param candidateChunks: the number of chunks identified to be moved
+ * @param chunksMoved: the number of chunks moved
+ */
+ void setDetails(const boost::optional<std::string>& errMsg,
+ int executionTime,
+ int candidateChunks,
+ int chunksMoved);
private:
// Convention: (M)andatory, (O)ptional, (S)pecial rule.
- std::string _server; // (M) hostname of server that we are making the change on.
- // Does not include port.
- bool _isServerSet;
- std::string _what; // (M) what the action being performed was.
- bool _isWhatSet;
- Date_t _time; // (M) time this change was made
- bool _isTimeSet;
- BSONObj _details; // (M) A BSONObj containing extra information about some operations
- bool _isDetailsSet;
+
+ // (M) hostname of server that we are making the change on. Does not include the port.
+ boost::optional<std::string> _server;
+ // (M) what the action being performed is.
+ boost::optional<std::string> _what;
+ // (M) time this change was made.
+ boost::optional<Date_t> _time;
+ // (M) A BSON document containing extra information about some operations
+ boost::optional<BSONObj> _details;
};
} // namespace mongo