Beispiel #1
0
 virtual bool run(const string& dbname, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
     string fromhost = cmdObj.getStringField("fromhost");
     if ( fromhost.empty() ) {
         /* copy from self */
         stringstream ss;
         ss << "localhost:" << cmdLine.port;
         fromhost = ss.str();
     }
     string fromdb = cmdObj.getStringField("fromdb");
     string todb = cmdObj.getStringField("todb");
     if ( fromhost.empty() || todb.empty() || fromdb.empty() ) {
         errmsg = "parms missing - {copydb: 1, fromhost: <hostname>, fromdb: <db>, todb: <db>}";
         return false;
     }
     Cloner c;
     string username = cmdObj.getStringField( "username" );
     string nonce = cmdObj.getStringField( "nonce" );
     string key = cmdObj.getStringField( "key" );
     if ( !username.empty() && !nonce.empty() && !key.empty() ) {
         uassert( 13008, "must call copydbgetnonce first", authConn_.get() );
         BSONObj ret;
         {
             dbtemprelease t;
             if ( !authConn_->runCommand( fromdb, BSON( "authenticate" << 1 << "user" << username << "nonce" << nonce << "key" << key ), ret ) ) {
                 errmsg = "unable to login " + string( ret );
                 return false;
             }
         }
         c.setConnection( authConn_.release() );
     }
     Client::Context ctx(todb);
     bool res = c.go(fromhost.c_str(), errmsg, fromdb, /*logForReplication=*/!fromRepl, /*slaveok*/false, /*replauth*/false, /*snapshot*/true);
     return res;
 }
        virtual bool run(OperationContext* txn,
                         const string&,
                         BSONObj& cmdObj,
                         int,
                         string& errmsg,
                         BSONObjBuilder& result) {

            string fromhost = cmdObj.getStringField("fromhost");
            if ( fromhost.empty() ) {
                /* copy from self */
                stringstream ss;
                ss << "localhost:" << serverGlobalParams.port;
                fromhost = ss.str();
            }

            const ConnectionString cs(uassertStatusOK(ConnectionString::parse(fromhost)));

            authConn_.reset(cs.connect(errmsg));
            if (!authConn_.get()) {
                return false;
            }

            BSONObj ret;

            if( !authConn_->runCommand( "admin", BSON( "getnonce" << 1 ), ret ) ) {
                errmsg = "couldn't get nonce " + ret.toString();
                return false;
            }

            result.appendElements( ret );
            return true;
        }
Beispiel #3
0
 static ClientConnections* threadInstance() {
     ClientConnections* cc = _perThread.get();
     if ( ! cc ) {
         cc = new ClientConnections();
         _perThread.reset( cc );
     }
     return cc;
 }
Beispiel #4
0
		disable_syscall_interruption() {
			if (_syscalls_interruptable.get() == NULL) {
				last_value = true;
				_syscalls_interruptable.reset(new bool(false));
			} else {
				last_value = *_syscalls_interruptable;
				*_syscalls_interruptable = false;
			}
		}
Beispiel #5
0
std::shared_ptr<CoreContext> CoreContext::CurrentContext(void) {
  if(!autoCurrentContext.get())
    return std::static_pointer_cast<CoreContext, GlobalCoreContext>(GetGlobalContext());

  std::shared_ptr<CoreContext>* retVal = autoCurrentContext.get();
  assert(retVal);
  assert(*retVal);
  return *retVal;
}
 ostream & operator()() {
     ThreadOutputStream * tos( threadOutputStream_.get() );
     if( tos == nullptr ) {
         tos = new ThreadOutputStream();
         threadOutputStream_.reset( tos );
     }
     return (*tos) << boost::posix_time::microsec_clock::universal_time() <<
             ' ' << format("%014s") % boost::this_thread::get_id() <<
             " [ " << format("%-20.20s") % name_ << " ] ";
 };
Beispiel #7
0
inline void worker(
    std::uint64_t updates
    )
{
    global_scratch.reset(new double);

    for (double i = 0.; i < updates; ++i)
        *global_scratch += 1. / (2. * i + 1.);

    global_scratch.reset();
}
        virtual bool run(OperationContext* txn,
                         const string&,
                         BSONObj& cmdObj,
                         int,
                         string& errmsg,
                         BSONObjBuilder& result) {

            const string fromDb = cmdObj.getStringField("fromdb");

            string fromHost = cmdObj.getStringField("fromhost");
            if ( fromHost.empty() ) {
                /* copy from self */
                stringstream ss;
                ss << "localhost:" << serverGlobalParams.port;
                fromHost = ss.str();
            }

            const ConnectionString cs(uassertStatusOK(ConnectionString::parse(fromHost)));

            BSONElement mechanismElement;
            Status status = bsonExtractField(cmdObj,
                                             saslCommandMechanismFieldName,
                                             &mechanismElement);
            if (!status.isOK()) {
                return appendCommandStatus(result, status);
            }

            BSONElement payloadElement;
            status = bsonExtractField(cmdObj, saslCommandPayloadFieldName, &payloadElement);
            if (!status.isOK()) {
                log() << "Failed to extract payload: " << status;
                return false;
            }

            authConn_.reset(cs.connect(errmsg));
            if (!authConn_.get()) {
                return false;
            }

            BSONObj ret;
            if( !authConn_->runCommand( fromDb,
                                        BSON( "saslStart" << 1 <<
                                              mechanismElement <<
                                              payloadElement),
                                        ret ) ) {
                return appendCommandStatus(result,
                                           Command::getStatusFromCommandResult(ret));

            }

            result.appendElements( ret );
            return true;
        }
Beispiel #9
0
    /** Get a scope from the pool of scopes matching the supplied pool name */
    auto_ptr<Scope> ScriptEngine::getPooledScope(const string& pool) {
        if (!scopeCache.get())
            scopeCache.reset(new ScopeCache());

        Scope* s = scopeCache->get(pool);
        if (!s)
            s = newScope();

        auto_ptr<Scope> p;
        p.reset(new PooledScope(pool, s));
        return p;
    }
		void checkTSSInit()
		{
			if(m_transactionInProgress.get() == 0)
			{
				m_transactionInProgress.reset(new bool);
				(*m_transactionInProgress) = false;
			}

			if(m_transaction.get() == 0)
			{
				m_transaction.reset(new DbTxn *);
				(*m_transaction) = NULL;
			}
		}
Beispiel #11
0
    /** Get a scope from the pool of scopes matching the supplied pool name */
    auto_ptr<Scope> ScriptEngine::getPooledScope(const string& pool, const string& scopeType) {
        if (!scopeCache.get())
            scopeCache.reset(new ScopeCache());

        Scope* s = scopeCache->get(pool + scopeType);
        if (!s)
            s = newScope();

        auto_ptr<Scope> p;
        p.reset(new PooledScope(pool + scopeType, s));
        p->setLocalDB(pool);
        p->loadStored(true);
        return p;
    }
