/** Unit test for TupleDesc.combine() */
  @Test
  public void combine() {
    TupleDesc td1, td2, td3;

    td1 = Utility.getTupleDesc(1, "td1");
    td2 = Utility.getTupleDesc(2, "td2");

    // test td1.combine(td2)
    td3 = TupleDesc.merge(td1, td2);
    assertEquals(3, td3.numFields());
    assertEquals(3 * Type.INT_TYPE.getLen(), td3.getSize());
    for (int i = 0; i < 3; ++i) assertEquals(Type.INT_TYPE, td3.getFieldType(i));
    assertEquals(combinedStringArrays(td1, td2, td3), true);

    // test td2.combine(td1)
    td3 = TupleDesc.merge(td2, td1);
    assertEquals(3, td3.numFields());
    assertEquals(3 * Type.INT_TYPE.getLen(), td3.getSize());
    for (int i = 0; i < 3; ++i) assertEquals(Type.INT_TYPE, td3.getFieldType(i));
    assertEquals(combinedStringArrays(td2, td1, td3), true);

    // test td2.combine(td2)
    td3 = TupleDesc.merge(td2, td2);
    assertEquals(4, td3.numFields());
    assertEquals(4 * Type.INT_TYPE.getLen(), td3.getSize());
    for (int i = 0; i < 4; ++i) assertEquals(Type.INT_TYPE, td3.getFieldType(i));
    assertEquals(combinedStringArrays(td2, td2, td3), true);
  }
  /**
   * Generates a byte array representing the contents of this page. Used to serialize this page to
   * disk.
   *
   * <p>The invariant here is that it should be possible to pass the byte array generated by
   * getPageData to the HeapPage constructor and have it produce an identical HeapPage object.
   *
   * @see #HeapPage
   * @return A byte array correspond to the bytes of this page.
   */
  public byte[] getPageData() {
    // int len = header.length*4 + BufferPool.PAGE_SIZE;
    int len = BufferPool.PAGE_SIZE;
    ByteArrayOutputStream baos = new ByteArrayOutputStream(len);
    DataOutputStream dos = new DataOutputStream(baos);

    // create the header of the page
    try {
      dos.write(header.getHeader());
    } catch (IOException e) {
      // this really shouldn't happen
      e.printStackTrace();
    }

    // create the tuples
    for (int i = 0; i < numSlots; i++) {

      // empty slot
      if (!getSlot(i)) {
        for (int j = 0; j < td.getSize(); j++) {
          try {
            dos.writeByte(0);
          } catch (IOException e) {
            e.printStackTrace();
          }
        }
        continue;
      }

      // non-empty slot
      for (int j = 0; j < td.numFields(); j++) {
        Field f = tuples[i].getField(j);
        try {
          f.serialize(dos);
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }

    // padding
    int zerolen = BufferPool.PAGE_SIZE - numSlots * td.getSize() - header.length();
    byte[] zeroes = new byte[zerolen];
    try {
      dos.write(zeroes, 0, zerolen);
    } catch (IOException e) {
      e.printStackTrace();
    }

    try {
      dos.flush();
    } catch (IOException e) {
      e.printStackTrace();
    }

    return baos.toByteArray();
  }
  /** Suck up tuples from the source file. */
  private Tuple readNextTuple(DataInputStream dis, int slotId) throws NoSuchElementException {
    // if associated bit is not set, read forward to the next tuple, and
    // return null.
    if (!getSlot(slotId)) {
      for (int i = 0; i < td.getSize(); i++) {
        try {
          dis.readByte();
        } catch (IOException e) {
          throw new NoSuchElementException("error reading empty tuple");
        }
      }
      return null;
    }

    // read fields in the tuple
    Tuple t = new Tuple(td);
    RecordID rid = new RecordID(pid, slotId);
    t.setRecordID(rid);
    try {
      for (int j = 0; j < td.numFields(); j++) {
        Field f = td.getType(j).parse(dis);
        t.setField(j, f);
      }
    } catch (java.text.ParseException e) {
      // e.printStackTrace();
      throw new NoSuchElementException("parsing error!");
    }

    return t;
  }
  // Test mix of INT_TYPE and STRING_TYPE.
  @Test
  public void new_getSizeTest() {
    Type[] typeAr = new Type[] {Type.INT_TYPE, Type.INT_TYPE, Type.STRING_TYPE, Type.STRING_TYPE};
    String[] fieldAr = new String[] {"number0", "number1", "string0", "string1"};
    TupleDesc td = new TupleDesc(typeAr, fieldAr);

    int length = 2 * Type.INT_TYPE.getLen() + 2 * Type.STRING_TYPE.getLen();
    assertEquals(length, td.getSize());
  }
  /** Unit test for TupleDesc.getSize() */
  @Test
  public void getSize() {
    int[] lengths = new int[] {1, 2, 1000};

    for (int len : lengths) {
      TupleDesc td = Utility.getTupleDesc(len);
      assertEquals(len * Type.INT_TYPE.getLen(), td.getSize());
    }
  }
  /**
   * Helper constructor to create a heap page to be used as buffer.
   *
   * @param data - Data to be put in tmp page
   * @param td - Tuple description for the corresponding table.
   * @throws IOException
   */
  private HeapPage(byte[] data, TupleDesc td) throws IOException {
    this.pid =
        null; // No need of a pid here as this page serves as a dummy buffer page and is meant to be
              // used independent of BufferManager.
    this.td = td;
    this.numSlots = (BufferPool.PAGE_SIZE * 8) / ((td.getSize() * 8) + 1);

    DataInputStream dis = new DataInputStream(new ByteArrayInputStream(data));
    this.header = new Header(dis);

    try {
      // allocate and read the actual records of this page
      tuples = new Tuple[numSlots];
      for (int i = 0; i < numSlots; i++) {
        tuples[i] = readNextTuple(dis, i);
      }
    } catch (NoSuchElementException e) {
      e.printStackTrace();
    }

    dis.close();
  }
  /**
   * Create a HeapPage from a set of bytes of data read from disk. The format of a HeapPage is a set
   * of 32-bit header words indicating the slots of the page that are in use, plus
   * (BufferPool.PAGE_SIZE/tuple size) tuple slots, where tuple size is the size of tuples in this
   * database table, which can be determined via {@link Catalog#getTupleDesc}.
   *
   * <p>The number of 32-bit header words is equal to:
   *
   * <p>(no. tuple slots / 32) + 1
   *
   * <p>
   *
   * @see Database#getCatalog
   * @see Catalog#getTupleDesc
   * @see BufferPool#PAGE_SIZE
   */
  public HeapPage(HeapPageId id, byte[] data) throws IOException {
    this.pid = id;
    this.td = Database.getCatalog().getTupleDesc(id.tableid());
    // this.numSlots = (BufferPool.PAGE_SIZE) / (td.getSize());
    this.numSlots = (BufferPool.PAGE_SIZE * 8) / ((td.getSize() * 8) + 1);
    // System.out.println(this.numSlots);
    DataInputStream dis = new DataInputStream(new ByteArrayInputStream(data));

    // allocate and read the header slots of this page
    header = new Header(dis);

    try {
      // allocate and read the actual records of this page
      tuples = new Tuple[numSlots];
      for (int i = 0; i < numSlots; i++) {
        tuples[i] = readNextTuple(dis, i);
      }
    } catch (NoSuchElementException e) {
      // e.printStackTrace();
    }

    dis.close();
  }
 /**
  * Retrieve the number of tuples on this page.
  *
  * @return the number of tuples on this page
  */
 private int getNumTuples() {
   // some code goes here
   int tupsPerPage = (BufferPool.PAGE_SIZE * 8) / ((td.getSize() * 8) + 1); // default to be floor
   return tupsPerPage;
 }
Beispiel #9
0
 /**
  * Retrieve the number of tuples on this page.
  *
  * @return the number of tuples on this page
  */
 private int getNumTuples() {
   // hdj
   return BufferPool.PAGE_SIZE * 8 / (td.getSize() * 8 + 1);
 }