~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/sftp.py

  • Committer: Carl Friedrich Bolz
  • Date: 2006-08-01 10:53:24 UTC
  • mto: (1711.2.131 jam-integration)
  • mto: This revision was merged to the branch mainline in revision 1947.
  • Revision ID: cfbolz@gmx.de-20060801105324-ef75a52712d00ed3
Refined the SocketDelay to charge latency only once per round-trip and to
charge a small bit of time per character sent/received. Time is spent by
increasing a counter.

Show diffs side-by-side

added added

removed removed

Lines of Context:
943
943
class SocketDelay(object):
944
944
    """A socket decorator to make TCP appear slower.
945
945
 
946
 
    This changes recv, send, and sendall to add a fixed latency to each 
947
 
    python call. It will therefore behave differently to the real underlying
948
 
    TCP stack which may only pay the latency price on each actual roundtrip
949
 
    rather than each packet initiated. We can come closer to the real
950
 
    behaviour by only charging latency for each roundtrip we detect - that is
951
 
    when recv is called, toggle a flag, and insert latency again only when
952
 
    send has been called in the middle. For now though, showing more latency
953
 
    than we have is probably acceptable.
954
 
 
955
 
    Not all methods are implemented, this is deliberate as this class is not
956
 
    a replacement for the builtin sockets layer. fileno is not implemented to
957
 
    prevent the proxy being bypassed.
 
946
    This changes recv, send, and sendall to add a fixed latency to each python
 
947
    call if a new roundtrip is detected. That is, when a recv is called and the
 
948
    flag new_roundtrip is set, latency is charged. Every send and send_all
 
949
    sets this flag.
 
950
 
 
951
    In addition every send, sendall and recv sleeps a bit per character send to
 
952
    simulate bandwidth.
 
953
 
 
954
    The function used to sleep moves a counter forwards to not make the tests
 
955
    slower. It could be made more clever, by adding the time that was passing
 
956
    between sleep calls to the simulated time too.
 
957
 
 
958
    Not all methods are implemented, this is deliberate as this class is not a
 
959
    replacement for the builtin sockets layer. fileno is not implemented to
 
960
    prevent the proxy being bypassed. 
958
961
    """
959
962
 
960
 
    def __init__(self, sock, latency):
 
963
    simulated_time = 0
 
964
 
 
965
    def __init__(self, sock, latency, time_per_char=0.0001,
 
966
                 really_sleep=False):
961
967
        self.sock = sock
962
968
        self.latency = latency
 
969
        self.really_sleep = really_sleep
 
970
        self.time_per_char = time_per_char
 
971
        self.new_roundtrip = False
 
972
 
 
973
    def sleep(self, s):
 
974
        if self.really_sleep:
 
975
            time.sleep(s)
 
976
        SocketDelay.simulated_time += s
963
977
 
964
978
    def close(self):
965
979
        return self.sock.close()
966
980
 
967
981
    def dup(self):
968
 
        return SocketDelay(self.sock.dup(), self.latency)
 
982
        return SocketDelay(self.sock.dup(), self.latency, self.time_per_char,
 
983
                           self._sleep)
969
984
 
970
985
    def getpeername(self, *args):
971
986
        return self.sock.getpeername(*args)
981
996
 
982
997
    def recv(self, *args):
983
998
        data = self.sock.recv(*args)
984
 
        if data:
985
 
            time.sleep(self.latency)
 
999
        if data and self.new_roundtrip:
 
1000
            self.new_roundtrip = False
 
1001
            self.sleep(self.latency)
 
1002
            self.sleep(len(data) * self.time_per_char)
986
1003
        return data
987
1004
 
988
 
    def sendall(self, *args):
989
 
        time.sleep(self.latency)
990
 
        return self.sock.sendall(*args)
 
1005
    def sendall(self, data, flags=0):
 
1006
        if not self.new_roundtrip:
 
1007
            self.new_roundtrip = True
 
1008
            self.sleep(self.latency)
 
1009
        self.sleep(len(data) * self.time_per_char)
 
1010
        return self.sock.sendall(data, flags)
991
1011
 
992
 
    def send(self, *args):
993
 
        time.sleep(self.latency)
994
 
        return self.sock.send(*args)
 
1012
    def send(self, data, flags=0):
 
1013
        if not self.new_roundtrip:
 
1014
            self.new_roundtrip = True
 
1015
            self.sleep(self.latency)
 
1016
        bytes_sent = self.sock.send(data, flags)
 
1017
        self.sleep(bytes_sent * self.time_per_char)
 
1018
        return bytes_sent
995
1019
 
996
1020
    def setblocking(self, *args):
997
1021
        return self.sock.setblocking(*args)