33
33
from bzrlib.lazy_import import lazy_import
 
34
34
lazy_import(globals(), """
 
35
37
from bzrlib import (
 
41
 
from bzrlib.smart import protocol
 
 
45
from bzrlib.smart import client, protocol
 
42
46
from bzrlib.transport import ssh
 
 
469
473
        return self._medium._get_line()
 
 
476
class _DebugCounter(object):
 
 
477
    """An object that counts the HPSS calls made to each client medium.
 
 
479
    When a medium is garbage-collected, or failing that when atexit functions
 
 
480
    are run, the total number of calls made on that medium are reported via
 
 
485
        self.counts = weakref.WeakKeyDictionary()
 
 
486
        client._SmartClient.hooks.install_named_hook(
 
 
487
            'call', self.increment_call_count, 'hpss call counter')
 
 
488
        atexit.register(self.flush_all)
 
 
490
    def track(self, medium):
 
 
491
        """Start tracking calls made to a medium.
 
 
493
        This only keeps a weakref to the medium, so shouldn't affect the
 
 
496
        medium_repr = repr(medium)
 
 
497
        # Add this medium to the WeakKeyDictionary
 
 
498
        self.counts[medium] = [0, medium_repr]
 
 
499
        # Weakref callbacks are fired in reverse order of their association
 
 
500
        # with the referenced object.  So we add a weakref *after* adding to
 
 
501
        # the WeakKeyDict so that we can report the value from it before the
 
 
502
        # entry is removed by the WeakKeyDict's own callback.
 
 
503
        ref = weakref.ref(medium, self.done)
 
 
505
    def increment_call_count(self, params):
 
 
506
        # Increment the count in the WeakKeyDictionary
 
 
507
        value = self.counts[params.medium]
 
 
511
        value = self.counts[ref]
 
 
512
        count, medium_repr = value
 
 
513
        # In case this callback is invoked for the same ref twice (by the
 
 
514
        # weakref callback and by the atexit function), set the call count back
 
 
515
        # to 0 so this item won't be reported twice.
 
 
518
            trace.note('HPSS calls: %d %s', count, medium_repr)
 
 
521
        for ref in list(self.counts.keys()):
 
 
524
_debug_counter = None
 
472
527
class SmartClientMedium(SmartMedium):
 
473
528
    """Smart client is a medium for sending smart protocol requests over."""
 
 
483
538
        # _remote_version_is_before tracks the bzr version the remote side
 
484
539
        # can be based on what we've seen so far.
 
485
540
        self._remote_version_is_before = None
 
 
541
        # Install debug hook function if debug flag is set.
 
 
542
        if 'hpss' in debug.debug_flags:
 
 
543
            global _debug_counter
 
 
544
            if _debug_counter is None:
 
 
545
                _debug_counter = _DebugCounter()
 
 
546
            _debug_counter.track(self)
 
487
548
    def _is_remote_before(self, version_tuple):
 
488
549
        """Is it possible the remote side supports RPCs for a given version?