summaryrefslogtreecommitdiff
path: root/src/mongo/db/repl/sync.cpp
diff options
context:
space:
mode:
authorApollon Oikonomopoulos <apoikos@debian.org>2016-01-14 00:10:06 +0200
committerApollon Oikonomopoulos <apollon@skroutz.gr>2016-01-14 00:10:06 +0200
commit374e1947abcd3e127a2a613aff73ecffdb9199ea (patch)
treed83973c3c9802450acd5b5e86fe0d4e8e60a3a1b /src/mongo/db/repl/sync.cpp
parent65585c90b12d6523bea75a2aebaae2a2fdf9e641 (diff)
Imported Upstream version 2.6.11upstream/2.6.11
Diffstat (limited to 'src/mongo/db/repl/sync.cpp')
-rw-r--r--src/mongo/db/repl/sync.cpp136
1 files changed, 136 insertions, 0 deletions
diff --git a/src/mongo/db/repl/sync.cpp b/src/mongo/db/repl/sync.cpp
new file mode 100644
index 00000000000..893226b01a4
--- /dev/null
+++ b/src/mongo/db/repl/sync.cpp
@@ -0,0 +1,136 @@
+/**
+* Copyright (C) 2008 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 <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/db/repl/sync.h"
+
+#include <string>
+
+#include "mongo/db/jsobj.h"
+#include "mongo/db/client.h"
+#include "mongo/db/diskloc.h"
+#include "mongo/db/structure/catalog/namespace_details.h"
+#include "mongo/db/pdfile.h"
+#include "mongo/db/repl/oplogreader.h"
+#include "mongo/db/catalog/collection.h"
+#include "mongo/util/assert_util.h"
+#include "mongo/util/log.h"
+
+namespace mongo {
+
+ void Sync::setHostname(const string& hostname) {
+ hn = hostname;
+ }
+
+ BSONObj Sync::getMissingDoc(const BSONObj& o) {
+ OplogReader missingObjReader; // why are we using OplogReader to run a non-oplog query?
+ const char *ns = o.getStringField("ns");
+
+ // capped collections
+ Collection* collection = cc().database()->getCollection(ns);
+ if ( collection && collection->isCapped() ) {
+ log() << "replication missing doc, but this is okay for a capped collection (" << ns << ")" << endl;
+ return BSONObj();
+ }
+
+ const int retryMax = 3;
+ for (int retryCount = 1; retryCount <= retryMax; ++retryCount) {
+ if (retryCount != 1) {
+ // if we are retrying, sleep a bit to let the network possibly recover
+ sleepsecs(retryCount * retryCount);
+ }
+ try {
+ bool ok = missingObjReader.connect(hn);
+ if (!ok) {
+ warning() << "network problem detected while connecting to the "
+ << "sync source, attempt " << retryCount << " of "
+ << retryMax << endl;
+ continue; // try again
+ }
+ }
+ catch (const SocketException&) {
+ warning() << "network problem detected while connecting to the "
+ << "sync source, attempt " << retryCount << " of "
+ << retryMax << endl;
+ continue; // try again
+ }
+
+ // might be more than just _id in the update criteria
+ BSONObj query = BSONObjBuilder().append(o.getObjectField("o2")["_id"]).obj();
+ BSONObj missingObj;
+ try {
+ missingObj = missingObjReader.findOne(ns, query);
+ }
+ catch (const SocketException&) {
+ warning() << "network problem detected while fetching a missing document from the "
+ << "sync source, attempt " << retryCount << " of "
+ << retryMax << endl;
+ continue; // try again
+ }
+ catch (DBException& e) {
+ log() << "replication assertion fetching missing object: " << e.what() << endl;
+ throw;
+ }
+
+ // success!
+ return missingObj;
+ }
+ // retry count exceeded
+ msgasserted(15916,
+ str::stream() << "Can no longer connect to initial sync source: " << hn);
+ }
+
+ bool Sync::shouldRetry(const BSONObj& o) {
+ // should already have write lock
+ const char *ns = o.getStringField("ns");
+ Client::Context ctx(ns);
+
+ // we don't have the object yet, which is possible on initial sync. get it.
+ log() << "replication info adding missing object" << endl; // rare enough we can log
+
+ BSONObj missingObj = getMissingDoc(o);
+
+ if( missingObj.isEmpty() ) {
+ log() << "replication missing object not found on source. presumably deleted later in oplog" << endl;
+ log() << "replication o2: " << o.getObjectField("o2").toString() << endl;
+ log() << "replication o firstfield: " << o.getObjectField("o").firstElementFieldName() << endl;
+
+ return false;
+ }
+ else {
+ Collection* collection = ctx.db()->getOrCreateCollection( ns );
+ verify( collection ); // should never happen
+ StatusWith<DiskLoc> result = collection->insertDocument( missingObj, true );
+ uassert(15917,
+ str::stream() << "failed to insert missing doc: " << result.toString(),
+ result.isOK() );
+
+ LOG(1) << "replication inserted missing doc: " << missingObj.toString() << endl;
+ return true;
+ }
+ }
+}