summaryrefslogtreecommitdiff
path: root/src/mongo/scripting
diff options
context:
space:
mode:
authorBenety Goh <benety@mongodb.com>2014-05-13 09:31:15 -0400
committerBenety Goh <benety@mongodb.com>2014-05-15 09:30:25 -0400
commitc576cdd324f847e0f047dfa5d1bee429d659efb2 (patch)
treec1da5166a10e815b9fc5f4f13673a00fa830cdc6 /src/mongo/scripting
parentd2e4b7d17a8b4a406f053e39f692f394d66e6b11 (diff)
downloadmongo-c576cdd324f847e0f047dfa5d1bee429d659efb2.tar.gz
SERVER-13798 add dependency on connection to cursor object tracker in JavaScript scripting engine
Diffstat (limited to 'src/mongo/scripting')
-rw-r--r--src/mongo/scripting/engine_v8.h20
-rw-r--r--src/mongo/scripting/v8_db.cpp50
-rw-r--r--src/mongo/scripting/v8_db.h2
3 files changed, 45 insertions, 27 deletions
diff --git a/src/mongo/scripting/engine_v8.h b/src/mongo/scripting/engine_v8.h
index f711911454c..a4262450c97 100644
--- a/src/mongo/scripting/engine_v8.h
+++ b/src/mongo/scripting/engine_v8.h
@@ -17,6 +17,7 @@
#pragma once
+#include <boost/shared_ptr.hpp>
#include <v8.h>
#include <vector>
@@ -60,13 +61,16 @@ namespace mongo {
class ObjTracker {
public:
/** Track an object to be freed when it is no longer referenced in JavaScript.
+ * Return handle to object instance shared pointer.
* @param instanceHandle persistent handle to the weakly referenced object
* @param rawData pointer to the object instance
*/
- void track(v8::Persistent<v8::Value> instanceHandle, _ObjType* instance) {
+ v8::Local<v8::External> track(v8::Persistent<v8::Value> instanceHandle,
+ _ObjType* instance) {
TrackedPtr* collectionHandle = new TrackedPtr(instance, this);
_container.insert(collectionHandle);
instanceHandle.MakeWeak(collectionHandle, deleteOnCollect);
+ return v8::External::New(&(collectionHandle->_objPtr));
}
/**
* Free any remaining objects and their TrackedPtrs. Invoked when the
@@ -94,7 +98,7 @@ namespace mongo {
TrackedPtr(_ObjType* instance, ObjTracker<_ObjType>* tracker) :
_objPtr(instance),
_tracker(tracker) { }
- scoped_ptr<_ObjType> _objPtr;
+ boost::shared_ptr<_ObjType> _objPtr;
ObjTracker<_ObjType>* _tracker;
};
@@ -294,9 +298,17 @@ namespace mongo {
v8::Persistent<v8::Object> getGlobal() { return _global; }
ObjTracker<BSONHolder> bsonHolderTracker;
- ObjTracker<DBClientWithCommands> dbClientWithCommandsTracker;
ObjTracker<DBClientBase> dbClientBaseTracker;
- ObjTracker<DBClientCursor> dbClientCursorTracker;
+ // Track both cursor and connection.
+ // This ensures the connection outlives the cursor.
+ struct DBConnectionAndCursor {
+ boost::shared_ptr<DBClientBase> conn;
+ boost::shared_ptr<DBClientCursor> cursor;
+ DBConnectionAndCursor(boost::shared_ptr<DBClientBase> conn,
+ boost::shared_ptr<DBClientCursor> cursor)
+ : conn(conn), cursor(cursor) { }
+ };
+ ObjTracker<DBConnectionAndCursor> dbConnectionAndCursor;
// These are all named after the JS constructor name + FT
v8::Handle<v8::FunctionTemplate> ObjectIdFT() const { return _ObjectIdFT; }
diff --git a/src/mongo/scripting/v8_db.cpp b/src/mongo/scripting/v8_db.cpp
index 3f085115322..2bc86b5e32b 100644
--- a/src/mongo/scripting/v8_db.cpp
+++ b/src/mongo/scripting/v8_db.cpp
@@ -143,18 +143,18 @@ namespace mongo {
return v8AssertionException(errmsg);
}
- DBClientWithCommands* conn;
+ DBClientBase* conn;
conn = cs.connect(errmsg);
if (!conn) {
return v8AssertionException(errmsg);
}
v8::Persistent<v8::Object> self = v8::Persistent<v8::Object>::New(args.This());
- scope->dbClientWithCommandsTracker.track(self, conn);
+ v8::Local<v8::External> connHandle = scope->dbClientBaseTracker.track(self, conn);
ScriptEngine::runConnectCallback(*conn);
- args.This()->SetInternalField(0, v8::External::New(conn));
+ args.This()->SetInternalField(0, connHandle);
args.This()->ForceSet(scope->v8StringData("slaveOk"), v8::Boolean::New(false));
args.This()->ForceSet(scope->v8StringData("host"), scope->v8StringData(host));
@@ -171,22 +171,23 @@ namespace mongo {
DBClientBase* conn = createDirectClient();
v8::Persistent<v8::Object> self = v8::Persistent<v8::Object>::New(args.This());
- scope->dbClientBaseTracker.track(self, conn);
+ v8::Local<v8::External> connHandle = scope->dbClientBaseTracker.track(self, conn);
- args.This()->SetInternalField(0, v8::External::New(conn));
+ args.This()->SetInternalField(0, connHandle);
args.This()->ForceSet(scope->v8StringData("slaveOk"), v8::Boolean::New(false));
args.This()->ForceSet(scope->v8StringData("host"), scope->v8StringData("EMBEDDED"));
return v8::Undefined();
}
- DBClientBase* getConnection(V8Scope* scope, const v8::Arguments& args) {
+ boost::shared_ptr<DBClientBase> getConnection(V8Scope* scope, const v8::Arguments& args) {
verify(scope->MongoFT()->HasInstance(args.This()));
verify(args.This()->InternalFieldCount() == 1);
v8::Local<v8::External> c = v8::External::Cast(*(args.This()->GetInternalField(0)));
- DBClientBase* conn = (DBClientBase*)(c->Value());
- massert(16667, "Unable to get db client connection", conn);
- return conn;
+ boost::shared_ptr<DBClientBase>* conn =
+ static_cast<boost::shared_ptr<DBClientBase>*>(c->Value());
+ massert(16667, "Unable to get db client connection", conn && conn->get());
+ return *conn;
}
/**
@@ -195,7 +196,7 @@ namespace mongo {
v8::Handle<v8::Value> mongoFind(V8Scope* scope, const v8::Arguments& args) {
argumentCheck(args.Length() == 7, "find needs 7 args")
argumentCheck(args[1]->IsObject(), "needs to be an object")
- DBClientBase * conn = getConnection(scope, args);
+ boost::shared_ptr<DBClientBase> conn = getConnection(scope, args);
const string ns = toSTLString(args[0]);
BSONObj fields;
BSONObj q = scope->v8ToMongo(args[1]->ToObject());
@@ -204,7 +205,7 @@ namespace mongo {
if (haveFields)
fields = scope->v8ToMongo(args[2]->ToObject());
- auto_ptr<mongo::DBClientCursor> cursor;
+ boost::shared_ptr<mongo::DBClientCursor> cursor;
int nToReturn = args[3]->Int32Value();
int nToSkip = args[4]->Int32Value();
int batchSize = args[5]->Int32Value();
@@ -216,9 +217,11 @@ namespace mongo {
}
v8::Handle<v8::Function> cons = scope->InternalCursorFT()->GetFunction();
- v8::Persistent<v8::Object> c = v8::Persistent<v8::Object>::New(cons->NewInstance());
+ v8::Handle<v8::Object> c = cons->NewInstance();
c->SetInternalField(0, v8::External::New(cursor.get()));
- scope->dbClientCursorTracker.track(c, cursor.release());
+ scope->dbConnectionAndCursor.track(
+ v8::Persistent<v8::Value>::New(c),
+ new V8Scope::DBConnectionAndCursor(conn, cursor));
return c;
}
@@ -227,19 +230,22 @@ namespace mongo {
argumentCheck(scope->NumberLongFT()->HasInstance(args[1]), "2nd arg must be a NumberLong")
argumentCheck(args[2]->IsUndefined() || args[2]->IsNumber(), "3rd arg must be a js Number")
- DBClientBase* conn = getConnection(scope, args);
+ boost::shared_ptr<DBClientBase> conn = getConnection(scope, args);
const string ns = toSTLString(args[0]);
long long cursorId = numberLongVal(scope, args[1]->ToObject());
- auto_ptr<mongo::DBClientCursor> cursor(new DBClientCursor(conn, ns, cursorId, 0, 0));
+ boost::shared_ptr<mongo::DBClientCursor> cursor(
+ new DBClientCursor(conn.get(), ns, cursorId, 0, 0));
if (!args[2]->IsUndefined())
cursor->setBatchSize(args[2]->Int32Value());
v8::Handle<v8::Function> cons = scope->InternalCursorFT()->GetFunction();
- v8::Persistent<v8::Object> c = v8::Persistent<v8::Object>::New(cons->NewInstance());
+ v8::Handle<v8::Object> c = cons->NewInstance();
c->SetInternalField(0, v8::External::New(cursor.get()));
- scope->dbClientCursorTracker.track(c, cursor.release());
+ scope->dbConnectionAndCursor.track(
+ v8::Persistent<v8::Value>::New(c),
+ new V8Scope::DBConnectionAndCursor(conn, cursor));
return c;
}
@@ -253,7 +259,7 @@ namespace mongo {
return v8AssertionException("js db in read only mode");
}
- DBClientBase * conn = getConnection(scope, args);
+ boost::shared_ptr<DBClientBase> conn = getConnection(scope, args);
const string ns = toSTLString(args[0]);
v8::Handle<v8::Integer> flags = args[2]->ToInteger();
@@ -301,7 +307,7 @@ namespace mongo {
return v8AssertionException("js db in read only mode");
}
- DBClientBase * conn = getConnection(scope, args);
+ boost::shared_ptr<DBClientBase> conn = getConnection(scope, args);
const string ns = toSTLString(args[0]);
v8::Handle<v8::Object> in = args[1]->ToObject();
@@ -327,7 +333,7 @@ namespace mongo {
return v8AssertionException("js db in read only mode");
}
- DBClientBase * conn = getConnection(scope, args);
+ boost::shared_ptr<DBClientBase> conn = getConnection(scope, args);
const string ns = toSTLString(args[0]);
v8::Handle<v8::Object> q = args[1]->ToObject();
@@ -343,7 +349,7 @@ namespace mongo {
}
v8::Handle<v8::Value> mongoAuth(V8Scope* scope, const v8::Arguments& args) {
- DBClientWithCommands* conn = getConnection(scope, args);
+ boost::shared_ptr<DBClientBase> conn = getConnection(scope, args);
if (NULL == conn)
return v8AssertionException("no connection");
@@ -372,7 +378,7 @@ namespace mongo {
v8::Handle<v8::Value> mongoLogout(V8Scope* scope, const v8::Arguments& args) {
argumentCheck(args.Length() == 1, "logout needs 1 arg")
- DBClientBase* conn = getConnection(scope, args);
+ boost::shared_ptr<DBClientBase> conn = getConnection(scope, args);
const string db = toSTLString(args[0]);
BSONObj ret;
conn->logout(db, ret);
diff --git a/src/mongo/scripting/v8_db.h b/src/mongo/scripting/v8_db.h
index 9de634b9471..c00cf703df9 100644
--- a/src/mongo/scripting/v8_db.h
+++ b/src/mongo/scripting/v8_db.h
@@ -29,7 +29,7 @@ namespace mongo {
/**
* get the DBClientBase connection from JS args
*/
- mongo::DBClientBase* getConnection(V8Scope* scope, const v8::Arguments& args);
+ boost::shared_ptr<mongo::DBClientBase> getConnection(V8Scope* scope, const v8::Arguments& args);
// Internal Cursor
v8::Handle<v8::FunctionTemplate> getInternalCursorFunctionTemplate(V8Scope* scope);