void run() { auto_ptr<PlanExecutor> run(getCollscan()); BSONObj obj; ASSERT_OK(dbtests::createIndex(&_opCtx, ns(), BSON("foo" << 1))); // Read some of it. for (int i = 0; i < 10; ++i) { ASSERT_EQUALS(PlanExecutor::ADVANCED, run->getNext(&obj, NULL)); ASSERT_EQUALS(i, obj["foo"].numberInt()); } // Save state and register. run->saveState(); registerExecutor(run.get()); // Drop a specific index. _client.dropIndex(ns(), BSON("foo" << 1)); // Unregister and restore state. deregisterExecutor(run.get()); run->restoreState(&_opCtx); // PlanExecutor was killed. ASSERT_EQUALS(PlanExecutor::DEAD, run->getNext(&obj, NULL)); }
void run() { auto_ptr<PlanExecutor> run(getCollscan()); BSONObj obj; // Read some of it. for (int i = 0; i < 10; ++i) { ASSERT_EQUALS(PlanExecutor::ADVANCED, run->getNext(&obj, NULL)); ASSERT_EQUALS(i, obj["foo"].numberInt()); } // Save state and register. run->saveState(); registerExecutor(run.get()); // Drop a DB that's not ours. We can't have a lock at all to do this as dropping a DB // requires a "global write lock." _ctx.reset(); _client.dropDatabase("somesillydb"); _ctx.reset(new Client::WriteContext(&_opCtx, ns())); // Unregister and restore state. deregisterExecutor(run.get()); run->restoreState(&_opCtx); ASSERT_EQUALS(PlanExecutor::ADVANCED, run->getNext(&obj, NULL)); ASSERT_EQUALS(10, obj["foo"].numberInt()); // Save state and register. run->saveState(); registerExecutor(run.get()); // Drop our DB. Once again, must give up the lock. _ctx.reset(); _client.dropDatabase("unittests"); _ctx.reset(new Client::WriteContext(&_opCtx, ns())); // Unregister and restore state. deregisterExecutor(run.get()); run->restoreState(&_opCtx); _ctx.reset(); // PlanExecutor was killed. ASSERT_EQUALS(PlanExecutor::DEAD, run->getNext(&obj, NULL)); }
void run() { auto_ptr<PlanExecutor> run(getCollscan()); BSONObj obj; // Read some of it. for (int i = 0; i < 10; ++i) { ASSERT_EQUALS(PlanExecutor::ADVANCED, run->getNext(&obj, NULL)); ASSERT_EQUALS(i, obj["foo"].numberInt()); } // Save state and register. run->saveState(); registerExecutor(run.get()); // Drop a collection that's not ours. _client.dropCollection("unittests.someboguscollection"); // Unregister and restore state. deregisterExecutor(run.get()); run->restoreState(&_opCtx); ASSERT_EQUALS(PlanExecutor::ADVANCED, run->getNext(&obj, NULL)); ASSERT_EQUALS(10, obj["foo"].numberInt()); // Save state and register. run->saveState(); registerExecutor(run.get()); // Drop our collection. _client.dropCollection(ns()); // Unregister and restore state. deregisterExecutor(run.get()); run->restoreState(&_opCtx); // PlanExecutor was killed. ASSERT_EQUALS(PlanExecutor::DEAD, run->getNext(&obj, NULL)); }
Bridge::Bridge( JSExecutorFactory* jsExecutorFactory, std::unique_ptr<ExecutorTokenFactory> executorTokenFactory, std::unique_ptr<BridgeCallback> callback) : m_callback(std::move(callback)), m_destroyed(std::make_shared<bool>(false)), m_executorTokenFactory(std::move(executorTokenFactory)) { std::unique_ptr<JSExecutor> mainExecutor = jsExecutorFactory->createJSExecutor(this); // cached to avoid locked map lookup in the common case m_mainExecutor = mainExecutor.get(); m_mainExecutorToken = folly::make_unique<ExecutorToken>(registerExecutor( std::move(mainExecutor), MessageQueues::getCurrentMessageQueueThread())); }
NativeToJsBridge::NativeToJsBridge( JSExecutorFactory* jsExecutorFactory, std::shared_ptr<ModuleRegistry> registry, std::shared_ptr<MessageQueueThread> jsQueue, std::unique_ptr<MessageQueueThread> nativeQueue, std::shared_ptr<InstanceCallback> callback) : m_destroyed(std::make_shared<bool>(false)) , m_mainExecutorToken(callback->createExecutorToken()) , m_delegate(std::make_shared<JsToNativeBridge>( this, registry, std::move(nativeQueue), callback)) { std::unique_ptr<JSExecutor> mainExecutor = jsExecutorFactory->createJSExecutor(m_delegate, jsQueue); // cached to avoid locked map lookup in the common case m_mainExecutor = mainExecutor.get(); registerExecutor(m_mainExecutorToken, std::move(mainExecutor), jsQueue); }
void run() { if ( supportsDocLocking() ) { return; } auto_ptr<PlanExecutor> run(getCollscan()); BSONObj obj; // Read some of it. for (int i = 0; i < 10; ++i) { ASSERT_EQUALS(PlanExecutor::ADVANCED, run->getNext(&obj, NULL)); ASSERT_EQUALS(i, obj["foo"].numberInt()); } // Register it. run->saveState(); registerExecutor(run.get()); // At this point it's safe to yield. forceYield would do that. Let's now simulate some // stuff going on in the yield. // Delete some data, namely the next 2 things we'd expect. _client.remove(ns(), BSON("foo" << 10)); _client.remove(ns(), BSON("foo" << 11)); // At this point, we're done yielding. We recover our lock. // Unregister the runner. deregisterExecutor(run.get()); // And clean up anything that happened before. run->restoreState(&_opCtx); // Make sure that the runner moved forward over the deleted data. We don't see foo==10 // or foo==11. for (int i = 12; i < N(); ++i) { ASSERT_EQUALS(PlanExecutor::ADVANCED, run->getNext(&obj, NULL)); ASSERT_EQUALS(i, obj["foo"].numberInt()); } ASSERT_EQUALS(PlanExecutor::IS_EOF, run->getNext(&obj, NULL)); }