def _process_kill_cursors_queue(self): """Process any pending kill cursors requests.""" address_to_cursor_ids = defaultdict(list) # Other threads or the GC may append to the queue concurrently. while True: try: address, cursor_ids = self.__kill_cursors_queue.pop() except IndexError: break address_to_cursor_ids[address].extend(cursor_ids) # Don't re-open topology if it's closed and there's no pending cursors. if address_to_cursor_ids: topology = self._get_topology() for address, cursor_ids in address_to_cursor_ids.items(): try: if address: server = topology.select_server_by_address(address) else: # Application called close_cursor() with no address. server = topology.select_server( writable_server_selector) server.send_message(message.kill_cursors(cursor_ids), self.__all_credentials) except ConnectionFailure as exc: warnings.warn("couldn't close cursor on %s: %s" % (address, exc))
def _process_kill_cursors_queue(self): """Process any pending kill cursors requests.""" address_to_cursor_ids = defaultdict(list) # Other threads or the GC may append to the queue concurrently. while True: try: address, cursor_ids = self.__kill_cursors_queue.pop() except IndexError: break address_to_cursor_ids[address].extend(cursor_ids) # Don't re-open topology if it's closed and there's no pending cursors. if address_to_cursor_ids: publish = monitoring.enabled() topology = self._get_topology() for address, cursor_ids in address_to_cursor_ids.items(): try: if address: # address could be a tuple or _CursorAddress, but # select_server_by_address needs (host, port). server = topology.select_server_by_address( tuple(address)) else: # Application called close_cursor() with no address. server = topology.select_server( writable_server_selector) if publish: start = datetime.datetime.now() data = message.kill_cursors(cursor_ids) if publish: duration = datetime.datetime.now() - start try: dbname, collname = address.namespace.split(".", 1) except AttributeError: dbname = collname = 'OP_KILL_CURSORS' command = SON([('killCursors', collname), ('cursors', cursor_ids)]) monitoring.publish_command_start( command, dbname, data[0], address) start = datetime.datetime.now() server.send_message(data, self.__all_credentials) if publish: duration = (datetime.datetime.now() - start) + duration # OP_KILL_CURSORS returns no reply, fake one. reply = {'cursorsUnknown': cursor_ids, 'ok': 1} monitoring.publish_command_success( duration, reply, 'killCursors', data[0], address) except ConnectionFailure as exc: warnings.warn("couldn't close cursor on %s: %s" % (address, exc))
def kill_cursors(self, cursor_ids): """Send a kill cursors message with the given ids. Raises :class:`TypeError` if `cursor_ids` is not an instance of ``list``. :Parameters: - `cursor_ids`: list of cursor ids to kill """ if not isinstance(cursor_ids, list): raise TypeError("cursor_ids must be a list") return self._send_message(message.kill_cursors(cursor_ids))
def close_cursor(self, cursor_id, _conn_id): """Close a single database cursor. Raises :class:`TypeError` if `cursor_id` is not an instance of ``(int, long)``. What closing the cursor actually means depends on this connection's cursor manager. :Parameters: - `cursor_id`: id of cursor to close """ if not isinstance(cursor_id, (int, long)): raise TypeError("cursor_id must be an instance of (int, long)") self._send_message(message.kill_cursors([cursor_id]), _connection_to_use=_conn_id)
def _process_kill_cursors_queue(self): """Process any pending kill cursors requests.""" address_to_cursor_ids = defaultdict(list) # Other threads or the GC may append to the queue concurrently. while True: try: address, cursor_ids = self.__kill_cursors_queue.pop() except IndexError: break address_to_cursor_ids[address].extend(cursor_ids) # Don't re-open topology if it's closed and there's no pending cursors. if address_to_cursor_ids: listeners = self._event_listeners publish = listeners.enabled_for_commands topology = self._get_topology() for address, cursor_ids in address_to_cursor_ids.items(): try: if address: # address could be a tuple or _CursorAddress, but # select_server_by_address needs (host, port). server = topology.select_server_by_address( tuple(address)) else: # Application called close_cursor() with no address. server = topology.select_server( writable_server_selector) try: namespace = address.namespace db, coll = namespace.split('.', 1) except AttributeError: namespace = None db = coll = "OP_KILL_CURSORS" spec = SON([('killCursors', coll), ('cursors', cursor_ids)]) with server.get_socket( self.__all_credentials) as sock_info: if (sock_info.max_wire_version >= 4 and namespace is not None): sock_info.command(db, spec) else: if publish: start = datetime.datetime.now() request_id, msg = message.kill_cursors(cursor_ids) if publish: duration = datetime.datetime.now() - start listeners.publish_command_start( spec, db, request_id, address) start = datetime.datetime.now() try: sock_info.send_message(msg, 0) except Exception as exc: if publish: dur = ((datetime.datetime.now() - start) + duration) listeners.publish_command_failure( dur, message._convert_exception(exc), 'killCursors', request_id, address) raise if publish: duration = ((datetime.datetime.now() - start) + duration) # OP_KILL_CURSORS returns no reply, fake one. reply = {'cursorsUnknown': cursor_ids, 'ok': 1} listeners.publish_command_success( duration, reply, 'killCursors', request_id, address) except ConnectionFailure as exc: warnings.warn("couldn't close cursor on %s: %s" % (address, exc))
def _process_kill_cursors_queue(self): """Process any pending kill cursors requests.""" address_to_cursor_ids = defaultdict(list) # Other threads or the GC may append to the queue concurrently. while True: try: address, cursor_ids = self.__kill_cursors_queue.pop() except IndexError: break address_to_cursor_ids[address].extend(cursor_ids) # Don't re-open topology if it's closed and there's no pending cursors. if address_to_cursor_ids: listeners = self._event_listeners publish = listeners.enabled_for_commands topology = self._get_topology() for address, cursor_ids in address_to_cursor_ids.items(): try: if address: # address could be a tuple or _CursorAddress, but # select_server_by_address needs (host, port). server = topology.select_server_by_address( tuple(address)) else: # Application called close_cursor() with no address. server = topology.select_server( writable_server_selector) try: namespace = address.namespace db, coll = namespace.split('.', 1) except AttributeError: namespace = None db = coll = "OP_KILL_CURSORS" spec = SON([('killCursors', coll), ('cursors', cursor_ids)]) with server.get_socket(self.__all_credentials) as sock_info: if (sock_info.max_wire_version >= 4 and namespace is not None): sock_info.command(db, spec) else: if publish: start = datetime.datetime.now() request_id, msg = message.kill_cursors(cursor_ids) if publish: duration = datetime.datetime.now() - start listeners.publish_command_start( spec, db, request_id, address) start = datetime.datetime.now() try: sock_info.send_message(msg, 0) except Exception as exc: if publish: dur = ((datetime.datetime.now() - start) + duration) listeners.publish_command_failure( dur, message._convert_exception(exc), 'killCursors', request_id, address) raise if publish: duration = ((datetime.datetime.now() - start) + duration) # OP_KILL_CURSORS returns no reply, fake one. reply = {'cursorsUnknown': cursor_ids, 'ok': 1} listeners.publish_command_success( duration, reply, 'killCursors', request_id, address) except ConnectionFailure as exc: warnings.warn("couldn't close cursor on %s: %s" % (address, exc))