コード例 #1
0
class TorrentFile(object):
    def __init__(self, file_length, pieces_hash_array, piece_size, fs):
        self.logger = logging.getLogger(__name__)

        self.pieces_num = file_length / PIECE_SIZE
        self.piece_list = []
        for piece in range(self.pieces_num):
            self.piece_list.append(
                Piece(piece, piece_size, fs, pieces_hash_array[piece]))
        #if have extra smaller pieces
        if file_length % PIECE_SIZE != 0:
            last_piece_size = file_length % piece_size
            self.piece_list.append(
                Piece(self.pieces_num, last_piece_size, fs,
                      pieces_hash_array[self.pieces_num]))
            self.pieces_num += 1
        self.bm = BitMap(self.pieces_num)
        self.logger.debug("init bm {}".format(self.bm))

    def update_bitmap(self):
        for i in range(self.pieces_num):
            if self.piece_list[i].is_complete():
                self.bm.set(i)
            else:
                self.bm.reset(i)

    def is_complete(self):
        # self.update_bitmap()
        return self.bm.all()

    ## return the missing pieces
    def missing_pieces(self):
        self.update_bitmap()
        missing_list = []
        for i in range(self.pieces_num):
            if not self.bm.test(i):
                missing_list.append(self.piece_list[i])
        return missing_list

    def set_piece(self, index, content):
        self.piece_list[index].set_block(content)
        self.piece_list[index].write_to_file()

    def get_info(self):
        for i in range(self.pieces_num):
            self.piece_list[i].get_info()
コード例 #2
0
class Piece(object):
    def __init__(self, piece_index, piece_size, fs, piece_hash):
        self.block_num = piece_size / BLOCK_SIZE
        self.block_list = []
        self.piece_index = piece_index
        self.piece_size = piece_size
        self.piece_hash = piece_hash
        for block in range(self.block_num):
            b = Block(piece_index, block, BLOCK_SIZE)
            self.block_list.append(b)
        #if have extra smaller blocks
        if piece_size % BLOCK_SIZE != 0:
            last_block_size = piece_size % BLOCK_SIZE

            #print self.block_num,last_block_size
            self.block_list.append(
                Block(self.piece_index, self.block_num, last_block_size))
            self.block_num += 1
        self.bm = BitMap(self.block_num)
        self.file = fs
        return

    def __hash__(self):
        return hash((self.piece_index, self.piece_size, self.piece_hash))

    def __eq__(self, other):
        return (self.piece_index, self.piece_size,
                self.piece_hash) == (other.piece_index, self.piece_size,
                                     self.piece_hash)

    def __ne__(self, other):
        return not (self == other)

    #check block's bitmap in disk and the whole SHA1
    def is_complete(self):
        #check SHA1
        self.file.seek(self.piece_index * PIECE_SIZE)
        content = self.file.read(self.piece_size)
        piecehash = hashlib.sha1(content).digest()

        # print piecehash, self.piece_hash
        # print self.piece_size
        return piecehash == self.piece_hash

    def written_piece_hash(self):
        self.file.seek(self.piece_index * PIECE_SIZE)
        content = self.file.read(self.piece_size)
        piecehash = hashlib.sha1(content).digest()
        return piecehash

    def update_bitmap(self):
        for i in range(len(self.block_list)):
            if self.block_list[i].is_complete():
                self.bm.set(i)
            else:
                self.bm.reset(i)

    def get_info(self):
        print "piece index:", self.piece_index, "  piece size:", self.piece_size
        #for i in range(self.block_num):
        #    self.block_list[i].get_info()

    ## set every block
    def set_block(self, content):
        size = len(content)
        for block in self.block_list:
            #print "boffset",block.block_offset
            block.set_complete(
                content[block.block_offset:min(block.block_offset +
                                               BLOCK_SIZE, size)])

    ## get the content from blocks and write to file
    def write_to_file(self):
        self.update_bitmap()
        if self.bm.all():
            payload = bytearray('')
            for block in self.block_list:
                payload += block.payload
            self.file.seek(self.piece_index * PIECE_SIZE)
            self.file.write(payload)

    def clear_data(self):
        for block in self.block_list:
            block.payload = None

    def expire(self):
        for block in self.block_list:
            block.mark_missing()
        self.bm = BitMap(self.block_num)
コード例 #3
0
class buddy_malloc:
    def __init__(self, size, start, headerSize, align):
        self.level = math.ceil(math.log2(size))
        self.size = 1 << self.level
        print("Total size for buddy: {}".format(self.size))
        self.level += 1
        self.buckets = [set() for i in range(self.level)]
        self.in_use = BitMap(2 ** self.level - 1)
        # initialize root node
        self.buckets[0].add(start)
        # misc stuffs
        self.base = start
        self.headerSize = headerSize
        self.align = align
        self.sizemap = {}

    def _ptr_to_index(self, ptr, level):
        return (1 << level) - 1 + ((ptr - self.base) >> (self.level - 1 - level))

    def _index_to_ptr(self, index, level):
        return self.base + ((index - (1 << level) + 1) << (self.level - 1 - level))

    def _parent(self, n):
        return (n - 1) >> 1
    
    def _lchild(self, n):
        return (n << 1) + 1
    
    def _rchild(self, n):
        return (n + 1) << 1

    def addToMap(self, addr, size):
        assert(addr not in self.sizemap)
        self.sizemap[addr] = size

    def malloc(self, size):
        if self.align != -1:
            left = size % self.align
            if left != 0:
                diff = self.align - left
            else:
                diff = 0
            # print 'aligning: adding %d to %d' % (diff, size)
            size += diff

        size += self.headerSize
        dest_level = self.level - 1 - math.ceil(math.log2(size))

        level = dest_level

        while not len(self.buckets[level]) and level >= 0:
            level -= 1

        has_flipped = False
        if level < 0:
            return (-1, 0)
        else:
            # split curr level
            while level != dest_level:
                blk = self.buckets[level].pop()
                idx = self._ptr_to_index(blk, level)
                level += 1
                self.buckets[level].add(blk)
                self.buckets[level].add(blk + (1 << (self.level - 1 - level)))
        
        addr = self.buckets[level].pop()
        idx = self._ptr_to_index(addr, level)
        while idx >= 0:
            self.in_use.set(idx)
            idx = self._parent(idx)
        self.addToMap(addr, 1 << (self.level - 1 - level))
        return (addr, 0)

    def free(self, addr):
        if addr not in self.sizemap:
            return -1
        level = self.level - 1 - math.ceil(math.log2(self.sizemap[addr]))
        idx = self._ptr_to_index(addr, level)

        while idx > 0:
            parent = self._parent(idx)
            neighbor = self._rchild(parent) if self._lchild(parent) == idx else self._lchild(parent)
            self.in_use.reset(idx)
            if not self.in_use.test(neighbor):
                # can merge
                self.buckets[level].remove(self._index_to_ptr(neighbor, level))
            else:
                break
            level -= 1
            idx = parent

        self.buckets[level].add(self._index_to_ptr(idx, level))

        del self.sizemap[addr]
        return 0
    
    def dump(self):
        print('Alloc List [ Size %d ]: ' % len(self.sizemap), end='')
        for item in self.sizemap.items():
            print('[ addr:%d sz:%d ]' % item, end='')
        print('')