45
45
import static com .mongodb .connection .ServerType .REPLICA_SET_GHOST ;
46
46
import static com .mongodb .connection .ServerType .SHARD_ROUTER ;
47
47
import static com .mongodb .connection .ServerType .STANDALONE ;
48
+ import static com .mongodb .internal .operation .ServerVersionHelper .SIX_DOT_ZERO_WIRE_VERSION ;
48
49
import static java .lang .String .format ;
49
50
50
51
public abstract class AbstractMultiServerCluster extends BaseCluster {
@@ -224,9 +225,7 @@ private boolean handleReplicaSetMemberChanged(final ServerDescription newDescrip
224
225
}
225
226
226
227
if (newDescription .getType () == REPLICA_SET_GHOST ) {
227
- if (LOGGER .isInfoEnabled ()) {
228
- LOGGER .info (format ("Server %s does not appear to be a member of an initiated replica set." , newDescription .getAddress ()));
229
- }
228
+ LOGGER .info (format ("Server %s does not appear to be a member of an initiated replica set." , newDescription .getAddress ()));
230
229
return true ;
231
230
}
232
231
@@ -247,64 +246,78 @@ private boolean handleReplicaSetMemberChanged(final ServerDescription newDescrip
247
246
if (newDescription .getCanonicalAddress () != null
248
247
&& !newDescription .getAddress ().equals (new ServerAddress (newDescription .getCanonicalAddress ()))
249
248
&& !newDescription .isPrimary ()) {
250
- if (LOGGER .isInfoEnabled ()) {
251
- LOGGER .info (format ("Canonical address %s does not match server address. Removing %s from client view of cluster" ,
252
- newDescription .getCanonicalAddress (), newDescription .getAddress ()));
253
- }
249
+ LOGGER .info (format ("Canonical address %s does not match server address. Removing %s from client view of cluster" ,
250
+ newDescription .getCanonicalAddress (), newDescription .getAddress ()));
254
251
removeServer (newDescription .getAddress ());
255
252
return true ;
256
253
}
257
254
258
- if (newDescription .isPrimary ()) {
259
- ObjectId electionId = newDescription .getElectionId ();
260
- Integer setVersion = newDescription .getSetVersion ();
261
- if (setVersion != null && electionId != null ) {
262
- if (isStalePrimary (newDescription )) {
263
- if (LOGGER .isInfoEnabled ()) {
264
- LOGGER .info (format ("Invalidating potential primary %s whose (set version, election id) tuple of (%d, %s) "
265
- + "is less than one already seen of (%d, %s)" ,
266
- newDescription .getAddress (),
267
- setVersion , electionId ,
268
- maxSetVersion , maxElectionId ));
269
- }
270
- addressToServerTupleMap .get (newDescription .getAddress ()).server .resetToConnecting ();
271
- return false ;
272
- }
255
+ if (!newDescription .isPrimary ()) {
256
+ return true ;
257
+ }
273
258
274
- if (!electionId .equals (maxElectionId )) {
275
- if (LOGGER .isInfoEnabled ()) {
276
- LOGGER .info (format ("Setting max election id to %s from replica set primary %s" , electionId ,
277
- newDescription .getAddress ()));
278
- }
279
- maxElectionId = electionId ;
280
- }
281
- }
259
+ if (isStalePrimary (newDescription )) {
260
+ invalidatePotentialPrimary (newDescription );
261
+ return false ;
262
+ }
282
263
283
- if (setVersion != null
284
- && (maxSetVersion == null || setVersion .compareTo (maxSetVersion ) > 0 )) {
285
- if (LOGGER .isInfoEnabled ()) {
286
- LOGGER .info (format ("Setting max set version to %d from replica set primary %s" , setVersion ,
287
- newDescription .getAddress ()));
288
- }
289
- maxSetVersion = setVersion ;
290
- }
264
+ maxElectionId = nullSafeMax (newDescription .getElectionId (), maxElectionId );
265
+ maxSetVersion = nullSafeMax (newDescription .getSetVersion (), maxSetVersion );
291
266
292
- if (isNotAlreadyPrimary (newDescription .getAddress ())) {
293
- LOGGER .info (format ("Discovered replica set primary %s" , newDescription .getAddress ()));
294
- }
295
- invalidateOldPrimaries (newDescription .getAddress ());
267
+ invalidateOldPrimaries (newDescription .getAddress ());
268
+
269
+ if (isNotAlreadyPrimary (newDescription .getAddress ())) {
270
+ LOGGER .info (format ("Discovered replica set primary %s with max election id %s and max set version %d" ,
271
+ newDescription .getAddress (), newDescription .getElectionId (), newDescription .getSetVersion ()));
296
272
}
273
+
297
274
return true ;
298
275
}
299
276
300
- private boolean isStalePrimary (final ServerDescription newDescription ) {
301
- if (maxSetVersion == null || maxElectionId == null ) {
302
- return false ;
277
+ private boolean isStalePrimary (final ServerDescription description ) {
278
+ ObjectId electionId = description .getElectionId ();
279
+ Integer setVersion = description .getSetVersion ();
280
+ if (description .getMaxWireVersion () >= SIX_DOT_ZERO_WIRE_VERSION ) {
281
+ return nullSafeCompareTo (electionId , maxElectionId ) < 0
282
+ || (nullSafeCompareTo (electionId , maxElectionId ) == 0 && nullSafeCompareTo (setVersion , maxSetVersion ) < 0 );
283
+ } else {
284
+ return setVersion != null && electionId != null
285
+ && (nullSafeCompareTo (setVersion , maxSetVersion ) < 0
286
+ || (nullSafeCompareTo (setVersion , maxSetVersion ) == 0
287
+ && nullSafeCompareTo (electionId , maxElectionId ) < 0 ));
303
288
}
289
+ }
290
+
291
+ private void invalidatePotentialPrimary (final ServerDescription newDescription ) {
292
+ LOGGER .info (format ("Invalidating potential primary %s whose (set version, election id) tuple of (%d, %s) "
293
+ + "is less than one already seen of (%d, %s)" ,
294
+ newDescription .getAddress (), newDescription .getSetVersion (), newDescription .getElectionId (),
295
+ maxSetVersion , maxElectionId ));
296
+ addressToServerTupleMap .get (newDescription .getAddress ()).server .resetToConnecting ();
297
+ }
304
298
305
- Integer setVersion = newDescription .getSetVersion ();
306
- return (setVersion == null || maxSetVersion .compareTo (setVersion ) > 0
307
- || (maxSetVersion .equals (setVersion ) && maxElectionId .compareTo (newDescription .getElectionId ()) > 0 ));
299
+ /**
300
+ * Implements the same contract as {@link Comparable#compareTo(Object)}, except that a null value is always considers less-than any
301
+ * other value (except null, which it considers as equal-to).
302
+ */
303
+ private static <T extends Comparable <T >> int nullSafeCompareTo (final T first , final T second ) {
304
+ if (first == null ) {
305
+ return second == null ? 0 : -1 ;
306
+ }
307
+ if (second == null ) {
308
+ return 1 ;
309
+ }
310
+ return first .compareTo (second );
311
+ }
312
+
313
+ private static <T extends Comparable <T >> T nullSafeMax (final T first , final T second ) {
314
+ if (first == null ) {
315
+ return second ;
316
+ }
317
+ if (second == null ) {
318
+ return first ;
319
+ }
320
+ return first .compareTo (second ) >= 0 ? first : second ;
308
321
}
309
322
310
323
private boolean isNotAlreadyPrimary (final ServerAddress address ) {
@@ -315,7 +328,7 @@ private boolean isNotAlreadyPrimary(final ServerAddress address) {
315
328
private boolean handleShardRouterChanged (final ServerDescription newDescription ) {
316
329
if (!newDescription .isShardRouter ()) {
317
330
LOGGER .error (format ("Expecting a %s, but found a %s. Removing %s from client view of cluster." ,
318
- SHARD_ROUTER , newDescription .getType (), newDescription .getAddress ()));
331
+ SHARD_ROUTER , newDescription .getType (), newDescription .getAddress ()));
319
332
removeServer (newDescription .getAddress ());
320
333
}
321
334
return true ;
0 commit comments