Beispiel #12
0
std::shared_ptr<CoreContext> CoreContext::SetCurrent(const std::shared_ptr<CoreContext>& ctxt) {
  const auto& currentContext = CurrentContextOrNull();

  // Short-circuit test, no need to proceed if we aren't changing the context:
  if (currentContext == ctxt)
    return currentContext;

  // Value is changing, update:
  auto retVal = currentContext;
  if (ctxt)
    autoCurrentContext.reset(new std::shared_ptr<CoreContext>(ctxt));
  else
    autoCurrentContext.reset();
  return retVal;
}
Beispiel #13
0
    Glob::Glob(const std::string& pattern, GlobFlags flags)
    {
        globObject.reset(this);

        posix::glob_t glob;
        posix::glob(pattern.c_str(), flags, &onGlobError, &glob);

        globObject.release();

        if (glob.gl_pathc) {
            for (char** p = glob.gl_pathv; *p != NULL; ++p) {
                pathNames_.push_back(*p);
            }
        }

        posix::globfree(&glob);
    }
Beispiel #14
0
    extern "C" int onGlobError(const char *epath, int eerrno)
    {
        std::string pathName(epath);
        std::error_code errorCode(eerrno, std::system_category());

        globObject->errors_.push_back(std::make_pair(pathName, errorCode));
        return globObject->onError(pathName, errorCode);
    }
Beispiel #15
0
 virtual ~PooledScope(){
     ScopeCache * sc = scopeCache.get();
     if ( sc ){
         sc->done( _pool , _real );
         _real = 0;
     }
     else {
         log() << "warning: scopeCache is empty!" << endl;
         delete _real;
         _real = 0;
     }
 }
Beispiel #16
0
 virtual bool run(const string& , BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
     string fromhost = cmdObj.getStringField("fromhost");
     if ( fromhost.empty() ) {
         /* copy from self */
         stringstream ss;
         ss << "localhost:" << cmdLine.port;
         fromhost = ss.str();
     }
     authConn_.reset( new DBClientConnection() );
     BSONObj ret;
     {
         dbtemprelease t;
         if ( !authConn_->connect( fromhost, errmsg ) )
             return false;
         if( !authConn_->runCommand( "admin", BSON( "getnonce" << 1 ), ret ) ) {
             errmsg = "couldn't get nonce " + string( ret );
             return false;
         }
     }
     result.appendElements( ret );
     return true;
 }
Beispiel #17
0
 virtual ~PooledScope() {
     ScopeCache* sc = scopeCache.get();
     if (sc) {
         sc->done(_pool, _real);
         _real = NULL;
     }
     else {
         // this means that the Scope was killed from a different thread
         // for example a cursor got timed out that has a $where clause
         LOG(3) << "warning: scopeCache is empty!" << endl;
         delete _real;
         _real = 0;
     }
 }
Beispiel #18
0
namespace mongo {
    long long Scope::_lastVersion = 1;
    static const unsigned kMaxJsFileLength = std::numeric_limits<unsigned>::max() - 1;

    ScriptEngine::ScriptEngine() : _scopeInitCallback() {
    }

    ScriptEngine::~ScriptEngine() {
    }

    Scope::Scope() : _localDBName(""),
                     _loadedVersion(0),
                     _numTimeUsed(0),
                     _lastRetIsNativeCode(false) {
    }

