Welcome, guest | Sign In | My Account | Store | Cart
import disk

################################################################################

class DiskDriver(disk.DiskDriver):

    # Get Configuration Information
    def info(self):
        return self.__blocks, self.__size

################################################################################

class DAL1:

    # DEFAULTS (16 MB)
    BLOCKS = (2 ** 12)
    SIZE = (2 ** 12)

    # Disk Abstraction Layer
    def __init__(self):
        self.__disk = DiskDriver(self.BLOCKS, self.SIZE)
        self.__blocks, self.__size = self.__disk.info()
        self.__end = self.__blocks * self.__size

    # Read Some Data
    def read(self, index, size):
        assert type(index) is int and 0 <= index < self.__end
        assert type(size) is int and index < index + size <= self.__end
        first_index = index
        last_index = index + size - 1
        first_block = first_index / self.__size + 1
        last_block = last_index / self.__size + 2
        stream = ''.join([self.__read(block) for block in \
                          range(first_block, last_block)])
        first_index = index % self.__size
        last_index = first_index + size
        return stream[first_index:last_index]

    # Write Some Data
    def write(self, index, data):
        size = len(data)
        assert type(index) is int and 0 <= index < self.__end
        assert type(data) is str and index < index + size <= self.__end
        first_index = index
        last_index = index + size - 1
        first_block = first_index / self.__size + 1
        last_block = last_index / self.__size + 2
        blocks = last_block - first_block
        if blocks == 1:
            if size == self.__size:
                self.__write(first_block, data)
            else:
                stream = self.__read(first_block)
                first_index = index % self.__size
                last_index = first_index + size
                stream = stream[:first_index] + data + stream[last_index:]
                self.__write(first_block, stream)
        else:
            if index % self.__size:
                stream = self.__read(first_block)
                first_index = index % self.__size
                last_index = self.__size - first_index
                stream = stream[:first_index] + data[:last_index]
                data = data[last_index:]
                self.__write(first_block, stream)
            else:
                last_index = self.__size
                stream = data[:last_index]
                data = data[last_index:]
                self.__write(first_block, stream)
            first_block += 1
            last_block -= 1
            for block in range(first_block, last_block):
                self.__write(block, data[:self.__size])
                data = data[self.__size:]
            size = len(data)
            if size == self.__size:
                self.__write(last_block, data)
            else:
                stream = self.__read(last_block)
                stream = data + stream[size:]
                self.__write(last_block, stream)

    # Erase Some Data
    def erase(self, index, size):
        assert type(index) is int and 0 <= index < self.__end
        assert type(size) is int and index < index + size <= self.__end
        first_index = index
        last_index = index + size - 1
        first_block = first_index / self.__size + 1
        last_block = last_index / self.__size + 2
        blocks = last_block - first_block
        if blocks == 1:
            if size == self.__size:
                self.__erase(first_block)
            else:
                stream = self.__read(first_block)
                first_index = index % self.__size
                last_index = first_index + size
                stream = stream[:first_index] + chr(0) * size + \
                         stream[last_index:]
                self.__write(first_block, stream)
        else:
            if index % self.__size:
                stream = self.__read(first_block)
                first_index = index % self.__size
                last_index = self.__size - first_index
                stream = stream[:first_index] + chr(0) * last_index
                self.__write(first_block, stream)
            else:
                self.__erase(first_block)
            first_block += 1
            last_block -= 1
            for block in range(first_block, last_block):
                self.__erase(block)
            last_index = index + size - 1
            size = (last_index % self.__size) + 1
            if size == self.__size:
                self.__erase(last_block)
            else:
                stream = self.__read(last_block)
                stream = chr(0) * size + stream[size:]
                self.__write(last_block, stream)

    # Probability Of Failure
    def fail(self, probability):
        self.__disk.fail(probability)

    # Dump To File
    def dump(self, name):
        self.__disk.dump(name)

    # Load From File
    def load(self, name):
        self.__disk.load(name)
        self.__blocks, self.__size = self.__disk.info()
        self.__end = self.__blocks * self.__size
        self.BLOCKS, self.SIZE = self.__blocks, self.__size

    # Private Utility Function
    def __read(self, block):
        while True:
            try:
                return self.__disk.read(block)
            except:
                pass

    # Private Utility Function
    def __write(self, block, data):
        while True:
            try:
                return self.__disk.write(block, data)
            except:
                pass

    # Private Utility Function
    def __erase(self, block):
        while True:
            try:
                return self.__disk.erase(block)
            except:
                pass

################################################################################

class Test:

    # DAL1 Test Class
    def __init__(self, size):
        self.__string = chr(0) * size

    # Read Some Data
    def read(self, index, size):
        assert type(index) is int and 0 <= index < len(self)
        assert type(size) is int and index < index + size <= len(self)
        return self.__string[index:index+size]

    # Write Some Data
    def write(self, index, data):
        assert type(index) is int and 0 <= index < len(self)
        assert type(data) is str and index < index + len(data) <= len(self)
        self.__string = self.__string[:index] + data + \
                        self.__string[index+len(data):]

    # Erase Some Data
    def erase(self, index, size):
        self.write(index, chr(0) * size)

    # Get Length Information
    def __len__(self):
        return len(self.__string)

################################################################################

def test():
    from os import urandom
    from random import randint
    BLOCKS = DAL1.BLOCKS = 100
    SIZE = DAL1.SIZE = 100
    test1 = DAL1()
    test2 = Test(BLOCKS * SIZE)
    test1.fail(0.999)
    for temp in range(BLOCKS / 2):
        print 'Write:', temp + 1, '/', BLOCKS / 2
        write = randint(0, (BLOCKS * SIZE) / 2), urandom(randint(1, SIZE * 2))
        test1.write(*write)
        test2.write(*write)
        index = randint((BLOCKS * SIZE) / 2, BLOCKS * SIZE)
        data = urandom(randint(1, SIZE * 2))
        write = index - len(data) + 1, data
        test1.write(*write)
        test2.write(*write)
    for temp in range(BLOCKS / 20):
        print 'Erase:', temp + 1, '/', BLOCKS / 20
        erase = randint(0, (BLOCKS * SIZE) / 2), randint(1, SIZE * 2)
        test1.erase(*erase)
        test2.erase(*erase)
        index = randint((BLOCKS * SIZE) / 2, BLOCKS * SIZE)
        size = randint(1, SIZE * 2)
        erase = index - size + 1, size
        test1.erase(*erase)
        test2.erase(*erase)
    raw_input('Tested To ' + str(test1.read(0, BLOCKS * SIZE) == \
                                 test2.read(0, BLOCKS * SIZE)))

################################################################################

if __name__ == '__main__':
    test()

History