void run(){ #ifdef MOZJS Scope * s = globalScriptEngine->createScope(); s->localConnect( "blah" ); s->invoke( "z = { _id : new ObjectId() , a : 123 };" , BSONObj() ); BSONObj out = s->getObject( "z" ); ASSERT_EQUALS( 123 , out["a"].number() ); ASSERT_EQUALS( jstOID , out["_id"].type() ); OID save = out["_id"].__oid(); s->setObject( "a" , out ); s->invoke( "y = { _id : a._id , a : 124 };" , BSONObj() ); out = s->getObject( "y" ); ASSERT_EQUALS( 124 , out["a"].number() ); ASSERT_EQUALS( jstOID , out["_id"].type() ); ASSERT_EQUALS( out["_id"].__oid().str() , save.str() ); s->invoke( "y = { _id : new ObjectId( a._id ) , a : 125 };" , BSONObj() ); out = s->getObject( "y" ); ASSERT_EQUALS( 125 , out["a"].number() ); ASSERT_EQUALS( jstOID , out["_id"].type() ); ASSERT_EQUALS( out["_id"].__oid().str() , save.str() ); delete s; #endif }
bool run(const string& , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) { BSONElement e = cmdObj.firstElement(); if ( e.type() != jstOID ) { errmsg = "need oid as first value"; return 0; } // get the command issuer's (a mongos) serverID const OID id = e.__oid(); // the command issuer is blocked awaiting a response // we want to do return at least at every 5 minutes so sockets don't timeout BSONObj z; if ( writeBackManager.getWritebackQueue(id.str())->queue.blockingPop( z, 5 * 60 /* 5 minutes */ ) ) { MONGO_LOG(1) << "WriteBackCommand got : " << z << endl; result.append( "data" , z ); } else { result.appendBool( "noop" , true ); } #ifdef _DEBUG // Sleep a short amount of time usually int sleepFor = rand() % 10; sleepmillis( sleepFor ); // Sleep a longer amount of time every once and awhile int sleepLong = rand() % 50; if( sleepLong == 0 ) sleepsecs( 2 ); #endif return true; }
bool handlePossibleShardedMessage( Message &m, DbResponse &dbresponse ){ if ( shardConfigServer.empty() ){ return false; } int op = m.data->operation(); if ( op < 2000 || op >= 3000 ) return false; const char *ns = m.data->_data + 4; string errmsg; if ( shardVersionOk( ns , errmsg ) ){ return false; } log() << "shardVersionOk failed ns:" << ns << " " << errmsg << endl; if ( doesOpGetAResponse( op ) ){ BufBuilder b( 32768 ); b.skip( sizeof( QueryResult ) ); { BSONObj obj = BSON( "$err" << errmsg ); b.append( obj.objdata() , obj.objsize() ); } QueryResult *qr = (QueryResult*)b.buf(); qr->_resultFlags() = QueryResult::ResultFlag_ErrSet | QueryResult::ResultFlag_ShardConfigStale; qr->len = b.len(); qr->setOperation( opReply ); qr->cursorId = 0; qr->startingFrom = 0; qr->nReturned = 1; b.decouple(); Message * resp = new Message(); resp->setData( qr , true ); dbresponse.response = resp; dbresponse.responseTo = m.data->id; return true; } OID * clientID = clientServerIds.get(); massert( 10422 , "write with bad shard config and no server id!" , clientID ); log() << "got write with an old config - writing back" << endl; BSONObjBuilder b; b.appendBool( "writeBack" , true ); b.append( "ns" , ns ); b.appendBinData( "msg" , m.data->len , bdtCustom , (char*)(m.data) ); log() << "writing back msg with len: " << m.data->len << " op: " << m.data->_operation << endl; clientQueues[clientID->str()]->push( b.obj() ); return true; }
bool run(const char *cmdns, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool){ BSONElement e = cmdObj.firstElement(); if ( e.type() != jstOID ){ errmsg = "need oid as first value"; return 0; } const OID id = e.__oid(); if ( ! clientQueues[id.str()] ) clientQueues[id.str()] = new BlockingQueue<BSONObj>(); BSONObj z = clientQueues[id.str()]->blockingPop(); log(1) << "WriteBackCommand got : " << z << endl; result.append( "data" , z ); return true; }
void testoid() { OID id; id.init(); // sleepsecs(3); OID b; // goes with sleep above... // b.init(); // assert( memcmp(id.getData(), b.getData(), 12) < 0 ); b.init( id.str() ); assert( b == id ); }
bool run(const string& , BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool){ BSONElement e = cmdObj.firstElement(); if ( e.type() != jstOID ){ errmsg = "need oid as first value"; return 0; } const OID id = e.__oid(); BSONObj z = getWritebackQueue(id.str())->blockingPop(); log(1) << "WriteBackCommand got : " << z << endl; result.append( "data" , z ); return true; }
JSBool object_id_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){ Convertor c( cx ); OID oid; if ( argc == 0 ){ oid.init(); } else { uassert( "object_id_constructor can't take more than 1 param" , argc == 1 ); oid.init( c.toString( argv[0] ) ); } jsval v = c.toval( oid.str().c_str() ); assert( JS_SetProperty( cx , obj , "str" , &v ) ); return JS_TRUE; }
v8::Handle<v8::Value> objectIdInit( const v8::Arguments& args ){ v8::Handle<v8::Object> it = args.This(); if ( it->IsUndefined() || it == v8::Context::GetCurrent()->Global() ){ v8::Function * f = getObjectIdCons(); it = f->NewInstance(); } OID oid; if ( args.Length() == 0 ){ oid.init(); } else { string s = toSTLString( args[0] ); oid.init( s ); } it->Set( String::New( "str" ) , String::New( oid.str().c_str() ) ); return it; }
bool run(const string& , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) { cc().curop()->suppressFromCurop(); cc().curop()->setExpectedLatencyMs( 30000 ); BSONElement e = cmdObj.firstElement(); if ( e.type() != jstOID ) { errmsg = "need oid as first value"; return 0; } // get the command issuer's (a mongos) serverID const OID id = e.__oid(); // the command issuer is blocked awaiting a response // we want to do return at least at every 5 minutes so sockets don't timeout BSONObj z; if ( writeBackManager.getWritebackQueue(id.str())->queue.blockingPop( z, 5 * 60 /* 5 minutes */ ) ) { LOG(1) << "WriteBackCommand got : " << z << endl; result.append( "data" , z ); } else { result.appendBool( "noop" , true ); } #ifdef _DEBUG PseudoRandom r(static_cast<int64_t>(time(0))); // Sleep a short amount of time usually int sleepFor = r.nextInt32( 10 ); sleepmillis( sleepFor ); // Sleep a longer amount of time every once and awhile int sleepLong = r.nextInt32( 50 ); if( sleepLong == 0 ) sleepsecs( 2 ); #endif return true; }
bool run(const string& , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) { BSONElement e = cmdObj.firstElement(); if ( e.type() != jstOID ) { errmsg = "need oid as first value"; return 0; } // get the command issuer's (a mongos) serverID const OID id = e.__oid(); // the command issuer is blocked awaiting a response // we want to do return at least at every 5 minutes so sockets don't timeout BSONObj z; if ( writeBackManager.getWritebackQueue(id.str())->queue.blockingPop( z, 5 * 60 /* 5 minutes */ ) ) { log(1) << "WriteBackCommand got : " << z << endl; result.append( "data" , z ); } else { result.appendBool( "noop" , true ); } return true; }
bool run(const char *cmdns, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool){ string configdb = cmdObj["configdb"].valuestrsafe(); { // configdb checking if ( configdb.size() == 0 ){ errmsg = "no configdb"; return false; } if ( shardConfigServer.size() == 0 ){ if ( ! cmdObj.getBoolField( "authoritative" ) ){ result.appendBool( "need_authoritative" , true ); errmsg = "first setShardVersion"; return false; } shardConfigServer = configdb; } else if ( shardConfigServer != configdb ){ errmsg = "specified a different configdb!"; return false; } } { // setting up ids if ( cmdObj["serverID"].type() != jstOID ){ // TODO: fix this //errmsg = "need serverID to be an OID"; //return 0; } else { OID clientId = cmdObj["serverID"].__oid(); if ( ! clientServerIds.get() ){ string s = clientId.str(); OID * nid = new OID(); nid->init( s ); clientServerIds.reset( nid ); if ( ! clientQueues[s] ) clientQueues[s] = new BlockingQueue<BSONObj>(); } else if ( clientId != *clientServerIds.get() ){ errmsg = "server id has changed!"; return 0; } } } unsigned long long version = getVersion( cmdObj["version"] , errmsg ); if ( ! version ) return false; NSVersions * versions = clientShardVersions.get(); if ( ! versions ){ log(1) << "entering shard mode for connection" << endl; versions = new NSVersions(); clientShardVersions.reset( versions ); } string ns = cmdObj["setShardVersion"].valuestrsafe(); if ( ns.size() == 0 ){ errmsg = "need to speciy fully namespace"; return false; } unsigned long long& oldVersion = (*versions)[ns]; if ( version < oldVersion ){ errmsg = "you already have a newer version"; result.appendTimestamp( "oldVersion" , oldVersion ); result.appendTimestamp( "newVersion" , version ); return false; } unsigned long long& myVersion = myVersions[ns]; if ( version < myVersion ){ errmsg = "going to older version for global"; return false; } if ( myVersion == 0 && ! cmdObj.getBoolField( "authoritative" ) ){ // need authoritative for first look result.appendBool( "need_authoritative" , true ); result.append( "ns" , ns ); errmsg = "first time for this ns"; return false; } result.appendTimestamp( "oldVersion" , oldVersion ); oldVersion = version; myVersion = version; result.append( "ok" , 1 ); return 1; }
Local< v8::Value > newId( const OID &id ) { v8::Function * idCons = getObjectIdCons(); v8::Handle<v8::Value> argv[1]; argv[0] = v8::String::New( id.str().c_str() ); return idCons->NewInstance( 1 , argv ); }
/* **************************************************************************** * * mongoSubscribeContext - */ HttpStatusCode mongoSubscribeContext(SubscribeContextRequest* requestP, SubscribeContextResponse* responseP, Format inFormat) { /* Take semaphore. The LM_S* family of macros combines semaphore release with return */ semTake(); LM_T(LmtMongo, ("Subscribe Context Request")); DBClientConnection* connection = getMongoConnection(); /* If expiration is not present, then use a default one */ if (requestP->duration.isEmpty()) { requestP->duration.set(DEFAULT_DURATION); } /* Calculate expiration (using the current time and the duration field in the request) */ long long expiration = getCurrentTime() + requestP->duration.parse(); LM_T(LmtMongo, ("Subscription expiration: %lu", expiration)); /* Create the mongoDB subscription document */ BSONObjBuilder sub; OID oid; oid.init(); sub.append("_id", oid); sub.append(CSUB_EXPIRATION, expiration); sub.append(CSUB_REFERENCE, requestP->reference.get()); /* Throttling */ if (!requestP->throttling.isEmpty()) { sub.append(CSUB_THROTTLING, requestP->throttling.parse()); } /* Build entities array */ BSONArrayBuilder entities; for (unsigned int ix = 0; ix < requestP->entityIdVector.size(); ++ix) { EntityId* en = requestP->entityIdVector.get(ix); entities.append(BSON(CSUB_ENTITY_ID << en->id << CSUB_ENTITY_TYPE << en->type << CSUB_ENTITY_ISPATTERN << en->isPattern)); } sub.append(CSUB_ENTITIES, entities.arr()); /* Build attributes array */ BSONArrayBuilder attrs; for (unsigned int ix = 0; ix < requestP->attributeList.size(); ++ix) { attrs.append(requestP->attributeList.get(ix)); } sub.append(CSUB_ATTRS, attrs.arr()); /* Build conditions array (including side-effect notifications and threads creation) */ bool notificationDone = false; BSONArray conds = processConditionVector(&requestP->notifyConditionVector, requestP->entityIdVector, requestP->attributeList, oid.str(), requestP->reference.get(), ¬ificationDone, inFormat); sub.append(CSUB_CONDITIONS, conds); if (notificationDone) { sub.append(CSUB_LASTNOTIFICATION, getCurrentTime()); sub.append(CSUB_COUNT, 1); } /* Adding format to use in notifications */ sub.append(CSUB_FORMAT, std::string(formatToString(inFormat))); /* Insert document in database */ BSONObj subDoc = sub.obj(); try { LM_T(LmtMongo, ("insert() in '%s' collection: '%s'", getSubscribeContextCollectionName(), subDoc.toString().c_str())); connection->insert(getSubscribeContextCollectionName(), subDoc); } catch( const DBException &e ) { responseP->subscribeError.errorCode.fill(SccReceiverInternalError, std::string("collection: ") + getSubscribeContextCollectionName() + " - insert(): " + subDoc.toString() + " - exception: " + e.what()); LM_SRE(SccOk,("Database error '%s'", responseP->subscribeError.errorCode.reasonPhrase.c_str())); } /* Fill the response element */ responseP->subscribeResponse.duration = requestP->duration; responseP->subscribeResponse.subscriptionId.set(oid.str()); responseP->subscribeResponse.throttling = requestP->throttling; LM_SR(SccOk); }
jsval toval( const BSONElement& e ) { switch( e.type() ) { case EOO: case jstNULL: case Undefined: return JSVAL_NULL; case NumberDouble: case NumberInt: return toval( e.number() ); case Symbol: // TODO: should we make a special class for this case String: return toval( e.valuestr() ); case Bool: return e.boolean() ? JSVAL_TRUE : JSVAL_FALSE; case Object: { BSONObj embed = e.embeddedObject().getOwned(); return toval( &embed ); } case Array: { BSONObj embed = e.embeddedObject().getOwned(); if ( embed.isEmpty() ) { return OBJECT_TO_JSVAL( JS_NewArrayObject( _context , 0 , 0 ) ); } int n = embed.nFields(); JSObject * array = JS_NewArrayObject( _context , n , 0 ); assert( array ); jsval myarray = OBJECT_TO_JSVAL( array ); for ( int i=0; i<n; i++ ) { jsval v = toval( embed[i] ); assert( JS_SetElement( _context , array , i , &v ) ); } return myarray; } case jstOID: { OID oid = e.__oid(); JSObject * o = JS_NewObject( _context , &object_id_class , 0 , 0 ); setProperty( o , "str" , toval( oid.str().c_str() ) ); return OBJECT_TO_JSVAL( o ); } case RegEx: { const char * flags = e.regexFlags(); uintN flagNumber = 0; while ( *flags ) { switch ( *flags ) { case 'g': flagNumber |= JSREG_GLOB; break; case 'i': flagNumber |= JSREG_FOLD; break; case 'm': flagNumber |= JSREG_MULTILINE; break; //case 'y': flagNumber |= JSREG_STICKY; break; default: log() << "warning: unknown regex flag:" << *flags << endl; } flags++; } JSObject * r = JS_NewRegExpObject( _context , (char*)e.regex() , strlen( e.regex() ) , flagNumber ); assert( r ); return OBJECT_TO_JSVAL( r ); } case Code: { JSFunction * func = compileFunction( e.valuestr() ); return OBJECT_TO_JSVAL( JS_GetFunctionObject( func ) ); } case CodeWScope: { JSFunction * func = compileFunction( e.codeWScopeCode() ); BSONObj extraScope = e.codeWScopeObject(); if ( ! extraScope.isEmpty() ) { log() << "warning: CodeWScope doesn't transfer to db.eval" << endl; } return OBJECT_TO_JSVAL( JS_GetFunctionObject( func ) ); } case Date: return OBJECT_TO_JSVAL( js_NewDateObjectMsec( _context , (jsdouble) e.date().millis ) ); case MinKey: return OBJECT_TO_JSVAL( JS_NewObject( _context , &minkey_class , 0 , 0 ) ); case MaxKey: return OBJECT_TO_JSVAL( JS_NewObject( _context , &maxkey_class , 0 , 0 ) ); case Timestamp: { JSObject * o = JS_NewObject( _context , ×tamp_class , 0 , 0 ); setProperty( o , "t" , toval( (double)(e.timestampTime()) ) ); setProperty( o , "i" , toval( (double)(e.timestampInc()) ) ); return OBJECT_TO_JSVAL( o ); } case NumberLong: { boost::uint64_t val = (boost::uint64_t)e.numberLong(); JSObject * o = JS_NewObject( _context , &numberlong_class , 0 , 0 ); setProperty( o , "floatApprox" , toval( (double)(boost::int64_t)( val ) ) ); if ( (boost::int64_t)val != (boost::int64_t)(double)(boost::int64_t)( val ) ) { // using 2 doubles here instead of a single double because certain double // bit patterns represent undefined values and sm might trash them setProperty( o , "top" , toval( (double)(boost::uint32_t)( val >> 32 ) ) ); setProperty( o , "bottom" , toval( (double)(boost::uint32_t)( val & 0x00000000ffffffff ) ) ); } return OBJECT_TO_JSVAL( o ); } case DBRef: { JSObject * o = JS_NewObject( _context , &dbpointer_class , 0 , 0 ); setProperty( o , "ns" , toval( e.dbrefNS() ) ); JSObject * oid = JS_NewObject( _context , &object_id_class , 0 , 0 ); setProperty( oid , "str" , toval( e.dbrefOID().str().c_str() ) ); setProperty( o , "id" , OBJECT_TO_JSVAL( oid ) ); return OBJECT_TO_JSVAL( o ); } case BinData: { JSObject * o = JS_NewObject( _context , &bindata_class , 0 , 0 ); int len; const char * data = e.binData( len ); assert( JS_SetPrivate( _context , o , new BinDataHolder( data ) ) ); setProperty( o , "len" , toval( len ) ); setProperty( o , "type" , toval( (int)e.binDataType() ) ); return OBJECT_TO_JSVAL( o ); } }