    Scope::~Scope() {
    }

    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));
            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:
            uassert(10206,  str::stream() << "can't append type from: " << t, 0);
        }
    }

    int Scope::invoke(const char* code, const BSONObj* args, const BSONObj* recv, int timeoutMs) {
        ScriptingFunction func = createFunction(code);
        uassert(10207,  "compile failed", func);
        return invoke(func, args, recv, timeoutMs);
    }

    bool Scope::execFile(const string& filename, bool printResult, bool reportError,
                         int timeoutMs) {

        boost::filesystem::path p(filename);
        if (!exists(p)) {
            log() << "file [" << filename << "] doesn't exist" << endl;
            return false;
        }

        // iterate directories and recurse using all *.js files in the directory
        if (boost::filesystem::is_directory(p)) {
            boost::filesystem::directory_iterator end;
            bool empty = true;

            for (boost::filesystem::directory_iterator it (p); it != end; it++) {
                empty = false;
                boost::filesystem::path sub(*it);
                if (!endsWith(sub.string().c_str(), ".js"))
                    continue;
                if (!execFile(sub.string().c_str(), printResult, reportError, timeoutMs))
                    return false;
            }

            if (empty) {
                log() << "directory [" << filename << "] doesn't have any *.js files" << endl;
                return false;
            }

            return true;
        }

        File f;
        f.open(filename.c_str(), true);
        fileofs fo = f.len();
        if (fo > kMaxJsFileLength) {
            warning() << "attempted to execute javascript file larger than 2GB" << endl;
            return false;
        }
        unsigned len = static_cast<unsigned>(fo);
        boost::scoped_array<char> data (new char[len+1]);
        data[len] = 0;
        f.read(0, data.get(), len);

        int offset = 0;
        if (data[0] == '#' && data[1] == '!') {
            const char* newline = strchr(data.get(), '\n');
            if (!newline)
                return true; // file of just shebang treated same as empty file
            offset = newline - data.get();
        }

        StringData code(data.get() + offset, len - offset);
        return exec(code, filename, printResult, reportError, timeoutMs);
    }

    void Scope::storedFuncMod() {
        _lastVersion++;
    }

    void Scope::validateObjectIdString(const string& str) {
        uassert(10448, "invalid object id: length", str.size() == 24);
        for (size_t i = 0; i < str.size(); i++)
            uassert(10430,  "invalid object id: not hex", std::isxdigit(str.at(i)));
    }

    void Scope::loadStored(bool ignoreNotConnected) {
        if (_localDBName.size() == 0) {
            if (ignoreNotConnected)
                return;
            uassert(10208,  "need to have locallyConnected already", _localDBName.size());
        }

        if (_loadedVersion == _lastVersion)
            return;

        _loadedVersion = _lastVersion;
        string coll = _localDBName + ".system.js";

        static DBClientBase* db = createDirectClient();
        auto_ptr<DBClientCursor> c = db->query(coll, Query(), 0, 0, NULL, QueryOption_SlaveOk, 0);
        massert(16669, "unable to get db client cursor from query", c.get());

        set<string> thisTime;
        while (c->more()) {
            BSONObj o = c->nextSafe();
            BSONElement n = o["_id"];
            BSONElement v = o["value"];

            uassert(10209, str::stream() << "name has to be a string: " << n, n.type() == String);
            uassert(10210, "value has to be set", v.type() != EOO);

            try {
                setElement(n.valuestr(), v);
                thisTime.insert(n.valuestr());
                _storedNames.insert(n.valuestr());
            }
            catch (const DBException& setElemEx) {
                log() << "unable to load stored JavaScript function " << n.valuestr()
                      << "(): " << setElemEx.what() << endl;
            }
        }

        // remove things from scope that were removed from the system.js collection
        for (set<string>::iterator i = _storedNames.begin(); i != _storedNames.end(); ) {
            if (thisTime.count(*i) == 0) {
                string toDelete = str::stream() << "delete " << *i;
                _storedNames.erase(i++);
                execSetup(toDelete, "clean up scope");
            }
            else {
                ++i;
            }
        }
    }

    ScriptingFunction Scope::createFunction(const char* code) {
        if (code[0] == '/' && code [1] == '*') {
            code += 2;
            while (code[0] && code[1]) {
                if (code[0] == '*' && code[1] == '/') {
                    code += 2;
                    break;
                }
                code++;
            }
        }

        map<string, ScriptingFunction>::iterator i = _cachedFunctions.find(code);
        if (i != _cachedFunctions.end())
            return i->second;
        // NB: we calculate the function number for v8 so the cache can be utilized to
        //     lookup the source on an exception, but SpiderMonkey uses the value
        //     returned by JS_CompileFunction.
        ScriptingFunction functionNumber = getFunctionCache().size() + 1;
        _cachedFunctions[code] = functionNumber;
        ScriptingFunction f = _createFunction(code, functionNumber);
        return f;
    }

    namespace JSFiles {
        extern const JSFile collection;
        extern const JSFile db;
        extern const JSFile mongo;
        extern const JSFile mr;
        extern const JSFile query;
        extern const JSFile utils;
        extern const JSFile utils_sh;
    }

    void Scope::execCoreFiles() {
        execSetup(JSFiles::utils);
        execSetup(JSFiles::utils_sh);
        execSetup(JSFiles::db);
        execSetup(JSFiles::mongo);
        execSetup(JSFiles::mr);
        execSetup(JSFiles::query);
        execSetup(JSFiles::collection);
    }

    /** install BenchRunner suite */
    void Scope::installBenchRun() {
        injectNative("benchRun", BenchRunner::benchRunSync);
        injectNative("benchRunSync", BenchRunner::benchRunSync);
        injectNative("benchStart", BenchRunner::benchStart);
        injectNative("benchFinish", BenchRunner::benchFinish);
    }

    typedef map<string, list<Scope*> > PoolToScopes;

    class ScopeCache {
    public:
        ScopeCache() : _mutex("ScopeCache") {
        }

        ~ScopeCache() {
            if (inShutdown())
                return;
            clear();
        }

        void done(const string& pool, Scope* s) {
            scoped_lock lk(_mutex);
            list<Scope*>& l = _pools[pool];
            bool oom = s->hasOutOfMemoryException();

            // do not keep too many contexts, or use them for too long
            if (l.size() > 10 || s->getTimeUsed() > 10 || oom || !s->getError().empty()) {
                delete s;
            }
            else {
                l.push_back(s);
                s->reset();
            }

            if (oom) {
                // out of mem, make some room
                log() << "Clearing all idle JS contexts due to out of memory" << endl;
                clear();
            }
        }

        Scope* get(const string& pool) {
            scoped_lock lk(_mutex);
            list<Scope*>& l = _pools[pool];
            if (l.size() == 0)
                return 0;

            Scope* s = l.back();
            l.pop_back();
            s->reset();
            s->incTimeUsed();
            return s;
        }

        void clear() {
            set<Scope*> seen;
            for (PoolToScopes::iterator i = _pools.begin(); i != _pools.end(); ++i) {
                for (list<Scope*>::iterator j = i->second.begin(); j != i->second.end(); ++j) {
                    Scope* s = *j;
                    fassert(16652, seen.insert(s).second);
                    delete s;
                }
            }
            _pools.clear();
        }

    private:
        PoolToScopes _pools;
        mongo::mutex _mutex;
    };

    thread_specific_ptr<ScopeCache> scopeCache;

    class PooledScope : public Scope {
    public:
        PooledScope(const std::string& pool, Scope* real) : _pool(pool), _real(real) {
            _real->loadStored(true);
        };
        virtual ~PooledScope() {
            ScopeCache* sc = scopeCache.get();
            if (sc) {
                sc->done(_pool, _real);
                _real = NULL;
            }
            else {
                // this means that the Scope was killed from a different thread
                // for example a cursor got timed out that has a $where clause
                LOG(3) << "warning: scopeCache is empty!" << endl;
                delete _real;
                _real = 0;
            }
        }

        // wrappers for the derived (_real) scope
        void reset() { _real->reset(); }
        void init(const BSONObj* data) { _real->init(data); }
        void localConnect(const char* dbName) { _real->localConnect(dbName); }
        void setLocalDB(const string& dbName) { _real->setLocalDB(dbName); }
        void loadStored(bool ignoreNotConnected = false) { _real->loadStored(ignoreNotConnected); }
        void externalSetup() { _real->externalSetup(); }
        void gc() { _real->gc(); }
        bool isKillPending() const { return _real->isKillPending(); }
        int type(const char* field) { return _real->type(field); }
        string getError() { return _real->getError(); }
        bool hasOutOfMemoryException() { return _real->hasOutOfMemoryException(); }
        void rename(const char* from, const char* to) { _real->rename(from, to); }
        double getNumber(const char* field) { return _real->getNumber(field); }
        string getString(const char* field) { return _real->getString(field); }
        bool getBoolean(const char* field) { return _real->getBoolean(field); }
        BSONObj getObject(const char* field) { return _real->getObject(field); }
        void setNumber(const char* field, double val) { _real->setNumber(field, val); }
        void setString(const char* field, const char* val) { _real->setString(field, val); }
        void setElement(const char* field, const BSONElement& val) {
            _real->setElement(field, val);
        }
        void setObject(const char* field, const BSONObj& obj, bool readOnly = true) {
            _real->setObject(field, obj, readOnly);
        }
        bool isLastRetNativeCode() { return _real->isLastRetNativeCode(); }

        void setBoolean(const char* field, bool val) { _real->setBoolean(field, val); }
        void setFunction(const char* field, const char* code) { _real->setFunction(field, code); }
        ScriptingFunction createFunction(const char* code) { return _real->createFunction(code); }
        int invoke(ScriptingFunction func, const BSONObj* args, const BSONObj* recv,
                   int timeoutMs, bool ignoreReturn, bool readOnlyArgs, bool readOnlyRecv) {
            return _real->invoke(func, args, recv, timeoutMs, ignoreReturn,
                                 readOnlyArgs, readOnlyRecv);
        }
        bool exec(const StringData& code, const string& name, bool printResult, bool reportError,
                  bool assertOnError, int timeoutMs = 0) {
            return _real->exec(code, name, printResult, reportError, assertOnError, timeoutMs);
        }
        bool execFile(const string& filename, bool printResult, bool reportError,
                      int timeoutMs = 0) {
            return _real->execFile(filename, printResult, reportError, timeoutMs);
        }
        void injectNative(const char* field, NativeFunction func, void* data) {
            _real->injectNative(field, func, data);
        }
        void append(BSONObjBuilder& builder, const char* fieldName, const char* scopeName) {
            _real->append(builder, fieldName, scopeName);
        }

    protected:
        FunctionCacheMap& getFunctionCache() { return _real->getFunctionCache(); }

        ScriptingFunction _createFunction(const char* code, ScriptingFunction functionNumber = 0) {
            return _real->_createFunction(code, functionNumber);
        }

    private:
        string _pool;
        Scope* _real;
    };

    /** Get a scope from the pool of scopes matching the supplied pool name */
    auto_ptr<Scope> ScriptEngine::getPooledScope(const string& pool, const string& scopeType) {
        if (!scopeCache.get())
            scopeCache.reset(new ScopeCache());

        Scope* s = scopeCache->get(pool + scopeType);
        if (!s)
            s = newScope();

        auto_ptr<Scope> p;
        p.reset(new PooledScope(pool + scopeType, s));
        p->setLocalDB(pool);
        p->loadStored(true);
        return p;
    }

    void ScriptEngine::threadDone() {
        ScopeCache* sc = scopeCache.get();
        if (sc)
            sc->clear();
    }

    void (*ScriptEngine::_connectCallback)(DBClientWithCommands&) = 0;
    const char* (*ScriptEngine::_checkInterruptCallback)() = 0;
    unsigned (*ScriptEngine::_getCurrentOpIdCallback)() = 0;
    ScriptEngine* globalScriptEngine = 0;

    bool hasJSReturn(const string& code) {
        size_t x = code.find("return");
        if (x == string::npos)
            return false;

        return (x == 0 || !isalpha(code[x-1])) &&
               !isalpha(code[x+6]);
    }

    const char* jsSkipWhiteSpace(const char* raw) {
        while (raw[0]) {
            while (isspace(*raw)) {
                ++raw;
            }
            if (raw[0] != '/' || raw[1] != '/')
                break;
            while (raw[0] && raw[0] != '\n')
                raw++;
        }
        return raw;
    }
}
Beispiel #19
0
namespace this_thread {

