Skip to content

Commit f7e5d1a

Browse files
committed
CXX-692 Check writeConcern errors in findAndModify
1 parent 1ed64da commit f7e5d1a

File tree

6 files changed

+53
-2
lines changed

6 files changed

+53
-2
lines changed

src/mongo/client/dbclient.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1393,6 +1393,11 @@ void DBClientBase::_findAndModify(const StringData& ns,
13931393
if (!ok)
13941394
throw OperationException(result);
13951395

1396+
// Check for any write concern errors
1397+
WriteResult writeResult;
1398+
writeResult._mergeWriteConcern(result);
1399+
writeResult._check(true);
1400+
13961401
out->appendElements(result.getObjectField("value"));
13971402
}
13981403

src/mongo/client/dbclient_rs.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,14 @@ class MONGO_CLIENT_API DBClientReplicaSet : public DBClientBase {
203203
*/
204204
static void setAuthPooledSecondaryConn(bool setting);
205205

206+
virtual int getMaxWireVersion() {
207+
return checkMaster()->getMaxWireVersion();
208+
}
209+
210+
virtual int getMinWireVersion() {
211+
return checkMaster()->getMinWireVersion();
212+
}
213+
206214
protected:
207215
/** Authorize. Authorizes all nodes as needed
208216
*/

src/mongo/client/dbclientinterface.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1463,10 +1463,10 @@ class MONGO_CLIENT_API DBClientBase : public DBClientWithCommands, public DBConn
14631463
_maxWireVersion = maxWireVersion;
14641464
}
14651465

1466-
int getMinWireVersion() {
1466+
virtual int getMinWireVersion() {
14671467
return _minWireVersion;
14681468
}
1469-
int getMaxWireVersion() {
1469+
virtual int getMaxWireVersion() {
14701470
return _maxWireVersion;
14711471
}
14721472
int getMaxBsonObjectSize() {

src/mongo/client/write_result.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ void WriteResult::_mergeCommandResult(const std::vector<WriteOperation*>& ops,
125125
_createWriteError(arrayIterator.next().Obj(), ops);
126126
}
127127

128+
_mergeWriteConcern(result);
129+
}
130+
131+
void WriteResult::_mergeWriteConcern(const BSONObj& result) {
128132
// Handle Write Concern Errors
129133
if (result.hasField("writeConcernError")) {
130134
BSONObj writeConcernError = result.getObjectField("writeConcernError");

src/mongo/client/write_result.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class MONGO_CLIENT_API WriteResult {
3434
friend class WireProtocolWriter;
3535
friend class CommandWriter;
3636
friend class BulkOperationBuilder;
37+
friend class DBClientBase;
3738

3839
public:
3940
/**
@@ -140,6 +141,7 @@ class MONGO_CLIENT_API WriteResult {
140141
const std::vector<BSONObj>& writeConcernErrors() const;
141142

142143
private:
144+
void _mergeWriteConcern(const BSONObj& result);
143145
void _mergeCommandResult(const std::vector<WriteOperation*>& ops, const BSONObj& result);
144146
void _mergeGleResult(const std::vector<WriteOperation*>& ops, const BSONObj& result);
145147

src/mongo/integration/replica_set/basic.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,18 @@ class RSBasicTest : public ReplicaSetTest {
4343
std::auto_ptr<DBClientReplicaSet> conn;
4444
};
4545

46+
bool serverGTE(DBClientBase* c, int major, int minor) {
47+
BSONObj result;
48+
c->runCommand("admin", BSON("buildinfo" << true), result);
49+
50+
std::vector<BSONElement> version = result.getField("versionArray").Array();
51+
int serverMajor = version[0].Int();
52+
int serverMinor = version[1].Int();
53+
54+
// std::pair uses lexicographic ordering
55+
return std::make_pair(serverMajor, serverMinor) >= std::make_pair(major, minor);
56+
}
57+
4658
TEST_F(RSBasicTest, InsertRecoversFromPrimaryFailure) {
4759
WriteConcern wcAll = WriteConcern().nodes(2).timeout(60000);
4860
conn->insert(TEST_NS, BSON("x" << 1), 0, &wcAll);
@@ -85,4 +97,24 @@ TEST_F(RSBasicTest, SecondaryQueryIsNotInteruptedByPrimaryFailure) {
8597
conn->findOne(TEST_NS, Query().readPref(ReadPreference_SecondaryOnly, BSONArray()));
8698
primary.start();
8799
}
100+
101+
TEST_F(RSBasicTest, FindAndModifyFailure) {
102+
if (serverGTE(conn.get(), 3, 1)) {
103+
WriteConcern wcAll = WriteConcern().nodes(5).journal(true);
104+
conn->insert(TEST_NS, BSON("_id" << 1 << "i" << 1));
105+
106+
// findAndModify is expected to throw since we want 5 nodes, and the replica set set only
107+
// has 3 nodes
108+
ASSERT_THROWS(conn->findAndModify(TEST_NS,
109+
BSON("i" << 1),
110+
BSON("$inc" << BSON("i" << 1)),
111+
false,
112+
false,
113+
BSONObj(),
114+
BSONObj(),
115+
&wcAll),
116+
OperationException);
117+
}
118+
}
119+
88120
} // namespace

0 commit comments

Comments
 (0)