Beispiel #1
0
void fillWriterVectors(const std::deque<BSONObj>& ops,
                       std::vector<std::vector<BSONObj>>* writerVectors) {
    for (std::deque<BSONObj>::const_iterator it = ops.begin(); it != ops.end(); ++it) {
        const BSONElement e = it->getField("ns");
        verify(e.type() == String);
        const char* ns = e.valuestr();
        int len = e.valuestrsize();
        uint32_t hash = 0;
        MurmurHash3_x86_32(ns, len, 0, &hash);

        const char* opType = it->getField("op").valuestrsafe();

        if (getGlobalServiceContext()->getGlobalStorageEngine()->supportsDocLocking() &&
            isCrudOpType(opType)) {
            BSONElement id;
            switch (opType[0]) {
                case 'u':
                    id = it->getField("o2").Obj()["_id"];
                    break;
                case 'd':
                case 'i':
                    id = it->getField("o").Obj()["_id"];
                    break;
            }

            const size_t idHash = BSONElement::Hasher()(id);
            MurmurHash3_x86_32(&idHash, sizeof(idHash), hash, &hash);
        }

        (*writerVectors)[hash % writerVectors->size()].push_back(*it);
    }
}
Beispiel #2
0
 string Command::parseNsCollectionRequired(const string& dbname, const BSONObj& cmdObj) const {
     // Accepts both BSON String and Symbol for collection name per SERVER-16260
     // TODO(kangas) remove Symbol support in MongoDB 3.0 after Ruby driver audit
     BSONElement first = cmdObj.firstElement();
     uassert(17009,
             "no collection name specified",
             first.canonicalType() == canonicalizeBSONType(mongo::String)
             && first.valuestrsize() > 0);
     std::string coll = first.valuestr();
     return dbname + '.' + coll;
 }
Beispiel #3
0
    void SyncTail::fillWriterVectors(const std::deque<BSONObj>& ops, 
                                              std::vector< std::vector<BSONObj> >* writerVectors) {
        for (std::deque<BSONObj>::const_iterator it = ops.begin();
             it != ops.end();
             ++it) {
            const BSONElement e = it->getField("ns");
            verify(e.type() == String);
            const char* ns = e.valuestr();
            int len = e.valuestrsize();
            uint32_t hash = 0;
            MurmurHash3_x86_32( ns, len, 0, &hash);

            (*writerVectors)[hash % writerVectors->size()].push_back(*it);
        }
    }
