diff options
author | Benety Goh <benety@mongodb.com> | 2014-05-13 09:31:15 -0400 |
---|---|---|
committer | Benety Goh <benety@mongodb.com> | 2014-05-15 09:30:25 -0400 |
commit | c576cdd324f847e0f047dfa5d1bee429d659efb2 (patch) | |
tree | c1da5166a10e815b9fc5f4f13673a00fa830cdc6 /src/mongo/scripting | |
parent | d2e4b7d17a8b4a406f053e39f692f394d66e6b11 (diff) | |
download | mongo-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.h | 20 | ||||
-rw-r--r-- | src/mongo/scripting/v8_db.cpp | 50 | ||||
-rw-r--r-- | src/mongo/scripting/v8_db.h | 2 |
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); |