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;
}
Beispiel #2
0
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;
}
Beispiel #5
0
    /*
    ** 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;
        }
    }
Beispiel #6
0
    /*
    ** 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;
        }
    }
Beispiel #7
0
        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;
            }
        }