	/**
	 * @intern
	 */
	extern thread_specific_ptr<bool> _syscalls_interruptable;
	
	/**
	 * Check whether system calls should be interruptable in
	 * the calling thread.
	 */
	bool syscalls_interruptable();
	
	class restore_syscall_interruption;

	/**
	 * Create this struct on the stack to temporarily enable system
	 * call interruption, until the object goes out of scope.
	 */
	class enable_syscall_interruption {
	private:
		bool last_value;
	public:
		enable_syscall_interruption() {
			if (_syscalls_interruptable.get() == NULL) {
				last_value = true;
				_syscalls_interruptable.reset(new bool(true));
			} else {
				last_value = *_syscalls_interruptable;
				*_syscalls_interruptable = true;
			}
		}
		
		~enable_syscall_interruption() {
			*_syscalls_interruptable = last_value;
		}
	};
	
	/**
	 * Create this struct on the stack to temporarily disable system
	 * call interruption, until the object goes out of scope.
	 * While system call interruption is disabled, the functions in
	 * InterruptableCalls will try until the return code is not EINTR.
	 */
	class disable_syscall_interruption {
	private:
		friend class restore_syscall_interruption;
		bool last_value;
	public:
		disable_syscall_interruption() {
			if (_syscalls_interruptable.get() == NULL) {
				last_value = true;
				_syscalls_interruptable.reset(new bool(false));
			} else {
				last_value = *_syscalls_interruptable;
				*_syscalls_interruptable = false;
			}
		}
		
		~disable_syscall_interruption() {
			*_syscalls_interruptable = last_value;
		}
	};
	
	/**
	 * Creating an object of this class on the stack will restore the
	 * system call interruption state to what it was before.
	 */
	class restore_syscall_interruption {
	private:
		int last_value;
	public:
		restore_syscall_interruption(const disable_syscall_interruption &intr) {
			assert(_syscalls_interruptable.get() != NULL);
			last_value = *_syscalls_interruptable;
			*_syscalls_interruptable = intr.last_value;
		}
		
		~restore_syscall_interruption() {
			*_syscalls_interruptable = last_value;
		}
	};

} // namespace this_thread
 void unlock ()
 {
     this_thread_hierarchy_value.reset(new unsigned long(previous_hierarchy_value));
     internal_mutex.unlock ();
 }
 void update_hierarchy_value ()
 {
     previous_hierarchy_value     =  *this_thread_hierarchy_value;
     this_thread_hierarchy_value.reset(new unsigned long(hierarchy_value));
 }
Beispiel #22
0
 void ScriptEngine::threadDone(){
     ScopeCache * sc = scopeCache.get();
     if ( sc ){
         sc->clear();
     }
 }
Beispiel #23
0
namespace mongo {

    long long Scope::_lastVersion = 1;
    
    int Scope::_numScopes = 0;

    Scope::Scope() : _localDBName("") , _loadedVersion(0){
        _numScopes++;
    }

    Scope::~Scope(){
        _numScopes--;
    }

    ScriptEngine::ScriptEngine() : _scopeInitCallback() {
    }

