<commit_before># file/page.rb
# <NAME>
# Translated from simpledb/file/Page.java
# 
# The contents of a disk block in memory.
# A page is treated as an array of BLOCK_SIZE bytes.
# There are methods to get/set values into this array,
# and to read/write the contents of this array to a disk block.
# 
# For an example of how to use Page and Block objects, 
# consider the following code fragment.  
# The first portion increments the integer at offset 792 of block 6 of file junk.  
# The second portion stores the string "hello" at offset 20 of a page, 
# and then appends it to a new block of the file.  
# It then reads that block into another page 
# and extracts the value "hello" into variable s.
# TODO: make this ruby-doco compatible...
# <pre>
# Page p1 = new Page();
# Block blk = new Block("junk", 6);
# p1.read(blk);
# int n = p1.getInt(792);
# p1.setInt(792, n+1);
# p1.write(blk);
#
# Page p2 = new Page();
# p2.setString(20, "hello");
# blk = p2.append("junk");
# Page p3 = new Page();
# p3.read(blk);
# String s = p3.getString(20);
# </pre>
# (<NAME>)
class Page

  # The number of bytes in a block.
  # This value is set unreasonably low, so that it is easier to create and test
  # databases having a lot of blocks. A more realistic value would be 4K.
  BLOCK_SIZE = 400

  # The size of an integer in bytes.
  INT_SIZE = 0.size

  # The maximum size, in bytes, of a string of length n.
  # A string is represented as the encoding of its characters,
  # preceded by an integer denoting the number of bytes in this encoding.
  # If the JVM uses the US-ASCII encoding, then each char
  # is stored in one byte, so a string of n characters
  # has a size of 4+n bytes.
  # @param n the size of the string
  # @return the maximum number of bytes required to store a string of size n
  def self.string_size(length)
    return length * 'c'.size
  end

  # Creates a new page.  Although the constructor takes no arguments,
  # it depends on a {@link FileMgrend object that it gets from the
  # method {@link simpledb.server.SimpleDB#fileMgr()end.
  # That object is created during system initialization.
  # Thus this constructor cannot be called until either
  # {@link simpledb.server.SimpleDB#init(String)end or
  # {@link simpledb.server.SimpleDB#initFileMgr(String)end or
  # {@link simpledb.server.SimpleDB#initFileAndLogMgr(String)end or
  # {@link simpledb.server.SimpleDB#initFileLogAndBufferMgr(String)end
  # is called first.
  def initialize
    @contents = ByteBuffer.allocate_direct(BLOCK_SIZE)
    @filemgr = SimpleDB.file_mgr
  end

  # Populates the page with the contents of the specified disk block.
  def read(block)
    synchronize { @filemgr.read(block, @contents) }
  end
  
  # Writes the contents of the page to the specified disk block.
  # @param blk a reference to a disk block
  def write(block)
    synchronize { @filemgr.write(block, @contents) }
  end

  # Appends the contents of the page to the specified file.
  # @param filename the name of the file
  # @return the reference to the newly-created disk block
  def append(filename)
    synchronize { return filemgr.append(filename, @contents) }
  end
  
  # Returns the integer value at a specified offset of the page.
  # If an integer was not stored at that location, 
  # the behavior of the method is unpredictable.
  # @param offset the byte offset within the page
  # @return the integer value at that offset
  def get_int(offset)
    synchronize do
      @contents.position(offset)
      return @contents.get_int
    end
  end
  
  # Writes an integer to the specified offset on the page.
  # @param offset the byte offset within the page
  # @param val the integer to be written to the page
  def set_int(offset, value)
    synchronize do
      contents.position(offset)
      contents.putInt(val)
    end
  end
  
  # Returns the string value at the specified offset of the page.
  # If a string was not stored at that location,
  # the behavior of the method is unpredictable.
  # @param offset the byte offset within the page<commit_msg>Adding some comments and todos for Page. [ci skip]<commit_after># file/page.rb
