/** * Copyright (C) 2013 10gen 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 . * * 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/db/range_deleter_mock_env.h" #include "mongo/db/service_context.h" #include "mongo/db/service_context_noop.h" #include "mongo/stdx/memory.h" namespace mongo { using std::set; using std::string; bool DeletedRangeCmp::operator()(const DeletedRange& lhs, const DeletedRange& rhs) const { const int nsComp = lhs.ns.compare(rhs.ns); if (nsComp < 0) { return true; } if (nsComp > 0) { return false; } return compareRanges(lhs.min, lhs.max, rhs.min, rhs.max) < 0; } RangeDeleterMockEnv::RangeDeleterMockEnv(): _pauseDelete(false), _pausedCount(0), _getCursorsCallCount(0) { setGlobalServiceContext(stdx::make_unique()); } void RangeDeleterMockEnv::addCursorId(StringData ns, CursorId id) { boost::lock_guard sl(_cursorMapMutex); _cursorMap[ns.toString()].insert(id); } void RangeDeleterMockEnv::removeCursorId(StringData ns, CursorId id) { boost::lock_guard sl(_cursorMapMutex); _cursorMap[ns.toString()].erase(id); } void RangeDeleterMockEnv::pauseDeletes() { boost::lock_guard sl(_pauseDeleteMutex); _pauseDelete = true; } void RangeDeleterMockEnv::resumeOneDelete() { boost::lock_guard sl(_pauseDeleteMutex); _pauseDelete = false; _pausedCV.notify_one(); } void RangeDeleterMockEnv::waitForNthGetCursor(uint64_t nthCall) { boost::unique_lock sl(_envStatMutex); while (_getCursorsCallCount < nthCall) { _cursorsCallCountUpdatedCV.wait(sl); } } void RangeDeleterMockEnv::waitForNthPausedDelete(uint64_t nthPause) { boost::unique_lock sl(_pauseDeleteMutex); while(_pausedCount < nthPause) { _pausedDeleteChangeCV.wait(sl); } } bool RangeDeleterMockEnv::deleteOccured() const { boost::lock_guard sl(_deleteListMutex); return !_deleteList.empty(); } DeletedRange RangeDeleterMockEnv::getLastDelete() const { boost::lock_guard sl(_deleteListMutex); return _deleteList.back(); } bool RangeDeleterMockEnv::deleteRange(OperationContext* txn, const RangeDeleteEntry& taskDetails, long long int* deletedDocs, string* errMsg) { { boost::unique_lock sl(_pauseDeleteMutex); bool wasInitiallyPaused = _pauseDelete; if (_pauseDelete) { _pausedCount++; _pausedDeleteChangeCV.notify_one(); } while (_pauseDelete) { _pausedCV.wait(sl); } _pauseDelete = wasInitiallyPaused; } { boost::lock_guard sl(_deleteListMutex); DeletedRange entry; entry.ns = taskDetails.options.range.ns; entry.min = taskDetails.options.range.minKey.getOwned(); entry.max = taskDetails.options.range.maxKey.getOwned(); entry.shardKeyPattern = taskDetails.options.range.keyPattern.getOwned(); _deleteList.push_back(entry); } return true; } void RangeDeleterMockEnv::getCursorIds( OperationContext* txn, StringData ns, set* in) { { boost::lock_guard sl(_cursorMapMutex); const set& _cursors = _cursorMap[ns.toString()]; std::copy(_cursors.begin(), _cursors.end(), inserter(*in, in->begin())); } { boost::lock_guard sl(_envStatMutex); _getCursorsCallCount++; _cursorsCallCountUpdatedCV.notify_one(); } } }