<s> from random import randrange , shuffle <EOL> from BitTornado . clock import clock <EOL> try : <EOL> True <EOL> except : <EOL> True = <NUM_LIT:1> <EOL> False = <NUM_LIT:0> <EOL> class Choker : <EOL> def __init__ ( self , config , schedule , picker , done = lambda : False ) : <EOL> self . config = config <EOL> self . round_robin_period = config [ '<STR_LIT>' ] <EOL> self . schedule = schedule <EOL> self . picker = picker <EOL> self . connections = [ ] <EOL> self . last_preferred = <NUM_LIT:0> <EOL> self . last_round_robin = clock ( ) <EOL> self . done = done <EOL> self . super_seed = False <EOL> self . paused = False <EOL> schedule ( self . _round_robin , <NUM_LIT:5> ) <EOL> def set_round_robin_period ( self , x ) : <EOL> self . round_robin_period = x <EOL> def _round_robin ( self ) : <EOL> self . schedule ( self . _round_robin , <NUM_LIT:5> ) <EOL> if self . super_seed : <EOL> cons = range ( len ( self . connections ) ) <EOL> to_close = [ ] <EOL> count = self . config [ '<STR_LIT>' ] - self . last_preferred <EOL> if count > <NUM_LIT:0> : <EOL> shuffle ( cons ) <EOL> for c in cons : <EOL> i = self . picker . next_have ( self . connections [ c ] , count > <NUM_LIT:0> ) <EOL> if i is None : <EOL> continue <EOL> if i < <NUM_LIT:0> : <EOL> to_close . append ( self . connections [ c ] ) <EOL> continue <EOL> self . connections [ c ] . send_have ( i ) <EOL> count -= <NUM_LIT:1> <EOL> for c in to_close : <EOL> c . close ( ) <EOL> if self . last_round_robin + self . round_robin_period < clock ( ) : <EOL> self . last_round_robin = clock ( ) <EOL> for i in xrange ( <NUM_LIT:1> , len ( self . connections ) ) : <EOL> c = self . connections [ i ] <EOL> u = c . get_upload ( ) <EOL> if u . is_choked ( ) and u . is_interested ( ) : <EOL> self . connections = self . connections [ i : ] + self . connections [ : i ] <EOL> break <EOL> self . _rechoke ( ) <EOL> def _rechoke ( self ) : <EOL> preferred = [ ] <EOL> maxuploads = self . config [ '<STR_LIT>' ] <EOL> if self . paused : <EOL> for c in self . connections : <EOL> c . get_upload ( ) . choke ( ) <EOL> return <EOL> if maxuploads > <NUM_LIT:1> : <EOL> for c in self . connections : <EOL> u = c . get_upload ( ) <EOL> if not u . is_interested ( ) : <EOL> continue <EOL> if self . done ( ) : <EOL> r = u . get_rate ( ) <EOL> else : <EOL> d = c . get_download ( ) <EOL> r = d . get_rate ( ) <EOL> if r < <NUM_LIT:1000> or d . is_snubbed ( ) : <EOL> continue <EOL> preferred . append ( ( - r , c ) ) <EOL> self . last_preferred = len ( preferred ) <EOL> preferred . sort ( ) <EOL> del preferred [ maxuploads - <NUM_LIT:1> : ] <EOL> preferred = [ x [ <NUM_LIT:1> ] for x in preferred ] <EOL> count = len ( preferred ) <EOL> hit = False <EOL> to_unchoke = [ ] <EOL> for c in self . connections : <EOL> u = c . get_upload ( ) <EOL> if c in preferred : <EOL> to_unchoke . append ( u ) <EOL> else : <EOL> if count < maxuploads or not hit : <EOL> to_unchoke . append ( u ) <EOL> if u . is_interested ( ) : <EOL> count += <NUM_LIT:1> <EOL> hit = True <EOL> else : <EOL> u . choke ( ) <EOL> for u in to_unchoke : <EOL> u . unchoke ( ) <EOL> def connection_made ( self , connection , p = None ) : <EOL> if p is None : <EOL> p = randrange ( - <NUM_LIT:2> , len ( self . connections ) + <NUM_LIT:1> ) <EOL> self . connections . insert ( max ( p , <NUM_LIT:0> ) , connection ) <EOL> self . _rechoke ( ) <EOL> def connection_lost ( self , connection ) : <EOL> self . connections . remove ( connection ) <EOL> self . picker . lost_peer ( connection ) <EOL> if connection . get_upload ( ) . is_interested ( ) and not connection . get_upload ( ) . is_choked ( ) : <EOL> self . _rechoke ( ) <EOL> def interested ( self , connection ) : <EOL> if not connection . get_upload ( ) . is_choked ( ) : <EOL> self . _rechoke ( ) <EOL> def not_interested ( self , connection ) : <EOL> if not connection . get_upload ( ) . is_choked ( ) : <EOL> self . _rechoke ( ) <EOL> def set_super_seed ( self ) : <EOL> while self . connections : <EOL> self . connections [ <NUM_LIT:0> ] . close ( ) <EOL> self . picker . set_superseed ( ) <EOL> self . super_seed = True <EOL> def pause ( self , flag ) : <EOL> self . paused = flag <EOL> self . _rechoke ( ) </s>
