Skip to content

Commit

Permalink
Revert "use selectors instead of select; improve performance of base …
Browse files Browse the repository at this point in the history
…1.0 or 1.1 selection"

This reverts commit 2822a0d.
  • Loading branch information
einarnn committed Jul 28, 2018
1 parent 720e61a commit c9f62b8
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 36 deletions.
4 changes: 0 additions & 4 deletions ncclient/transport/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ def __init__(self, capabilities):
self._notification_q = Queue()
self._client_capabilities = capabilities
self._server_capabilities = None # yet
self._base = 1.0
self._id = None # session-id
self._connected = False # to be set/cleared by subclass implementation
logger.debug('%r created: client_capabilities=%r' %
Expand Down Expand Up @@ -108,9 +107,6 @@ def err_cb(err):
raise error[0]
#if ':base:1.0' not in self.server_capabilities:
# raise MissingCapabilityError(':base:1.0')
if 'urn:ietf:params:netconf:base:1.1' in self._server_capabilities and 'urn:ietf:params:netconf:base:1.1' in self._client_capabilities:
logger.debug("After 'hello' message selecting netconf:base:1.1 for encoding")
self._base = 1.1
logger.info('initialized: session-id=%s | server_capabilities=%s' %
(self._id, self._server_capabilities))

Expand Down
76 changes: 44 additions & 32 deletions ncclient/transport/ssh.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,6 @@
from lxml import etree
from select import select

try:
import selectors
except ImportError:
import selectors2 as selectors

from ncclient.capabilities import Capabilities

import paramiko
Expand Down Expand Up @@ -169,6 +164,7 @@ def _parse11(self):
chunk = b''.join(chunk_list)
message_list.append(textify(chunk))
break # done reading
logger.debug('x: %s', x)
if state == idle:
if x == b'\n':
state = instart
Expand Down Expand Up @@ -542,43 +538,59 @@ def run(self):
def start_delim(data_len): return '\n#%s\n'%(data_len)

try:
s = selectors.DefaultSelector()
s.register(chan, selectors.EVENT_READ)
logger.debug('selector type = %s', s.__class__.__name__)
while True:

# Log what netconf:base version we are using this time
# round the loop; _base is updated when we receive the
# server's capabilities.
logger.debug('Currently selected netconf:base:%0.1f', self._base)

# Will wakeup evey TICK seconds to check if something
# to send, more quickly if something to read (due to
# select returning chan in readable list).
events = s.select(timeout=TICK)
if events:
# select on a paramiko ssh channel object does not ever return it in the writable list, so channels don't exactly emulate the socket api
r, w, e = select([chan], [], [], TICK)
# will wakeup evey TICK seconds to check if something to send, more if something to read (due to select returning chan in readable list)
if r:
data = chan.recv(BUF_SIZE)
if data:
self._buffer.write(data)
if self._base == 1.1:
self._parse11()
if self._server_capabilities:
if 'urn:ietf:params:netconf:base:1.1' in self._server_capabilities and 'urn:ietf:params:netconf:base:1.1' in self._client_capabilities:
logger.debug("Selecting netconf:base:1.1 for encoding")
self._parse11()
elif 'urn:ietf:params:netconf:base:1.0' in self._server_capabilities or 'urn:ietf:params:xml:ns:netconf:base:1.0' in self._server_capabilities or 'urn:ietf:params:netconf:base:1.0' in self._client_capabilities:
logger.debug("Selecting netconf:base:1.0 for encoding")
self._parse10()
else: raise Exception
else:
self._parse10()
self._parse10() # HELLO msg uses EOM markers.
else:
raise SessionCloseError(self._buffer.getvalue())
if not q.empty() and chan.send_ready():
logger.debug("Sending message")
data = q.get()
if self._base == 1.1:
data = "%s%s%s" % (start_delim(len(data)), data, END_DELIM)
else:
data = "%s%s" % (data, MSG_DELIM)
logger.debug("Sending: %s", data)
while data:
n = chan.send(data)
if n <= 0:
raise SessionCloseError(self._buffer.getvalue(), data)
data = data[n:]
try:
# send a HELLO msg using v1.0 EOM markers.
validated_element(data, tags='{urn:ietf:params:xml:ns:netconf:base:1.0}hello')
data = "%s%s"%(data, MSG_DELIM)
except XMLError:
# this is not a HELLO msg
# we publish v1.1 support
if 'urn:ietf:params:netconf:base:1.1' in self._client_capabilities:
if self._server_capabilities:
if 'urn:ietf:params:netconf:base:1.1' in self._server_capabilities:
# send using v1.1 chunked framing
data = "%s%s%s"%(start_delim(len(data)), data, END_DELIM)
elif 'urn:ietf:params:netconf:base:1.0' in self._server_capabilities or 'urn:ietf:params:xml:ns:netconf:base:1.0' in self._server_capabilities:
# send using v1.0 EOM markers
data = "%s%s"%(data, MSG_DELIM)
else: raise Exception
else:
logger.debug('HELLO msg was sent, but server capabilities are still not known')
raise Exception
# we publish only v1.0 support
else:
# send using v1.0 EOM markers
data = "%s%s"%(data, MSG_DELIM)
finally:
logger.debug("Sending: %s", data)
while data:
n = chan.send(data)
if n <= 0:
raise SessionCloseError(self._buffer.getvalue(), data)
data = data[n:]
except Exception as e:
logger.debug("Broke out of main loop, error=%r", e)
self._dispatch_error(e)
Expand Down

0 comments on commit c9f62b8

Please sign in to comment.