@@ -33,7 +33,11 @@ class SSLError(socket.error):
3333from bson .py3compat import imap , itervalues , _unicode , integer_types
3434from bson .son import SON
3535from pymongo import auth , helpers , thread_util , __version__
36- from pymongo .common import MAX_MESSAGE_SIZE , ORDERED_TYPES
36+ from pymongo .common import (MAX_BSON_SIZE ,
37+ MAX_MESSAGE_SIZE ,
38+ MAX_WIRE_VERSION ,
39+ MAX_WRITE_BATCH_SIZE ,
40+ ORDERED_TYPES )
3741from pymongo .errors import (AutoReconnect ,
3842 ConnectionFailure ,
3943 ConfigurationError ,
@@ -401,36 +405,49 @@ class SocketInfo(object):
401405 :Parameters:
402406 - `sock`: a raw socket object
403407 - `pool`: a Pool instance
404- - `ismaster`: optional IsMaster instance, response to ismaster on `sock`
405408 - `address`: the server's (host, port)
406409 """
407- def __init__ (self , sock , pool , ismaster , address ):
410+ def __init__ (self , sock , pool , address ):
408411 self .sock = sock
409412 self .address = address
410413 self .authset = set ()
411414 self .closed = False
412415 self .last_checkin_time = _time ()
413- self .is_writable = ismaster .is_writable if ismaster else None
414- self .max_wire_version = ismaster .max_wire_version if ismaster else None
415- self .max_bson_size = ismaster .max_bson_size if ismaster else None
416- self .max_message_size = (
417- ismaster .max_message_size if ismaster else MAX_MESSAGE_SIZE )
418- self .max_write_batch_size = (
419- ismaster .max_write_batch_size if ismaster else None )
420- self .supports_sessions = (
421- ismaster and ismaster .logical_session_timeout_minutes is not None )
416+ self .performed_handshake = False
417+ self .is_writable = False
418+ self .max_wire_version = MAX_WIRE_VERSION
419+ self .max_bson_size = MAX_BSON_SIZE
420+ self .max_message_size = MAX_MESSAGE_SIZE
421+ self .max_write_batch_size = MAX_WRITE_BATCH_SIZE
422+ self .supports_sessions = False
423+ self .is_mongos = False
422424
423425 self .listeners = pool .opts .event_listeners
424426
425- if ismaster :
426- self .is_mongos = ismaster .server_type == SERVER_TYPE .Mongos
427- else :
428- self .is_mongos = None
429-
430427 # The pool's pool_id changes with each reset() so we can close sockets
431428 # created before the last reset.
432429 self .pool_id = pool .pool_id
433430
431+ def ismaster (self , metadata , cluster_time ):
432+ cmd = SON ([('ismaster' , 1 )])
433+ if not self .performed_handshake :
434+ cmd ['client' ] = metadata
435+ self .performed_handshake = True
436+
437+ if self .max_wire_version >= 6 and cluster_time is not None :
438+ cmd ['$clusterTime' ] = cluster_time
439+
440+ ismaster = IsMaster (self .command ('admin' , cmd , publish_events = False ))
441+ self .is_writable = ismaster .is_writable
442+ self .max_wire_version = ismaster .max_wire_version
443+ self .max_bson_size = ismaster .max_bson_size
444+ self .max_message_size = ismaster .max_message_size
445+ self .max_write_batch_size = ismaster .max_write_batch_size
446+ self .supports_sessions = (
447+ ismaster .logical_session_timeout_minutes is not None )
448+ self .is_mongos = ismaster .server_type == SERVER_TYPE .Mongos
449+ return ismaster
450+
434451 def command (self , dbname , spec , slave_ok = False ,
435452 read_preference = ReadPreference .PRIMARY ,
436453 codec_options = DEFAULT_CODEC_OPTIONS , check = True ,
@@ -441,7 +458,8 @@ def command(self, dbname, spec, slave_ok=False,
441458 collation = None ,
442459 session = None ,
443460 client = None ,
444- retryable_write = False ):
461+ retryable_write = False ,
462+ publish_events = True ):
445463 """Execute a command or raise an error.
446464
447465 :Parameters:
@@ -461,6 +479,7 @@ def command(self, dbname, spec, slave_ok=False,
461479 - `session`: optional ClientSession instance.
462480 - `client`: optional MongoClient for gossipping $clusterTime.
463481 - `retryable_write`: True if this command is a retryable write.
482+ - `publish_events`: Should we publish events for this command?
464483 """
465484 self .validate_session (client , session )
466485 if (read_concern and self .max_wire_version < 4
@@ -487,11 +506,12 @@ def command(self, dbname, spec, slave_ok=False,
487506 if retryable_write :
488507 spec ['txnNumber' ] = session ._transaction_id ()
489508 self .send_cluster_time (spec , session , client )
509+ listeners = self .listeners if publish_events else None
490510 try :
491511 return command (self .sock , dbname , spec , slave_ok ,
492512 self .is_mongos , read_preference , codec_options ,
493513 session , client , check , allowable_errors ,
494- self .address , check_keys , self . listeners ,
514+ self .address , check_keys , listeners ,
495515 self .max_bson_size , read_concern ,
496516 parse_write_concern_error = parse_write_concern_error ,
497517 collation = collation )
@@ -860,29 +880,16 @@ def connect(self):
860880 sock = None
861881 try :
862882 sock = _configured_socket (self .address , self .opts )
863- if self .handshake :
864- cmd = SON ([
865- ('ismaster' , 1 ),
866- ('client' , self .opts .metadata )
867- ])
868- ismaster = IsMaster (
869- command (sock ,
870- 'admin' ,
871- cmd ,
872- False ,
873- False ,
874- ReadPreference .PRIMARY ,
875- DEFAULT_CODEC_OPTIONS ,
876- None ,
877- None ))
878- else :
879- ismaster = None
880- return SocketInfo (sock , self , ismaster , self .address )
881883 except socket .error as error :
882884 if sock is not None :
883885 sock .close ()
884886 _raise_connection_failure (self .address , error )
885887
888+ sock_info = SocketInfo (sock , self , self .address )
889+ if self .handshake :
890+ sock_info .ismaster (self .opts .metadata , None )
891+ return sock_info
892+
886893 @contextlib .contextmanager
887894 def get_socket (self , all_credentials , checkout = False ):
888895 """Get a socket from the pool. Use with a "with" statement.
0 commit comments