コード例 #1
0
ファイル: Cache.py プロジェクト: smoothit/smoothit-client
 def _init_callback_handler(self):
     self.handlers = PeerCallbackHandlers(self._get_name(),
                                            self._cache_config.get_report_interval())
     self.handlers.register_handler(PeerReporter(self._get_name()))
     self.handlers.register_handler(CacheActiveDownloadTracker())
     
     if self._cache_config.get_sis_url() is not None:
         ip_addr = net_utils.get_own_ip_addr()
         iop_url = self._cache_config.get_sis_iop_url()
         self.handlers.register_handler(PeerActivityReportEmitter(
                 (ip_addr, self._cache_config.get_port()),
                 self._cache_config.get_report_interval(),
                 sis_iop_endpoint_url=iop_url))
     
     if self._cache_config.get_report_to() is not None:
         if self._cache_config.get_report_to() == 'local_report':
             global local_reporter
             local_reporter = PeerLocalReporter(self._get_name(), self._cache_config.get_id(),
                                            self.session, self._cache_config.get_directory())
             self.handlers.register_handler(local_reporter)
         else:
             self.handlers.register_handler(PeerHTTPReporter(self._get_name(),
                                                               self._cache_config.get_id(),
                                                               self._cache_config.get_report_to(),
                                                               self.sconfig,
                                                               self._cache_config.get_compress_xml_reports(),
                                                               self._cache_config.get_serialization_method(),
                                                               is_iop=True))
コード例 #2
0
        def setup_callback_handlers(session, scfg):
            self._handlers = PeerCallbackHandlers(
                self._get_name(), self._config.get_report_interval())
            self._handlers.register_handler(PeerReporter(self._get_name()))
            self._handlers.register_handler(
                ClientStatistics(self._config.get_directory(),
                                 self._config.get_id()))

            if self._config.is_hap_enabled():
                self._logger.info("HAP support enabled")
                self._handlers.register_handler(ClientHAPHandler(self._config))

            if self._config.get_sis_url() != None:
                ip_addr = net_utils.get_own_ip_addr()
                self._handlers.register_handler(
                    PeerActivityReportEmitter(
                        (ip_addr, self._config.get_port()),
                        self._config.get_activity_report_interval(),
                        sis_iop_endpoint_url=self._config.get_sis_iop_url()))

            if self._config.get_exit_on() == constants.EXIT_ON_ALL_FINISHED:
                self._handlers.register_handler(
                    ClientUptimeHandler(session,
                                        method=constants.EXIT_ON_ALL_FINISHED,
                                        callback=self._on_exit))
            elif self._config.get_exit_on() == constants.EXIT_ON_PLAYBACK_DONE:
                self._handlers.register_handler(
                    ClientUptimeHandler(session,
                                        method=constants.EXIT_ON_PLAYBACK_DONE,
                                        callback=self._on_exit))
            elif self._config.get_exit_on() == constants.EXIT_ON_SEEDING_TIME:
                self._handlers.register_handler(
                    ClientUptimeHandler(
                        session,
                        method=constants.EXIT_ON_SEEDING_TIME,
                        max_seeding_time=self._config.get_seeding_time(),
                        callback=self._on_exit))

            if self._config.get_report_to() is not None:
                if self._config.get_report_to() == 'local_report':
                    self._local_reporter = PeerLocalReporter(
                        self._get_name(), self._config.get_id(), session,
                        self._config.get_directory())
                    self._handlers.register_handler(self._local_reporter)
                else:
                    self._handlers.register_handler(
                        PeerHTTPReporter(
                            self._get_name(),
                            self._config.get_id(),
                            self._config.get_report_to(),
                            scfg,
                            self._config.get_compress_xml_reports(),
                            self._config.get_serialization_method(),
                            report_interval=self._config.get_report_interval())
                    )
