Status CatalogManagerCommon::_log(OperationContext* txn, const StringData& logCollName, const std::string& what, const std::string& operationNS, const BSONObj& detail) { Date_t now = grid.shardRegistry()->getExecutor()->now(); const std::string hostName = grid.shardRegistry()->getNetwork()->getHostName(); const string changeId = str::stream() << hostName << "-" << now.toString() << "-" << OID::gen(); ChangeLogType changeLog; changeLog.setChangeId(changeId); changeLog.setServer(hostName); changeLog.setClientAddr(txn->getClient()->clientAddress(true)); changeLog.setTime(now); changeLog.setNS(operationNS); changeLog.setWhat(what); changeLog.setDetails(detail); BSONObj changeLogBSON = changeLog.toBSON(); log() << "about to log metadata event into " << logCollName << ": " << changeLogBSON; const NamespaceString nss("config", logCollName); Status result = insertConfigDocument(txn, nss.ns(), changeLogBSON); if (!result.isOK()) { warning() << "Error encountered while logging config change with ID [" << changeId << "] into collection " << logCollName << ": " << result; } return result; }
StatusWith<executor::TaskExecutor::CallbackHandle> TaskExecutorMock::scheduleWorkAt( Date_t when, const CallbackFn& work) { if (shouldFailScheduleWorkAtRequest()) { return Status(ErrorCodes::OperationFailed, str::stream() << "failed to schedule work at " << when.toString()); } return getExecutor()->scheduleWorkAt(when, work); }
void ShardingTestFixture::expectConfigCollectionInsert(const HostAndPort& configHost, StringData collName, Date_t timestamp, const std::string& what, const std::string& ns, const BSONObj& detail) { onCommand([&](const RemoteCommandRequest& request) { ASSERT_EQUALS(configHost, request.target); ASSERT_EQUALS("config", request.dbname); BatchedInsertRequest actualBatchedInsert; std::string errmsg; ASSERT_TRUE(actualBatchedInsert.parseBSON(request.dbname, request.cmdObj, &errmsg)); ASSERT_EQ("config", actualBatchedInsert.getNS().db()); ASSERT_EQ(collName, actualBatchedInsert.getNS().coll()); auto inserts = actualBatchedInsert.getDocuments(); ASSERT_EQUALS(1U, inserts.size()); const ChangeLogType& actualChangeLog = assertGet(ChangeLogType::fromBSON(inserts.front())); ASSERT_EQUALS(operationContext()->getClient()->clientAddress(true), actualChangeLog.getClientAddr()); ASSERT_EQUALS(detail, actualChangeLog.getDetails()); ASSERT_EQUALS(ns, actualChangeLog.getNS()); ASSERT_EQUALS(network()->getHostName(), actualChangeLog.getServer()); ASSERT_EQUALS(timestamp, actualChangeLog.getTime()); ASSERT_EQUALS(what, actualChangeLog.getWhat()); // Handle changeId specially because there's no way to know what OID was generated std::string changeId = actualChangeLog.getChangeId(); size_t firstDash = changeId.find("-"); size_t lastDash = changeId.rfind("-"); const std::string serverPiece = changeId.substr(0, firstDash); const std::string timePiece = changeId.substr(firstDash + 1, lastDash - firstDash - 1); const std::string oidPiece = changeId.substr(lastDash + 1); ASSERT_EQUALS(grid.getNetwork()->getHostName(), serverPiece); ASSERT_EQUALS(timestamp.toString(), timePiece); OID generatedOID; // Just make sure this doesn't throws and assume the OID is valid generatedOID.init(oidPiece); BatchedCommandResponse response; response.setOk(true); return response.toBSON(); }); }
Status CatalogManagerReplicaSet::logChange(OperationContext* txn, const string& clientAddress, const string& what, const string& ns, const BSONObj& detail) { if (_changeLogCollectionCreated.load() == 0) { BSONObj createCmd = BSON("create" << ChangeLogType::ConfigNS << "capped" << true << "size" << kChangeLogCollectionSize); auto result = grid.shardRegistry()->runCommandOnConfigWithNotMasterRetries("config", createCmd); if (!result.isOK()) { LOG(1) << "couldn't create changelog collection: " << causedBy(result.getStatus()); return result.getStatus(); } Status commandStatus = Command::getStatusFromCommandResult(result.getValue()); if (commandStatus.isOK() || commandStatus == ErrorCodes::NamespaceExists) { _changeLogCollectionCreated.store(1); } else { LOG(1) << "couldn't create changelog collection: " << causedBy(commandStatus); return commandStatus; } } Date_t now = grid.shardRegistry()->getExecutor()->now(); const std::string hostName = grid.shardRegistry()->getNetwork()->getHostName(); const string changeId = str::stream() << hostName << "-" << now.toString() << "-" << OID::gen(); ChangeLogType changeLog; changeLog.setChangeId(changeId); changeLog.setServer(hostName); changeLog.setClientAddr(clientAddress); changeLog.setTime(now); changeLog.setNS(ns); changeLog.setWhat(what); changeLog.setDetails(detail); BSONObj changeLogBSON = changeLog.toBSON(); log() << "about to log metadata event: " << changeLogBSON; Status result = insert(txn, ChangeLogType::ConfigNS, changeLogBSON, NULL); if (!result.isOK()) { warning() << "Error encountered while logging config change with ID " << changeId << ": " << result; } return result; }
/* ** Build Json string that represent this element. */ void MongoElement::buildJsonString(Concatenator &con) { switch (_bsonElement.type()) { /** double precision floating point value */ case NumberDouble: con.append(QString::number(_bsonElement.Double())); break; /** character string, stored in utf8 */ case String: { /* ** If you'll write: ** ** int valsize = element.valuesize(); ** int strsize = element.valuestrsize(); ** int bytescount = qstrlen(element.valuestr()); ** ** You'll get: ** ** bytescount + 1 == strsize ** strsize + 4 == valsize ** ** So: ** bytescount + 5 == valsize ** */ QString res = QString::fromUtf8(_bsonElement.valuestr(), _bsonElement.valuestrsize() - 1); con.append(res); } break; /** an embedded object */ case Object: { MongoDocumentPtr doc = asDocument(); doc->buildJsonString(con); } break; /** an embedded array */ case Array: { MongoDocumentPtr doc = asDocument(); doc->buildJsonString(con); } break; /** binary data */ case BinData: { mongo::BinDataType binType = _bsonElement.binDataType(); if (binType == mongo::newUUID || binType == mongo::bdtUUID) { std::string uuid = HexUtils::formatUuid(_bsonElement, AppRegistry::instance().settingsManager()->uuidEncoding()); con.append(QString::fromStdString(uuid)); break; } con.append("<binary>"); } break; /** Undefined type */ case Undefined: con.append("<undefined>"); break; /** ObjectId */ case jstOID: { QString idValue = QString::fromStdString(_bsonElement.OID().toString()); QString objectId = QString("ObjectId(\"%1\")").arg(idValue); con.append(objectId); } break; /** boolean type */ case Bool: con.append(_bsonElement.Bool() ? "true" : "false"); break; /** date type */ case Date: { long long ms = (long long) _bsonElement.Date().millis; boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1)); boost::posix_time::time_duration diff = boost::posix_time::millisec(ms); boost::posix_time::ptime time = epoch + diff; std::stringstream strm; //boost::date_time::time_facet *timeFacet = new boost::date_time::time_facet("%a, %d %b %Y %H:%M:%S.%f GMT"); // "%Y---%m-%d %H:%M:%S" boost::posix_time::time_facet *facet = new boost::posix_time::time_facet("%Y-%m-%d %H:%M:%S"); strm.imbue(std::locale(strm.getloc(), facet)); strm << time; con.append(QString::fromStdString(strm.str())); break; /* // this code is left untill the upper one will stabilize unsigned long long millis = _bsonElement.Date().millis; if ((long long)millis >= 0 && ((long long)millis/1000) < (std::numeric_limits<time_t>::max)()) { con.append(QString::fromStdString(_bsonElement.Date().toString())); } break; */ } /** null type */ case jstNULL: con.append(QString("<null>")); break; /** regular expression, a pattern with options */ case RegEx: { con.append("/" + QString::fromUtf8(_bsonElement.regex()) + "/"); for ( const char *f = _bsonElement.regexFlags(); *f; ++f ) { switch ( *f ) { case 'g': case 'i': case 'm': con.append(QString(*f)); default: break; } } } break; /** deprecated / will be redesigned */ case DBRef: break; /** deprecated / use CodeWScope */ case Code: con.append(QString::fromUtf8(_bsonElement._asCode().data())); break; /** a programming language (e.g., Python) symbol */ case Symbol: con.append(QString::fromUtf8(_bsonElement.valuestr(), _bsonElement.valuestrsize() - 1)); break; /** javascript code that can execute on the database server, with SavedContext */ case CodeWScope: { mongo::BSONObj scope = _bsonElement.codeWScopeObject(); if (!scope.isEmpty() ) { con.append(QString::fromUtf8(_bsonElement._asCode().data())); break; } } break; /** 32 bit signed integer */ case NumberInt: con.append(QString::number(_bsonElement.Int())); break; /** Updated to a Date with value next OpTime on insert */ case Timestamp: { Date_t date = _bsonElement.timestampTime(); unsigned long long millis = date.millis; if ((long long)millis >= 0 && ((long long)millis/1000) < (std::numeric_limits<time_t>::max)()) { con.append(QString::fromStdString(date.toString())); } break; } /** 64 bit integer */ case NumberLong: con.append(QString::number(_bsonElement.Long())); break; default: con.append("<unsupported>"); break; } }
/* ** Build Json string that represent this element. */ void MongoElement::buildJsonString(std::string &con) { switch (_bsonElement.type()) { /** double precision floating point value */ case NumberDouble: con.append(QtUtils::toStdString<std::string>(QString::number(_bsonElement.Double(),'g',14))); break; /** character string, stored in utf8 */ case String: { /* ** If you'll write: ** ** int valsize = element.valuesize(); ** int strsize = element.valuestrsize(); ** int bytescount = qstrlen(element.valuestr()); ** ** You'll get: ** ** bytescount + 1 == strsize ** strsize + 4 == valsize ** ** So: ** bytescount + 5 == valsize ** */ con.append(_bsonElement.valuestr(), _bsonElement.valuestrsize() - 1); } break; /** an embedded object */ case Object: { MongoDocumentPtr doc = asDocument(); doc->buildJsonString(con); } break; /** an embedded array */ case Array: { MongoDocumentPtr doc = asDocument(); doc->buildJsonString(con); } break; /** binary data */ case BinData: { mongo::BinDataType binType = _bsonElement.binDataType(); if (binType == mongo::newUUID || binType == mongo::bdtUUID) { std::string uuid = HexUtils::formatUuid(_bsonElement, AppRegistry::instance().settingsManager()->uuidEncoding()); con.append(uuid); break; } con.append("<binary>"); } break; /** Undefined type */ case Undefined: con.append("<undefined>"); break; /** ObjectId */ case jstOID: { std::string idValue = _bsonElement.OID().toString(); char buff[256]={0}; sprintf(buff,"ObjectId(\"%s\")",idValue.c_str()); con.append(buff); } break; /** boolean type */ case Bool: con.append(_bsonElement.Bool() ? "true" : "false"); break; /** date type */ case Date: { long long ms = (long long) _bsonElement.Date().millis; boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1)); boost::posix_time::time_duration diff = boost::posix_time::millisec(ms); boost::posix_time::ptime time = epoch + diff; std::string date = miutil::isotimeString(time,false,AppRegistry::instance().settingsManager()->timeZone()==LocalTime); con.append(date); break; } /** null type */ case jstNULL: con.append("<null>"); break; /** regular expression, a pattern with options */ case RegEx: { con.append("/" + std::string(_bsonElement.regex()) + "/"); for ( const char *f = _bsonElement.regexFlags(); *f; ++f ) { switch ( *f ) { case 'g': case 'i': case 'm': con+=*f; default: break; } } } break; /** deprecated / will be redesigned */ case DBRef: break; /** deprecated / use CodeWScope */ case Code: con.append(_bsonElement._asCode()); break; /** a programming language (e.g., Python) symbol */ case Symbol: con.append(_bsonElement.valuestr(), _bsonElement.valuestrsize() - 1); break; /** javascript code that can execute on the database server, with SavedContext */ case CodeWScope: { mongo::BSONObj scope = _bsonElement.codeWScopeObject(); if (!scope.isEmpty() ) { con.append(_bsonElement._asCode()); break; } } break; /** 32 bit signed integer */ case NumberInt: { char num[16]={0}; sprintf(num,"%d",_bsonElement.Int()); con.append(num); break; } /** Updated to a Date with value next OpTime on insert */ case Timestamp: { Date_t date = _bsonElement.timestampTime(); unsigned long long millis = date.millis; if ((long long)millis >= 0 && ((long long)millis/1000) < (std::numeric_limits<time_t>::max)()) { con.append(date.toString()); } break; } /** 64 bit integer */ case NumberLong: { char num[32]={0}; sprintf(num,"%lld",_bsonElement.Long()); con.append(num); break; } default: con.append("<unsupported>"); break; } }
void buildJsonString(const mongo::BSONElement &elem,std::string &con, UUIDEncoding uuid, SupportedTimes tz) { switch (elem.type()) { case NumberDouble: { char dob[32] = {0}; sprintf(dob, "%f", elem.Double()); con.append(dob); } break; case String: { con.append(elem.valuestr(), elem.valuestrsize() - 1); } break; case Object: { buildJsonString(elem.Obj(), con, uuid, tz); } break; case Array: { buildJsonString(elem.Obj(), con, uuid, tz); } break; case BinData: { mongo::BinDataType binType = elem.binDataType(); if (binType == mongo::newUUID || binType == mongo::bdtUUID) { std::string uu = HexUtils::formatUuid(elem, uuid); con.append(uu); break; } con.append("<binary>"); } break; case Undefined: con.append("<undefined>"); break; case jstOID: { std::string idValue = elem.OID().toString(); char buff[256] = {0}; sprintf(buff, "ObjectId(\"%s\")", idValue.c_str()); con.append(buff); } break; case Bool: con.append(elem.Bool() ? "true" : "false"); break; case Date: { long long ms = (long long) elem.Date().millis; boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1)); boost::posix_time::time_duration diff = boost::posix_time::millisec(ms); boost::posix_time::ptime time = epoch + diff; std::string date = miutil::isotimeString(time,false,tz==LocalTime); con.append(date); break; } case jstNULL: con.append("<null>"); break; case RegEx: { con.append("/" + std::string(elem.regex()) + "/"); for ( const char *f = elem.regexFlags(); *f; ++f ) { switch ( *f ) { case 'g': case 'i': case 'm': con+=*f; default: break; } } } break; case DBRef: break; case Code: con.append(elem._asCode()); break; case Symbol: con.append(elem.valuestr(), elem.valuestrsize() - 1); break; case CodeWScope: { mongo::BSONObj scope = elem.codeWScopeObject(); if (!scope.isEmpty() ) { con.append(elem._asCode()); break; } } break; case NumberInt: { char num[16]={0}; sprintf(num,"%d",elem.Int()); con.append(num); break; } case Timestamp: { Date_t date = elem.timestampTime(); unsigned long long millis = date.millis; if ((long long)millis >= 0 && ((long long)millis/1000) < (std::numeric_limits<time_t>::max)()) { con.append(date.toString()); } break; } case NumberLong: { char num[32]={0}; sprintf(num,"%lld",elem.Long()); con.append(num); break; } default: con.append("<unsupported>"); break; } }