    ScriptEngine::~ScriptEngine(){
    }

    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;
        default:
            stringstream temp;
            temp << "can't append type from:";
            temp << t;
            uassert( 10206 ,  temp.str() , 0 );
        }
        
    }

    int Scope::invoke( const char* code , const BSONObj& args, int timeoutMs ){
        ScriptingFunction func = createFunction( code );
        uassert( 10207 ,  "compile failed" , func );
        return invoke( func , args, timeoutMs );
    }
    
    bool Scope::execFile( const string& filename , bool printResult , bool reportError , bool assertOnError, int timeoutMs ){
        
        path p( filename );

        if ( ! exists( p ) ){
            cout << "file [" << filename << "] doesn't exist" << endl;
            if ( assertOnError )
                assert( 0 );
            return false;
        }

        // iterate directories and recurse using all *.js files in the directory
        if ( is_directory( p ) ){
            directory_iterator end;
            bool empty = true;
            for (directory_iterator it (p); it != end; it++){
                empty = false;
                path sub (*it);
                if (!endsWith(sub.string().c_str(), ".js"))
                    continue;
                if (!execFile(sub.string().c_str(), printResult, reportError, assertOnError, timeoutMs))
                    return false;
            }

            if (empty){
                cout << "directory [" << filename << "] doesn't have any *.js files" << endl;
                if ( assertOnError )
                    assert( 0 );
                return false;
            }

            return true;
        }
        
        File f;
        f.open( filename.c_str() , true );

        fileofs L = f.len();
        assert( L <= 0x7ffffffe );
        char * data = (char*)malloc( (size_t) L+1 );
        data[L] = 0;
        f.read( 0 , data , (size_t) L );
        
        return exec( data , filename , printResult , reportError , assertOnError, timeoutMs );
    }

    void Scope::storedFuncMod(){
        _lastVersion++;
    }
    
    void Scope::validateObjectIdString( const string &str ) {
        massert( 10448 , "invalid object id: length", str.size() == 24 );

        for ( string::size_type i=0; i<str.size(); i++ ){
            char c = str[i];
            if ( ( c >= '0' && c <= '9' ) ||
                ( c >= 'a' && c <= 'f' ) ||
                ( c >= 'A' && c <= 'F' ) ){
                continue;
            }
            massert( 10430 ,  "invalid object id: not hex", false );
        }        
    }

    void Scope::loadStored( bool ignoreNotConnected ){
        if ( _localDBName.size() == 0 ){
            if ( ignoreNotConnected )
                return;
            uassert( 10208 ,  "need to have locallyConnected already" , _localDBName.size() );
        }
        if ( _loadedVersion == _lastVersion )
            return;
        
        _loadedVersion = _lastVersion;

        string coll = _localDBName + ".system.js";
        
        static DBClientBase * db = createDirectClient();
        auto_ptr<DBClientCursor> c = db->query( coll , Query() );
        
        set<string> thisTime;
        
        while ( c->more() ){
            BSONObj o = c->next();

            BSONElement n = o["_id"];
            BSONElement v = o["value"];
            
            uassert( 10209 ,  "name has to be a string" , n.type() == String );
            uassert( 10210 ,  "value has to be set" , v.type() != EOO );
            
            setElement( n.valuestr() , v );

            thisTime.insert( n.valuestr() );
            _storedNames.insert( n.valuestr() );
            
        }

        // --- remove things from scope that were removed

        list<string> toremove;

        for ( set<string>::iterator i=_storedNames.begin(); i!=_storedNames.end(); i++ ){
            string n = *i;
            if ( thisTime.count( n ) == 0 )
                toremove.push_back( n );
        }
        
        for ( list<string>::iterator i=toremove.begin(); i!=toremove.end(); i++ ){
            string n = *i;
            _storedNames.erase( n );
            execSetup( (string)"delete " + n , "clean up scope" );
        }

    }

    ScriptingFunction Scope::createFunction( const char * code ){
        if ( code[0] == '/' && code [1] == '*' ){
            code += 2;
            while ( code[0] && code[1] ){
                if ( code[0] == '*' && code[1] == '/' ){
                    code += 2;
                    break;
                }
                code++;
            }
        }
        map<string,ScriptingFunction>::iterator i = _cachedFunctions.find( code );
        if ( i != _cachedFunctions.end() )
            return i->second;
        ScriptingFunction f = _createFunction( code );
        _cachedFunctions[code] = f;
        return f;
    }
    
    typedef map< string , list<Scope*> > PoolToScopes;

    class ScopeCache {
    public:

        ScopeCache(){
            _magic = 17;
        }
        
        ~ScopeCache(){
            assert( _magic == 17 );
            _magic = 1;

            if ( inShutdown() )
                return;
            
            clear();
        }

        void done( const string& pool , Scope * s ){
            scoped_lock lk( _mutex );
            list<Scope*> & l = _pools[pool];
            if ( l.size() > 10 ){
                delete s;
            }
            else {
                l.push_back( s );
                s->reset();
            }
        }
        
        Scope * get( const string& pool ){
            scoped_lock lk( _mutex );
            list<Scope*> & l = _pools[pool];
            if ( l.size() == 0 )
                return 0;
            
            Scope * s = l.back();
            l.pop_back();
            s->reset();
            return s;
        }
        
        void clear(){
            set<Scope*> seen;
            
            for ( PoolToScopes::iterator i=_pools.begin() ; i != _pools.end(); i++ ){
                for ( list<Scope*>::iterator j=i->second.begin(); j != i->second.end(); j++ ){
                    Scope * s = *j;
                    assert( ! seen.count( s ) );
                    delete s;
                    seen.insert( s );
                }
            }
            
            _pools.clear();
        }

    private:
        PoolToScopes _pools;
        mongo::mutex _mutex;
        int _magic;
    };

    thread_specific_ptr<ScopeCache> scopeCache;

    class PooledScope : public Scope {
    public:
        PooledScope( const string pool , Scope * real ) : _pool( pool ) , _real( real ){
            _real->loadStored( true );
        };
        virtual ~PooledScope(){
            ScopeCache * sc = scopeCache.get();
            if ( sc ){
                sc->done( _pool , _real );
                _real = 0;
            }
            else {
                log() << "warning: scopeCache is empty!" << endl;
                delete _real;
                _real = 0;
            }
        }
        
        void reset(){
            _real->reset();
        }
        void init( BSONObj * data ){
            _real->init( data );
        }
        
        void localConnect( const char * dbName ){
            _real->localConnect( dbName );
        }
        void externalSetup(){
            _real->externalSetup();
        }
        
        double getNumber( const char *field ){
            return _real->getNumber( field );
        }
        string getString( const char *field ){
            return _real->getString( field );
        }
        bool getBoolean( const char *field ){
            return _real->getBoolean( field );
        }
        BSONObj getObject( const char *field ){
            return _real->getObject( field );
        }

        int type( const char *field ){
            return _real->type( field );
        }

        void setElement( const char *field , const BSONElement& val ){
            _real->setElement( field , val );
        }
        void setNumber( const char *field , double val ){
            _real->setNumber( field , val );
        }
        void setString( const char *field , const char * val ){
            _real->setString( field , val );
        }
        void setObject( const char *field , const BSONObj& obj , bool readOnly=true ){
            _real->setObject( field , obj , readOnly );
        }
        void setBoolean( const char *field , bool val ){
            _real->setBoolean( field , val );
        }
        void setThis( const BSONObj * obj ){
            _real->setThis( obj );
        }
        
        ScriptingFunction createFunction( const char * code ){
            return _real->createFunction( code );
        }

        ScriptingFunction _createFunction( const char * code ){
            return _real->createFunction( code );
        }

        /**
         * @return 0 on success
         */
        int invoke( ScriptingFunction func , const BSONObj& args, int timeoutMs , bool ignoreReturn ){
            return _real->invoke( func , args , timeoutMs , ignoreReturn );
        }

        string getError(){
            return _real->getError();
        }
        
        bool exec( const string& code , const string& name , bool printResult , bool reportError , bool assertOnError, int timeoutMs = 0 ){
            return _real->exec( code , name , printResult , reportError , assertOnError , timeoutMs );
        }
        bool execFile( const string& filename , bool printResult , bool reportError , bool assertOnError, int timeoutMs = 0 ){
            return _real->execFile( filename , printResult , reportError , assertOnError , timeoutMs );
        }
        
        void injectNative( const char *field, NativeFunction func ){
            _real->injectNative( field , func );
        }
        
        void gc(){
            _real->gc();
        }

    private:
        string _pool;
        Scope * _real;
    };

    auto_ptr<Scope> ScriptEngine::getPooledScope( const string& pool ){
        if ( ! scopeCache.get() ){
            scopeCache.reset( new ScopeCache() );
        }

        Scope * s = scopeCache->get( pool );
        if ( ! s ){
            s = newScope();
        }
        
        auto_ptr<Scope> p;
        p.reset( new PooledScope( pool , s ) );
        return p;
    }
    
    void ScriptEngine::threadDone(){
        ScopeCache * sc = scopeCache.get();
        if ( sc ){
            sc->clear();
        }
    }
    
    void ( *ScriptEngine::_connectCallback )( DBClientWithCommands & ) = 0;
    
    ScriptEngine * globalScriptEngine;

    bool hasJSReturn( const string& code ){
        size_t x = code.find( "return" );
        if ( x == string::npos )
            return false;

        return 
            ( x == 0 || ! isalpha( code[x-1] ) ) &&
            ! isalpha( code[x+6] );
    }
}
Beispiel #24
0
CoreContext::~CoreContext(void) {
  // Evict from the parent's child list first, if we have a parent:
  if(m_pParent)
  {
    expiredContext();

    // Also clear out any parent pointers:
    std::lock_guard<std::mutex> lk(m_pParent->m_stateBlock->m_lock);
    m_pParent->m_children.erase(m_backReference);
  }

  // The autoCurrentContext pointer holds a shared_ptr to this--if we're in a dtor, and our caller
  // still holds a reference to us, then we have a serious problem.
  assert(
    !autoCurrentContext.get() ||
    !autoCurrentContext.get()->use_count() ||
    autoCurrentContext.get()->get() != this
  );

  // Notify all ContextMember instances that their parent is going away
  onTeardown(*this);

  // Tell all context members that we're tearing down:
  for(ContextMember* q : m_contextMembers)
    q->NotifyContextTeardown();

  // Perform unlinking, if requested:
  if(m_unlinkOnTeardown)
    for (const auto& ccType : m_concreteTypes) {
      uint8_t* pBase = (uint8_t*)ccType.value.ptr();

      // Enumerate all slots and unlink them one at a time
      for (auto cur = ccType.stump->pHead; cur; cur = cur->pFlink) {
        if (cur->autoRequired)
          // Only unlink slots that were Autowired.  AutoRequired slots will never participate
          // in a cycle (because we would wind up with constructive chaos) so we don't really
          // need to worry about them.  Furthermore, there are cases where users may want to
          // refer to a context member in their destructor; in that case, they should use
          // AutoRequired to enforce the relationship.
          continue;

        auto& slot = *reinterpret_cast<DeferrableAutowiring*>(pBase + cur->slotOffset);
        if (!slot.IsAutowired())
          // Nothing to do here, just short-circuit
          continue;

        auto q = m_typeMemos.find(slot.GetType());
        if (q == m_typeMemos.end())
          // Weird.  A slot is present on a member of this context, but the wired type doesn't
          // have a memo entry anywhere.
          continue;

        if (!q->second.m_local)
          // Entry exists, but was not locally satisfied.  We can circle around.
          continue;

        // OK, interior pointer and context teardown is underway, clear it out
        slot.reset();
      }
    }
}
Beispiel #25
0
void CoreContext::EvictCurrent(void) {
  autoCurrentContext.reset();
}
Beispiel #26
0
		restore_syscall_interruption(const disable_syscall_interruption &intr) {
			assert(_syscalls_interruptable.get() != NULL);
			last_value = *_syscalls_interruptable;
			*_syscalls_interruptable = intr.last_value;
		}