コード例 #3
0
 def setup_callback_handlers(session, scfg):
     self._handlers = PeerCallbackHandlers(self._get_name(), self._config.get_report_interval())
     self._handlers.register_handler(PeerReporter(self._get_name()))
     self._handlers.register_handler(ClientStatistics(self._config.get_directory(),
                                                self._config.get_id()))
     
     if self._config.is_hap_enabled():
         self._logger.info("HAP support enabled")
         self._handlers.register_handler(ClientHAPHandler(self._config))
     
     if self._config.get_sis_url() != None:
         ip_addr = net_utils.get_own_ip_addr()
         self._handlers.register_handler(PeerActivityReportEmitter(
             (ip_addr, self._config.get_port()),
             self._config.get_activity_report_interval(),
             sis_iop_endpoint_url=self._config.get_sis_iop_url()))
         
     if self._config.get_exit_on() == constants.EXIT_ON_ALL_FINISHED:
         self._handlers.register_handler(ClientUptimeHandler(session,
                                                       method=constants.EXIT_ON_ALL_FINISHED,
                                                       callback=self._on_exit))
     elif self._config.get_exit_on() == constants.EXIT_ON_PLAYBACK_DONE:
         self._handlers.register_handler(ClientUptimeHandler(session,
                                                       method=constants.EXIT_ON_PLAYBACK_DONE,
                                                       callback=self._on_exit))
     elif self._config.get_exit_on() == constants.EXIT_ON_SEEDING_TIME:
         self._handlers.register_handler(ClientUptimeHandler(session,
                                                       method=constants.EXIT_ON_SEEDING_TIME,
                                                       max_seeding_time=self._config.get_seeding_time(),
                                                       callback=self._on_exit))
         
     if self._config.get_report_to() is not None:
         if self._config.get_report_to() == 'local_report':
             self._local_reporter = PeerLocalReporter(self._get_name(),
                                                  self._config.get_id(),
                                                  session,
                                                  self._config.get_directory())
             self._handlers.register_handler(self._local_reporter)
         else:
             self._handlers.register_handler(PeerHTTPReporter(self._get_name(),
                                                          self._config.get_id(),
                                                          self._config.get_report_to(),
                                                          scfg,
                                                          self._config.get_compress_xml_reports(),
                                                          self._config.get_serialization_method(),
                                                          report_interval=self._config.get_report_interval()))