Beispiel #4
0
bool RegexMatchExpression::matchesSingleElement(const BSONElement& e) const {
    switch (e.type()) {
        case String:
        case Symbol: {
            // String values stored in documents can contain embedded NUL bytes. We construct a
            // pcrecpp::StringPiece instance using the full length of the string to avoid truncating
            // 'data' early.
            pcrecpp::StringPiece data(e.valuestr(), e.valuestrsize() - 1);
            return _re->PartialMatch(data);
        }
        case RegEx:
            return _regex == e.regex() && _flags == e.regexFlags();
        default:
            return false;
    }
}
Beispiel #5
0
FieldParser::FieldState FieldParser::extract(BSONElement elem,
                                             const BSONField<string>& field,
                                             string* out,
                                             string* errMsg) {
    if (elem.eoo()) {
        if (field.hasDefault()) {
            *out = field.getDefault();
            return FIELD_DEFAULT;
        } else {
            return FIELD_NONE;
        }
    }

    if (elem.type() == String) {
        // Extract everything, including embedded null characters.
        *out = string(elem.valuestr(), elem.valuestrsize() - 1);
        return FIELD_SET;
    }

    _genFieldErrMsg(elem, field, "string", errMsg);
    return FIELD_INVALID;
}
Beispiel #6
0
 // fromBSON to Key format
 KeyV1Owned::KeyV1Owned(const BSONObj& obj) {
     BSONObj::iterator i(obj);
     unsigned char bits = 0;
     while( 1 ) { 
         BSONElement e = i.next();
         if( i.more() )
             bits |= cHASMORE;
         switch( e.type() ) { 
         case MinKey:
             b.appendUChar(cminkey|bits);
             break;
         case jstNULL:
             b.appendUChar(cnull|bits);
             break;
         case MaxKey:
             b.appendUChar(cmaxkey|bits);
             break;
         case Bool:
             b.appendUChar( (e.boolean()?ctrue:cfalse) | bits );
             break;
         case jstOID:
             b.appendUChar(coid|bits);
             b.appendBuf(&e.__oid(), sizeof(OID));
             break;
         case BinData:
             {
                 int t = e.binDataType();
                 // 0-7 and 0x80 to 0x87 are supported by Key
                 if( (t & 0x78) == 0 && t != ByteArrayDeprecated ) {
                     int len;
                     const char * d = e.binData(len);
                     if( len <= BinDataLenMax ) {
                         int code = BinDataLengthToCode[len];
                         if( code >= 0 ) {
                             if( t >= 128 )
                                 t = (t-128) | 0x08;
                             dassert( (code&t) == 0 );
                             b.appendUChar( cbindata|bits );
                             b.appendUChar( code | t );
                             b.appendBuf(d, len);
                             break;
                         }
                     }
                 }
                 traditional(obj);
                 return;
             }
         case Date:
             b.appendUChar(cdate|bits);
             b.appendStruct(e.date());
             break;
         case String:
             {
                 b.appendUChar(cstring|bits);
                 // note we do not store the terminating null, to save space.
                 unsigned x = (unsigned) e.valuestrsize() - 1;
                 if( x > 255 ) { 
                     traditional(obj);
                     return;
                 }
                 b.appendUChar(x);
                 b.appendBuf(e.valuestr(), x);
                 break;
             }
         case NumberInt:
             b.appendUChar(cint|bits);
             b.appendNum((double) e._numberInt());
             break;
         case NumberLong:
             {
                 long long n = e._numberLong();
                 long long m = 2LL << 52;
                 DEV {
                     long long d = m-1;
                     verify( ((long long) ((double) -d)) == -d );
                 }
                 if( n >= m || n <= -m ) {
                     // can't represent exactly as a double
                     traditional(obj);
                     return;
                 }
                 b.appendUChar(clong|bits);
                 b.appendNum((double) n);
                 break;
             }
         case NumberDouble:
             {
                 double d = e._numberDouble();
                 if( isNaN(d) ) {
                     traditional(obj);
                     return;
                 }
                 b.appendUChar(cdouble|bits);
                 b.appendNum(d);
                 break;
             }
         default:
             // if other types involved, store as traditional BSON
             traditional(obj);
             return;
         }
         if( !i.more() )
             break;
         bits = 0;
     }
     _keyData = (const unsigned char *) b.buf();
     dassert( b.len() == dataSize() ); // check datasize method is correct
     dassert( (*_keyData & cNOTUSED) == 0 );
 }
 static inline StringData makeStringDataFromBSONElement(const BSONElement& element) {
     return StringData(element.valuestr(), element.valuestrsize() - 1);
 }
