Beispiel #1
0
    def __init__(self, doneflag, add_task, external_add_task, max_files_open, num_disk_threads):
        self.add_task = add_task
        self.file_to_torrent = {}
        self.waiting_ops = []

        self.active_file_to_handles = DictWithSets()
        self.open_file_to_handles = DictWithLists()

        self.set_max_files_open(max_files_open)
Beispiel #2
0
    def __init__(self, doneflag, add_task, external_add_task,
                 max_files_open, num_disk_threads):
        self.doneflag = doneflag
        self.external_add_task = external_add_task
        self.file_to_torrent = {}

        self.free_handle_condition = threading.Condition()
        self.active_file_to_handles = DictWithSets()
        self.open_file_to_handles = DictWithLists()

        self.set_max_files_open(max_files_open)

        self.diskq = Queue.Queue()
        for i in xrange(num_disk_threads):
            t = threading.Thread(target=self._disk_thread,
                                 name="disk_thread-%s" % (i+1))
            t.start()

        self.doneflag.addCallback(self.finalize)
Beispiel #3
0
class FilePool(object):

    def __init__(self, doneflag, add_task, external_add_task, max_files_open, num_disk_threads):
        self.add_task = add_task
        self.file_to_torrent = {}
        self.waiting_ops = []

        self.active_file_to_handles = DictWithSets()
        self.open_file_to_handles = DictWithLists()

        self.set_max_files_open(max_files_open)

    def close_all(self):
        df = Deferred()
        self._close_all(df)
        return df

    def _close_all(self, df):
        failures = {}

        while len(self.open_file_to_handles) > 0:
            filename, handle = self.open_file_to_handles.popitem()
            try:
                handle.close()
            except:
                failures[self.file_to_torrent[filename]] = Failure()

        for torrent, failure in failures.iteritems():
            torrent.got_exception(failure)

        if self.get_open_file_count() > 0:
            # it would be nice to wait on the deferred for the outstanding ops
            self.add_task(0.5, self._close_all, df)
        else:
            df.callback(True)

    def close_files(self, file_set):
        df = Deferred()
        self._close_files(df, file_set)
        return df

    def _close_files(self, df, file_set):
        failure = None
        done = False

        filenames = self.open_file_to_handles.keys()
        for filename in filenames:
            if filename not in file_set:
                continue
            handles = self.open_file_to_handles.poprow(filename)
            for handle in handles:
                try:
                    handle.close()
                except:
                    failure = Failure()

        done = True
        for filename in file_set.iterkeys():
            if filename in self.active_file_to_handles:
                done = False
                break

        if failure is not None:
            df.errback(failure)

        if not done:
            # it would be nice to wait on the deferred for the outstanding ops
            self.add_task(0.5, self._close_files, df, file_set)
        else:
            df.callback(True)

    def set_max_files_open(self, max_files_open):
        if max_files_open <= 0:
            max_files_open = 1e100
        self.max_files_open = max_files_open
        self.close_all()

    def add_files(self, files, torrent):
        for filename in files:
            if filename in self.file_to_torrent:
                raise BTFailure(_("File %s belongs to another running torrent")
                                % filename)
        for filename in files:
            self.file_to_torrent[filename] = torrent

    def remove_files(self, files):
        for filename in files:
            del self.file_to_torrent[filename]

    def _ensure_exists(self, filename, length=0):
        if not os.path.exists(filename):
            f = os.path.split(filename)[0]
            if f != '' and not os.path.exists(f):
                os.makedirs(f)
            f = file(filename, 'wb')
            make_file_sparse(filename, f, length)
            f.close()

    def get_open_file_count(self):
        t = self.open_file_to_handles.total_length()
        t += self.active_file_to_handles.total_length()
        return t

    def free_handle_notify(self):
        if self.waiting_ops:
            args = self.waiting_ops.pop(0)
            self._produce_handle(*args)

    def acquire_handle(self, filename, for_write, length=0):
        df = Deferred()

        if filename not in self.file_to_torrent:
            raise UnregisteredFileException()
        
        if self.active_file_to_handles.total_length() == self.max_files_open:
            self.waiting_ops.append((df, filename, for_write, length))
        else:
            self._produce_handle(df, filename, for_write, length)
            
        return df

    def _produce_handle(self, df, filename, for_write, length):
        if filename in self.open_file_to_handles:
            handle = self.open_file_to_handles.pop_from_row(filename)
            if for_write and not is_open_for_write(handle.mode):
                handle.close()
                handle = open_sparse_file(filename, 'rb+', length=length)
            #elif not for_write and is_open_for_write(handle.mode):
            #    handle.close()
            #    handle = file(filename, 'rb', 0)
        else:
            if self.get_open_file_count() == self.max_files_open:
                oldfname, oldhandle = self.open_file_to_handles.popitem()
                oldhandle.close()
            self._ensure_exists(filename, length)
            if for_write:
                handle = open_sparse_file(filename, 'rb+', length=length)
            else:
                handle = open_sparse_file(filename, 'rb', length=length)

        self.active_file_to_handles.push_to_row(filename, handle)
        df.callback(handle)

    def release_handle(self, filename, handle):
        self.active_file_to_handles.remove_fom_row(filename, handle)
        self.open_file_to_handles.push_to_row(filename, handle)
        self.free_handle_notify()