コード例 #4
0
class Client(object):
    def __init__(self, client_config):
        self._config = client_config
        self._logger = logging.getLogger(self._get_name())
        self._local_reporter = None

        if self._config.get_logfile() is not None:
            logfile_directory = FileUtils.get_path_from_full_filename(
                self._config.get_logfile())
            if self._config.get_logfile().find(os.path.normcase('/')) > -1 and \
                    not os.access(logfile_directory, os.F_OK):
                os.mkdir(logfile_directory)

        torrent_file = self._config.get_single_torrent()
        if torrent_file is not None:
            if not os.access(torrent_file, os.F_OK):
                self._logger.error(
                    "The specified torrent file %s does not exist." %
                    torrent_file)
                self._on_exit()

    def _get_name(self):
        return "%s.%i" % (self.__class__.__name__, self._config.get_id())

    def _cleanup(self, signal=None, func=None):
        if self._config.get_delete_directories():
            FileUtils.remove_directory_recursively(
                self._config.get_directory())
            FileUtils.remove_directory_recursively(
                self._config.get_state_directory())
            self._logger.warn("Removed directories %s and %s" %
                              (self._config.get_directory(),
                               self._config.get_state_directory()))

    def start_client(self):
        self._setup_client()
        self._start_downloads()
        set_exit_handler(self._on_exit)

        try:
            while True:
                time.sleep(5)
            time.sleep(self._config.get_report_interval())
        except KeyboardInterrupt:
            pass
        finally:
            self._on_exit()

    def _setup_client(self):
        def setup_directories():
            if not os.access(self._config.get_directory(), os.F_OK):
                os.mkdir(self._config.get_directory())
            if self._config.get_state_directory():
                if not os.access(self._config.get_state_directory(), os.F_OK):
                    os.mkdir(self._config.get_state_directory())
            else:
                state_dir = tempfile.mkdtemp()
                self._config.set_state_directory(state_dir)

        def setup_scfg():
            scfg = SessionStartupConfig()
            scfg.set_state_dir(self._config.get_state_directory())
            scfg.set_listen_port(self._config.get_port())
            scfg.set_overlay(False)
            scfg.set_megacache(False)
            scfg.set_upnp_mode(UPNPMODE_DISABLED)
            return scfg

        def setup_callback_handlers(session, scfg):
            self._handlers = PeerCallbackHandlers(
                self._get_name(), self._config.get_report_interval())
            self._handlers.register_handler(PeerReporter(self._get_name()))
            self._handlers.register_handler(
                ClientStatistics(self._config.get_directory(),
                                 self._config.get_id()))

            if self._config.is_hap_enabled():
                self._logger.info("HAP support enabled")
                self._handlers.register_handler(ClientHAPHandler(self._config))

            if self._config.get_sis_url() != None:
                ip_addr = net_utils.get_own_ip_addr()
                self._handlers.register_handler(
                    PeerActivityReportEmitter(
                        (ip_addr, self._config.get_port()),
                        self._config.get_activity_report_interval(),
                        sis_iop_endpoint_url=self._config.get_sis_iop_url()))

            if self._config.get_exit_on() == constants.EXIT_ON_ALL_FINISHED:
                self._handlers.register_handler(
                    ClientUptimeHandler(session,
                                        method=constants.EXIT_ON_ALL_FINISHED,
                                        callback=self._on_exit))
            elif self._config.get_exit_on() == constants.EXIT_ON_PLAYBACK_DONE:
                self._handlers.register_handler(
                    ClientUptimeHandler(session,
                                        method=constants.EXIT_ON_PLAYBACK_DONE,
                                        callback=self._on_exit))
            elif self._config.get_exit_on() == constants.EXIT_ON_SEEDING_TIME:
                self._handlers.register_handler(
                    ClientUptimeHandler(
                        session,
                        method=constants.EXIT_ON_SEEDING_TIME,
                        max_seeding_time=self._config.get_seeding_time(),
                        callback=self._on_exit))

            if self._config.get_report_to() is not None:
                if self._config.get_report_to() == 'local_report':
                    self._local_reporter = PeerLocalReporter(
                        self._get_name(), self._config.get_id(), session,
                        self._config.get_directory())
                    self._handlers.register_handler(self._local_reporter)
                else:
                    self._handlers.register_handler(
                        PeerHTTPReporter(
                            self._get_name(),
                            self._config.get_id(),
                            self._config.get_report_to(),
                            scfg,
                            self._config.get_compress_xml_reports(),
                            self._config.get_serialization_method(),
                            report_interval=self._config.get_report_interval())
                    )

        setup_directories()
        self._logger.info("Client directory is at %s" %
                          self._config.get_directory())
        self._logger.info("Client state directory is at %s" %
                          self._config.get_state_directory())
        scfg = setup_scfg()
        self._session = Session(scfg)
        self._session.set_supporter_seed(
            self._config.is_supporter_seed())  #TODO: parameterize!!!
        self._logger.error("Supporter IPs are: " +
                           self._config.get_supporter_ip())
        self._session.set_supporter_ips(self._config.get_supporter_ip())
        setup_callback_handlers(self._session, scfg)

        source = self._config.get_ranking_source()
        endpoint = self._config.get_sis_client_endpoint()
        ranking = RankingPolicy.selectRankingSource(source, conf=self._config)
        NeighborSelection.createMechanism(
            self._config.get_ns_mode(),
            ranking,
            locality_pref=self._config.get_locality_preference())
        BiasedUnchoking.BiasedUnchoking(self._config.get_peer_selection_mode(),
                                        ranking)

    def _start_downloads(self):
        torrent_files = []
        if self._config.get_single_torrent() is not None:
            torrent_files.append(self._config.get_single_torrent())
        else:
            torrent_files = files_list(
                self._config.get_directory(),
                [constants.TORRENT_DOWNLOAD_EXT, constants.TORRENT_VOD_EXT])
        if len(torrent_files) == 0:
            self._logger.error("No torrents found.")
            self._on_exit()
            os._exit(1)
        for torrent in torrent_files:
            self._start_download(torrent)

    def _start_download(self, torrent):
        tdef = TorrentDef.load(torrent)
        dscfg = DownloadStartupConfig()
        #disable PEX protocol, otherwise it will crash if two clients are running on the same machine!
        #dscfg.set_ut_pex_max_addrs_from_peer(0)

        dscfg.set_dest_dir(self._config.get_directory())
        if common_utils.has_torrent_video_files(
                tdef) and not self._config.is_supporter_seed():
            dscfg.set_video_event_callback(self._handlers.video_event_callback)
        self._logger.warn("Download directory: " + dscfg.get_dest_dir())
        dscfg.set_max_speed(UPLOAD, self._config.get_upload_limit())
        dscfg.set_max_speed(DOWNLOAD, self._config.get_download_limit())
        con_lim = self._config.get_connection_limit()
        dscfg.set_max_conns(con_lim)
        dscfg.set_max_conns_to_initiate((con_lim + 1) / 2)
        dscfg.set_min_peers((con_lim + 2) / 3)
        dscfg.set_max_uploads(self._config.get_max_upload_slots_per_download())
        dscfg.set_peer_type("G")

        self._logger.warn("Files available: %s" % tdef.get_files())

        if dscfg.get_mode() == DLMODE_VOD:
            self._logger.warn("RUN in streaming mode")
            if tdef.is_multifile_torrent():
                for file in tdef.get_files():
                    if file.endswith(".avi"):
                        dscfg.set_selected_files([file])
                        break
        else:
            self._logger.warn("RUN in file sharing mode")

        d = self._session.start_download(tdef, dscfg)
        d.set_state_callback(self._handlers.state_callback, getpeerlist=True)

    def _on_exit(self, signal=None, func=None):
        if self._local_reporter is not None:
            self._local_reporter.write_stats()
        # stop all active downloads
        for download in self._session.get_downloads():
            download.stop()
        # shutting down session
        self._session.shutdown(checkpoint=False, gracetime=2.0)
        # call the provided method (cleanup purposes)
        self._cleanup(signal, func)
        os._exit(0)
