Compare commits
9 Commits
wireVersio
...
r3.0.0-rc6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8dd41ae580 | ||
|
|
d1aaa562f7 | ||
|
|
6fa02fef66 | ||
|
|
f8267b2689 | ||
|
|
797afb0ef9 | ||
|
|
78e1975857 | ||
|
|
43e58e67ca | ||
|
|
ef668908b1 | ||
|
|
1e4e8de086 |
@@ -3,7 +3,7 @@
|
||||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = MongoDB
|
||||
PROJECT_NUMBER = 2.8.0-rc6-pre-
|
||||
PROJECT_NUMBER = 3.0.0-rc6
|
||||
OUTPUT_DIRECTORY = docs/doxygen
|
||||
CREATE_SUBDIRS = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include "mongo/db/catalog/collection_options.h"
|
||||
#include "mongo/db/catalog/database_catalog_entry.h"
|
||||
#include "mongo/db/catalog/database_holder.h"
|
||||
#include "mongo/db/concurrency/write_conflict_exception.h"
|
||||
#include "mongo/db/dbhelpers.h"
|
||||
#include "mongo/db/global_environment_experiment.h"
|
||||
#include "mongo/db/global_environment_d.h"
|
||||
@@ -262,20 +263,26 @@ namespace mongo {
|
||||
CollectionOptions options = coll->getCollectionOptions( txn );
|
||||
if ( !options.temp )
|
||||
continue;
|
||||
try {
|
||||
WriteUnitOfWork wunit(txn);
|
||||
Status status = dropCollection( txn, ns );
|
||||
if ( !status.isOK() ) {
|
||||
warning() << "could not drop temp collection '" << ns << "': " << status;
|
||||
continue;
|
||||
}
|
||||
|
||||
WriteUnitOfWork wunit(txn);
|
||||
Status status = dropCollection( txn, ns );
|
||||
if ( !status.isOK() ) {
|
||||
warning() << "could not drop temp collection '" << ns << "': " << status;
|
||||
continue;
|
||||
string cmdNs = _name + ".$cmd";
|
||||
repl::logOp( txn,
|
||||
"c",
|
||||
cmdNs.c_str(),
|
||||
BSON( "drop" << nsToCollectionSubstring( ns ) ) );
|
||||
wunit.commit();
|
||||
}
|
||||
catch (const WriteConflictException& exp) {
|
||||
warning() << "could not drop temp collection '" << ns << "' due to "
|
||||
"WriteConflictException";
|
||||
txn->recoveryUnit()->commitAndRestart();
|
||||
}
|
||||
|
||||
string cmdNs = _name + ".$cmd";
|
||||
repl::logOp( txn,
|
||||
"c",
|
||||
cmdNs.c_str(),
|
||||
BSON( "drop" << nsToCollectionSubstring( ns ) ) );
|
||||
wunit.commit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,10 @@
|
||||
* it in the license file.
|
||||
*/
|
||||
|
||||
#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kCommand
|
||||
|
||||
#include "mongo/platform/basic.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -38,11 +42,13 @@
|
||||
#include "mongo/db/client.h"
|
||||
#include "mongo/db/commands.h"
|
||||
#include "mongo/db/commands/dbhash.h"
|
||||
#include "mongo/db/concurrency/write_conflict_exception.h"
|
||||
#include "mongo/db/dbdirectclient.h"
|
||||
#include "mongo/db/jsobj.h"
|
||||
#include "mongo/db/matcher/matcher.h"
|
||||
#include "mongo/db/operation_context_impl.h"
|
||||
#include "mongo/db/repl/oplog.h"
|
||||
#include "mongo/util/log.h"
|
||||
|
||||
namespace mongo {
|
||||
|
||||
@@ -149,11 +155,26 @@ namespace mongo {
|
||||
};
|
||||
|
||||
Client::Context ctx(txn, ns);
|
||||
bool failed = repl::applyOperation_inlock(txn,
|
||||
ctx.db(),
|
||||
temp,
|
||||
false,
|
||||
alwaysUpsert);
|
||||
|
||||
bool failed;
|
||||
while (true) {
|
||||
try {
|
||||
// We assume that in the WriteConflict retry case, either the op rolls back
|
||||
// any changes it makes or is otherwise safe to rerun.
|
||||
failed = repl::applyOperation_inlock(txn,
|
||||
ctx.db(),
|
||||
temp,
|
||||
false,
|
||||
alwaysUpsert);
|
||||
break;
|
||||
}
|
||||
catch (const WriteConflictException& wce) {
|
||||
LOG(2) << "WriteConflictException in applyOps command, retrying.";
|
||||
txn->recoveryUnit()->commitAndRestart();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ab.append(!failed);
|
||||
if ( failed )
|
||||
errors++;
|
||||
@@ -184,13 +205,26 @@ namespace mongo {
|
||||
}
|
||||
}
|
||||
|
||||
const BSONObj cmdRewritten = cmdBuilder.done();
|
||||
|
||||
// We currently always logOp the command regardless of whether the individial ops
|
||||
// succeeded and rely on any failures to also happen on secondaries. This isn't
|
||||
// perfect, but it's what the command has always done and is part of its "correct"
|
||||
// behavior.
|
||||
WriteUnitOfWork wunit(txn);
|
||||
repl::logOp(txn, "c", tempNS.c_str(), cmdBuilder.done());
|
||||
wunit.commit();
|
||||
while (true) {
|
||||
try {
|
||||
WriteUnitOfWork wunit(txn);
|
||||
repl::logOp(txn, "c", tempNS.c_str(), cmdRewritten);
|
||||
wunit.commit();
|
||||
break;
|
||||
}
|
||||
catch (const WriteConflictException& wce) {
|
||||
LOG(2) <<
|
||||
"WriteConflictException while logging applyOps command, retrying.";
|
||||
txn->recoveryUnit()->commitAndRestart();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (errors != 0) {
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "mongo/db/catalog/database.h"
|
||||
#include "mongo/db/catalog/database_holder.h"
|
||||
#include "mongo/db/catalog/index_create.h"
|
||||
#include "mongo/db/concurrency/write_conflict_exception.h"
|
||||
#include "mongo/db/operation_context_impl.h"
|
||||
#include "mongo/util/assert_util.h"
|
||||
#include "mongo/util/log.h"
|
||||
@@ -125,72 +126,100 @@ namespace {
|
||||
|
||||
Collection* c = db->getCollection( ns.ns() );
|
||||
if ( !c ) {
|
||||
WriteUnitOfWork wunit(txn);
|
||||
c = db->getOrCreateCollection( txn, ns.ns() );
|
||||
verify(c);
|
||||
wunit.commit();
|
||||
while (true) {
|
||||
try {
|
||||
WriteUnitOfWork wunit(txn);
|
||||
c = db->getOrCreateCollection( txn, ns.ns() );
|
||||
verify(c);
|
||||
wunit.commit();
|
||||
break;
|
||||
}
|
||||
catch (const WriteConflictException& wce) {
|
||||
LOG(2) << "WriteConflictException while creating collection in IndexBuilder"
|
||||
<< ", retrying.";
|
||||
txn->recoveryUnit()->commitAndRestart();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Show which index we're building in the curop display.
|
||||
txn->getCurOp()->setQuery(_index);
|
||||
|
||||
MultiIndexBlock indexer(txn, c);
|
||||
indexer.allowInterruption();
|
||||
bool haveSetBgIndexStarting = false;
|
||||
while (true) {
|
||||
Status status = Status::OK();
|
||||
try {
|
||||
MultiIndexBlock indexer(txn, c);
|
||||
indexer.allowInterruption();
|
||||
|
||||
if (allowBackgroundBuilding)
|
||||
indexer.allowBackgroundBuilding();
|
||||
if (allowBackgroundBuilding)
|
||||
indexer.allowBackgroundBuilding();
|
||||
|
||||
Status status = Status::OK();
|
||||
IndexDescriptor* descriptor(NULL);
|
||||
try {
|
||||
status = indexer.init(_index);
|
||||
if ( status.code() == ErrorCodes::IndexAlreadyExists ) {
|
||||
if (allowBackgroundBuilding) {
|
||||
// Must set this in case anyone is waiting for this build.
|
||||
_setBgIndexStarting();
|
||||
|
||||
IndexDescriptor* descriptor(NULL);
|
||||
try {
|
||||
status = indexer.init(_index);
|
||||
if ( status.code() == ErrorCodes::IndexAlreadyExists ) {
|
||||
if (allowBackgroundBuilding) {
|
||||
// Must set this in case anyone is waiting for this build.
|
||||
_setBgIndexStarting();
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
if (status.isOK()) {
|
||||
if (allowBackgroundBuilding) {
|
||||
descriptor = indexer.registerIndexBuild();
|
||||
if (!haveSetBgIndexStarting) {
|
||||
_setBgIndexStarting();
|
||||
haveSetBgIndexStarting = true;
|
||||
}
|
||||
invariant(dbLock);
|
||||
dbLock->relockWithMode(MODE_IX);
|
||||
}
|
||||
|
||||
Lock::CollectionLock colLock(txn->lockState(), ns.ns(), MODE_IX);
|
||||
status = indexer.insertAllDocumentsInCollection();
|
||||
}
|
||||
|
||||
if (status.isOK()) {
|
||||
if (allowBackgroundBuilding) {
|
||||
dbLock->relockWithMode(MODE_X);
|
||||
}
|
||||
WriteUnitOfWork wunit(txn);
|
||||
indexer.commit();
|
||||
wunit.commit();
|
||||
}
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
if (status.isOK()) {
|
||||
if (allowBackgroundBuilding) {
|
||||
descriptor = indexer.registerIndexBuild();
|
||||
_setBgIndexStarting();
|
||||
invariant(dbLock);
|
||||
dbLock->relockWithMode(MODE_IX);
|
||||
catch (const DBException& e) {
|
||||
status = e.toStatus();
|
||||
}
|
||||
|
||||
Lock::CollectionLock colLock(txn->lockState(), ns.ns(), MODE_IX);
|
||||
status = indexer.insertAllDocumentsInCollection();
|
||||
}
|
||||
|
||||
if (status.isOK()) {
|
||||
if (allowBackgroundBuilding) {
|
||||
dbLock->relockWithMode(MODE_X);
|
||||
Database* db = dbHolder().get(txn, ns.db());
|
||||
fassert(28553, db);
|
||||
fassert(28554, db->getCollection(ns.ns()));
|
||||
indexer.unregisterIndexBuild(descriptor);
|
||||
}
|
||||
|
||||
if (status.code() == ErrorCodes::InterruptedAtShutdown) {
|
||||
// leave it as-if kill -9 happened. This will be handled on restart.
|
||||
indexer.abortWithoutCleanup();
|
||||
}
|
||||
WriteUnitOfWork wunit(txn);
|
||||
indexer.commit();
|
||||
wunit.commit();
|
||||
}
|
||||
}
|
||||
catch (const DBException& e) {
|
||||
status = e.toStatus();
|
||||
}
|
||||
catch (const WriteConflictException& wce) {
|
||||
status = wce.toStatus();
|
||||
}
|
||||
|
||||
if (allowBackgroundBuilding) {
|
||||
dbLock->relockWithMode(MODE_X);
|
||||
Database* db = dbHolder().get(txn, ns.db());
|
||||
fassert(28553, db);
|
||||
fassert(28554, db->getCollection(ns.ns()));
|
||||
indexer.unregisterIndexBuild(descriptor);
|
||||
}
|
||||
if (status.code() != ErrorCodes::WriteConflict)
|
||||
return status;
|
||||
|
||||
if (status.code() == ErrorCodes::InterruptedAtShutdown) {
|
||||
// leave it as-if kill -9 happened. This will be handled on restart.
|
||||
indexer.abortWithoutCleanup();
|
||||
}
|
||||
|
||||
return status;
|
||||
LOG(2) << "WriteConflictException while creating index in IndexBuilder, retrying.";
|
||||
txn->recoveryUnit()->commitAndRestart();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<BSONObj>
|
||||
|
||||
@@ -737,16 +737,21 @@ namespace {
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
BufBuilder bb;
|
||||
BSONObjBuilder ob;
|
||||
BSONObjBuilder runCommandResult;
|
||||
|
||||
// Applying commands in repl is done under Global W-lock, so it is safe to not
|
||||
// perform the current DB checks after reacquiring the lock.
|
||||
invariant(txn->lockState()->isW());
|
||||
|
||||
_runCommands(txn, ns, o, bb, ob, true, 0);
|
||||
_runCommands(txn, ns, o, bb, runCommandResult, true, 0);
|
||||
// _runCommands takes care of adjusting opcounters for command counting.
|
||||
Status status = Command::getStatusFromCommandResult(ob.done());
|
||||
Status status = Command::getStatusFromCommandResult(runCommandResult.done());
|
||||
switch (status.code()) {
|
||||
case ErrorCodes::WriteConflict: {
|
||||
// Need to throw this up to a higher level where it will be caught and the
|
||||
// operation retried.
|
||||
throw WriteConflictException();
|
||||
}
|
||||
case ErrorCodes::BackgroundOperationInProgressForDatabase: {
|
||||
Lock::TempRelease release(txn->lockState());
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// devnull_kv_engine.cpp
|
||||
|
||||
/**
|
||||
* Copyright (C) 2014 MongoDB Inc.
|
||||
*
|
||||
@@ -28,8 +26,11 @@
|
||||
* it in the license file.
|
||||
*/
|
||||
|
||||
#include "mongo/platform/basic.h"
|
||||
|
||||
#include "mongo/db/storage/devnull/devnull_kv_engine.h"
|
||||
|
||||
#include "mongo/base/disallow_copying.h"
|
||||
#include "mongo/db/storage/in_memory/in_memory_record_store.h"
|
||||
#include "mongo/db/storage/record_store.h"
|
||||
#include "mongo/db/storage/sorted_data_interface.h"
|
||||
@@ -175,12 +176,25 @@ namespace mongo {
|
||||
BSONObj _dummy;
|
||||
};
|
||||
|
||||
class DevNullSortedDataBuilderInterface : public SortedDataBuilderInterface {
|
||||
MONGO_DISALLOW_COPYING(DevNullSortedDataBuilderInterface);
|
||||
|
||||
public:
|
||||
DevNullSortedDataBuilderInterface() { }
|
||||
|
||||
virtual Status addKey(const BSONObj& key, const RecordId& loc) {
|
||||
return Status::OK();
|
||||
}
|
||||
};
|
||||
|
||||
class DevNullSortedDataInterface : public SortedDataInterface {
|
||||
public:
|
||||
virtual ~DevNullSortedDataInterface() { }
|
||||
|
||||
virtual SortedDataBuilderInterface* getBulkBuilder(OperationContext* txn,
|
||||
bool dupsAllowed) { return NULL; }
|
||||
bool dupsAllowed) {
|
||||
return new DevNullSortedDataBuilderInterface();
|
||||
}
|
||||
|
||||
virtual Status insert(OperationContext* txn,
|
||||
const BSONObj& key,
|
||||
|
||||
@@ -46,8 +46,9 @@
|
||||
#include "mongo/db/storage/wiredtiger/wiredtiger_session_cache.h"
|
||||
#include "mongo/db/storage/wiredtiger/wiredtiger_util.h"
|
||||
#include "mongo/db/storage_options.h"
|
||||
#include "mongo/util/log.h"
|
||||
#include "mongo/util/assert_util.h"
|
||||
#include "mongo/util/fail_point.h"
|
||||
#include "mongo/util/log.h"
|
||||
#include "mongo/util/mongoutils/str.h"
|
||||
|
||||
#if 0
|
||||
@@ -330,7 +331,7 @@ namespace {
|
||||
WT_CURSOR *c = curwrap.get();
|
||||
if (!c)
|
||||
return true;
|
||||
int ret = c->next(c);
|
||||
int ret = WT_OP_CHECK(c->next(c));
|
||||
if (ret == WT_NOTFOUND)
|
||||
return true;
|
||||
invariantWTOK(ret);
|
||||
@@ -349,9 +350,10 @@ namespace {
|
||||
KeyString data( key, _ordering );
|
||||
WiredTigerItem item( data.getBuffer(), data.getSize() );
|
||||
c->set_key( c, item.Get() );
|
||||
int ret = c->search(c);
|
||||
if ( ret == WT_NOTFOUND )
|
||||
int ret = WT_OP_CHECK(c->search(c));
|
||||
if (ret == WT_NOTFOUND) {
|
||||
return false;
|
||||
}
|
||||
invariantWTOK( ret );
|
||||
|
||||
// If the key exists, check if we already have this loc at this key. If so, we don't
|
||||
@@ -449,7 +451,7 @@ namespace {
|
||||
|
||||
_cursor->set_value(_cursor, valueItem.Get());
|
||||
|
||||
invariantWTOK(_cursor->insert(_cursor));
|
||||
invariantWTOK(WT_OP_CHECK(_cursor->insert(_cursor)));
|
||||
invariantWTOK(_cursor->reset(_cursor));
|
||||
|
||||
return Status::OK();
|
||||
@@ -543,7 +545,7 @@ namespace {
|
||||
_cursor->set_key(_cursor, keyItem.Get());
|
||||
_cursor->set_value(_cursor, valueItem.Get());
|
||||
|
||||
invariantWTOK(_cursor->insert(_cursor));
|
||||
invariantWTOK(WT_OP_CHECK(_cursor->insert(_cursor)));
|
||||
invariantWTOK(_cursor->reset(_cursor));
|
||||
|
||||
_records.clear();
|
||||
@@ -677,7 +679,7 @@ namespace {
|
||||
void advanceWTCursor() {
|
||||
invalidateCache();
|
||||
WT_CURSOR *c = _cursor.get();
|
||||
int ret = _forward ? c->next(c) : c->prev(c);
|
||||
int ret = WT_OP_CHECK(_forward ? c->next(c) : c->prev(c));
|
||||
if ( ret == WT_NOTFOUND ) {
|
||||
_eof = true;
|
||||
return;
|
||||
@@ -695,7 +697,7 @@ namespace {
|
||||
const WiredTigerItem keyItem(_key.getBuffer(), _key.getSize());
|
||||
c->set_key(c, keyItem.Get());
|
||||
|
||||
int ret = c->search_near(c, &cmp);
|
||||
int ret = WT_OP_CHECK(c->search_near(c, &cmp));
|
||||
if ( ret == WT_NOTFOUND ) {
|
||||
_eof = true;
|
||||
TRACE_CURSOR << "\t not found";
|
||||
@@ -717,13 +719,13 @@ namespace {
|
||||
if (_forward) {
|
||||
// We need to be >=
|
||||
if (cmp < 0) {
|
||||
ret = c->next(c);
|
||||
ret = WT_OP_CHECK(c->next(c));
|
||||
}
|
||||
}
|
||||
else {
|
||||
// We need to be <=
|
||||
if (cmp > 0) {
|
||||
ret = c->prev(c);
|
||||
ret = WT_OP_CHECK(c->prev(c));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1003,7 +1005,7 @@ namespace {
|
||||
WiredTigerItem valueItem(value.getBuffer(), value.getSize());
|
||||
c->set_key( c, keyItem.Get() );
|
||||
c->set_value( c, valueItem.Get() );
|
||||
int ret = c->insert( c );
|
||||
int ret = WT_OP_CHECK(c->insert(c));
|
||||
|
||||
if ( ret == WT_ROLLBACK && !dupsAllowed ) {
|
||||
// if there is a conflict on a unique key, it means there is a dup key
|
||||
@@ -1019,7 +1021,7 @@ namespace {
|
||||
// we put them all in the "list"
|
||||
// Note that we can't omit AllZeros when there are multiple locs for a value. When we remove
|
||||
// down to a single value, it will be cleaned up.
|
||||
ret = c->search(c);
|
||||
ret = WT_OP_CHECK(c->search(c));
|
||||
invariantWTOK( ret );
|
||||
|
||||
WT_ITEM old;
|
||||
@@ -1069,7 +1071,7 @@ namespace {
|
||||
|
||||
if ( !dupsAllowed ) {
|
||||
// nice and clear
|
||||
int ret = c->remove(c);
|
||||
int ret = WT_OP_CHECK(c->remove(c));
|
||||
if (ret == WT_NOTFOUND) {
|
||||
return;
|
||||
}
|
||||
@@ -1079,7 +1081,7 @@ namespace {
|
||||
|
||||
// dups are allowed, so we have to deal with a vector of RecordIds.
|
||||
|
||||
int ret = c->search(c);
|
||||
int ret = WT_OP_CHECK(c->search(c));
|
||||
if ( ret == WT_NOTFOUND )
|
||||
return;
|
||||
invariantWTOK( ret );
|
||||
@@ -1099,7 +1101,7 @@ namespace {
|
||||
if (records.empty() && !br.remaining()) {
|
||||
// This is the common case: we are removing the only loc for this key.
|
||||
// Remove the whole entry.
|
||||
invariantWTOK(c->remove(c));
|
||||
invariantWTOK(WT_OP_CHECK(c->remove(c)));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1171,7 +1173,7 @@ namespace {
|
||||
|
||||
c->set_key(c, keyItem.Get());
|
||||
c->set_value(c, valueItem.Get());
|
||||
int ret = c->insert( c );
|
||||
int ret = WT_OP_CHECK(c->insert(c));
|
||||
|
||||
if ( ret != WT_DUPLICATE_KEY )
|
||||
return wtRCToStatus( ret );
|
||||
@@ -1189,7 +1191,7 @@ namespace {
|
||||
KeyString data( key, _ordering, loc );
|
||||
WiredTigerItem item( data.getBuffer(), data.getSize() );
|
||||
c->set_key(c, item.Get() );
|
||||
int ret = c->remove(c);
|
||||
int ret = WT_OP_CHECK(c->remove(c));
|
||||
if (ret != WT_NOTFOUND) {
|
||||
invariantWTOK(ret);
|
||||
}
|
||||
|
||||
@@ -51,7 +51,6 @@
|
||||
#include "mongo/db/storage/wiredtiger/wiredtiger_util.h"
|
||||
#include "mongo/util/assert_util.h"
|
||||
#include "mongo/util/fail_point.h"
|
||||
#include "mongo/util/fail_point_service.h"
|
||||
#include "mongo/util/log.h"
|
||||
#include "mongo/util/mongoutils/str.h"
|
||||
#include "mongo/util/scopeguard.h"
|
||||
@@ -65,6 +64,7 @@ namespace mongo {
|
||||
using std::string;
|
||||
|
||||
namespace {
|
||||
|
||||
static const int kMinimumRecordStoreVersion = 1;
|
||||
static const int kCurrentRecordStoreVersion = 1; // New record stores use this by default.
|
||||
static const int kMaximumRecordStoreVersion = 1;
|
||||
@@ -80,17 +80,10 @@ namespace {
|
||||
return (appMetadata.getValue().getIntField("oplogKeyExtractionVersion") == 1);
|
||||
}
|
||||
|
||||
// Throws a WriteConflictException to ensure the calling code can handle it
|
||||
MONGO_FP_DECLARE(wtWriteConflictException);
|
||||
|
||||
void checkWriteConflictExceptionFPEnabled() {
|
||||
if (MONGO_FAIL_POINT(wtWriteConflictException)) {
|
||||
throw WriteConflictException();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
MONGO_FP_DECLARE(WTWriteConflictException);
|
||||
|
||||
const std::string kWiredTigerEngineName = "wiredTiger";
|
||||
|
||||
const long long WiredTigerRecordStore::kCollectionScanOnCreationThreshold = 10000;
|
||||
@@ -316,14 +309,12 @@ namespace {
|
||||
}
|
||||
|
||||
RecordData WiredTigerRecordStore::dataFor(OperationContext* txn, const RecordId& loc) const {
|
||||
checkWriteConflictExceptionFPEnabled();
|
||||
|
||||
// ownership passes to the shared_array created below
|
||||
WiredTigerCursor curwrap( _uri, _instanceId, true, txn);
|
||||
WT_CURSOR *c = curwrap.get();
|
||||
invariant( c );
|
||||
c->set_key(c, _makeKey(loc));
|
||||
int ret = c->search(c);
|
||||
int ret = WT_OP_CHECK(c->search(c));
|
||||
massert(28556, "Didn't find RecordId in WiredTigerRecordStore", ret != WT_NOTFOUND);
|
||||
invariantWTOK(ret);
|
||||
return _getData(curwrap);
|
||||
@@ -331,13 +322,11 @@ namespace {
|
||||
|
||||
bool WiredTigerRecordStore::findRecord( OperationContext* txn,
|
||||
const RecordId& loc, RecordData* out ) const {
|
||||
checkWriteConflictExceptionFPEnabled();
|
||||
|
||||
WiredTigerCursor curwrap( _uri, _instanceId, true, txn);
|
||||
WT_CURSOR *c = curwrap.get();
|
||||
invariant( c );
|
||||
c->set_key(c, _makeKey(loc));
|
||||
int ret = c->search(c);
|
||||
int ret = WT_OP_CHECK(c->search(c));
|
||||
if (ret == WT_NOTFOUND) {
|
||||
return false;
|
||||
}
|
||||
@@ -347,13 +336,11 @@ namespace {
|
||||
}
|
||||
|
||||
void WiredTigerRecordStore::deleteRecord( OperationContext* txn, const RecordId& loc ) {
|
||||
checkWriteConflictExceptionFPEnabled();
|
||||
|
||||
WiredTigerCursor cursor( _uri, _instanceId, true, txn );
|
||||
cursor.assertInActiveTxn();
|
||||
WT_CURSOR *c = cursor.get();
|
||||
c->set_key(c, _makeKey(loc));
|
||||
int ret = c->search(c);
|
||||
int ret = WT_OP_CHECK(c->search(c));
|
||||
invariantWTOK(ret);
|
||||
|
||||
WT_ITEM old_value;
|
||||
@@ -362,7 +349,7 @@ namespace {
|
||||
|
||||
int old_length = old_value.size;
|
||||
|
||||
ret = c->remove(c);
|
||||
ret = WT_OP_CHECK(c->remove(c));
|
||||
invariantWTOK(ret);
|
||||
|
||||
_changeNumRecords(txn, -1);
|
||||
@@ -438,9 +425,10 @@ namespace {
|
||||
WT_CURSOR *c = curwrap.get();
|
||||
RecordId newestOld;
|
||||
int ret = 0;
|
||||
while (( sizeSaved < sizeOverCap || docsRemoved < docsOverCap ) &&
|
||||
docsRemoved < 1000 &&
|
||||
(ret = c->next(c)) == 0 ) {
|
||||
while ((sizeSaved < sizeOverCap || docsRemoved < docsOverCap) &&
|
||||
(docsRemoved < 1000) &&
|
||||
(ret = WT_OP_CHECK(c->next(c))) == 0) {
|
||||
|
||||
int64_t key;
|
||||
ret = c->get_key(c, &key);
|
||||
invariantWTOK(ret);
|
||||
@@ -465,18 +453,21 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
if (ret != WT_NOTFOUND) invariantWTOK(ret);
|
||||
if (ret != WT_NOTFOUND) {
|
||||
invariantWTOK(ret);
|
||||
}
|
||||
|
||||
if (docsRemoved > 0) {
|
||||
// if we scanned to the end of the collection or past our insert, go back one
|
||||
if ( ret == WT_NOTFOUND || newestOld >= justInserted ) {
|
||||
ret = c->prev(c);
|
||||
if (ret == WT_NOTFOUND || newestOld >= justInserted) {
|
||||
ret = WT_OP_CHECK(c->prev(c));
|
||||
}
|
||||
invariantWTOK(ret);
|
||||
|
||||
WiredTigerCursor startWrap( _uri, _instanceId, true, txn);
|
||||
WT_CURSOR* start = startWrap.get();
|
||||
start->next(start);
|
||||
ret = WT_OP_CHECK(start->next(start));
|
||||
invariantWTOK(ret);
|
||||
|
||||
invariantWTOK(session->truncate(session, NULL, start, c, NULL));
|
||||
_changeNumRecords(txn, -docsRemoved);
|
||||
@@ -509,8 +500,6 @@ namespace {
|
||||
const char* data,
|
||||
int len,
|
||||
bool enforceQuota ) {
|
||||
checkWriteConflictExceptionFPEnabled();
|
||||
|
||||
if ( _isCapped && len > _cappedMaxSize ) {
|
||||
return StatusWith<RecordId>( ErrorCodes::BadValue,
|
||||
"object to insert exceeds cappedMaxSize" );
|
||||
@@ -546,7 +535,7 @@ namespace {
|
||||
c->set_key(c, _makeKey(loc));
|
||||
WiredTigerItem value(data, len);
|
||||
c->set_value(c, value.Get());
|
||||
int ret = c->insert(c);
|
||||
int ret = WT_OP_CHECK(c->insert(c));
|
||||
if (ret) {
|
||||
return StatusWith<RecordId>(wtRCToStatus(ret, "WiredTigerRecordStore::insertRecord"));
|
||||
}
|
||||
@@ -598,7 +587,7 @@ namespace {
|
||||
WT_CURSOR *c = curwrap.get();
|
||||
invariant( c );
|
||||
c->set_key(c, _makeKey(loc));
|
||||
int ret = c->search(c);
|
||||
int ret = WT_OP_CHECK(c->search(c));
|
||||
invariantWTOK(ret);
|
||||
|
||||
WT_ITEM old_value;
|
||||
@@ -610,7 +599,7 @@ namespace {
|
||||
c->set_key(c, _makeKey(loc));
|
||||
WiredTigerItem value(data, len);
|
||||
c->set_value(c, value.Get());
|
||||
ret = c->insert(c);
|
||||
ret = WT_OP_CHECK(c->insert(c));
|
||||
invariantWTOK(ret);
|
||||
|
||||
_increaseDataSize(txn, len - old_length);
|
||||
@@ -873,11 +862,8 @@ namespace {
|
||||
OperationContext* txn,
|
||||
const RecordId& startingPosition) const {
|
||||
|
||||
if (!_useOplogHack) {
|
||||
if (!_useOplogHack)
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
checkWriteConflictExceptionFPEnabled();
|
||||
|
||||
{
|
||||
WiredTigerRecoveryUnit* wru = WiredTigerRecoveryUnit::get(txn);
|
||||
@@ -889,7 +875,7 @@ namespace {
|
||||
|
||||
int cmp;
|
||||
c->set_key(c, _makeKey(startingPosition));
|
||||
int ret = c->search_near(c, &cmp);
|
||||
int ret = WT_OP_CHECK(c->search_near(c, &cmp));
|
||||
if (ret == 0 && cmp > 0) ret = c->prev(c); // landed one higher than startingPosition
|
||||
if (ret == WT_NOTFOUND) return RecordId(); // nothing <= startingPosition
|
||||
invariantWTOK(ret);
|
||||
|
||||
@@ -41,6 +41,13 @@
|
||||
#include "mongo/db/storage/record_store.h"
|
||||
#include "mongo/db/storage/capped_callback.h"
|
||||
#include "mongo/platform/atomic_word.h"
|
||||
#include "mongo/util/fail_point_service.h"
|
||||
|
||||
/**
|
||||
* Either executes the specified operation and returns it's value or randomly throws a write
|
||||
* conflict exception if the WTWriteConflictException failpoint is enabled.
|
||||
*/
|
||||
#define WT_OP_CHECK(x) (((MONGO_FAIL_POINT(WTWriteConflictException))) ? (WT_ROLLBACK) : (x))
|
||||
|
||||
namespace mongo {
|
||||
|
||||
@@ -282,4 +289,8 @@ namespace mongo {
|
||||
WiredTigerSizeStorer* _sizeStorer; // not owned, can be NULL
|
||||
int _sizeStorerCounter;
|
||||
};
|
||||
|
||||
// WT failpoint to throw write conflict exceptions randomly
|
||||
MONGO_FP_FORWARD_DECLARE(WTWriteConflictException);
|
||||
|
||||
}
|
||||
|
||||
@@ -117,7 +117,9 @@ MongoRunner.binVersionSubs = [ new MongoRunner.VersionSub(/^latest$/, ""),
|
||||
// Latest unstable and next stable are effectively the
|
||||
// same release
|
||||
new MongoRunner.VersionSub(/^2\.7(\..*){0,1}/, ""),
|
||||
new MongoRunner.VersionSub(/^2\.8(\..*){0,1}/, "") ];
|
||||
new MongoRunner.VersionSub(/^2\.8(\..*){0,1}/, ""),
|
||||
new MongoRunner.VersionSub(/^3\.0(\..*){0,1}/, ""),
|
||||
new MongoRunner.VersionSub(/^3\.1(\..*){0,1}/, "") ];
|
||||
|
||||
MongoRunner.getBinVersionFor = function(version) {
|
||||
|
||||
|
||||
@@ -26,28 +26,33 @@
|
||||
* then also delete it in the license file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Should NOT be included by other header files. Include only in source files.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "mongo/base/init.h"
|
||||
#include "mongo/util/fail_point_registry.h"
|
||||
|
||||
namespace mongo {
|
||||
|
||||
/**
|
||||
* @return the global fail point registry.
|
||||
*/
|
||||
FailPointRegistry* getGlobalFailPointRegistry();
|
||||
|
||||
/**
|
||||
* Convenience macro for declaring a fail point. Must be used in global scope and
|
||||
* never in a block with limited scope (ie, inside functions, loops, etc.)
|
||||
* Convenience macro for declaring a fail point. Must be used in global scope and never in a
|
||||
* block with limited scope (ie, inside functions, loops, etc.).
|
||||
*
|
||||
* NOTE: Never use in header files, only sources.
|
||||
*/
|
||||
#define MONGO_FP_DECLARE(fp) FailPoint fp; \
|
||||
MONGO_INITIALIZER_GENERAL(fp, ("FailPointRegistry"), ("AllFailPointsRegistered")) \
|
||||
(::mongo::InitializerContext* context) { \
|
||||
return getGlobalFailPointRegistry()->addFailPoint(#fp, &fp); \
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience macro for defining a fail point in a header scope.
|
||||
*/
|
||||
#define MONGO_FP_FORWARD_DECLARE(fp) extern FailPoint fp;
|
||||
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace mongo {
|
||||
* 1.2.3-rc4-pre-
|
||||
* If you really need to do something else you'll need to fix _versionArray()
|
||||
*/
|
||||
const char versionString[] = "2.8.0-rc6-pre-";
|
||||
const char versionString[] = "3.0.0-rc6";
|
||||
|
||||
// See unit test for example outputs
|
||||
BSONArray toVersionArray(const char* version){
|
||||
|
||||
33
src/third_party/wiredtiger/src/include/btree.i
vendored
33
src/third_party/wiredtiger/src/include/btree.i
vendored
@@ -34,6 +34,31 @@ __wt_page_is_modified(WT_PAGE *page)
|
||||
*/
|
||||
#define WT_ALLOC_OVERHEAD 32U
|
||||
|
||||
/*
|
||||
* Track a field in the cache. Use atomic CAS so that we can reliably avoid
|
||||
* decrementing the cache below zero - since we use an unsigned number.
|
||||
* Track if we would go below zero in a diagnostic build - something has gone
|
||||
* wrong.
|
||||
*/
|
||||
#ifdef HAVE_DIAGNOSTIC
|
||||
#define WT_CACHE_DECR(session, f, sz) do { \
|
||||
uint64_t __val = f; \
|
||||
uint64_t __sz = WT_MIN(__val, sz); \
|
||||
if (__sz < sz) \
|
||||
__wt_errx(session, "%s underflow: decrementing %" \
|
||||
WT_SIZET_FMT, #f, sz); \
|
||||
while (!WT_ATOMIC_CAS8(f, __val, __val - __sz)) \
|
||||
__val = f, __sz = WT_MIN(__val, __sz); \
|
||||
} while (0)
|
||||
#else
|
||||
#define WT_CACHE_DECR(session, f, sz) do { \
|
||||
uint64_t __val = f; \
|
||||
uint64_t __sz = WT_MIN(__val, sz); \
|
||||
while (!WT_ATOMIC_CAS8(f, __val, __val - __sz)) \
|
||||
__val = f, __sz = WT_MIN(__val, __sz); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* __wt_cache_page_inmem_incr --
|
||||
* Increment a page's memory footprint in the cache.
|
||||
@@ -66,11 +91,11 @@ __wt_cache_page_inmem_decr(WT_SESSION_IMPL *session, WT_PAGE *page, size_t size)
|
||||
size += WT_ALLOC_OVERHEAD;
|
||||
|
||||
cache = S2C(session)->cache;
|
||||
(void)WT_ATOMIC_SUB8(cache->bytes_inmem, size);
|
||||
(void)WT_ATOMIC_SUB8(page->memory_footprint, size);
|
||||
WT_CACHE_DECR(session, cache->bytes_inmem, size);
|
||||
WT_CACHE_DECR(session, page->memory_footprint, size);
|
||||
if (__wt_page_is_modified(page)) {
|
||||
(void)WT_ATOMIC_SUB8(cache->bytes_dirty, size);
|
||||
(void)WT_ATOMIC_SUB8(page->modify->bytes_dirty, size);
|
||||
WT_CACHE_DECR(session, cache->bytes_dirty, size);
|
||||
WT_CACHE_DECR(session, page->modify->bytes_dirty, size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user