コード例 #1
0
ファイル: StorageWrapper.py プロジェクト: Python3pkg/Horde
 def pickle(self):
     if self.have.complete():
         return {'pieces': 1}
     pieces = Bitfield(len(self.hashes))
     places = []
     partials = []
     for p in range(len(self.hashes)):
         if self.blocked[p] or p not in self.places:
             continue
         h = self.have[p]
         pieces[p] = h
         pp = self.dirty.get(p)
         if not h and not pp:  # no data
             places.extend([self.places[p], self.places[p]])
         elif self.places[p] != p:
             places.extend([p, self.places[p]])
         if h or not pp:
             continue
         pp.sort()
         r = []
         while len(pp) > 1:
             if pp[0][0] + pp[0][1] == pp[1][0]:
                 pp[0] = list(pp[0])
                 pp[0][1] += pp[1][1]
                 del pp[1]
             else:
                 r.extend(pp[0])
                 del pp[0]
         r.extend(pp[0])
         partials.extend([p, r])
     return {
         'pieces': pieces.tostring(),
         'places': places,
         'partials': partials
     }
コード例 #2
0
ファイル: StorageWrapper.py プロジェクト: Python3pkg/Horde
 def get_have_list_cloaked(self):
     if self.have_cloaked_data is None:
         newhave = Bitfield(copyfrom=self.have)
         unhaves = []
         n = min(randrange(2, 5),
                 len(self.hashes))  # between 2-4 unless torrent is small
         while len(unhaves) < n:
             unhave = randrange(min(32, len(
                 self.hashes)))  # all in first 4 bytes
             if not unhave in unhaves:
                 unhaves.append(unhave)
                 newhave[unhave] = False
         self.have_cloaked_data = (newhave.tostring(), unhaves)
     return self.have_cloaked_data
コード例 #3
0
 def __init__(self, downloader, connection):
     self.downloader = downloader
     self.connection = connection
     self.choked = True
     self.interested = False
     self.active_requests = []
     self.measure = Measure(downloader.max_rate_period)
     self.peermeasure = Measure(downloader.max_rate_period)
     self.have = Bitfield(downloader.numpieces)
     self.last = -1000
     self.last2 = -1000
     self.example_interest = None
     self.backlog = 2
     self.ip = connection.get_ip()
     self.guard = BadDataGuard(self)
コード例 #4
0
ファイル: Connecter.py プロジェクト: chenqing24/Horde
 def got_message(self, connection, message):
     c = self.connections[connection]
     t = message[0]
     if t == BITFIELD and c.got_anything:
         connection.close()
         return
     c.got_anything = True
     if (t in [CHOKE, UNCHOKE, INTERESTED, NOT_INTERESTED]
             and len(message) != 1):
         connection.close()
         return
     if t == CHOKE:
         c.download.got_choke()
     elif t == UNCHOKE:
         c.download.got_unchoke()
     elif t == INTERESTED:
         if not c.download.have.complete():
             c.upload.got_interested()
     elif t == NOT_INTERESTED:
         c.upload.got_not_interested()
     elif t == HAVE:
         if len(message) != 5:
             connection.close()
             return
         i = toint(message[1:])
         if i >= self.numpieces:
             connection.close()
             return
         if c.download.got_have(i):
             c.upload.got_not_interested()
     elif t == BITFIELD:
         try:
             b = Bitfield(self.numpieces, message[1:])
         except ValueError:
             connection.close()
             return
         if c.download.got_have_bitfield(b):
             c.upload.got_not_interested()
     elif t == REQUEST:
         if len(message) != 13:
             connection.close()
             return
         i = toint(message[1:5])
         if i >= self.numpieces:
             connection.close()
             return
         c.got_request(i, toint(message[5:9]), toint(message[9:]))
     elif t == CANCEL:
         if len(message) != 13:
             connection.close()
             return
         i = toint(message[1:5])
         if i >= self.numpieces:
             connection.close()
             return
         c.upload.got_cancel(i, toint(message[5:9]), toint(message[9:]))
     elif t == PIECE:
         if len(message) <= 9:
             connection.close()
             return
         i = toint(message[1:5])
         if i >= self.numpieces:
             connection.close()
             return
         if c.download.got_piece(i, toint(message[5:9]), message[9:]):
             self.got_piece(i)
     else:
         connection.close()