コード例 #5
0
class Client(object):
    def __init__(self, client_config):
        self._config = client_config
        self._logger = logging.getLogger(self._get_name())
        self._local_reporter = None
        
        if self._config.get_logfile() is not None:
            logfile_directory = FileUtils.get_path_from_full_filename(self._config.get_logfile())
            if self._config.get_logfile().find(os.path.normcase('/')) > -1 and \
                    not os.access(logfile_directory, os.F_OK):
                os.mkdir(logfile_directory)
        
        torrent_file = self._config.get_single_torrent()
        if torrent_file is not None:
            if not os.access(torrent_file, os.F_OK):
                self._logger.error("The specified torrent file %s does not exist." % torrent_file)
                self._on_exit()
        
    def _get_name(self):
        return "%s.%i" % (self.__class__.__name__, self._config.get_id())
    
    def _cleanup(self, signal=None, func=None):
        if self._config.get_delete_directories():
            FileUtils.remove_directory_recursively(self._config.get_directory())
            FileUtils.remove_directory_recursively(self._config.get_state_directory())
            self._logger.warn("Removed directories %s and %s" % (self._config.get_directory(),
                                                                 self._config.get_state_directory()))
        
    def start_client(self):
        self._setup_client()
        self._start_downloads()
        set_exit_handler(self._on_exit)
        
        try:
            while True:
                time.sleep(5)
            time.sleep(self._config.get_report_interval())
        except KeyboardInterrupt:
            pass
        finally:
            self._on_exit()
            
    def _setup_client(self):
        def setup_directories():
            if not os.access(self._config.get_directory(), os.F_OK):
                os.mkdir(self._config.get_directory())
            if self._config.get_state_directory():
                if not os.access(self._config.get_state_directory(), os.F_OK):
                    os.mkdir(self._config.get_state_directory())
            else:
                state_dir = tempfile.mkdtemp()
                self._config.set_state_directory(state_dir)
        
        def setup_scfg():
            scfg = SessionStartupConfig()
            scfg.set_state_dir(self._config.get_state_directory())
            scfg.set_listen_port(self._config.get_port())
            scfg.set_overlay(False)
            scfg.set_megacache(False)
            scfg.set_upnp_mode(UPNPMODE_DISABLED)
            return scfg
        
        def setup_callback_handlers(session, scfg):
            self._handlers = PeerCallbackHandlers(self._get_name(), self._config.get_report_interval())
            self._handlers.register_handler(PeerReporter(self._get_name()))
            self._handlers.register_handler(ClientStatistics(self._config.get_directory(),
                                                       self._config.get_id()))
            
            if self._config.is_hap_enabled():
                self._logger.info("HAP support enabled")
                self._handlers.register_handler(ClientHAPHandler(self._config))
            
            if self._config.get_sis_url() != None:
                ip_addr = net_utils.get_own_ip_addr()
                self._handlers.register_handler(PeerActivityReportEmitter(
                    (ip_addr, self._config.get_port()),
                    self._config.get_activity_report_interval(),
                    sis_iop_endpoint_url=self._config.get_sis_iop_url()))
                
            if self._config.get_exit_on() == constants.EXIT_ON_ALL_FINISHED:
                self._handlers.register_handler(ClientUptimeHandler(session,
                                                              method=constants.EXIT_ON_ALL_FINISHED,
                                                              callback=self._on_exit))
            elif self._config.get_exit_on() == constants.EXIT_ON_PLAYBACK_DONE:
                self._handlers.register_handler(ClientUptimeHandler(session,
                                                              method=constants.EXIT_ON_PLAYBACK_DONE,
                                                              callback=self._on_exit))
            elif self._config.get_exit_on() == constants.EXIT_ON_SEEDING_TIME:
                self._handlers.register_handler(ClientUptimeHandler(session,
                                                              method=constants.EXIT_ON_SEEDING_TIME,
                                                              max_seeding_time=self._config.get_seeding_time(),
                                                              callback=self._on_exit))
                
            if self._config.get_report_to() is not None:
                if self._config.get_report_to() == 'local_report':
                    self._local_reporter = PeerLocalReporter(self._get_name(),
                                                         self._config.get_id(),
                                                         session,
                                                         self._config.get_directory())
                    self._handlers.register_handler(self._local_reporter)
                else:
                    self._handlers.register_handler(PeerHTTPReporter(self._get_name(),
                                                                 self._config.get_id(),
                                                                 self._config.get_report_to(),
                                                                 scfg,
                                                                 self._config.get_compress_xml_reports(),
                                                                 self._config.get_serialization_method(),
                                                                 report_interval=self._config.get_report_interval()))
                
        setup_directories()
        self._logger.info("Client directory is at %s" % self._config.get_directory())
        self._logger.info("Client state directory is at %s" % self._config.get_state_directory())
        scfg = setup_scfg()
        self._session = Session(scfg)
        self._session.set_supporter_seed(self._config.is_supporter_seed())#TODO: parameterize!!!
        self._logger.error("Supporter IPs are: "+self._config.get_supporter_ip())
        self._session.set_supporter_ips(self._config.get_supporter_ip())
        setup_callback_handlers(self._session, scfg)
        
        source = self._config.get_ranking_source()
        endpoint = self._config.get_sis_client_endpoint()
        ranking = RankingPolicy.selectRankingSource(source, conf=self._config)
        NeighborSelection.createMechanism(self._config.get_ns_mode(), ranking,
                                          locality_pref=self._config.get_locality_preference())
        BiasedUnchoking.BiasedUnchoking(self._config.get_peer_selection_mode(), ranking) 
        
    def _start_downloads(self):
        torrent_files = []
        if self._config.get_single_torrent() is not None:
            torrent_files.append(self._config.get_single_torrent())
        else:
            torrent_files = files_list(self._config.get_directory(), [constants.TORRENT_DOWNLOAD_EXT, constants.TORRENT_VOD_EXT])
        if len(torrent_files) == 0:
            self._logger.error("No torrents found.")
            self._on_exit()
            os._exit(1)
        for torrent in torrent_files:
            self._start_download(torrent)
            
    def _start_download(self, torrent):
        tdef = TorrentDef.load(torrent)
        dscfg = DownloadStartupConfig()
        #disable PEX protocol, otherwise it will crash if two clients are running on the same machine!
        #dscfg.set_ut_pex_max_addrs_from_peer(0)
        
        dscfg.set_dest_dir(self._config.get_directory())
        if common_utils.has_torrent_video_files(tdef) and not self._config.is_supporter_seed():
            dscfg.set_video_event_callback(self._handlers.video_event_callback)
        self._logger.warn("Download directory: " + dscfg.get_dest_dir())
        dscfg.set_max_speed(UPLOAD, self._config.get_upload_limit())
        dscfg.set_max_speed(DOWNLOAD, self._config.get_download_limit())
        con_lim = self._config.get_connection_limit()
        dscfg.set_max_conns(con_lim)
        dscfg.set_max_conns_to_initiate((con_lim+1)/2)
        dscfg.set_min_peers((con_lim+2)/3)
        dscfg.set_max_uploads(self._config.get_max_upload_slots_per_download())
        dscfg.set_peer_type("G")
        
        self._logger.warn("Files available: %s" % tdef.get_files())
        
        if dscfg.get_mode() == DLMODE_VOD:
            self._logger.warn("RUN in streaming mode")
            if tdef.is_multifile_torrent():
                for file in tdef.get_files():
                    if file.endswith(".avi"):
                        dscfg.set_selected_files([file])
                        break
        else:
            self._logger.warn("RUN in file sharing mode")
            
        d = self._session.start_download(tdef, dscfg)
        d.set_state_callback(self._handlers.state_callback, getpeerlist=True)
      
    def _on_exit(self, signal=None, func=None):
        if self._local_reporter is not None:
            self._local_reporter.write_stats()
        # stop all active downloads
        for download in self._session.get_downloads():
            download.stop()
        # shutting down session
        self._session.shutdown(checkpoint=False, gracetime=2.0)
        # call the provided method (cleanup purposes)
        self._cleanup(signal, func)
        os._exit(0)
