Ejemplo n.º 1
0
 BSONObj DBClientWithCommands::mapreduce(const string &ns, const string &jsmapf, const string &jsreducef, BSONObj query, MROutput output) {
     BSONObjBuilder b;
     b.append("mapreduce", nsGetCollection(ns));
     b.appendCode("map", jsmapf);
     b.appendCode("reduce", jsreducef);
     if( !query.isEmpty() )
         b.append("query", query);
     b.append("out", output.out);
     BSONObj info;
     runCommand(nsGetDB(ns), b.done(), info);
     return info;
 }
Ejemplo n.º 2
0
        void run(){
            Scope * s = globalScriptEngine->createScope();
            
            {
                BSONObjBuilder b;
                b.append( "a" , 1 );
                b.appendCode( "b" , "function(){ out.b = 11; }" );
                b.appendCodeWScope( "c" , "function(){ out.c = 12; }" , BSONObj() );
                b.appendCodeWScope( "d" , "function(){ out.d = 13 + bleh; }" , BSON( "bleh" << 5 ) );
                s->setObject( "foo" , b.obj() );
            }
            
            s->invokeSafe( "out = {}; out.a = foo.a; foo.b(); foo.c();" , BSONObj() );
            BSONObj out = s->getObject( "out" );
            
            ASSERT_EQUALS( 1 , out["a"].number() );
            ASSERT_EQUALS( 11 , out["b"].number() );
            ASSERT_EQUALS( 12 , out["c"].number() );

            //s->invokeSafe( "foo.d() " , BSONObj() );
            //out = s->getObject( "out" );
            //ASSERT_EQUALS( 18 , out["d"].number() );
            

            delete s;
        }
Ejemplo n.º 3
0
    void append( BSONObjBuilder& b , string name , jsval val , BSONType oldType = EOO , int depth=0 ) {
        //cout << "name: " << name << "\t" << typeString( val ) << " oldType: " << oldType << endl;
        switch ( JS_TypeOfValue( _context , val ) ) {

        case JSTYPE_VOID:
            b.appendUndefined( name.c_str() );
            break;
        case JSTYPE_NULL:
            b.appendNull( name.c_str() );
            break;

        case JSTYPE_NUMBER: {
            double d = toNumber( val );
            if ( oldType == NumberInt && ((int)d) == d )
                b.append( name.c_str() , (int)d );
            else
                b.append( name.c_str() , d );
            break;
        }
        case JSTYPE_STRING:
            b.append( name.c_str() , toString( val ) );
            break;
        case JSTYPE_BOOLEAN:
            b.appendBool( name.c_str() , toBoolean( val ) );
            break;

        case JSTYPE_OBJECT: {
            JSObject * o = JSVAL_TO_OBJECT( val );
            if ( ! o || o == JSVAL_NULL ) {
                b.appendNull( name.c_str() );
            }
            else if ( ! appendSpecialDBObject( this , b , name , val , o ) ) {
                BSONObj sub = toObject( o , depth );
                if ( JS_IsArrayObject( _context , o ) ) {
                    b.appendArray( name.c_str() , sub );
                }
                else {
                    b.append( name.c_str() , sub );
                }
            }
            break;
        }

        case JSTYPE_FUNCTION: {
            string s = toString(val);
            if ( s[0] == '/' ) {
                appendRegex( b , name , s );
            }
            else {
                b.appendCode( name.c_str() , getFunctionCode( val ).c_str() );
            }
            break;
        }

        default:
            uassert( 10217 ,  (string)"can't append field.  name:" + name + " type: " + typeString( val ) , 0 );
        }
    }
Ejemplo n.º 4
0
 bool DBClientWithCommands::eval(const string &dbname, const string &jscode, BSONObj& info, BSONElement& retValue, BSONObj *args) {
     BSONObjBuilder b;
     b.appendCode("$eval", jscode.c_str());
     if ( args )
         b.appendArray("args", *args);
     bool ok = runCommand(dbname, b.done(), info);
     if ( ok )
         retValue = info.getField("retval");
     return ok;
 }