コード例 #5
0
ファイル: StorageWrapper.py プロジェクト: Python3pkg/Horde
    def unpickle(self, data, valid_places):
        got = {}
        places = {}
        dirty = {}
        download_history = {}
        stat_active = {}
        stat_numfound = self.stat_numfound
        amount_obtained = self.amount_obtained
        amount_inactive = self.amount_inactive
        amount_left = self.amount_left
        inactive_requests = [x for x in self.inactive_requests]
        restored_partials = []

        try:
            if data['pieces'] == 1:  # a seed
                assert not data.get('places', None)
                assert not data.get('partials', None)
                have = Bitfield(len(self.hashes))
                for i in range(len(self.hashes)):
                    have[i] = True
                assert have.complete()
                _places = []
                _partials = []
            else:
                have = Bitfield(len(self.hashes), data['pieces'])
                _places = data['places']
                assert len(_places) % 2 == 0
                _places = [_places[x:x + 2] for x in range(0, len(_places), 2)]
                _partials = data['partials']
                assert len(_partials) % 2 == 0
                _partials = [
                    _partials[x:x + 2] for x in range(0, len(_partials), 2)
                ]

            for index, place in _places:
                if place not in valid_places:
                    continue
                assert index not in got
                assert place not in got
                places[index] = place
                got[index] = 1
                got[place] = 1

            for index in range(len(self.hashes)):
                if have[index]:
                    if index not in places:
                        if index not in valid_places:
                            have[index] = False
                            continue
                        assert index not in got
                        places[index] = index
                        got[index] = 1
                    length = self._piecelen(index)
                    amount_obtained += length
                    stat_numfound += 1
                    amount_inactive -= length
                    amount_left -= length
                    inactive_requests[index] = None

            for index, plist in _partials:
                assert index not in dirty
                assert not have[index]
                if index not in places:
                    if index not in valid_places:
                        continue
                    assert index not in got
                    places[index] = index
                    got[index] = 1
                assert len(plist) % 2 == 0
                plist = [plist[x:x + 2] for x in range(0, len(plist), 2)]
                dirty[index] = plist
                stat_active[index] = 1
                download_history[index] = {}
                # invert given partials
                length = self._piecelen(index)
                l = []
                if plist[0][0] > 0:
                    l.append((0, plist[0][0]))
                for i in range(len(plist) - 1):
                    end = plist[i][0] + plist[i][1]
                    assert not end > plist[i + 1][0]
                    l.append((end, plist[i + 1][0] - end))
                end = plist[-1][0] + plist[-1][1]
                assert not end > length
                if end < length:
                    l.append((end, length - end))
                # split them to request_size
                ll = []
                amount_obtained += length
                amount_inactive -= length
                for nb, nl in l:
                    while nl > 0:
                        r = min(nl, self.request_size)
                        ll.append((nb, r))
                        amount_inactive += r
                        amount_obtained -= r
                        nb += self.request_size
                        nl -= self.request_size
                inactive_requests[index] = ll
                restored_partials.append(index)

            assert amount_obtained + amount_inactive == self.amount_desired
        except:
            #            print_exc()
            return []  # invalid data, discard everything

        self.have = have
        self.places = places
        self.dirty = dirty
        self.download_history = download_history
        self.stat_active = stat_active
        self.stat_numfound = stat_numfound
        self.amount_obtained = amount_obtained
        self.amount_inactive = amount_inactive
        self.amount_left = amount_left
        self.inactive_requests = inactive_requests

        return restored_partials
コード例 #6
0
ファイル: StorageWrapper.py プロジェクト: Python3pkg/Horde
    def __init__(self,
                 storage,
                 request_size,
                 hashes,
                 piece_size,
                 finished,
                 failed,
                 statusfunc=dummy_status,
                 flag=fakeflag(),
                 check_hashes=True,
                 data_flunked=lambda x: None,
                 backfunc=None,
                 config={},
                 unpauseflag=fakeflag(True)):
        self.storage = storage
        self.request_size = int(request_size)
        self.hashes = hashes
        self.piece_size = int(piece_size)
        self.piece_length = int(piece_size)
        self.finished = finished
        self.failed = failed
        self.statusfunc = statusfunc
        self.flag = flag
        self.check_hashes = check_hashes
        self.data_flunked = data_flunked
        self.backfunc = backfunc
        self.config = config
        self.unpauseflag = unpauseflag

        self.alloc_type = config.get('alloc_type', 'normal')
        self.double_check = config.get('double_check', 0)
        self.triple_check = config.get('triple_check', 0)
        if self.triple_check:
            self.double_check = True
        self.bgalloc_enabled = False
        self.bgalloc_active = False
        self.total_length = storage.get_total_length()
        self.amount_left = self.total_length
        if self.total_length <= self.piece_size * (len(hashes) - 1):
            raise ValueError('bad data in responsefile - total too small')
        if self.total_length > self.piece_size * len(hashes):
            raise ValueError('bad data in responsefile - total too big')
        self.numactive = [0] * len(hashes)
        self.inactive_requests = [1] * len(hashes)
        self.amount_inactive = self.total_length
        self.amount_obtained = 0
        self.amount_desired = self.total_length
        self.have = Bitfield(len(hashes))
        self.have_cloaked_data = None
        self.blocked = [False] * len(hashes)
        self.blocked_holes = []
        self.blocked_movein = Olist()
        self.blocked_moveout = Olist()
        self.waschecked = [False] * len(hashes)
        self.places = {}
        self.holes = []
        self.stat_active = {}
        self.stat_new = {}
        self.dirty = {}
        self.stat_numflunked = 0
        self.stat_numdownloaded = 0
        self.stat_numfound = 0
        self.download_history = {}
        self.failed_pieces = {}
        self.out_of_place = 0
        self.write_buf_max = config['write_buffer_size'] * 1048576
        self.write_buf_size = 0
        self.write_buf = {}  # structure:  piece: [(start, data), ...]
        self.write_buf_list = []

        self.initialize_tasks = [[
            'checking existing data', 0, self.init_hashcheck,
            self.hashcheckfunc
        ], ['moving data', 1, self.init_movedata, self.movedatafunc
            ], ['allocating disk space', 1, self.init_alloc, self.allocfunc]]

        self.backfunc(self._bgalloc, 0.1)
        self.backfunc(self._bgsync, max(self.config['auto_flush'] * 60, 60))