コード例 #6
0
ファイル: Cache.py プロジェクト: smoothit/smoothit-client
class Cache:
    ''' This class is used to start the cache applictaion.
    '''
    
    def __init__(self, cache_config):
        self._cache_config = cache_config
        self.active_downloads = {}
        self.stopped_downloads = {}
        self.save_dir = cache_config.get_directory()
        self.disc_space = cache_config.get_space_limit() * 1024 * 1024
        self.available_disc_space = self.disc_space
        self.dl_lock = RLock()
        
        self._logger = None
        self.ranking = None
        self.filtering = None
        self.replacement_strategy = None
        self.ratemanager = None
        self.handlers = None
        
        self._init_logger()
        self._init_cache_console()
        self._init_before_session()
        self.start_session(self._cache_config.get_port())
        self._init_after_session()
        self._init_callback_handler()
        self._init_selector()
        
    def _get_name(self):
        return "%s.%i" % (self.__class__.__name__, self._cache_config.get_id())
        
    def _init_logger(self):
        self._logger = logging.getLogger(self._get_name())
        
        self._logger.info("Initialized logger")
        global logger
        logger = self._logger
        
         
    def _init_cache_console(self):
        if self._cache_config.has_cache_console():
            CacheConsole.start_cache_console(self)
        
    def _init_before_session(self):
        self.ranking = RankingPolicy.selectRankingSource(self._cache_config.get_ranking_source(),
                                                    conf=self._cache_config)
        self._logger.warning("Ranking source is %s" % self.ranking)
        
        exclude_below = 1# allow only non-remote connections!
        self.filtering = NeighborSelection.createMechanism(self._cache_config.get_ns_mode(),
                                                            self.ranking,
                                                            exclude_below=exclude_below,
                                                            locality_pref=self._cache_config.get_locality_preference())
        self._logger.warning("Neighbor selection is %s" % self.filtering)
        self.max_downloads = self._cache_config.get_max_downloads()
        
    def _init_after_session(self):
        policy_name = self._cache_config.get_replacement_strategy()
        self.replacement_strategy = ReplacementStrategy.getInstance(self, policy_name)
        self.ratemanager = Ratemanager.getInstance(self, self._cache_config)
        self.ratemanager.set_dl_limit(self._cache_config.get_download_limit())
        self.ratemanager.set_ul_limit(self._cache_config.get_upload_limit())
        self.ratemanager.set_connection_limit(self._cache_config.get_connection_limit())
        
    def _init_callback_handler(self):
        self.handlers = PeerCallbackHandlers(self._get_name(),
                                               self._cache_config.get_report_interval())
        self.handlers.register_handler(PeerReporter(self._get_name()))
        self.handlers.register_handler(CacheActiveDownloadTracker())
        
        if self._cache_config.get_sis_url() is not None:
            ip_addr = net_utils.get_own_ip_addr()
            iop_url = self._cache_config.get_sis_iop_url()
            self.handlers.register_handler(PeerActivityReportEmitter(
                    (ip_addr, self._cache_config.get_port()),
                    self._cache_config.get_report_interval(),
                    sis_iop_endpoint_url=iop_url))
        
        if self._cache_config.get_report_to() is not None:
            if self._cache_config.get_report_to() == 'local_report':
                global local_reporter
                local_reporter = PeerLocalReporter(self._get_name(), self._cache_config.get_id(),
                                               self.session, self._cache_config.get_directory())
                self.handlers.register_handler(local_reporter)
            else:
                self.handlers.register_handler(PeerHTTPReporter(self._get_name(),
                                                                  self._cache_config.get_id(),
                                                                  self._cache_config.get_report_to(),
                                                                  self.sconfig,
                                                                  self._cache_config.get_compress_xml_reports(),
                                                                  self._cache_config.get_serialization_method(),
                                                                  is_iop=True))
                
    def _init_selector(self):
        selector = None
        mode = self._cache_config.get_torrent_selection_mechanism()
        if mode == 'local_folder':
            selector = LocalFolderSelector.LocalFolderSelector(self._cache_config.get_torrent_directory())
            self._logger.info("Run in local folder mode")
        elif mode == 'SIS':
            #selector = self._cache_config.get_ws_client() 
            selector = IoP_WSClientImpl(self._cache_config.get_sis_iop_url())
            selector.set_torrent_dir(self._cache_config.get_torrent_directory())
            #FIXME: we now create these instances twice!!! once in cache config and then here! Should rather use a wrapper here!
            self._logger.info("Run in WS torrent selection mode")
        else:
            raise ConfigurationException("Unsupported torrent selection mechanism!"+str())
                                         
        assert selector is not None
        self._logger.info("Use torrent selection method "+str(selector))
        
        interval = self._cache_config.get_torrent_selection_interval()
        max_torrents = self._cache_config.get_max_torrents()
        assert max_torrents >= self.max_downloads
        stay_in_torrents = self._cache_config.get_stay_in_torrents()
        self.torrent_selection = TorrentSelection.start_torrent_selection(
                                    self, selector,
                                    selection_interval=interval,
                                    max_torrents=max_torrents, stay_in_torrents=stay_in_torrents)


        
    def start_session(self, port):
        ''' Sets the values of the SessionStartupConfig an creates
            a new session.
        '''
        
        self.sconfig = API.SessionStartupConfig()
        self.sconfig.set_state_dir(self._cache_config.get_directory())    
        self.sconfig.set_listen_port(port)    
        self.sconfig.set_overlay(False)
        self.sconfig.set_megacache(False)
        self.sconfig.set_upnp_mode(simpledefs.UPNPMODE_DISABLED)
        self.session = API.Session(self.sconfig)
        global session
        session = self.session
                   
    def join_swarm(self, tdef, id):
        ''' Starts a new download with the given torrent definition. This method
            tries to allocate disc space and to get a download slot before the
            new download can be started. If the cache already contains the 
            specified download and it is stopped, this method can be used to
            restart the download. The id is used to identify the download.
        '''
        self.dl_lock.acquire()
        try:
            dl = self.get_download(id, stopped=True, pop=True)
            if not dl == None:
                if self.get_download_slot():
                    self.restart_download(id, dl)
                return True
            length = tdef.get_length(tdef.get_files())
            if self.allocate_disc_space(length):
                try:
                    dlcfg = self.get_startup_config()
                    dl = self.session.start_download(tdef, dlcfg)
                    self._logger.info("Join new swarm %s" % dl.get_def().get_name())
                    dl.set_state_callback(self.handlers.state_callback, getpeerlist=True)
                    if self.get_download_slot():
                        self.active_downloads[id] = dl
                    else:
                        time.sleep(5)
                        dl.stop()
                        self.stopped_downloads[id]=dl
                    return True
                except:
                    self.available_disc_space += length
                    self._logger.warn("Failed to start download: "+tdef.get_name(), exc_info=True)
                    return False 
            else:
                self._logger.warn("Failed to allocate disc space for "+tdef.get_name())
                return False
        except :
            self._logger.warn("Failed to join swarm "+tdef.get_name(), exc_info=True)
            return False
        finally:
            #print >> sys.stderr,"After join: active %s and stopped %s" % (self.active_downloads, self.stopped_downloads)
            self.dl_lock.release()

    def print_active(self):
        list = []
        for dl in self.active_downloads.values():
            list.append(dl.get_def().get_name())
        self._logger.error("active: %s" % list)
    
    def leave_swarm(self, id, delete=False): 
        ''' This method stops a currently running download.
            In addition the files of a running or stopped download can be deleted.
        '''
        assert id in self.active_downloads.keys() , id
        
        self.dl_lock.acquire()
        try:
            if delete:
                dl = self.get_download(id, stopped=True, pop=True)
                length = dl.get_def().get_length(dl.get_def().get_files())
                self.available_disc_space += length
            else:
                dl = self.get_download(id, pop=True)
                self._logger.info("Leave swarm %s" % dl.get_def().get_name())
                self.stopped_downloads[id] = dl
            dl.stop_remove(delete, delete)
            return True
        except:
            traceback.print_exc()
            return False
        finally:
            self.dl_lock.release()
            
    def restart_download(self, id, dl):
        ''' Restarts a stopped download.
        ''' 
        self._logger.info("Re-join swarm %s" % dl.get_def().get_name())
        dl.set_max_speed(simpledefs.DOWNLOAD, 1)#TODO: reuse config!!!
        dl.set_max_speed(simpledefs.UPLOAD, 1)
        dl.restart()
        dl.set_state_callback(self.handlers.state_callback, getpeerlist=True)
        self.active_downloads[id] = dl
        time.sleep(3)
        self.update_download_settings()
        
    def get_download_slot(self):
        ''' This method checks if a download slot is available.
            If no download slot is available the replacement strategy is
            used to stop a running download.
        '''
        if len(self.active_downloads) < self.max_downloads:
            return True
        else:
            return self.replacement_strategy.get_download_slot()
    
    def get_startup_config(self):
        ''' Sets values of the DownloadStartupConfig.
        '''
        
        dlcfg = API.DownloadStartupConfig()
        dlcfg.set_dest_dir(self.save_dir)
        dlcfg.set_max_speed(simpledefs.DOWNLOAD, 1)
        dlcfg.set_max_speed(simpledefs.UPLOAD, 1)
        dlcfg.set_max_uploads(self._cache_config.get_max_upload_slots_per_download())
        min_uploads = min(dlcfg.get_min_uploads(), self._cache_config.get_max_upload_slots_per_download())
        dlcfg.set_min_uploads(min_uploads)
        
        return dlcfg
    
    def get_download(self, id, stopped=False, pop=False):
        ''' Returns the download specified by the id.
        '''
        
        #print >> sys.stderr, "Check torrent: "+id
        #print >> sys.stderr, "Stopped: ", self.stopped_downloads
        #print >> sys.stderr, "Active: ", self.active_downloads
        if stopped:
            downloads = self.stopped_downloads
        else:
            downloads = self.active_downloads
            
        for (dl_id, dl) in downloads.items():
            if dl_id == id:
                if pop:
                    del downloads[dl_id]
                return dl 
        return None
        
    def is_running(self, id):
        ''' Returns if the download specified by the id is currently running.
        '''
        return self.active_downloads.has_key(id)
        #return not(self.get_download(id) == None)
    
    def is_stopped(self, id):
        ''' Returns if the download specified by the id is currently stopped.
        '''
        
        return not(self.get_download(id, stopped=True) == None)
    
    def update_download_settings(self):
        ''' Updates the transmission rates of all running downloads.
        '''
        
        self.dl_lock.acquire()
        try:
            self.ratemanager.adjust_speeds(self.active_downloads)
        finally:
            self.dl_lock.release()
    
    def allocate_disc_space(self, file_size): 
        ''' Checks if enough disc space for the download is available
            and tries to free up the needed disc space.
        '''
        #print >> sys.stderr, "Available space: %d, required space: %d " % (self.available_disc_space, file_size)
        if file_size <= self.available_disc_space:
            self.available_disc_space -= file_size
            return True
         
        if self.replacement_strategy.free_up_disc_space(file_size):
            self.available_disc_space -= file_size
            return True
        
        return False
        
    def start_connections(self, id, peer_dict):
        ''' Starts new connections.
        '''
        
        # select active or passive download?
        assert id in self.active_downloads.keys() or id in self.stopped_downloads.keys()
        dl = self.active_downloads[id]
        #print>>sys.stderr, "download: %s session %s" % (dl, dl.sd)
        #TODO: acquire locks before starting connections?
        if dl.sd is None: # race condition? connect to them later! 
            return
        
        bt1dl = dl.sd.get_bt1download()
        stats = dl.sd.get_stats(False)
        
        if stats[0] != None:
            return
        
        for torrent_id, list_of_peers in peer_dict.items():
            for peer in list_of_peers:
                ip, port = peer
                try:
                    bt1dl.startConnection(ip, port, False) # False means -> immediate connection
                except:
                    self._logger.warn("Failed to connect to %s for torrent id %s" % (str(peer), str(torrent_id)), exc_info = True)
       
    def set_dl_limit(self, limit):
        ''' Sets the download limit of the cache and updates the rates
            for all running downloads.
        '''
        
        self.ratemanager.set_dl_limit(limit)
        self.update_download_settings()
        
    def set_ul_limit(self, limit):
        ''' Sets the download limit of the cache and updates the rates
            for all running downloads.
        '''
        
        self.ratemanager.set_ul_limit(limit)
        self.update_download_settings()
            
    def set_hostname(self):
        ''' This method is used to get the hostname of the cache,
            which is used by the cache_local mode of the NeighborSelection.
        '''
        
        own_ip = self.session.get_external_ip()
        hostname = socket.gethostbyaddr(own_ip)
        NeighborSelection.getInstance().set_cache_hostname(hostname)
        
    def get_status(self):
        ''' Returns the current status of the cache and its running downloads.
        '''
        return CacheStatus(self.active_downloads, self.stopped_downloads, self)

    def get_active_downloads_ids(self):
        ''' Return list of active torrent ids.
        '''
        return list(self.active_downloads.keys())

    def get_up_rated_downloads(self):
        ''' Return list of active torrent ids sorted by the descending upload rate.
        '''
        rated = [] # download id to rate!
        status = self.get_status()
        for ds in status.downloadstats:
            id = ds['id']
            rate = ds['up_rate']
            if id in self.active_downloads:
                rated.append( (rate, id) )
        return [id for (rate, id) in sorted(rated, reverse=True)]
    
    def run_forever(self):
        try:
            while True:
                time.sleep(30)
        except KeyboardInterrupt:
            on_exit()