Beispiel #8
0
        std::string jsonString(BSONElement &elem, JsonStringFormat format, bool includeFieldNames, int pretty, UUIDEncoding uuidEncoding)
        {
            BSONType t = elem.type();
            int sign;
            if ( t == Undefined )
                return "undefined";

            stringstream s;
            if ( includeFieldNames )
                s << '"' << escape( elem.fieldName() ) << "\" : ";
            switch ( elem.type() ) {
            case mongo::String:
            case Symbol:
                s << '"' << escape( string(elem.valuestr(), elem.valuestrsize()-1) ) << '"';
                break;
            case NumberLong:
                s << "NumberLong(" << elem._numberLong() << ")";
                break;
            case NumberInt:
            case NumberDouble:
                if ( elem.number() >= -numeric_limits< double >::max() &&
                        elem.number() <= numeric_limits< double >::max() ) {
                    s.precision( 16 );
                    s << elem.number();
                }
                else if ( mongo::isNaN(elem.number()) ) {
                    s << "NaN";
                }
                else if ( mongo::isInf(elem.number(), &sign) ) {
                    s << ( sign == 1 ? "Infinity" : "-Infinity");
                }
                else {
                    StringBuilder ss;
                    ss << "Number " << elem.number() << " cannot be represented in JSON";
                    string message = ss.str();
                    //massert( 10311 ,  message.c_str(), false );
                }
                break;
            case mongo::Bool:
                s << ( elem.boolean() ? "true" : "false" );
                break;
            case jstNULL:
                s << "null";
                break;
            case Object: {
                BSONObj obj = elem.embeddedObject();
                s << jsonString(obj, format, pretty, uuidEncoding);
                }
                break;
            case mongo::Array: {
                if ( elem.embeddedObject().isEmpty() ) {
                    s << "[]";
                    break;
                }
                s << "[ ";
                BSONObjIterator i( elem.embeddedObject() );
                BSONElement e = i.next();
                if ( !e.eoo() ) {
                    int count = 0;
                    while ( 1 ) {
                        if( pretty ) {
                            s << '\n';
                            for( int x = 0; x < pretty; x++ )
                                s << "    ";
                        }

                        if (strtol(e.fieldName(), 0, 10) > count) {
                            s << "undefined";
                        }
                        else {
                            s << jsonString(e, format, false, pretty?pretty+1:0, uuidEncoding);
                            e = i.next();
                        }
                        count++;
                        if ( e.eoo() ) {
                            s << '\n';
                            for( int x = 0; x < pretty - 1; x++ )
                                s << "    ";
                            s << "]";
                            break;
                        }
                        s << ", ";
                    }
                }
                //s << " ]";
                break;
            }
            case DBRef: {
                mongo::OID *x = (mongo::OID *) (elem.valuestr() + elem.valuestrsize());
                if ( format == TenGen )
                    s << "Dbref( ";
                else
                    s << "{ \"$ref\" : ";
                s << '"' << elem.valuestr() << "\", ";
                if ( format != TenGen )
                    s << "\"$id\" : ";
                s << '"' << *x << "\" ";
                if ( format == TenGen )
                    s << ')';
                else
                    s << '}';
                break;
            }
            case jstOID:
                if ( format == TenGen ) {
                    s << "ObjectId(";
                }
                else {
                    s << "{ \"$oid\" : ";
                }
                s << '"' << elem.__oid() << '"';
                if ( format == TenGen ) {
                    s << ")";
                }
                else {
                    s << " }";
                }
                break;
            case BinData: {
                int len = *(int *)( elem.value() );
                BinDataType type = BinDataType( *(char *)( (int *)( elem.value() ) + 1 ) );

                if (type == mongo::bdtUUID || type == mongo::newUUID) {
                    s << HexUtils::formatUuid(elem, uuidEncoding);
                    break;
                }

                s << "{ \"$binary\" : \"";
                char *start = ( char * )( elem.value() ) + sizeof( int ) + 1;
                base64::encode( s , start , len );
                s << "\", \"$type\" : \"" << hex;
                s.width( 2 );
                s.fill( '0' );
                s << type << dec;
                s << "\" }";
                break;
            }
            case mongo::Date:
                if ( format == Strict )
                    s << "{ \"$date\" : ";
                else
                    s << "ISODate(";
                if( pretty ) {
                    Date_t d = elem.date();

                    long long ms = (long long) d.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 timestr = miutil::isotimeString(time, true, true);
                    s << '"' << timestr << '"';

        /*            if( d == 0 ) s << '0';
                    else
                        //P s << '"' << elem.date().toString() << '"';
                        s << '"' << elem.date().millis << '"';*/

                }
                else
                    s << elem.date();
                if ( format == Strict )
                    s << " }";
                else
                    s << ")";
                break;
            case RegEx:
                if ( format == Strict ) {
                    s << "{ \"$regex\" : \"" << escape( elem.regex() );
                    s << "\", \"$options\" : \"" << elem.regexFlags() << "\" }";
                }
                else {
                    s << "/" << escape( elem.regex() , true ) << "/";
                    // FIXME Worry about alpha order?
                    for ( const char *f = elem.regexFlags(); *f; ++f ) {
                        switch ( *f ) {
                        case 'g':
                        case 'i':
                        case 'm':
                            s << *f;
                        default:
                            break;
                        }
                    }
                }
                break;

            case CodeWScope: {
                BSONObj scope = elem.codeWScopeObject();
                if ( ! scope.isEmpty() ) {
                    s << "{ \"$code\" : " << elem._asCode() << " , "
                      << " \"$scope\" : " << scope.jsonString() << " }";
                    break;
                }
            }

            case Code:
                s << elem._asCode();
                break;

            case Timestamp:
                if ( format == TenGen ) {
                    s << "Timestamp(" << ( elem.timestampTime() / 1000 ) << ", " << elem.timestampInc() << ")";
                }
                else {
                    s << "{ \"$timestamp\" : { \"t\" : " << ( elem.timestampTime() / 1000 ) << ", \"i\" : " << elem.timestampInc() << " } }";
                }
                break;

            case MinKey:
                s << "{ \"$minKey\" : 1 }";
                break;

            case MaxKey:
                s << "{ \"$maxKey\" : 1 }";
                break;

            default:
                StringBuilder ss;
                ss << "Cannot create a properly formatted JSON string with "
                   << "element: " << elem.toString() << " of type: " << elem.type();
                string message = ss.str();
                //massert( 10312 ,  message.c_str(), false );
            }
            return s.str();
        }