# <NAME>
# Translated from simpledb/file/Page.java
# 
# The contents of a disk block in memory.
# A page is treated as an array of BLOCK_SIZE bytes.
# There are methods to get/set values into this array,
# and to read/write the contents of this array to a disk block.
# 
# For an example of how to use Page and Block objects, 
# consider the following code fragment.  
# The first portion increments the integer at offset 792 of block 6 of file junk.  
# The second portion stores the string "hello" at offset 20 of a page, 
# and then appends it to a new block of the file.  
# It then reads that block into another page 
# and extracts the value "hello" into variable s.
# TODO: update this Java example to the Ruby implementation.
# <tt>
# Page p1 = new Page();
# Block blk = new Block("junk", 6);
# p1.read(blk);
# int n = p1.getInt(792);
# p1.setInt(792, n+1);
# p1.write(blk);
#
# Page p2 = new Page();
# p2.setString(20, "hello");
# blk = p2.append("junk");
# Page p3 = new Page();
# p3.read(blk);
# String s = p3.getString(20);
# </tt>
# (<NAME>)
class Page

  # The number of bytes in a block.
  # This value is set unreasonably low, so that it is easier to create and test
  # databases having a lot of blocks. A more realistic value would be 4K.
  BLOCK_SIZE = 400

  # The size of an integer in bytes.
  INT_SIZE = 0.size

  # The maximum size, in bytes, of a string of length n.
  # A string is represented as the encoding of its characters,
  # preceded by an integer denoting the number of bytes in this encoding.
  # If the JVM uses the US-ASCII encoding, then each char
  # is stored in one byte, so a string of n characters
  # has a size of 4+n bytes.
  # @param n the size of the string
  # @return the maximum number of bytes required to store a string of size n
  def self.string_size(length)
    return length * 'c'.size
  end

  # Creates a new page.  Although the constructor takes no arguments,
  # it depends on a {@link FileMgrend object that it gets from the
  # method {@link simpledb.server.SimpleDB#fileMgr()end.
  # That object is created during system initialization.
  # Thus this constructor cannot be called until either
  # {@link simpledb.server.SimpleDB#init(String)end or
  # {@link simpledb.server.SimpleDB#initFileMgr(String)end or
  # {@link simpledb.server.SimpleDB#initFileAndLogMgr(String)end or
  # {@link simpledb.server.SimpleDB#initFileLogAndBufferMgr(String)end
  # is called first.
  def initialize
    @contents = ByteBuffer.allocate_direct(BLOCK_SIZE) #TODO
                                                       # http://stackoverflow.com/questions/10323/why-doesnt-ruby-have-a-real-stringbuffer-or-stringio
                                                       # http://stackoverflow.com/questions/1211461/what-is-rubys-stringio-class-really
                                                       # http://docs.oracle.com/javase/6/docs/api/java/nio/ByteBuffer.html
                                                       # http://stackoverflow.com/questions/7158124/create-bytebuffer-like-object-in-ruby
    @filemgr = SimpleDB.file_mgr #TODO
  end

  # Populates the page with the contents of the specified disk block.
  def read(block)
    synchronize { @filemgr.read(block, @contents) }
  end
  
  # Writes the contents of the page to the specified disk block.
  # @param blk a reference to a disk block
  def write(block)
    synchronize { @filemgr.write(block, @contents) }
  end

  # Appends the contents of the page to the specified file.
  # @param filename the name of the file
  # @return the reference to the newly-created disk block
  def append(filename)
    synchronize { return filemgr.append(filename, @contents) }
  end
  
  # Returns the integer value at a specified offset of the page.
  # If an integer was not stored at that location, 
  # the behavior of the method is unpredictable.
  # @param offset the byte offset within the page
  # @return the integer value at that offset
  def get_int(offset)
    synchronize do
      @contents.position(offset)
      return @contents.get_int
    end
  end
  
  # Writes an integer to the specified offset on the page.
  # @param offset the byte offset within the page
  # @param val the integer to be written to the page
  def set_int(offset, value)
    synchronize do
      @contents.position(offset)
      @contents.put_int(value)
    end
  end
  
  # Returns the string value at the specified offset of the page.
  # If a string was not stored at that location,
  # the behavior of the method is unpredictable.
  # @param offset the byte offset within the page
{'fraction_non_alphanumeric': 0.07947628345009762, 'fraction_numerical': 0.010336510853336396, 'mean_word_length': 3.1094856064181218, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2937109', 'n_tokens_mistral': 2633, 'n_tokens_neox': 2561, 'n_words': 1117}