";
bool web = _webCommands->find(name) != _webCommands->end();
if (web)
ss << "";
ss << name;
if (web)
ss << "";
ss << " | \n";
ss << "";
if (isWriteCommandForConfigServer()) {
ss << "W ";
} else {
ss << "R ";
}
if (slaveOk())
ss << "S ";
if (adminOnly())
ss << "A";
ss << " | ";
ss << "";
if (helpStr != "no help defined") {
const char* p = helpStr.c_str();
while (*p) {
if (*p == '<') {
ss << "<";
p++;
continue;
} else if (*p == '{')
ss << "";
else if (*p == '}') {
ss << "} ";
p++;
continue;
}
if (strncmp(p, "http:", 5) == 0) {
ss << "";
q = p;
if (str::startsWith(q, "http://www.mongodb.org/display/"))
q += 31;
while (*q && *q != ' ' && *q != '\n') {
ss << (*q == '+' ? ' ' : *q);
q++;
if (*q == '#')
while (*q && *q != ' ' && *q != '\n')
q++;
}
ss << "";
p = q;
continue;
}
if (*p == '\n')
ss << " ";
else
ss << *p;
p++;
}
}
ss << " | ";
ss << "
\n";
}
Command::Command(StringData _name, bool web, StringData oldName)
: name(_name.toString()),
_commandsExecutedMetric("commands." + _name.toString() + ".total", &_commandsExecuted),
_commandsFailedMetric("commands." + _name.toString() + ".failed", &_commandsFailed) {
// register ourself.
if (_commands == 0)
_commands = new CommandMap();
if (_commandsByBestName == 0)
_commandsByBestName = new CommandMap();
Command*& c = (*_commands)[name];
if (c)
log() << "warning: 2 commands with name: " << _name << endl;
c = this;
(*_commandsByBestName)[name] = this;
if (web) {
if (_webCommands == 0)
_webCommands = new CommandMap();
(*_webCommands)[name] = this;
}
if (!oldName.empty())
(*_commands)[oldName.toString()] = this;
}
void Command::help(stringstream& help) const {
help << "no help defined";
}
Command* Command::findCommand(StringData name) {
CommandMap::const_iterator i = _commands->find(name);
if (i == _commands->end())
return 0;
return i->second;
}
bool Command::appendCommandStatus(BSONObjBuilder& result, const Status& status) {
appendCommandStatus(result, status.isOK(), status.reason());
BSONObj tmp = result.asTempObj();
if (!status.isOK() && !tmp.hasField("code")) {
result.append("code", status.code());
}
return status.isOK();
}
void Command::appendCommandStatus(BSONObjBuilder& result, bool ok, const std::string& errmsg) {
BSONObj tmp = result.asTempObj();
bool have_ok = tmp.hasField("ok");
bool have_errmsg = tmp.hasField("errmsg");
if (!have_ok)
result.append("ok", ok ? 1.0 : 0.0);
if (!ok && !have_errmsg) {
result.append("errmsg", errmsg);
}
}
void Command::appendCommandWCStatus(BSONObjBuilder& result, const Status& status) {
if (!status.isOK()) {
WCErrorDetail wcError;
wcError.setErrCode(status.code());
wcError.setErrMessage(status.reason());
result.append("writeConcernError", wcError.toBSON());
}
}
Status Command::getStatusFromCommandResult(const BSONObj& result) {
return mongo::getStatusFromCommandResult(result);
}
Status Command::parseCommandCursorOptions(const BSONObj& cmdObj,
long long defaultBatchSize,
long long* batchSize) {
invariant(batchSize);
*batchSize = defaultBatchSize;
BSONElement cursorElem = cmdObj["cursor"];
if (cursorElem.eoo()) {
return Status::OK();
}
if (cursorElem.type() != mongo::Object) {
return Status(ErrorCodes::TypeMismatch, "cursor field must be missing or an object");
}
BSONObj cursor = cursorElem.embeddedObject();
BSONElement batchSizeElem = cursor["batchSize"];
const int expectedNumberOfCursorFields = batchSizeElem.eoo() ? 0 : 1;
if (cursor.nFields() != expectedNumberOfCursorFields) {
return Status(ErrorCodes::BadValue,
"cursor object can't contain fields other than batchSize");
}
if (batchSizeElem.eoo()) {
return Status::OK();
}
if (!batchSizeElem.isNumber()) {
return Status(ErrorCodes::TypeMismatch, "cursor.batchSize must be a number");
}
// This can change in the future, but for now all negatives are reserved.
if (batchSizeElem.numberLong() < 0) {
return Status(ErrorCodes::BadValue, "cursor.batchSize must not be negative");
}
*batchSize = batchSizeElem.numberLong();
return Status::OK();
}
Status Command::checkAuthForCommand(ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
std::vector