diff options
author | Dianna Hohensee <dianna.hohensee@10gen.com> | 2016-04-06 11:06:10 -0400 |
---|---|---|
committer | Dianna Hohensee <dianna.hohensee@10gen.com> | 2016-04-06 11:06:10 -0400 |
commit | 202fd419457c47650be27accb038a700134797ed (patch) | |
tree | 842d58673be0d3eaf992eca8566931fb1c77cc7e | |
parent | 36f3ff8da1f7ae3710ceacc4e13adfd4abdb99da (diff) | |
download | mongo-202fd419457c47650be27accb038a700134797ed.tar.gz |
Revert "SERVER-23445 create LocalClient class for local queries/writes, implement a find query interface"
This reverts commit 02779909333ff4333c316b54b9fbb2fdd635e15a.
-rw-r--r-- | src/mongo/db/SConscript | 24 | ||||
-rw-r--r-- | src/mongo/db/dbhelpers.cpp | 6 | ||||
-rw-r--r-- | src/mongo/db/dbhelpers.h | 25 | ||||
-rw-r--r-- | src/mongo/db/local_client.cpp | 145 | ||||
-rw-r--r-- | src/mongo/db/local_client.h | 135 | ||||
-rw-r--r-- | src/mongo/db/local_client_test.cpp | 183 |
6 files changed, 17 insertions, 501 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript index 2bd2e2403f0..deac8c6ec4c 100644 --- a/src/mongo/db/SConscript +++ b/src/mongo/db/SConscript @@ -114,30 +114,6 @@ env.CppUnitTest( env.CppUnitTest('record_id_test', 'record_id_test.cpp', LIBDEPS=[]) env.Library( - target='local_client', - source=[ - 'local_client.cpp', - ], - LIBDEPS=[ - 'query/query', - ] -) - -env.CppUnitTest( - target='local_client_test', - source=[ - 'local_client_test.cpp', - ], - LIBDEPS=[ - 'local_client', - 'repl/replmocks', - 'serveronly', - '$BUILD_DIR/mongo/util/ntservice_mock', - ], - NO_CRUTCH = True, -) - -env.Library( target='startup_warnings_common', source=[ 'startup_warnings_common.cpp', diff --git a/src/mongo/db/dbhelpers.cpp b/src/mongo/db/dbhelpers.cpp index 3b572eacbab..fa7824f0768 100644 --- a/src/mongo/db/dbhelpers.cpp +++ b/src/mongo/db/dbhelpers.cpp @@ -107,6 +107,9 @@ void Helpers::ensureIndex(OperationContext* txn, wunit.commit(); } +/* fetch a single object from collection ns that matches query + set your db SavedContext first +*/ bool Helpers::findOne(OperationContext* txn, Collection* collection, const BSONObj& query, @@ -119,6 +122,9 @@ bool Helpers::findOne(OperationContext* txn, return true; } +/* fetch a single object from collection ns that matches query + set your db SavedContext first +*/ RecordId Helpers::findOne(OperationContext* txn, Collection* collection, const BSONObj& query, diff --git a/src/mongo/db/dbhelpers.h b/src/mongo/db/dbhelpers.h index 334857bd10a..53d0839711b 100644 --- a/src/mongo/db/dbhelpers.h +++ b/src/mongo/db/dbhelpers.h @@ -69,26 +69,23 @@ struct Helpers { bool unique, const char* name); - /** - * Fetches a single BSONObj document from the given collection that matches query. - * - * @param collection - collection to be queried. - * @param query - the query to perform. Note this is the low level portion of query so - * "orderby : ..." won't work. - * @param result - holds the found BSONObj document, if found. - * @param requireIndex - if true, assert if no index for the query. A way to guard against - * writing a slow query. - * @return true if a document is found. - */ + /* fetch a single object from collection ns that matches query. + set your db SavedContext first. + + @param query - the query to perform. note this is the low level portion of query so + "orderby : ..." won't work. + + @param requireIndex if true, assert if no index for the query. a way to guard against + writing a slow query. + + @return true if object found + */ static bool findOne(OperationContext* txn, Collection* collection, const BSONObj& query, BSONObj& result, bool requireIndex = false); - /** - * Fetches the RecordId location of a single object from collection ns that matches query. - */ static RecordId findOne(OperationContext* txn, Collection* collection, const BSONObj& query, diff --git a/src/mongo/db/local_client.cpp b/src/mongo/db/local_client.cpp deleted file mode 100644 index f9aded6e30b..00000000000 --- a/src/mongo/db/local_client.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/** - * Copyright (C) 2016 MongoDB Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects - * for all of the code used other than as permitted herein. If you modify - * file(s) with this exception, you may extend this exception to your - * version of the file(s), but you are not obligated to do so. If you do not - * wish to do so, delete this exception statement from your version. If you - * delete this exception statement from all source files in the program, - * then also delete it in the license file. - */ - -#include "mongo/platform/basic.h" - -#include "mongo/db/local_client.h" - -#include "mongo/db/db_raii.h" -#include "mongo/db/exec/working_set_common.h" -#include "mongo/db/matcher/extensions_callback_real.h" -#include "mongo/db/query/get_executor.h" - -namespace mongo { - -LocalClient::LocalClient(OperationContext* txn) : _txn(txn) {} - -StatusWith<LocalClient::LocalCursor> LocalClient::query(const NamespaceString& nss, - const BSONObj& query, - const BSONObj& sort) { - LocalCursor localCursor(_txn, nss, query, sort); - Status initStatus = localCursor._init(); - if (!initStatus.isOK()) { - return initStatus; - } - return std::move(localCursor); -} - -LocalClient::LocalCursor::LocalCursor(OperationContext* txn, - const NamespaceString& nss, - const BSONObj& query, - const BSONObj& sort) - : _txn(txn), _nss(nss), _query(query), _sort(sort) {} - -#if defined(_MSC_VER) && _MSC_VER < 1900 -LocalClient::LocalCursor::LocalCursor(LocalCursor&& other) - : _txn(std::move(other._txn)), - _nss(std::move(other._nss)), - _query(std::move(other._query)), - _sort(std::move(other._sort)), - _exec(std::move(other._exec)) {} - -LocalClient::LocalCursor& LocalClient::LocalCursor::operator=(LocalCursor&& other) { - _txn = std::move(other._txn); - _nss = std::move(other._nss); - _query = std::move(other._query); - _sort = std::move(other._sort); - _exec = std::move(other._exec); - return *this; -} -#endif - -Status LocalClient::LocalCursor::_init() { - // This function does its own locking, so the lock should not be held. - invariant(!_txn->lockState()->isLocked()); - - if (!_nss.isValid()) { - return {ErrorCodes::InvalidNamespace, - str::stream() << "Invalid collection name: '" << _nss.ns()}; - } - - auto lpq = LiteParsedQuery::makeAsFindCmd(_nss, - _query, - BSONObj(), // projection - _sort); - ExtensionsCallbackReal extensionsCallback(_txn, &_nss); - - auto canonicalQuery = CanonicalQuery::canonicalize(lpq.release(), extensionsCallback); - if (!canonicalQuery.isOK()) { - return canonicalQuery.getStatus(); - } - - AutoGetCollection ctx(_txn, _nss, MODE_IS); - Collection* collection = ctx.getCollection(); - - auto statusWithPlanExecutor = getExecutor( - _txn, collection, std::move(canonicalQuery.getValue()), PlanExecutor::YIELD_AUTO); - if (!statusWithPlanExecutor.isOK()) { - return statusWithPlanExecutor.getStatus(); - } - _exec = std::move(statusWithPlanExecutor.getValue()); - _exec->saveState(); - - return Status::OK(); -} - -StatusWith<boost::optional<BSONObj>> LocalClient::LocalCursor::next() { - // If _exec is not set, an error occurred or the cursor was exhausted on the previous call. - invariant(_exec); - // This function does its own locking, so the lock should not be held. - invariant(!_txn->lockState()->isLocked()); - AutoGetCollection ctx(_txn, _nss, MODE_IS); - - if (!_exec->restoreState()) { - _exec.reset(); - return {ErrorCodes::OperationFailed, - str::stream() - << "PlanExecutor could not be restored in LocalClient::LocalCursor::next()"}; - } - - BSONObj doc; - PlanExecutor::ExecState state = _exec->getNext(&doc, NULL); - - if (state == PlanExecutor::IS_EOF) { - _exec.reset(); - return {boost::none}; - } - - if (state != PlanExecutor::ADVANCED) { - _exec.reset(); - return {ErrorCodes::OperationFailed, - str::stream() << "PlanExecutor error: " << WorkingSetCommon::toStatusString(doc)}; - } - - doc = doc.getOwned(); - _exec->saveState(); - - return {doc}; -} - -} // namespace mongo diff --git a/src/mongo/db/local_client.h b/src/mongo/db/local_client.h deleted file mode 100644 index 3b385f9fcee..00000000000 --- a/src/mongo/db/local_client.h +++ /dev/null @@ -1,135 +0,0 @@ -/** - * Copyright (C) 2016 MongoDB Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects - * for all of the code used other than as permitted herein. If you modify - * file(s) with this exception, you may extend this exception to your - * version of the file(s), but you are not obligated to do so. If you do not - * wish to do so, delete this exception statement from your version. If you - * delete this exception statement from all source files in the program, - * then also delete it in the license file. - */ - -#pragma once - -#include "mongo/base/disallow_copying.h" -#include "mongo/base/status_with.h" -#include "mongo/bson/bsonobj.h" -#include "mongo/db/namespace_string.h" - -namespace mongo { - -class OperationContext; -class PlanExecutor; - -/** - * LocalClient handles local -- not over the network -- queries and writes. It acquires all - * necessary collection locks: these locks should not be held by the caller. - * - * LocalClient is associated with a particular OperationContext and should not be passed between - * threads. - */ -class LocalClient { - MONGO_DISALLOW_COPYING(LocalClient); - -public: - class LocalCursor; - - LocalClient(OperationContext* txn); - - /** - * Sets up a local find query. Returns a LocalCursor object from which to request the next - * document that matches "query" in order "sort" from collection "nss". - * - * The caller should not hold the collection lock: locking is handled internally. - */ - StatusWith<LocalCursor> query(const NamespaceString& nss, - const BSONObj& query, - const BSONObj& sort); - - /** - * LocalCursor sets up and executes a local find query. - * - * Collection locking is handled internally. Lock is released between next() calls. - * - * The caller need only request the next document after instantiating the LocalCursor and - * calling init(). - */ - class LocalCursor { - public: - friend class LocalClient; - -#if defined(_MSC_VER) && _MSC_VER < 1900 - LocalCursor(LocalCursor&& other); - LocalCursor& operator=(LocalCursor&& other); -#else - LocalCursor(LocalCursor&& other) = default; - LocalCursor& operator=(LocalCursor&& other) = default; -#endif - - /** - * Seeks the next document that matches the query. Returns an error Status or an optional - * BSONObj. If optional is empty, there are no more documents that match "_query"; - * otherwise the next document is returned. - * - * ErrorCodes::OperationFailed is returned if the PlanExecutor encounters an unrecoverable - * error or something happens to the collection -- such as an index or the collection - * itself being dropped -- between calls or when the PlanExecutor yields. - * - * Locking is handled internally: expects the collection lock not to be held. - */ - StatusWith<boost::optional<BSONObj>> next(); - - private: - /** - * Instantiates a LocalCursor that returns documents from collection "nss" matching "query" - * in the "sort" order. - */ - LocalCursor(OperationContext* txn, - const NamespaceString& nss, - const BSONObj& query, - const BSONObj& sort); - - /** - * Attempts to set up the find query, returns a Status to indicate success or failure. - * - * Locking is handled internally: expects the collection lock not to be held. - */ - Status _init(); - - OperationContext* _txn; - - // The collection in which to search. - NamespaceString _nss; - - // Contains the query that selects documents to return. - BSONObj _query; - - // Contains the sort order information. - BSONObj _sort; - - // Find query PlanExecutor from which to request the next document. - std::unique_ptr<PlanExecutor> _exec; - }; - -private: - OperationContext* const _txn; -}; - -} // namespace mongo diff --git a/src/mongo/db/local_client_test.cpp b/src/mongo/db/local_client_test.cpp deleted file mode 100644 index 3b77b81701b..00000000000 --- a/src/mongo/db/local_client_test.cpp +++ /dev/null @@ -1,183 +0,0 @@ -/** - * Copyright (C) 2016 MongoDB Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects - * for all of the code used other than as permitted herein. If you modify - * file(s) with this exception, you may extend this exception to your - * version of the file(s), but you are not obligated to do so. If you do not - * wish to do so, delete this exception statement from your version. If you - * delete this exception statement from all source files in the program, - * then also delete it in the license file. - */ - -#include "mongo/platform/basic.h" - -#include "mongo/db/local_client.h" - -#include <boost/optional.hpp> - -#include "mongo/base/checked_cast.h" -#include "mongo/db/client.h" -#include "mongo/db/catalog/collection.h" -#include "mongo/db/catalog/database_holder.h" -#include "mongo/db/db_raii.h" -#include "mongo/db/service_context.h" -#include "mongo/db/service_context_d.h" -#include "mongo/db/repl/replication_coordinator_global.h" -#include "mongo/db/repl/replication_coordinator_mock.h" -#include "mongo/unittest/temp_dir.h" -#include "mongo/unittest/unittest.h" - -namespace mongo { -namespace { - -using unittest::assertGet; - -class LocalClientTest : public unittest::Test { -protected: - ServiceContext::UniqueOperationContext _txn; - -private: - void setUp() override; - void tearDown() override; -}; - -void LocalClientTest::setUp() { - ServiceContext* serviceContext = getGlobalServiceContext(); - if (!serviceContext->getGlobalStorageEngine()) { - // When using the 'devnull' storage engine, it is fine for the temporary directory to - // go away after the global storage engine is initialized. - unittest::TempDir tempDir("local_client_test"); - storageGlobalParams.dbpath = tempDir.path(); - storageGlobalParams.dbpath = tempDir.path(); - storageGlobalParams.engine = "ephemeralForTest"; - storageGlobalParams.engineSetByUser = true; - checked_cast<ServiceContextMongoD*>(getGlobalServiceContext())->createLockFile(); - serviceContext->initializeGlobalStorageEngine(); - } - Client::initThreadIfNotAlready(); - _txn = serviceContext->makeOperationContext(&cc()); - - const repl::ReplSettings replSettings = {}; - repl::setGlobalReplicationCoordinator(new repl::ReplicationCoordinatorMock(replSettings)); -} - -void LocalClientTest::tearDown() { - { - Lock::GlobalWrite globalLock(_txn->lockState()); - BSONObjBuilder unused; - invariant(dbHolder().closeAll(_txn.get(), unused, false)); - } - _txn.reset(); - repl::setGlobalReplicationCoordinator(nullptr); -} - -/** - * Sets up a collection "nss" and populates it with documents. - */ -void setUpCollection(OperationContext* txn, - const NamespaceString& nss, - std::vector<BSONObj> documentVector) { - AutoGetOrCreateDb autoDb(txn, nss.db(), MODE_X); - WriteUnitOfWork wuow(txn); - auto coll = autoDb.getDb()->getCollection(nss.ns()); - if (!coll) { - coll = autoDb.getDb()->createCollection(txn, nss.ns()); - } - ASSERT(coll); - for (const BSONObj& doc : documentVector) { - ASSERT_OK(coll->insertDocument(txn, doc, false)); - } - wuow.commit(); -} - -/** - * Drops collection "nss". - */ -void dropCollection(OperationContext* txn, const NamespaceString& nss) { - AutoGetOrCreateDb autoDb(txn, nss.db(), MODE_X); - ASSERT_EQUALS(Status::OK(), autoDb.getDb()->dropCollection(txn, nss.ns())); -} - -// Successful ordered find query. -TEST_F(LocalClientTest, FindQuerySuccessful) { - LocalClient localClient(_txn.get()); - NamespaceString nss("test.foo"); - BSONObj firstDocument = BSON("_id" << 1 << "v" << 2); - BSONObj secondDocument = BSON("_id" << 4 << "v" << 2); - std::vector<BSONObj> documentVector = {firstDocument, secondDocument}; - setUpCollection(_txn.get(), nss, documentVector); - - // Set up find query that matches documents in the collection. - StatusWith<LocalClient::LocalCursor> localCursor = - localClient.query(nss, BSON("v" << 2), BSON("_id" << 1)); - ASSERT_OK(localCursor.getStatus()); - - // Retrieve the first document and check it. - boost::optional<BSONObj> document = assertGet(localCursor.getValue().next()); - ASSERT_TRUE(document); - ASSERT_EQUALS(*document, firstDocument); - - // Retrieve the second document and check it. - document = assertGet(localCursor.getValue().next()); - ASSERT_TRUE(document); - ASSERT_EQUALS(*document, secondDocument); - - // Check that the cursor is exhausted: no more documents to retrieve. - document = assertGet(localCursor.getValue().next()); - ASSERT_FALSE(document); - - dropCollection(_txn.get(), nss); -} - -// No documents match the find query. -TEST_F(LocalClientTest, FindQueryNoDocumentsFound) { - LocalClient localClient(_txn.get()); - NamespaceString nss("test.foo"); - std::vector<BSONObj> documentVector = {BSON("_id" << 1 << "v" << 2)}; - setUpCollection(_txn.get(), nss, documentVector); - - // Set up find query that does not match any documents in the collection. - StatusWith<LocalClient::LocalCursor> localCursor = - localClient.query(nss, BSON("v" << 4), BSON("_id" << 1)); - ASSERT_OK(localCursor.getStatus()); - - // Request the next document and receive nothing, with no errors. - boost::optional<BSONObj> document = assertGet(localCursor.getValue().next()); - ASSERT_FALSE(document); - - dropCollection(_txn.get(), nss); -} - -// Collection being queried does not exist. -TEST_F(LocalClientTest, FindQueryInitNoCollection) { - LocalClient localClient(_txn.get()); - - // Set up find query on a non-existent collection. - StatusWith<LocalClient::LocalCursor> localCursor = - localClient.query(NamespaceString("test.bam"), BSON("v" << 4), BSON("_id" << 1)); - ASSERT_OK(localCursor.getStatus()); - - // Request the next document and receive nothing, with no errors. - boost::optional<BSONObj> document = assertGet(localCursor.getValue().next()); - ASSERT_FALSE(document); -} - -} // namespace -} // namespace mongo |