Beispiel #9
0
// fromBSON to Key format
KeyV1Owned::KeyV1Owned(const BSONObj& obj) {
    BSONObj::iterator i(obj);
    assert( i.more() );
    unsigned char bits = 0;
    while( 1 ) {
        BSONElement e = i.next();
        if( i.more() )
            bits |= cHASMORE;
        switch( e.type() ) {
        case MinKey:
            b.appendUChar(cminkey|bits);
            break;
        case jstNULL:
            b.appendUChar(cnull|bits);
            break;
        case MaxKey:
            b.appendUChar(cmaxkey|bits);
            break;
        case Bool:
            b.appendUChar( (e.boolean()?ctrue:cfalse) | bits );
            break;
        case jstOID:
            b.appendUChar(coid|bits);
            b.appendBuf(&e.__oid(), sizeof(OID));
            break;
        case BinData:
        {
            int t = e.binDataType();
            // 0-7 and 0x80 to 0x87 are supported by Key
            if( (t & 0x78) == 0 && t != ByteArrayDeprecated ) {
                int len;
                const char * d = e.binData(len);
                int code = BinDataLengthToCode[len];
                if( code >= 0 ) {
                    if( t >= 128 )
                        t = (t-128) | 0x08;
                    dassert( (code&t) == 0 );
                    b.appendUChar( cbindata|bits );
                    b.appendUChar( code | t );
                    b.appendBuf(d, len);
                    break;
                }
            }
            traditional(obj);
            return;
        }
        case Date:
            b.appendUChar(cdate|bits);
            b.appendStruct(e.date());
            break;
        case String:
        {
            b.appendUChar(cstring|bits);
            // note we do not store the terminating null, to save space.
            unsigned x = (unsigned) e.valuestrsize() - 1;
            if( x > 255 ) {
                traditional(obj);
                return;
            }
            b.appendUChar(x);
            b.appendBuf(e.valuestr(), x);
            break;
        }
        case NumberInt:
            b.appendUChar(cint|bits);
            b.appendNum((double) e._numberInt());
            break;
        case NumberLong:
        {
            long long n = e._numberLong();
            double d = (double) n;
            if( d != n ) {
                traditional(obj);
                return;
            }
            b.appendUChar(clong|bits);
            b.appendNum(d);
            break;
        }
        case NumberDouble:
        {
            double d = e._numberDouble();
            bool nan = !( d <= numeric_limits< double >::max() &&
                          d >= -numeric_limits< double >::max() );
            if( !nan ) {
                b.appendUChar(cdouble|bits);
                b.appendNum(d);
                break;
            }
            // else fall through and return a traditional BSON obj so our compressed keys need not check for nan
        }
        default:
            // if other types involved, store as traditional BSON
            traditional(obj);
            return;
        }
        if( !i.more() )
            break;
        bits = 0;
    }
    _keyData = (const unsigned char *) b.buf();
    dassert( b.len() == dataSize() ); // check datasize method is correct
    dassert( (*_keyData & cNOTUSED) == 0 );
}