summaryrefslogtreecommitdiff
path: root/src/mongo/scripting/engine.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/scripting/engine.h')
-rw-r--r--src/mongo/scripting/engine.h458
1 files changed, 243 insertions, 215 deletions
diff --git a/src/mongo/scripting/engine.h b/src/mongo/scripting/engine.h
index 9b99d438fc4..b3426d544ab 100644
--- a/src/mongo/scripting/engine.h
+++ b/src/mongo/scripting/engine.h
@@ -34,225 +34,253 @@
#include "mongo/platform/atomic_word.h"
namespace mongo {
- typedef unsigned long long ScriptingFunction;
- typedef BSONObj (*NativeFunction)(const BSONObj& args, void* data);
- typedef std::map<std::string, ScriptingFunction> FunctionCacheMap;
+typedef unsigned long long ScriptingFunction;
+typedef BSONObj (*NativeFunction)(const BSONObj& args, void* data);
+typedef std::map<std::string, ScriptingFunction> FunctionCacheMap;
+
+class DBClientWithCommands;
+class DBClientBase;
+class OperationContext;
+
+struct JSFile {
+ const char* name;
+ const StringData& source;
+};
+
+class Scope {
+ MONGO_DISALLOW_COPYING(Scope);
+
+public:
+ Scope();
+ virtual ~Scope();
+
+ virtual void reset() = 0;
+ virtual void init(const BSONObj* data) = 0;
+ virtual void registerOperation(OperationContext* txn) = 0;
+ virtual void unregisterOperation() = 0;
+
+ void init(const char* data) {
+ BSONObj o(data);
+ init(&o);
+ }
+
+ virtual void localConnectForDbEval(OperationContext* txn, const char* dbName) = 0;
+ virtual void externalSetup() = 0;
+ virtual void setLocalDB(const std::string& localDBName) {
+ _localDBName = localDBName;
+ }
+
+ virtual BSONObj getObject(const char* field) = 0;
+ virtual std::string getString(const char* field) = 0;
+ virtual bool getBoolean(const char* field) = 0;
+ virtual double getNumber(const char* field) = 0;
+ virtual int getNumberInt(const char* field) {
+ return (int)getNumber(field);
+ }
+ virtual long long getNumberLongLong(const char* field) {
+ return static_cast<long long>(getNumber(field));
+ }
+
+ virtual void setElement(const char* field, const BSONElement& e) = 0;
+ virtual void setNumber(const char* field, double val) = 0;
+ virtual void setString(const char* field, StringData val) = 0;
+ virtual void setObject(const char* field, const BSONObj& obj, bool readOnly = true) = 0;
+ virtual void setBoolean(const char* field, bool val) = 0;
+ virtual void setFunction(const char* field, const char* code) = 0;
+
+ virtual int type(const char* field) = 0;
+
+ virtual void append(BSONObjBuilder& builder, const char* fieldName, const char* scopeName);
+
+ virtual void rename(const char* from, const char* to) = 0;
+
+ virtual std::string getError() = 0;
+
+ virtual bool hasOutOfMemoryException() = 0;
+
+ virtual bool isKillPending() const = 0;
+
+ virtual void gc() = 0;
+
+ virtual ScriptingFunction createFunction(const char* code);
+
+ /**
+ * @return 0 on success
+ */
+ int invoke(const char* code, const BSONObj* args, const BSONObj* recv, int timeoutMs = 0);
+
+ virtual int invoke(ScriptingFunction func,
+ const BSONObj* args,
+ const BSONObj* recv,
+ int timeoutMs = 0,
+ bool ignoreReturn = false,
+ bool readOnlyArgs = false,
+ bool readOnlyRecv = false) = 0;
+
+ void invokeSafe(ScriptingFunction func,
+ const BSONObj* args,
+ const BSONObj* recv,
+ int timeoutMs = 0,
+ bool ignoreReturn = false,
+ bool readOnlyArgs = false,
+ bool readOnlyRecv = false) {
+ int res = invoke(func, args, recv, timeoutMs, ignoreReturn, readOnlyArgs, readOnlyRecv);
+ if (res == 0)
+ return;
+ uasserted(9004, std::string("invoke failed: ") + getError());
+ }
+
+ void invokeSafe(const char* code, const BSONObj* args, const BSONObj* recv, int timeoutMs = 0) {
+ if (invoke(code, args, recv, timeoutMs) == 0)
+ return;
+ uasserted(9005, std::string("invoke failed: ") + getError());
+ }
+
+ virtual void injectNative(const char* field, NativeFunction func, void* data = 0) = 0;
+
+ virtual bool exec(StringData code,
+ const std::string& name,
+ bool printResult,
+ bool reportError,
+ bool assertOnError,
+ int timeoutMs = 0) = 0;
+
+ virtual void execSetup(StringData code, const std::string& name = "setup") {
+ exec(code, name, false, true, true, 0);
+ }
+
+ void execSetup(const JSFile& file) {
+ execSetup(file.source, file.name);
+ }
+
+ virtual bool execFile(const std::string& filename,
+ bool printResult,
+ bool reportError,
+ int timeoutMs = 0);
+
+ void execCoreFiles();
+
+ virtual void loadStored(OperationContext* txn, bool ignoreNotConnected = false);
+
+ /**
+ * if any changes are made to .system.js, call this
+ * right now its just global - slightly inefficient, but a lot simpler
+ */
+ static void storedFuncMod(OperationContext* txn);
+
+ static void validateObjectIdString(const std::string& str);
+
+ /** increments the number of times a scope was used */
+ void incTimesUsed() {
+ ++_numTimesUsed;
+ }
+
+ /** gets the number of times a scope was used */
+ int getTimesUsed() const {
+ return _numTimesUsed;
+ }
- class DBClientWithCommands;
- class DBClientBase;
- class OperationContext;
+ /** return true if last invoke() return'd native code */
+ virtual bool isLastRetNativeCode() {
+ return _lastRetIsNativeCode;
+ }
- struct JSFile {
- const char* name;
- const StringData& source;
- };
-
- class Scope {
- MONGO_DISALLOW_COPYING(Scope);
- public:
- Scope();
- virtual ~Scope();
-
- virtual void reset() = 0;
- virtual void init(const BSONObj* data) = 0;
- virtual void registerOperation(OperationContext* txn) = 0;
- virtual void unregisterOperation() = 0;
-
- void init(const char* data) {
- BSONObj o(data);
- init(&o);
- }
-
- virtual void localConnectForDbEval(OperationContext* txn, const char* dbName) = 0;
- virtual void externalSetup() = 0;
- virtual void setLocalDB(const std::string& localDBName) { _localDBName = localDBName; }
-
- virtual BSONObj getObject(const char* field) = 0;
- virtual std::string getString(const char* field) = 0;
- virtual bool getBoolean(const char* field) = 0;
- virtual double getNumber(const char* field) = 0;
- virtual int getNumberInt(const char* field) { return (int)getNumber(field); }
- virtual long long getNumberLongLong(const char* field) {
- return static_cast<long long>(getNumber(field));
- }
-
- virtual void setElement(const char* field, const BSONElement& e) = 0;
- virtual void setNumber(const char* field, double val) = 0;
- virtual void setString(const char* field, StringData val) = 0;
- virtual void setObject(const char* field, const BSONObj& obj, bool readOnly=true) = 0;
- virtual void setBoolean(const char* field, bool val) = 0;
- virtual void setFunction(const char* field, const char* code) = 0;
-
- virtual int type(const char* field) = 0;
-
- virtual void append(BSONObjBuilder& builder, const char* fieldName, const char* scopeName);
-
- virtual void rename(const char* from, const char* to) = 0;
-
- virtual std::string getError() = 0;
-
- virtual bool hasOutOfMemoryException() = 0;
-
- virtual bool isKillPending() const = 0;
-
- virtual void gc() = 0;
-
- virtual ScriptingFunction createFunction(const char* code);
-
- /**
- * @return 0 on success
- */
- int invoke(const char* code, const BSONObj* args, const BSONObj* recv, int timeoutMs = 0);
-
- virtual int invoke(ScriptingFunction func, const BSONObj* args, const BSONObj* recv,
- int timeoutMs = 0, bool ignoreReturn = false, bool readOnlyArgs = false,
- bool readOnlyRecv = false) = 0;
-
- void invokeSafe(ScriptingFunction func, const BSONObj* args, const BSONObj* recv,
- int timeoutMs = 0, bool ignoreReturn = false, bool readOnlyArgs = false,
- bool readOnlyRecv = false) {
- int res = invoke(func, args, recv, timeoutMs, ignoreReturn,
- readOnlyArgs, readOnlyRecv);
- if (res == 0)
- return;
- uasserted(9004, std::string("invoke failed: ") + getError());
- }
-
- void invokeSafe(const char* code, const BSONObj* args, const BSONObj* recv,
- int timeoutMs = 0) {
- if (invoke(code, args, recv, timeoutMs) == 0)
- return;
- uasserted(9005, std::string("invoke failed: ") + getError());
- }
-
- virtual void injectNative(const char* field, NativeFunction func, void* data = 0) = 0;
-
- virtual bool exec(StringData code, const std::string& name, bool printResult,
- bool reportError, bool assertOnError, int timeoutMs = 0) = 0;
-
- virtual void execSetup(StringData code, const std::string& name = "setup") {
- exec(code, name, false, true, true, 0);
- }
-
- void execSetup(const JSFile& file) {
- execSetup(file.source, file.name);
- }
-
- virtual bool execFile(const std::string& filename, bool printResult, bool reportError,
- int timeoutMs = 0);
-
- void execCoreFiles();
-
- virtual void loadStored(OperationContext* txn, bool ignoreNotConnected = false);
-
- /**
- * if any changes are made to .system.js, call this
- * right now its just global - slightly inefficient, but a lot simpler
- */
- static void storedFuncMod(OperationContext *txn);
-
- static void validateObjectIdString(const std::string& str);
-
- /** increments the number of times a scope was used */
- void incTimesUsed() { ++_numTimesUsed; }
+ class NoDBAccess {
+ Scope* _s;
- /** gets the number of times a scope was used */
- int getTimesUsed() const { return _numTimesUsed; }
-
- /** return true if last invoke() return'd native code */
- virtual bool isLastRetNativeCode() { return _lastRetIsNativeCode; }
-
- class NoDBAccess {
- Scope* _s;
- public:
- NoDBAccess(Scope* s) : _s(s) {
- }
- ~NoDBAccess() {
- _s->rename("____db____", "db");
- }
- };
- NoDBAccess disableDBAccess(const char* why) {
- rename("db", "____db____");
- return NoDBAccess(this);
- }
-
- protected:
- friend class PooledScope;
-
- /**
- * RecoveryUnit::Change subclass used to commit work for
- * Scope::storedFuncMod logOp listener.
- */
- class StoredFuncModLogOpHandler;
-
- virtual FunctionCacheMap& getFunctionCache() { return _cachedFunctions; }
- virtual ScriptingFunction _createFunction(const char* code,
- ScriptingFunction functionNumber = 0) = 0;
-
- std::string _localDBName;
- int64_t _loadedVersion;
- std::set<std::string> _storedNames;
- static AtomicInt64 _lastVersion;
- FunctionCacheMap _cachedFunctions;
- int _numTimesUsed;
- bool _lastRetIsNativeCode; // v8 only: set to true if eval'd script returns a native func
- };
-
- class ScriptEngine : public KillOpListenerInterface {
- MONGO_DISALLOW_COPYING(ScriptEngine);
public:
- ScriptEngine();
- virtual ~ScriptEngine();
-
- virtual Scope* newScope() {
- return createScope();
+ NoDBAccess(Scope* s) : _s(s) {}
+ ~NoDBAccess() {
+ _s->rename("____db____", "db");
}
-
- virtual void runTest() = 0;
-
- virtual bool utf8Ok() const = 0;
-
- static void setup();
-
- /** gets a scope from the pool or a new one if pool is empty
- * @param db The db name
- * @param scopeType A unique id to limit scope sharing.
- * This must include authenticated users.
- * @return the scope
- */
- std::unique_ptr<Scope> getPooledScope(OperationContext* txn,
- const std::string& db,
- const std::string& scopeType);
-
- void setScopeInitCallback(void (*func)(Scope&)) { _scopeInitCallback = func; }
- static void setConnectCallback(void (*func)(DBClientWithCommands&)) {
- _connectCallback = func;
- }
- static void runConnectCallback(DBClientWithCommands& c) {
- if (_connectCallback)
- _connectCallback(c);
- }
-
- // engine implementation may either respond to interrupt events or
- // poll for interrupts. the interrupt functions must not wait indefinitely on a lock.
- virtual void interrupt(unsigned opId) {}
- virtual void interruptAll() {}
-
- static std::string getInterpreterVersionString();
-
- protected:
- virtual Scope* createScope() = 0;
- void (*_scopeInitCallback)(Scope&);
-
- private:
- static void (*_connectCallback)(DBClientWithCommands&);
};
-
- void installGlobalUtils(Scope& scope);
- bool hasJSReturn(const std::string& s);
- const char* jsSkipWhiteSpace(const char* raw);
-
- DBClientBase* createDirectClient(OperationContext* txn);
-
- extern ScriptEngine* globalScriptEngine;
+ NoDBAccess disableDBAccess(const char* why) {
+ rename("db", "____db____");
+ return NoDBAccess(this);
+ }
+
+protected:
+ friend class PooledScope;
+
+ /**
+ * RecoveryUnit::Change subclass used to commit work for
+ * Scope::storedFuncMod logOp listener.
+ */
+ class StoredFuncModLogOpHandler;
+
+ virtual FunctionCacheMap& getFunctionCache() {
+ return _cachedFunctions;
+ }
+ virtual ScriptingFunction _createFunction(const char* code,
+ ScriptingFunction functionNumber = 0) = 0;
+
+ std::string _localDBName;
+ int64_t _loadedVersion;
+ std::set<std::string> _storedNames;
+ static AtomicInt64 _lastVersion;
+ FunctionCacheMap _cachedFunctions;
+ int _numTimesUsed;
+ bool _lastRetIsNativeCode; // v8 only: set to true if eval'd script returns a native func
+};
+
+class ScriptEngine : public KillOpListenerInterface {
+ MONGO_DISALLOW_COPYING(ScriptEngine);
+
+public:
+ ScriptEngine();
+ virtual ~ScriptEngine();
+
+ virtual Scope* newScope() {
+ return createScope();
+ }
+
+ virtual void runTest() = 0;
+
+ virtual bool utf8Ok() const = 0;
+
+ static void setup();
+
+ /** gets a scope from the pool or a new one if pool is empty
+ * @param db The db name
+ * @param scopeType A unique id to limit scope sharing.
+ * This must include authenticated users.
+ * @return the scope
+ */
+ std::unique_ptr<Scope> getPooledScope(OperationContext* txn,
+ const std::string& db,
+ const std::string& scopeType);
+
+ void setScopeInitCallback(void (*func)(Scope&)) {
+ _scopeInitCallback = func;
+ }
+ static void setConnectCallback(void (*func)(DBClientWithCommands&)) {
+ _connectCallback = func;
+ }
+ static void runConnectCallback(DBClientWithCommands& c) {
+ if (_connectCallback)
+ _connectCallback(c);
+ }
+
+ // engine implementation may either respond to interrupt events or
+ // poll for interrupts. the interrupt functions must not wait indefinitely on a lock.
+ virtual void interrupt(unsigned opId) {}
+ virtual void interruptAll() {}
+
+ static std::string getInterpreterVersionString();
+
+protected:
+ virtual Scope* createScope() = 0;
+ void (*_scopeInitCallback)(Scope&);
+
+private:
+ static void (*_connectCallback)(DBClientWithCommands&);
+};
+
+void installGlobalUtils(Scope& scope);
+bool hasJSReturn(const std::string& s);
+const char* jsSkipWhiteSpace(const char* raw);
+
+DBClientBase* createDirectClient(OperationContext* txn);
+
+extern ScriptEngine* globalScriptEngine;
}