Example #1
0
 def test_page(self):
     SimpleDB.init_file_mgr("test")
     page = MaxPage()
     page.set_int(0, 99999)
     page.set_string(4, "This is the sample string.")
     page.append("temp_sample_file")
     self.assertEqual(len(page._contents), 400)
     self.assertEqual(SimpleDB.fm.size("temp_sample_file"), 1)
     blk1 = Block("temp_sample_file", 1)
     page.write(blk1)
     page.clear_contents()
     page.append("temp_sample_file")
     self.assertEqual(SimpleDB.fm.size("temp_sample_file"), 3)
     blk2 = Block("temp_sample_file", 1)
     page.read(blk2)
     self.assertEqual(page.get_int(0), 99999)
     self.assertEqual(page.get_string(4), "This is the sample string.")
     self.assertEqual(page.get_int(4), 26*4)
Example #2
0
class BufferSlot:
    """
    An individual buffer.
    A buffer wraps a page and stores information about its status,
    such as the disk block associated with the page,
    the number of times the block has been pinned,
    whether the contents of the page have been modified,
    and if so, the id of the modifying transaction and
    the LSN of the corresponding log record.
    """

    def __init__(self):
        """
        Creates a new buffer, wrapping a new
        simpledb.simpledb.file.Page page.
        This constructor is called exclusively by the class BasicBufferMgr.
        It depends on the simpledb.log.LogMgr LogMgr object that it gets from the class simpledb.server.SimpleDB.
        That object is created during system initialization. Thus this constructor cannot be called until
        simpledb.server.SimpleDB.initFileAndLogMgr(String) or is called first.
        """
        self._contents = MaxPage()
        self._blk = None
        self._pins = 0
        self._modified_by = -1
        self._log_sequence_number = -1

    def get_int(self, offset):
        """
        Returns the integer value at the specified offset of the buffer's page.
        If an integer was not stored at that location, the behavior of the method is unpredictable.
        :param offset: the byte offset of the page
        :return: the integer value at that offset
        """
        return self._contents.get_int(offset)

    def get_string(self, offset):
        """
        Returns the string value at the specified offset of the buffer's page.
        If a string was not stored at that location, the behavior of the method is unpredictable.
        :param offset: the byte offset of the page
        :return: the string value at that offset
        """
        return self._contents.get_string(offset)

    def set_int(self, offset, val, txnum, lsn):
        """
        Writes an integer to the specified offset of the buffer's page.
        This method assumes that the transaction has already written an appropriate log record.
        The buffer saves the id of the transaction and the LSN of the log record.
        A negative lsn value indicates that a log record was not necessary.
        :param offset: the byte offset within the page
        :param val: the new integer value to be written
        :param txnum: the id of the transaction performing the modification
        :param lsn: the LSN of the corresponding log record
        """
        self._modified_by = txnum
        if lsn >= 0:
            self._log_sequence_number = lsn
        self._contents.set_int(offset, val)

    def set_string(self, offset, val, txnum, lsn):
        """
        Writes a string to the specified offset of the buffer's page.
        This method assumes that the transaction has already written an appropriate log record.
        A negative lsn value indicates that a log record was not necessary.
        The buffer saves the id of the transaction and the LSN of the log record.
        :param offset: the byte offset within the page
        :param val: the new string value to be written
        :param txnum: the id of the transaction performing the modification
        :param lsn: the LSN of the corresponding log record
        """
        assert isinstance(val, str)
        self._modified_by = txnum
        if lsn >= 0:
            self._log_sequence_number = lsn
        self._contents.set_string(offset, val)

    def block(self):
        """
        Returns a reference to the disk block that the buffer is pinned to.
        :return: a reference to a disk block
        """
        return self._blk

    def flush(self):
        """
        Writes the page to its disk block if the page is dirty.
        The method ensures that the corresponding log
        record has been written to disk prior to writing the page to disk.
        """
        if self._modified_by > 0:
            SimpleDB.log_mgr().flush(self._log_sequence_number)
            self._contents.write(self._blk)
            self._modified_by = -1

    def pin(self):
        """
        Increases the buffer's pin count.
        """
        self._pins += 1

    def unpin(self):
        """
        Decreases the buffer's pin count.
        """
        self._pins -= 1

    def is_pinned(self):
        """
        Returns true if the buffer is currently pinned (that is, if it has a nonzero pin count).
        :return: true if the buffer is pinned
        """
        return self._pins > 0

    def is_modified_by(self, txnum):
        """
        Returns true if the buffer is dirty due to a modification by the specified transaction.
        :param txnum: the id of the transaction
        :return: true if the transaction modified the buffer
        """
        return self._modified_by == txnum

    def assign_to_block(self, b):
        """
        Reads the contents of the specified block into the buffer's page.
        If the buffer was dirty, then the contents of the previous page are first written to disk.
        :param b: a reference to the data block
        """
        assert isinstance(b, Block)
        self.flush()
        self._blk = b
        self._contents.read(self._blk)
        self._pins = 0

    def assign_to_new(self, filename, fmtr):
        """
        Initializes the buffer's page according to the specified formatter,
        and appends the page to the specified file.
        If the buffer was dirty, then the contents
        of the previous page are first written to disk.
        :param filename: the name of the file
        :param fmtr: a page formatter, used to initialize the page
        """
        assert isinstance(filename, str)
        assert isinstance(fmtr, PageFormatter)
        self.flush()
        fmtr.format(self._contents)
        self._blk = self._contents.append(filename)
        self._pins = 0