Beispiel #27
0
namespace mongo {

    // SERVER-4328 todo review for concurrency
    // :(
    thread_specific_ptr<DBClientBase> authConn_;

    /* Usage:
     * admindb.$cmd.findOne( { copydbgetnonce: 1, fromhost: <connection string> } );
     *
     * Run against the mongod that is the intended target for the "copydb" command.  Used to get a
     * nonce from the source of a "copydb" operation for authentication purposes.  See the
     * description of the "copydb" command below.
     */
    class CmdCopyDbGetNonce : public Command {
    public:
        CmdCopyDbGetNonce() : Command("copydbgetnonce") { }

        virtual bool adminOnly() const {
            return true;
        }

        virtual bool slaveOk() const {
            return false;
        }

        virtual bool isWriteCommandForConfigServer() const { return false; }

        virtual void addRequiredPrivileges(const std::string& dbname,
                                           const BSONObj& cmdObj,
                                           std::vector<Privilege>* out) {
            // No auth required
        }

        virtual void help( stringstream &help ) const {
            help << "get a nonce for subsequent copy db request from secure server\n";
            help << "usage: {copydbgetnonce: 1, fromhost: <hostname>}";
        }

        virtual bool run(OperationContext* txn,
                         const string&,
                         BSONObj& cmdObj,
                         int,
                         string& errmsg,
                         BSONObjBuilder& result,
                         bool fromRepl) {

            string fromhost = cmdObj.getStringField("fromhost");
            if ( fromhost.empty() ) {
                /* copy from self */
                stringstream ss;
                ss << "localhost:" << serverGlobalParams.port;
                fromhost = ss.str();
            }

            BSONObj ret;

            ConnectionString cs = ConnectionString::parse(fromhost, errmsg);
            if (!cs.isValid()) {
                return false;
            }

            authConn_.reset(cs.connect(errmsg));
            if (!authConn_.get()) {
                return false;
            }

            if( !authConn_->runCommand( "admin", BSON( "getnonce" << 1 ), ret ) ) {
                errmsg = "couldn't get nonce " + ret.toString();
                return false;
            }

            result.appendElements( ret );
            return true;
        }

    } cmdCopyDBGetNonce;

} // namespace mongo
Beispiel #28
0
namespace mongo {