Ejemplo n.º 5
0
 void Scope::append( BSONObjBuilder & builder , const char * fieldName , const char * scopeName ){
     int t = type( scopeName );
     
     switch ( t ){
     case Object:
         builder.append( fieldName , getObject( scopeName ) );
         break;
     case Array:
         builder.appendArray( fieldName , getObject( scopeName ) );
         break;
     case NumberDouble:
         builder.append( fieldName , getNumber( scopeName ) );
         break;
     case NumberInt:
         builder.append( fieldName , getNumberInt( scopeName ) );
         break;
     case NumberLong:
         builder.append( fieldName , getNumberLongLong( scopeName ) );
         break;
     case String:
         builder.append( fieldName , getString( scopeName ).c_str() );
         break;
     case Bool:
         builder.appendBool( fieldName , getBoolean( scopeName ) );
         break;
     case jstNULL:
     case Undefined:
         builder.appendNull( fieldName );
         break;
     case Date:
         // TODO: make signed
         builder.appendDate( fieldName , Date_t((unsigned long long)getNumber( scopeName )) );
         break;
     case Code:
         builder.appendCode( fieldName , getString( scopeName ) );
         break;
     default:
         stringstream temp;
         temp << "can't append type from:";
         temp << t;
         uassert( 10206 ,  temp.str() , 0 );
     }
     
 }
