summaryrefslogtreecommitdiff
path: root/scripting/engine.h
diff options
context:
space:
mode:
Diffstat (limited to 'scripting/engine.h')
-rw-r--r--scripting/engine.h134
1 files changed, 103 insertions, 31 deletions
diff --git a/scripting/engine.h b/scripting/engine.h
index e097401..62afd77 100644
--- a/scripting/engine.h
+++ b/scripting/engine.h
@@ -20,10 +20,23 @@
#include "../pch.h"
#include "../db/jsobj.h"
-extern const char * jsconcatcode; // TODO: change name to mongoJSCode
-
namespace mongo {
+ struct JSFile {
+ const char* name;
+ const StringData& source;
+ };
+
+ 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 servers;
+ extern const JSFile utils;
+ }
+
typedef unsigned long long ScriptingFunction;
typedef BSONObj (*NativeFunction) ( const BSONObj &args );
@@ -31,20 +44,35 @@ namespace mongo {
public:
Scope();
virtual ~Scope();
-
+
virtual void reset() = 0;
- virtual void init( BSONObj * data ) = 0;
- void init( const char * data ){
+ virtual void init( const BSONObj * data ) = 0;
+ void init( const char * data ) {
BSONObj o( data , 0 );
init( &o );
}
-
+
virtual void localConnect( const char * dbName ) = 0;
virtual void externalSetup() = 0;
-
+
+ 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 );
+ }
+
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 (long long)getNumber( field ); }
+ virtual int getNumberInt( const char *field ) { return (int)getNumber( field ); }
+ virtual long long getNumberLongLong( const char *field ) { return (long long)getNumber( field ); }
virtual string getString( const char *field ) = 0;
virtual bool getBoolean( const char *field ) = 0;
virtual BSONObj getObject( const char *field ) = 0;
@@ -59,52 +87,68 @@ namespace mongo {
virtual void setObject( const char *field , const BSONObj& obj , bool readOnly=true ) = 0;
virtual void setBoolean( const char *field , bool val ) = 0;
virtual void setThis( const BSONObj * obj ) = 0;
-
+
virtual ScriptingFunction createFunction( const char * code );
-
+
+ virtual void rename( const char * from , const char * to ) = 0;
/**
* @return 0 on success
*/
virtual int invoke( ScriptingFunction func , const BSONObj& args, int timeoutMs = 0 , bool ignoreReturn = false ) = 0;
- void invokeSafe( ScriptingFunction func , const BSONObj& args, int timeoutMs = 0 ){
+ void invokeSafe( ScriptingFunction func , const BSONObj& args, int timeoutMs = 0 ) {
int res = invoke( func , args , timeoutMs );
if ( res == 0 )
return;
throw UserException( 9004 , (string)"invoke failed: " + getError() );
}
virtual string getError() = 0;
-
+
int invoke( const char* code , const BSONObj& args, int timeoutMs = 0 );
- void invokeSafe( const char* code , const BSONObj& args, int timeoutMs = 0 ){
+ void invokeSafe( const char* code , const BSONObj& args, int timeoutMs = 0 ) {
if ( invoke( code , args , timeoutMs ) == 0 )
return;
throw UserException( 9005 , (string)"invoke failed: " + getError() );
}
- virtual bool exec( const string& code , const string& name , bool printResult , bool reportError , bool assertOnError, int timeoutMs = 0 ) = 0;
- virtual void execSetup( const string& code , const string& name = "setup" ){
+ virtual bool exec( const StringData& code , const string& name , bool printResult , bool reportError , bool assertOnError, int timeoutMs = 0 ) = 0;
+ virtual void execSetup( const StringData& code , const string& name = "setup" ) {
exec( code , name , false , true , true , 0 );
}
+
+ void execSetup( const JSFile& file) {
+ execSetup(file.source, file.name);
+ }
+
+ void execCoreFiles() {
+ // keeping same order as in SConstruct
+ execSetup(JSFiles::utils);
+ execSetup(JSFiles::db);
+ execSetup(JSFiles::mongo);
+ execSetup(JSFiles::mr);
+ execSetup(JSFiles::query);
+ execSetup(JSFiles::collection);
+ }
+
virtual bool execFile( const string& filename , bool printResult , bool reportError , bool assertOnError, int timeoutMs = 0 );
-
+
virtual void injectNative( const char *field, NativeFunction func ) = 0;
virtual void gc() = 0;
void loadStored( 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();
-
- static int getNumScopes(){
+
+ static int getNumScopes() {
return _numScopes;
}
-
+
static void validateObjectIdString( const string &str );
-
+
protected:
virtual ScriptingFunction _createFunction( const char * code ) = 0;
@@ -117,16 +161,16 @@ namespace mongo {
static int _numScopes;
};
-
+
void installGlobalUtils( Scope& scope );
class DBClientWithCommands;
-
+
class ScriptEngine : boost::noncopyable {
public:
ScriptEngine();
virtual ~ScriptEngine();
-
+
virtual Scope * newScope() {
Scope *s = createScope();
if ( s && _scopeInitCallback )
@@ -134,35 +178,63 @@ namespace mongo {
installGlobalUtils( *s );
return s;
}
-
+
virtual void runTest() = 0;
-
+
virtual bool utf8Ok() const = 0;
static void setup();
auto_ptr<Scope> getPooledScope( const string& pool );
void threadDone();
-
+
struct Unlocker { virtual ~Unlocker() {} };
virtual auto_ptr<Unlocker> newThreadUnlocker() { return auto_ptr< Unlocker >( new Unlocker ); }
-
+
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 opSpec ) {}
+ virtual void interruptAll() {}
+
+ static void setGetInterruptSpecCallback( unsigned ( *func )() ) { _getInterruptSpecCallback = func; }
+ static bool haveGetInterruptSpecCallback() { return _getInterruptSpecCallback; }
+ static unsigned getInterruptSpec() {
+ massert( 13474, "no _getInterruptSpecCallback", _getInterruptSpecCallback );
+ return _getInterruptSpecCallback();
+ }
+
+ static void setCheckInterruptCallback( const char * ( *func )() ) { _checkInterruptCallback = func; }
+ static bool haveCheckInterruptCallback() { return _checkInterruptCallback; }
+ static const char * checkInterrupt() {
+ return _checkInterruptCallback ? _checkInterruptCallback() : "";
+ }
+ static bool interrupted() {
+ const char *r = checkInterrupt();
+ return r && r[ 0 ];
+ }
+
protected:
virtual Scope * createScope() = 0;
-
+
private:
void ( *_scopeInitCallback )( Scope & );
static void ( *_connectCallback )( DBClientWithCommands & );
+ static const char * ( *_checkInterruptCallback )();
+ static unsigned ( *_getInterruptSpecCallback )();
};
bool hasJSReturn( const string& s );
+ const char * jsSkipWhiteSpace( const char * raw );
+
extern ScriptEngine * globalScriptEngine;
}