⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 storage.py

📁 BitTorrentABC-Linux-V.2.4.3源码
💻 PY
字号:
# Written by Bram Cohen# see LICENSE.txt for license informationfrom sha import shafrom cStringIO import StringIOfrom threading import Lockfrom time import timefrom bisect import bisect_righttrue = 1false = 0DEBUG = falsedef dummy_status(fractionDone = None, activity = None):    passclass Storage:    def __init__(self, files, open, exists, getsize, statusfunc, doneflag, config, failed):        # can raise IOError and ValueError        self.doneflag = doneflag        self.failed = failed        self.ranges = []        numfiles = 0        total = 0l        so_far = 0l        self.handles = {}        self.whandles = {}        self.tops = {}        self.lock = Lock()        for file, length in files:            #if doneflag.isSet():    # bail out if doneflag is set            #    return            if length != 0:                self.ranges.append((total, total + length, file))                numfiles += 1                total += length                if exists(file):                    l = getsize(file)                    if l > length:                        h = open(file, 'rb+')                        h.truncate(length)                        h.close()                        l = length                else:                    l = 0                    open(file, 'wb+').close()                                    self.tops[file] = l                so_far += l        self.begins = [i[0] for i in self.ranges]        self.total_length = total        self.max_files_open = config['max_files_open']        if self.max_files_open > 0 and numfiles > self.max_files_open:            self.handlebuffer = []        else:            self.handlebuffer = None                        def was_preallocated(self, pos, length):        for file, begin, end in self._intervals(pos, length):            if self.tops.get(file, 0) < end:                return false        return true    def set_readonly(self):        # may raise IOError or OSError        for file in self.whandles.keys():            self.lock.acquire()            old = self.handles[file]            old.flush()            old.close()            self.handles[file] = open(file, 'rb')            self.lock.release()        self.whandles = {}    def get_total_length(self):        return self.total_length    def _get_file_handle(self, file, for_write):        if self.handles.has_key(file):            if for_write and not self.whandles.has_key(file):                f = self.handles[file]                del self.handles[file]                f.close()                try:                    self.handles[file] = open(file, 'rb+')                except IOError, e:                    self.failed('unable to reopen '+file+': '+str(e))                    return None                self.whandles[file] = 1                            if self.handlebuffer is not None:                pos = self.handlebuffer.index(file)                if pos < len(self.handlebuffer)-1:                    del self.handlebuffer[pos]                    self.handlebuffer.append(file)        else:            try:                if for_write:                    self.handles[file] = open(file, 'rb+')                    self.whandles[file] = 1                else:                    self.handles[file] = open(file, 'rb')            except IOError, e:                self.failed('unable to open '+file+': '+str(e))                return None                        if self.handlebuffer is not None:                self.handlebuffer.append(file)                if len(self.handlebuffer) > self.max_files_open:                    x = self.handlebuffer.pop(0)                    if self.whandles.has_key(x):                        del self.whandles[x]                        self.handles[x].flush()                    f = self.handles[x]                    del self.handles[x]                    f.close()        return self.handles[file]    def _intervals(self, pos, amount):        r = []        stop = pos + amount        p = bisect_right(self.begins, pos) - 1        while p < len(self.ranges) and self.ranges[p][0] < stop:            begin, end, file = self.ranges[p]            r.append((file, max(pos, begin) - begin, min(end, stop) - begin))            p += 1        return r    def read(self, pos, amount):        r = []        for file, pos, end in self._intervals(pos, amount):            self.lock.acquire()            h = self._get_file_handle(file, false)            h.seek(pos)            r.append(h.read(end - pos))            self.lock.release()        return ''.join(r)    def write(self, pos, s):        # might raise an IOError        total = 0        for file, begin, end in self._intervals(pos, len(s)):            self.lock.acquire()            h = self._get_file_handle(file, true)            if h is None:                return            h.seek(begin)            h.write(s[total: total + end - begin])            self.lock.release()            total += end - begin    def top_off(self):        for begin, end, file in self.ranges:            l = end - begin            if l < self.tops.get(file, 0):                self.lock.acquire()                h = self._get_file_handle(file, true)                if h is None:                    return None                h.seek(l-1)                h.write(chr(0xFF))                self.lock.release()    def flush(self):        # may raise IOError or OSError        for file in self.whandles.keys():            self.lock.acquire()            self.handles[file].flush()            self.lock.release()    def close(self):        for h in self.handles.values():            try:                h.close()            except:                passdef lrange(a, b, c):    r = []    while a < b:        r.append(a)        a += c    return r# everything below is for testingfrom fakeopen import FakeOpendef test_Storage_simple():    f = FakeOpen()    m = Storage([('a', 5)], f.open, f.exists, f.getsize, dummy_status)    assert f.files.keys() == ['a']    m.write(0, 'abc')    assert m.read(0, 3) == 'abc'    m.write(2, 'abc')    assert m.read(2, 3) == 'abc'    m.write(1, 'abc')    assert m.read(0, 5) == 'aabcc'    def test_Storage_multiple():    f = FakeOpen()    m = Storage([('a', 5), ('2', 4), ('c', 3)],         f.open, f.exists, f.getsize, dummy_status)    x = f.files.keys()    x.sort()    assert x == ['2', 'a', 'c']    m.write(3, 'abc')    assert m.read(3, 3) == 'abc'    m.write(5, 'ab')    assert m.read(4, 3) == 'bab'    m.write(3, 'pqrstuvw')    assert m.read(3, 8) == 'pqrstuvw'    m.write(3, 'abcdef')    assert m.read(3, 7) == 'abcdefv'def test_Storage_zero():    f = FakeOpen()    Storage([('a', 0)], f.open, f.exists, f.getsize, dummy_status)    assert f.files == {'a': []}def test_resume_zero():    f = FakeOpen({'a': ''})    Storage([('a', 0)], f.open, f.exists, f.getsize, dummy_status)    assert f.files == {'a': []}def test_Storage_with_zero():    f = FakeOpen()    m = Storage([('a', 3), ('b', 0), ('c', 3)],         f.open, f.exists, f.getsize, dummy_status)    m.write(2, 'abc')    assert m.read(2, 3) == 'abc'    x = f.files.keys()    x.sort()    assert x == ['a', 'b', 'c']    assert len(f.files['a']) == 3    assert len(f.files['b']) == 0def test_Storage_resume():    f = FakeOpen({'a': 'abc'})    m = Storage([('a', 4)],         f.open, f.exists, f.getsize, dummy_status)    assert f.files.keys() == ['a']    assert m.read(0, 3) == 'abc'def test_Storage_mixed_resume():    f = FakeOpen({'b': 'abc'})    m = Storage([('a', 3), ('b', 4)],         f.open, f.exists, f.getsize, dummy_status)    x = f.files.keys()    x.sort()    assert x == ['a', 'b']    assert m.read(3, 3) == 'abc'

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -