Statistics
| Branch: | Tag: | Revision:

root / ncclient / rpc / listener.py @ 94803aaf

History | View | Annotate | Download (2.4 kB)

1
# Copyright 2009 Shikhar Bhushan
2
#
3
# Licensed under the Apache License, Version 2.0 (the "License");
4
# you may not use this file except in compliance with the License.
5
# You may obtain a copy of the License at
6
#
7
#    http://www.apache.org/licenses/LICENSE-2.0
8
#
9
# Unless required by applicable law or agreed to in writing, software
10
# distributed under the License is distributed on an "AS IS" BASIS,
11
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
# See the License for the specific language governing permissions and
13
# limitations under the License.
14

    
15
from threading import Lock
16
from weakref import WeakValueDictionary
17

    
18
import logging
19
logger = logging.getLogger('ncclient.rpc.listener')
20

    
21
class RPCReplyListener(Listener):
22
    
23
    # one instance per session
24
    def __new__(cls, session):
25
        instance = session.get_listener_instance(cls)
26
        if instance is None:
27
            instance = object.__new__(cls)
28
            instance._lock = Lock()
29
            instance._id2rpc = WeakValueDictionary()
30
            instance._pipelined = session.can_pipeline
31
            instance._errback = None
32
            session.add_listener(instance)
33
        return instance
34
    
35
    def register(self, id, rpc):
36
        with self._lock:
37
            self._id2rpc[id] = rpc
38
    
39
    def callback(self, root, raw):
40
        tag, attrs = root
41
        if __(tag) != 'rpc-reply':
42
            return
43
        rpc = None
44
        for key in attrs:
45
            if __(key) == 'message-id':
46
                id = attrs[key]
47
                try:
48
                    with self._lock:
49
                        rpc = self._id2rpc.pop(id)
50
                except KeyError:
51
                    logger.warning('no object registered for message-id: [%s]' % id)
52
                except Exception as e:
53
                    logger.debug('error - %r' % e)
54
                break
55
        else:
56
            if not self._pipelined:
57
                with self._lock:
58
                    assert(len(self._id2rpc) == 1)
59
                    rpc = self._id2rpc.values()[0]
60
                    self._id2rpc.clear()
61
            else:
62
                logger.warning('<rpc-reply> without message-id received: %s' % raw)
63
        logger.debug('delivering to %r' % rpc)
64
        rpc.deliver(raw)
65
    
66
    def set_errback(self, errback):
67
        self._errback = errback
68
    
69
    def errback(self, err):
70
        if self._errback is not None:
71
            self._errback(err)