Ejemplo n.º 6
0
void Scope::append(BSONObjBuilder& builder, const char* fieldName, const char* scopeName) {
    int t = type(scopeName);
    switch (t) {
    case Object:
        builder.append(fieldName, getObject(scopeName));
        break;
    case Array:
        builder.appendArray(fieldName, getObject(scopeName));
        break;
    case NumberDouble:
        builder.append(fieldName, getNumber(scopeName));
        break;
    case NumberInt:
        builder.append(fieldName, getNumberInt(scopeName));
        break;
    case NumberLong:
        builder.append(fieldName, getNumberLongLong(scopeName));
        break;
    case NumberDecimal:
        builder.append(fieldName, getNumberDecimal(scopeName));
        break;
    case String:
        builder.append(fieldName, getString(scopeName));
        break;
    case Bool:
        builder.appendBool(fieldName, getBoolean(scopeName));
        break;
    case jstNULL:
    case Undefined:
        builder.appendNull(fieldName);
        break;
    case Date:
        builder.appendDate(
            fieldName,
            Date_t::fromMillisSinceEpoch(static_cast<long long>(getNumber(scopeName))));
        break;
    case Code:
        builder.appendCode(fieldName, getString(scopeName));
        break;
    default:
        uassert(10206, str::stream() << "can't append type from: " << t, 0);
    }
}
Ejemplo n.º 7
0
void v8ToMongoElement( BSONObjBuilder & b , v8::Handle<v8::String> name , const string sname , v8::Handle<v8::Value> value ){
        
    if ( value->IsString() ){
        if ( sname == "$where" )
            b.appendCode( sname.c_str() , toSTLString( value ).c_str() );
        else
            b.append( sname.c_str() , toSTLString( value ).c_str() );
        return;
    }
        
    if ( value->IsFunction() ){
        b.appendCode( sname.c_str() , toSTLString( value ).c_str() );
        return;
    }
    
    if ( value->IsNumber() ){
        b.append( sname.c_str() , value->ToNumber()->Value() );
        return;
    }
    
    if ( value->IsArray() ){
        BSONObj sub = v8ToMongo( value->ToObject() );
        b.appendArray( sname.c_str() , sub );
        return;
    }
    
    if ( value->IsDate() ){
        b.appendDate( sname.c_str() , (unsigned long long )(v8::Date::Cast( *value )->NumberValue()) );
        return;
    }
    
    if ( value->IsObject() ){
        string s = toSTLString( value );
        if ( s.size() && s[0] == '/' ){
            s = s.substr( 1 );
            string r = s.substr( 0 , s.find( "/" ) );
            string o = s.substr( s.find( "/" ) + 1 );
            b.appendRegex( sname.c_str() , r.c_str() , o.c_str() );
        }
        else if ( value->ToObject()->GetPrototype()->IsObject() &&
                  value->ToObject()->GetPrototype()->ToObject()->HasRealNamedProperty( String::New( "isObjectId" ) ) ){
            OID oid;
            oid.init( toSTLString( value ) );
            b.appendOID( sname.c_str() , &oid );
        }
        else {
            BSONObj sub = v8ToMongo( value->ToObject() );
            b.append( sname.c_str() , sub );
        }
        return;
    }
    
    if ( value->IsBoolean() ){
        b.appendBool( sname.c_str() , value->ToBoolean()->Value() );
        return;
    }
    
    else if ( value->IsUndefined() ){
        return;
    }
    
    else if ( value->IsNull() ){
        b.appendNull( sname.c_str() );
        return;
    }

    cout << "don't know how to covert to mongo field [" << name << "]\t" << value << endl;
}
/* ****************************************************************************
*
* addTriggeredSubscriptions -
*/
static bool addTriggeredSubscriptions
(
  ContextRegistration                   cr,
  map<string, TriggeredSubscription*>&  subs,
  std::string&                          err,
  std::string                           tenant
)
{

  BSONArrayBuilder          entitiesNoPatternA;
  std::vector<std::string>  idJsV;
  std::vector<std::string>  typeJsV;

  for (unsigned int ix = 0; ix < cr.entityIdVector.size(); ++ix)
  {
    // FIXME: take into account subscriptions with no type
    EntityId* enP = cr.entityIdVector[ix];

    // The registration of isPattern=true entities is not supported, so we don't include them here
    if (enP->isPattern == "false")
    {
      entitiesNoPatternA.append(BSON(CASUB_ENTITY_ID << enP->id <<
                                     CASUB_ENTITY_TYPE << enP->type <<
                                     CASUB_ENTITY_ISPATTERN << "false"));
      idJsV.push_back(enP->id);
      typeJsV.push_back(enP->type);
    }
  }

  BSONArrayBuilder attrA;
  for (unsigned int ix = 0; ix < cr.contextRegistrationAttributeVector.size(); ++ix)
  {
    ContextRegistrationAttribute* craP = cr.contextRegistrationAttributeVector[ix];
    attrA.append(craP->name);
  }

  BSONObjBuilder queryNoPattern;
  queryNoPattern.append(CASUB_ENTITIES, BSON("$in" << entitiesNoPatternA.arr()));
  if (attrA.arrSize() > 0)
  {
    // If we don't do this checking, the {$in: [] } in the attribute name part will
    // make the query fail
    //

    // queryB.append(CASUB_ATTRS, BSON("$in" << attrA.arr()));
    queryNoPattern.append("$or", BSON_ARRAY(
                            BSON(CASUB_ATTRS << BSON("$in" << attrA.arr())) <<
                            BSON(CASUB_ATTRS << BSON("$size" << 0))));
  }
  else
  {
    queryNoPattern.append(CASUB_ATTRS, BSON("$size" << 0));
  }
  queryNoPattern.append(CASUB_EXPIRATION, BSON("$gt" << (long long) getCurrentTime()));


  //
  // This is JavaScript code that runs in MongoDB engine. As far as I know, this is the only
  // way to do a "reverse regex" query in MongoDB (see
  // http://stackoverflow.com/questions/15966991/mongodb-reverse-regex/15989520).
  // Note that although we are using a isPattern=true in the MongoDB query besides $where, we
  // also need to check that in the if statement in the JavaScript function given that a given
  // sub document could include both isPattern=true and isPattern=false documents
  //
  std::string idJsString = "[ ";

  for (unsigned int ix = 0; ix < idJsV.size(); ++ix)
  {
    if (ix != idJsV.size() - 1)
    {
      idJsString += "\""+idJsV[ix]+ "\" ,";
    }
    else
    {
      idJsString += "\"" +idJsV[ix]+ "\"";
    }
  }
  idJsString += " ]";

  std::string typeJsString = "[ ";

  for (unsigned int ix = 0; ix < typeJsV.size(); ++ix)
  {
    if (ix != typeJsV.size() - 1)
    {
      typeJsString += "\"" +typeJsV[ix] + "\" ,";
    }
    else
    {
      typeJsString += "\"" + typeJsV[ix] + "\"";
    }
  }
  typeJsString += " ]";

  std::string function = std::string("function()") +
    "{" +
      "enId = " + idJsString + ";" +
      "enType = " + typeJsString + ";" +
      "for (var i=0; i < this." + CASUB_ENTITIES + ".length; i++) {" +
        "if (this." + CASUB_ENTITIES + "[i]." + CASUB_ENTITY_ISPATTERN + " == \"true\") {" +
          "for (var j = 0; j < enId.length; j++) {" +
            "if (enId[j].match(this." + CASUB_ENTITIES + "[i]." + CASUB_ENTITY_ID +
              ") && this." + CASUB_ENTITIES + "[i]." + CASUB_ENTITY_TYPE + " == enType[j]) {" +
              "return true; " +
            "}" +
          "}" +
        "}" +
      "}" +
      "return false; " +
    "}";
  LM_T(LmtMongo, ("JS function: %s", function.c_str()));


  std::string     entPatternQ = CSUB_ENTITIES "." CSUB_ENTITY_ISPATTERN;
  BSONObjBuilder  queryPattern;

  queryPattern.append(entPatternQ, "true");
  queryPattern.append(CASUB_EXPIRATION, BSON("$gt" << (long long) getCurrentTime()));
  queryPattern.appendCode("$where", function);

  auto_ptr<DBClientCursor> cursor;
  BSONObj                  query = BSON("$or" << BSON_ARRAY(queryNoPattern.obj() << queryPattern.obj()));

  TIME_STAT_MONGO_READ_WAIT_START();
  DBClientBase* connection = getMongoConnection();
  if (!collectionQuery(connection, getSubscribeContextAvailabilityCollectionName(tenant), query, &cursor, &err))
  {
    TIME_STAT_MONGO_READ_WAIT_STOP();
    releaseMongoConnection(connection);
    return false;
  }
  TIME_STAT_MONGO_READ_WAIT_STOP();

  /* For each one of the subscriptions found, add it to the map (if not already there) */
  while (moreSafe(cursor))
  {
    BSONObj     sub;
    std::string err;
    if (!nextSafeOrErrorF(cursor, &sub, &err))
    {
      LM_E(("Runtime Error (exception in nextSafe(): %s - query: %s)", err.c_str(), query.toString().c_str()));
      continue;
    }
    BSONElement idField = getFieldF(sub, "_id");

    //
    // BSONElement::eoo returns true if 'not found', i.e. the field "_id" doesn't exist in 'sub'
    //
    // Now, if 'getFieldF(sub, "_id")' is not found, if we continue, calling OID() on it, then we get
    // an exception and the broker crashes.
    //
    if (idField.eoo() == true)
    {
      std::string details = std::string("error retrieving _id field in doc: '") + sub.toString() + "'";
      alarmMgr.dbError(details);
      continue;
    }
    alarmMgr.dbErrorReset();

    std::string subIdStr = idField.OID().toString();

    if (subs.count(subIdStr) == 0)
    {
      LM_T(LmtMongo, ("adding subscription: '%s'", sub.toString().c_str()));

      //
      // FIXME P4: Once ctx availability notification formats get defined for NGSIv2,
      //           the first parameter for TriggeredSubscription will have "normalized" as default value
      //
      TriggeredSubscription* trigs = new TriggeredSubscription(
        sub.hasField(CASUB_FORMAT)? stringToRenderFormat(getStringFieldF(sub, CASUB_FORMAT)) : NGSI_V1_LEGACY,
        getStringFieldF(sub, CASUB_REFERENCE),
        subToAttributeList(sub));

      subs.insert(std::pair<string, TriggeredSubscription*>(subIdStr, trigs));
    }
  }
  releaseMongoConnection(connection);

  return true;
}
Ejemplo n.º 9
0
    void v8ToMongoElement( BSONObjBuilder & b , v8::Handle<v8::String> name , const string sname , v8::Handle<v8::Value> value ){
        
        if ( value->IsString() ){
            b.append( sname.c_str() , toSTLString( value ).c_str() );
            return;
        }
        
        if ( value->IsFunction() ){
            b.appendCode( sname.c_str() , toSTLString( value ).c_str() );
            return;
        }
    
        if ( value->IsNumber() ){
            if ( value->IsInt32() )
                b.append( sname.c_str(), int( value->ToInt32()->Value() ) );
            else
                b.append( sname.c_str() , value->ToNumber()->Value() );
            return;
        }
    
        if ( value->IsArray() ){
            BSONObj sub = v8ToMongo( value->ToObject() );
            b.appendArray( sname.c_str() , sub );
            return;
        }
    
        if ( value->IsDate() ){
            b.appendDate( sname.c_str() , Date_t(v8::Date::Cast( *value )->NumberValue()) );
            return;
        }

        if ( value->IsExternal() )
            return;
        
        if ( value->IsObject() ){
            // The user could potentially modify the fields of these special objects,
            // wreaking havoc when we attempt to reinterpret them.  Not doing any validation
            // for now...
            Local< v8::Object > obj = value->ToObject();
            if ( obj->InternalFieldCount() && obj->GetInternalField( 0 )->IsNumber() ) {
                switch( obj->GetInternalField( 0 )->ToInt32()->Value() ) { // NOTE Uint32's Value() gave me a linking error, so going with this instead
                    case Timestamp:
                        b.appendTimestamp( sname.c_str(),
                                          Date_t( v8::Date::Cast( *obj->Get( v8::String::New( "time" ) ) )->NumberValue() ),
                                          obj->Get( v8::String::New( "i" ) )->ToInt32()->Value() );
                        return;
                    case MinKey:
                        b.appendMinKey( sname.c_str() );
                        return;
                    case MaxKey:
                        b.appendMaxKey( sname.c_str() );
                        return;
                    default:
                        assert( "invalid internal field" == 0 );
                }
            }
            string s = toSTLString( value );
            if ( s.size() && s[0] == '/' ){
                s = s.substr( 1 );
                string r = s.substr( 0 , s.rfind( "/" ) );
                string o = s.substr( s.rfind( "/" ) + 1 );
                b.appendRegex( sname.c_str() , r.c_str() , o.c_str() );
            }
            else if ( value->ToObject()->GetPrototype()->IsObject() &&
                      value->ToObject()->GetPrototype()->ToObject()->HasRealNamedProperty( v8::String::New( "isObjectId" ) ) ){
                OID oid;
                oid.init( toSTLString( value ) );
                b.appendOID( sname.c_str() , &oid );
            }
            else if ( !value->ToObject()->GetHiddenValue( v8::String::New( "__NumberLong" ) ).IsEmpty() ) {
                // TODO might be nice to potentially speed this up with an indexed internal
                // field, but I don't yet know how to use an ObjectTemplate with a
                // constructor.
                unsigned long long val =
                ( (unsigned long long)( value->ToObject()->Get( v8::String::New( "top" ) )->ToInt32()->Value() ) << 32 ) +
                (unsigned)( value->ToObject()->Get( v8::String::New( "bottom" ) )->ToInt32()->Value() );
                b.append( sname.c_str(), (long long)val );
            }
            else if ( !value->ToObject()->GetHiddenValue( v8::String::New( "__DBPointer" ) ).IsEmpty() ) {
                OID oid;
                oid.init( toSTLString( value->ToObject()->Get( v8::String::New( "id" ) ) ) );
                string ns = toSTLString( value->ToObject()->Get( v8::String::New( "ns" ) ) );
                b.appendDBRef( sname.c_str(), ns.c_str(), oid );                
            }
            else if ( !value->ToObject()->GetHiddenValue( v8::String::New( "__BinData" ) ).IsEmpty() ) {
                int len = obj->Get( v8::String::New( "len" ) )->ToInt32()->Value();
                v8::String::Utf8Value data( obj->Get( v8::String::New( "data" ) ) );
                const char *dataArray = *data;
                assert( data.length() == len );
                b.appendBinData( sname.c_str(),
                                len,
                                mongo::BinDataType( obj->Get( v8::String::New( "type" ) )->ToInt32()->Value() ),
                                dataArray );
            } else {
                BSONObj sub = v8ToMongo( value->ToObject() );
                b.append( sname.c_str() , sub );
            }
            return;
        }
    
        if ( value->IsBoolean() ){
            b.appendBool( sname.c_str() , value->ToBoolean()->Value() );
            return;
        }
    
        else if ( value->IsUndefined() ){
            b.appendUndefined( sname.c_str() );
            return;
        }
    
        else if ( value->IsNull() ){
            b.appendNull( sname.c_str() );
            return;
        }

        cout << "don't know how to convert to mongo field [" << name << "]\t" << value << endl;
    }