Example #3
0
class BufferSlot:
    """
    An individual buffer.
    A buffer wraps a page and stores information about its status,
    such as the disk block associated with the page,
    the number of times the block has been pinned,
    whether the contents of the page have been modified,
    and if so, the id of the modifying transaction and
    the LSN of the corresponding log record.
    """
    def __init__(self):
        """
        Creates a new buffer, wrapping a new
        simpledb.simpledb.file.Page page.
        This constructor is called exclusively by the class BasicBufferMgr.
        It depends on the simpledb.log.LogMgr LogMgr object that it gets from the class simpledb.server.SimpleDB.
        That object is created during system initialization. Thus this constructor cannot be called until
        simpledb.server.SimpleDB.initFileAndLogMgr(String) or is called first.
        """
        self._contents = MaxPage()
        self._blk = None
        self._pins = 0
        self._modified_by = -1
        self._log_sequence_number = -1

    def get_int(self, offset):
        """
        Returns the integer value at the specified offset of the buffer's page.
        If an integer was not stored at that location, the behavior of the method is unpredictable.
        :param offset: the byte offset of the page
        :return: the integer value at that offset
        """
        return self._contents.get_int(offset)

    def get_string(self, offset):
        """
        Returns the string value at the specified offset of the buffer's page.
        If a string was not stored at that location, the behavior of the method is unpredictable.
        :param offset: the byte offset of the page
        :return: the string value at that offset
        """
        return self._contents.get_string(offset)

    def set_int(self, offset, val, txnum, lsn):
        """
        Writes an integer to the specified offset of the buffer's page.
        This method assumes that the transaction has already written an appropriate log record.
        The buffer saves the id of the transaction and the LSN of the log record.
        A negative lsn value indicates that a log record was not necessary.
        :param offset: the byte offset within the page
        :param val: the new integer value to be written
        :param txnum: the id of the transaction performing the modification
        :param lsn: the LSN of the corresponding log record
        """
        self._modified_by = txnum
        if lsn >= 0:
            self._log_sequence_number = lsn
        self._contents.set_int(offset, val)

    def set_string(self, offset, val, txnum, lsn):
        """
        Writes a string to the specified offset of the buffer's page.
        This method assumes that the transaction has already written an appropriate log record.
        A negative lsn value indicates that a log record was not necessary.
        The buffer saves the id of the transaction and the LSN of the log record.
        :param offset: the byte offset within the page
        :param val: the new string value to be written
        :param txnum: the id of the transaction performing the modification
        :param lsn: the LSN of the corresponding log record
        """
        assert isinstance(val, str)
        self._modified_by = txnum
        if lsn >= 0:
            self._log_sequence_number = lsn
        self._contents.set_string(offset, val)

    def block(self):
        """
        Returns a reference to the disk block that the buffer is pinned to.
        :return: a reference to a disk block
        """
        return self._blk

    def flush(self):
        """
        Writes the page to its disk block if the page is dirty.
        The method ensures that the corresponding log
        record has been written to disk prior to writing the page to disk.
        """
        if self._modified_by > 0:
            SimpleDB.log_mgr().flush(self._log_sequence_number)
            self._contents.write(self._blk)
            self._modified_by = -1

    def pin(self):
        """
        Increases the buffer's pin count.
        """
        self._pins += 1

    def unpin(self):
        """
        Decreases the buffer's pin count.
        """
        self._pins -= 1

    def is_pinned(self):
        """
        Returns true if the buffer is currently pinned (that is, if it has a nonzero pin count).
        :return: true if the buffer is pinned
        """
        return self._pins > 0

    def is_modified_by(self, txnum):
        """
        Returns true if the buffer is dirty due to a modification by the specified transaction.
        :param txnum: the id of the transaction
        :return: true if the transaction modified the buffer
        """
        return self._modified_by == txnum

    def assign_to_block(self, b):
        """
        Reads the contents of the specified block into the buffer's page.
        If the buffer was dirty, then the contents of the previous page are first written to disk.
        :param b: a reference to the data block
        """
        assert isinstance(b, Block)
        self.flush()
        self._blk = b
        self._contents.read(self._blk)
        self._pins = 0

    def assign_to_new(self, filename, fmtr):
        """
        Initializes the buffer's page according to the specified formatter,
        and appends the page to the specified file.
        If the buffer was dirty, then the contents
        of the previous page are first written to disk.
        :param filename: the name of the file
        :param fmtr: a page formatter, used to initialize the page
        """
        assert isinstance(filename, str)
        assert isinstance(fmtr, PageFormatter)
        self.flush()
        fmtr.format(self._contents)
        self._blk = self._contents.append(filename)
        self._pins = 0