    long long Scope::_lastVersion = 1;
    
    int Scope::_numScopes = 0;

    Scope::Scope() : _localDBName("") , _loadedVersion(0){
        _numScopes++;
    }

    Scope::~Scope(){
        _numScopes--;
    }

    ScriptEngine::ScriptEngine(){
    }

    ScriptEngine::~ScriptEngine(){
    }

    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:
            builder.appendDate( fieldName , (unsigned long long) getNumber( scopeName ) );
            break;
        default:
            stringstream temp;
            temp << "can't append type from:";
            temp << t;
            uassert( temp.str() , 0 );
        }
        
    }

    int Scope::invoke( const char* code , const BSONObj& args, int timeoutMs ){
        ScriptingFunction func = createFunction( code );
        uassert( "compile failed" , func );
        return invoke( func , args, timeoutMs );
    }
    
    bool Scope::execFile( const string& filename , bool printResult , bool reportError , bool assertOnError, int timeoutMs ){
        
        path p( filename );

        if ( ! exists( p ) ){
            cout << "file [" << filename << "] doesn't exist" << endl;
            if ( assertOnError )
                assert( 0 );
            return false;
        }

        if ( is_directory( p ) ){
            cout << "can't read directory [" << filename << "]" << endl;
            if ( assertOnError )
                assert( 0 );
            return false;
        }
        
        File f;
        f.open( filename.c_str() );

        fileofs L = f.len();
        assert( L <= 0x7ffffffe );
        char * data = (char*)malloc( (size_t) L+1 );
        data[L] = 0;
        f.read( 0 , data , (size_t) L );
        
        return exec( data , filename , printResult , reportError , assertOnError, timeoutMs );
    }

    void Scope::storedFuncMod(){
        _lastVersion++;
    }

    void Scope::loadStored( bool ignoreNotConnected ){
        if ( _localDBName.size() == 0 ){
            if ( ignoreNotConnected )
                return;
            uassert( "need to have locallyConnected already" , _localDBName.size() );
        }
        if ( _loadedVersion == _lastVersion )
            return;
        
        _loadedVersion = _lastVersion;

        static DBClientBase * db = createDirectClient();
        
        auto_ptr<DBClientCursor> c = db->query( _localDBName + ".system.js" , Query() );
        while ( c->more() ){
            BSONObj o = c->next();

            BSONElement n = o["_id"];
            BSONElement v = o["value"];
            
            uassert( "name has to be a string" , n.type() == String );
            uassert( "value has to be set" , v.type() != EOO );
            
            setElement( n.valuestr() , v );
        }
    }

    ScriptingFunction Scope::createFunction( const char * code ){
        if ( code[0] == '/' && code [1] == '*' ){
            code += 2;
            while ( code[0] && code[1] ){
                if ( code[0] == '*' && code[1] == '/' ){
                    code += 2;
                    break;
                }
                code++;
            }
        }
        map<string,ScriptingFunction>::iterator i = _cachedFunctions.find( code );
        if ( i != _cachedFunctions.end() )
            return i->second;
        ScriptingFunction f = _createFunction( code );
        _cachedFunctions[code] = f;
        return f;
    }
    
    typedef map< string , list<Scope*> > PoolToScopes;

    class ScopeCache {
    public:

        ScopeCache(){
            _magic = 17;
        }
        
        ~ScopeCache(){
            assert( _magic == 17 );
            _magic = 1;

            if ( inShutdown() )
                return;
            
            clear();
        }

        void done( const string& pool , Scope * s ){
            boostlock lk( _mutex );
            list<Scope*> & l = _pools[pool];
            if ( l.size() > 10 ){
                delete s;
            }
            else {
                l.push_back( s );
                s->reset();
            }
        }
        
        Scope * get( const string& pool ){
            boostlock lk( _mutex );
            list<Scope*> & l = _pools[pool];
            if ( l.size() == 0 )
                return 0;
            
            Scope * s = l.back();
            l.pop_back();
            s->reset();
            return s;
        }
        
        void clear(){
            set<Scope*> seen;
            
            for ( PoolToScopes::iterator i=_pools.begin() ; i != _pools.end(); i++ ){
                for ( list<Scope*>::iterator j=i->second.begin(); j != i->second.end(); j++ ){
                    Scope * s = *j;
                    assert( ! seen.count( s ) );
                    delete s;
                    seen.insert( s );
                }
            }
            
            _pools.clear();
        }

    private:
        PoolToScopes _pools;
        boost::mutex _mutex;
        int _magic;
    };

    thread_specific_ptr<ScopeCache> scopeCache;

    class PooledScope : public Scope {
    public:
        PooledScope( const string pool , Scope * real ) : _pool( pool ) , _real( real ){
            _real->loadStored( true );
        };
        virtual ~PooledScope(){
            ScopeCache * sc = scopeCache.get();
            if ( sc ){
                sc->done( _pool , _real );
                _real = 0;
            }
            else {
                log() << "warning: scopeCache is empty!" << endl;
                delete _real;
                _real = 0;
            }
        }
        
        void reset(){
            _real->reset();
        }
        void init( BSONObj * data ){
            _real->init( data );
        }
        
        void localConnect( const char * dbName ){
            _real->localConnect( dbName );
        }
        void externalSetup(){
            _real->externalSetup();
        }
        
        double getNumber( const char *field ){
            return _real->getNumber( field );
        }
        string getString( const char *field ){
            return _real->getString( field );
        }
        bool getBoolean( const char *field ){
            return _real->getBoolean( field );
        }
        BSONObj getObject( const char *field ){
            return _real->getObject( field );
        }

        int type( const char *field ){
            return _real->type( field );
        }

        void setElement( const char *field , const BSONElement& val ){
            _real->setElement( field , val );
        }
        void setNumber( const char *field , double val ){
            _real->setNumber( field , val );
        }
        void setString( const char *field , const char * val ){
            _real->setString( field , val );
        }
        void setObject( const char *field , const BSONObj& obj , bool readOnly=true ){
            _real->setObject( field , obj , readOnly );
        }
        void setBoolean( const char *field , bool val ){
            _real->setBoolean( field , val );
        }
        void setThis( const BSONObj * obj ){
            _real->setThis( obj );
        }
        
        ScriptingFunction createFunction( const char * code ){
            return _real->createFunction( code );
        }

        ScriptingFunction _createFunction( const char * code ){
            return _real->createFunction( code );
        }

        /**
         * @return 0 on success
         */
        int invoke( ScriptingFunction func , const BSONObj& args, int timeoutMs , bool ignoreReturn ){
            return _real->invoke( func , args , timeoutMs , ignoreReturn );
        }

        string getError(){
            return _real->getError();
        }
        
        bool exec( const string& code , const string& name , bool printResult , bool reportError , bool assertOnError, int timeoutMs = 0 ){
            return _real->exec( code , name , printResult , reportError , assertOnError , timeoutMs );
        }
        bool execFile( const string& filename , bool printResult , bool reportError , bool assertOnError, int timeoutMs = 0 ){
            return _real->execFile( filename , printResult , reportError , assertOnError , timeoutMs );
        }
        
        void injectNative( const char *field, NativeFunction func ){
            _real->injectNative( field , func );
        }
        
        void gc(){
            _real->gc();
        }

    private:
        string _pool;
        Scope * _real;
    };

    auto_ptr<Scope> ScriptEngine::getPooledScope( const string& pool ){
        if ( ! scopeCache.get() ){
            scopeCache.reset( new ScopeCache() );
        }

        Scope * s = scopeCache->get( pool );
        if ( ! s ){
            s = createScope();
        }
        
        auto_ptr<Scope> p;
        p.reset( new PooledScope( pool , s ) );
        return p;
    }
    
    void ScriptEngine::threadDone(){
        ScopeCache * sc = scopeCache.get();
        if ( sc ){
            sc->clear();
        }
    }
    
    ScriptEngine * globalScriptEngine;
}
namespace mongo {