Ejemplo n.º 10
0
/* ****************************************************************************
*
* addTriggeredSubscriptions
*
*/
static bool addTriggeredSubscriptions(ContextRegistration                  cr,
                                      map<string, TriggeredSubscription*>& subs,
                                      std::string&                         err,
                                      std::string                          tenant)
{
    DBClientBase* connection = NULL;

    BSONArrayBuilder entitiesNoPatternA;
    std::vector<std::string> idJsV;
    std::vector<std::string> typeJsV;

    for (unsigned int ix = 0; ix < cr.entityIdVector.size(); ++ix ) {
        //FIXME: take into account subscriptions with no type
        EntityId* enP = cr.entityIdVector.get(ix);
        /* The registration of isPattern=true entities is not supported, so we don't include them here */
        if (enP->isPattern == "false") {
            entitiesNoPatternA.append(BSON(CASUB_ENTITY_ID << enP->id << CASUB_ENTITY_TYPE << enP->type << CASUB_ENTITY_ISPATTERN << "false"));
            idJsV.push_back(enP->id);
            typeJsV.push_back(enP->type);
        }
    }
    BSONArrayBuilder attrA;
    for (unsigned int ix = 0; ix < cr.contextRegistrationAttributeVector.size(); ++ix) {
        ContextRegistrationAttribute* craP = cr.contextRegistrationAttributeVector.get(ix);
        attrA.append(craP->name);
    }

    BSONObjBuilder queryNoPattern;
    queryNoPattern.append(CASUB_ENTITIES, BSON("$in" << entitiesNoPatternA.arr()));
    if (attrA.arrSize() > 0) {
        /* If we don't do this checking, the {$in: [] } in the attribute name part will
         * make the query fail*/
        //queryB.append(CASUB_ATTRS, BSON("$in" << attrA.arr()));
        queryNoPattern.append("$or", BSON_ARRAY(
                          BSON(CASUB_ATTRS << BSON("$in" << attrA.arr())) <<
                          BSON(CASUB_ATTRS << BSON("$size" << 0))
                          ));
    }
    else {
        queryNoPattern.append(CASUB_ATTRS, BSON("$size" << 0));
    }
    queryNoPattern.append(CASUB_EXPIRATION, BSON("$gt" << (long long) getCurrentTime()));

    /* This is JavaScript code that runs in MongoDB engine. As far as I know, this is the only
     * way to do a "reverse regex" query in MongoDB (see
     * http://stackoverflow.com/questions/15966991/mongodb-reverse-regex/15989520).
     * Note that although we are using a isPattern=true in the MongoDB query besides $where, we
     * also need to check that in the if statement in the JavaScript function given that a given
     * sub document could include both isPattern=true and isPattern=false documents */
    std::string idJsString = "[ ";
    for (unsigned int ix = 0; ix < idJsV.size(); ++ix ) {
        if (ix != idJsV.size()-1) {
            idJsString += "\""+idJsV[ix]+ "\" ,";
        }
        else {
            idJsString += "\"" +idJsV[ix]+ "\"";
        }
    }
    idJsString += " ]";

    std::string typeJsString = "[ ";
    for (unsigned int ix = 0; ix < typeJsV.size(); ++ix ) {
        if (ix != typeJsV.size()-1) {
            typeJsString += "\"" +typeJsV[ix] + "\" ,";
        }
        else {
            typeJsString += "\"" + typeJsV[ix] + "\"";
        }
    }
    typeJsString += " ]";

    std::string function = std::string("function()") +
         "{" +
            "enId = "+idJsString+ ";" +
            "enType = "+typeJsString+ ";" +
            "for (var i=0; i < this."+CASUB_ENTITIES+".length; i++) {" +
                "if (this."+CASUB_ENTITIES+"[i]."+CASUB_ENTITY_ISPATTERN+" == \"true\") {" +
                    "for (var j=0; j < enId.length; j++) {" +
                       "if (enId[j].match(this."+CASUB_ENTITIES+"[i]."+CASUB_ENTITY_ID+") && this."+CASUB_ENTITIES+"[i]."+CASUB_ENTITY_TYPE+" == enType[j]) {" +
                          "return true; " +
                       "}" +
                    "}" +
                "}" +
            "}" +
            "return false; " +
         "}";
    LM_T(LmtMongo, ("JS function: %s", function.c_str()));

    std::string entPatternQ = CSUB_ENTITIES "." CSUB_ENTITY_ISPATTERN;

    BSONObjBuilder queryPattern;
    queryPattern.append(entPatternQ, "true");
    queryPattern.append(CASUB_EXPIRATION, BSON("$gt" << (long long) getCurrentTime()));
    queryPattern.appendCode("$where", function);

    BSONObj query = BSON("$or" << BSON_ARRAY(queryNoPattern.obj() << queryPattern.obj()));

    /* Do the query */
    auto_ptr<DBClientCursor> cursor;
    LM_T(LmtMongo, ("query() in '%s' collection: '%s'", getSubscribeContextAvailabilityCollectionName(tenant).c_str(), query.toString().c_str()));
    try
    {
        connection = getMongoConnection();
        cursor = connection->query(getSubscribeContextAvailabilityCollectionName(tenant).c_str(), query);

        /*
         * We have observed that in some cases of DB errors (e.g. the database daemon is down) instead of
         * raising an exception, the query() method sets the cursor to NULL. In this case, we raise the
         * exception ourselves
         */
        if (cursor.get() == NULL)
        {
            throw DBException("Null cursor from mongo (details on this is found in the source code)", 0);
        }

        releaseMongoConnection(connection);

        LM_I(("Database Operation Successful (%s)", query.toString().c_str()));
    }
    catch (const DBException &e)
    {
        releaseMongoConnection(connection);

        err = std::string("collection: ") + getSubscribeContextAvailabilityCollectionName(tenant).c_str() +
               " - query(): " + query.toString() +
               " - exception: " + e.what();
        LM_E(("Database Error (%s)", err.c_str()));

        return false;
    }
    catch (...)
    {
        releaseMongoConnection(connection);

        err = std::string("collection: ") + getSubscribeContextAvailabilityCollectionName(tenant).c_str() +
               " - query(): " + query.toString() +
               " - exception: " + "generic";
        LM_E(("Database Error (%s)", err.c_str()));
        return false;
    }

    /* For each one of the subscriptions found, add it to the map (if not already there) */
    while (cursor->more())
    {
        BSONObj     sub     = cursor->next();
        BSONElement idField = sub.getField("_id");

        //
        // BSONElement::eoo returns true if 'not found', i.e. the field "_id" doesn't exist in 'sub'
        //
        // Now, if 'sub.getField("_id")' is not found, if we continue, calling OID() on it, then we get
        // an exception and the broker crashes.
        //
        if (idField.eoo() == true)
        {
          LM_E(("Database Error (error retrieving _id field in doc: %s)", sub.toString().c_str()));
          continue;
        }

        std::string subIdStr = idField.OID().toString();

        if (subs.count(subIdStr) == 0) {
            LM_T(LmtMongo, ("adding subscription: '%s'", sub.toString().c_str()));

            TriggeredSubscription* trigs = new TriggeredSubscription(sub.hasField(CASUB_FORMAT) ? stringToFormat(STR_FIELD(sub, CASUB_FORMAT)) : XML,
                                                                     STR_FIELD(sub, CASUB_REFERENCE),
                                                                     subToAttributeList(sub));

            subs.insert(std::pair<string, TriggeredSubscription*>(subIdStr, trigs));
        }
    }

    return true;
}