    using std::string;
    using std::stringstream;

    // SERVER-4328 todo review for concurrency
    // :(
    thread_specific_ptr<DBClientBase> authConn_;

    /* Usage:
     * admindb.$cmd.findOne( { copydbgetnonce: 1, fromhost: <connection string> } );
     *
     * Run against the mongod that is the intended target for the "copydb" command.  Used to get a
     * nonce from the source of a "copydb" operation for authentication purposes.  See the
     * description of the "copydb" command below.
     */
    class CmdCopyDbGetNonce : public Command {
    public:
        CmdCopyDbGetNonce() : Command("copydbgetnonce") { }

        virtual bool adminOnly() const {
            return true;
        }

        virtual bool slaveOk() const {
            return false;
        }

        virtual bool isWriteCommandForConfigServer() const { return false; }

        virtual void addRequiredPrivileges(const std::string& dbname,
                                           const BSONObj& cmdObj,
                                           std::vector<Privilege>* out) {
            // No auth required
        }

        virtual void help( stringstream &help ) const {
            help << "get a nonce for subsequent copy db request from secure server\n";
            help << "usage: {copydbgetnonce: 1, fromhost: <hostname>}";
        }

        virtual bool run(OperationContext* txn,
                         const string&,
                         BSONObj& cmdObj,
                         int,
                         string& errmsg,
                         BSONObjBuilder& result) {

            string fromhost = cmdObj.getStringField("fromhost");
            if ( fromhost.empty() ) {
                /* copy from self */
                stringstream ss;
                ss << "localhost:" << serverGlobalParams.port;
                fromhost = ss.str();
            }

            const ConnectionString cs(uassertStatusOK(ConnectionString::parse(fromhost)));

            authConn_.reset(cs.connect(errmsg));
            if (!authConn_.get()) {
                return false;
            }

            BSONObj ret;

            if( !authConn_->runCommand( "admin", BSON( "getnonce" << 1 ), ret ) ) {
                errmsg = "couldn't get nonce " + ret.toString();
                return false;
            }

            result.appendElements( ret );
            return true;
        }

    } cmdCopyDBGetNonce;

    /* Usage:
     * admindb.$cmd.findOne( { copydbsaslstart: 1,
     *                         fromhost: <connection string>,
     *                         mechanism: <String>,
     *                         payload: <BinaryOrString> } );
     *
     * Run against the mongod that is the intended target for the "copydb" command.  Used to
     * initialize a SASL auth session for a "copydb" operation for authentication purposes.
     */
    class CmdCopyDbSaslStart : public Command {
    public:
        CmdCopyDbSaslStart() : Command("copydbsaslstart") { }

        virtual bool adminOnly() const {
            return true;
        }

        virtual bool slaveOk() const {
            return false;
        }

        virtual bool isWriteCommandForConfigServer() const { return false; }

        virtual Status checkAuthForCommand(ClientBasic* client,
                                           const std::string& dbname,
                                           const BSONObj& cmdObj) {
            // No auth required
            return Status::OK();
        }

        virtual void help( stringstream &help ) const {
            help << "Initialize a SASL auth session for subsequent copy db request "
                    "from secure server\n";
        }

        virtual bool run(OperationContext* txn,
                         const string&,
                         BSONObj& cmdObj,
                         int,
                         string& errmsg,
                         BSONObjBuilder& result) {

            const string fromDb = cmdObj.getStringField("fromdb");

            string fromHost = cmdObj.getStringField("fromhost");
            if ( fromHost.empty() ) {
                /* copy from self */
                stringstream ss;
                ss << "localhost:" << serverGlobalParams.port;
                fromHost = ss.str();
            }

            const ConnectionString cs(uassertStatusOK(ConnectionString::parse(fromHost)));

            BSONElement mechanismElement;
            Status status = bsonExtractField(cmdObj,
                                             saslCommandMechanismFieldName,
                                             &mechanismElement);
            if (!status.isOK()) {
                return appendCommandStatus(result, status);
            }

            BSONElement payloadElement;
            status = bsonExtractField(cmdObj, saslCommandPayloadFieldName, &payloadElement);
            if (!status.isOK()) {
                log() << "Failed to extract payload: " << status;
                return false;
            }

            authConn_.reset(cs.connect(errmsg));
            if (!authConn_.get()) {
                return false;
            }

            BSONObj ret;
            if( !authConn_->runCommand( fromDb,
                                        BSON( "saslStart" << 1 <<
                                              mechanismElement <<
                                              payloadElement),
                                        ret ) ) {
                return appendCommandStatus(result,
                                           Command::getStatusFromCommandResult(ret));

            }

            result.appendElements( ret );
            return true;
        }

    } cmdCopyDBSaslStart;

} // namespace mongo
Beispiel #30
0
const std::shared_ptr<CoreContext>& CoreContext::CurrentContextOrNull(void) {
  static const std::shared_ptr<CoreContext> empty;
  auto retVal = autoCurrentContext.get();
  return retVal ? *retVal : empty;
}