/** 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; }
/** * 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(); }
public Tuple getNext() throws NoSuchElementException, TransactionAbortedException { try { Tuple tuple = new Tuple(td); for (int i = 0; i < td.numFields(); i++) { IntField intf = IntField.createIntField(in.readInt()); tuple.setField(i, intf); } return tuple; } catch (EOFException eof) { throw new NoSuchElementException(eof.getMessage()); } catch (Exception e) { e.printStackTrace(); BufferPool.Instance().abortTransaction(tid); closeConnection(); throw new TransactionAbortedException(e); } }
/** * Adds the specified tuple to the page; the tuple should be updated to reflect that it is now * stored on this page. * * @throws DbException if the page is full (no empty slots) or tupledesc is mismatch. * @param t The tuple to add. */ public void insertTuple(Tuple t) throws DbException { // some code goes here // not necessary for lab1 RecordId targetrid = t.getRecordId(); if (getNumEmptySlots() == 0 || !td.equals(t.getTupleDesc())) { throw new DbException("Either page is full or tuple desc doesn't match"); } for (int i = 0; i < getNumTuples(); i++) { if (!isSlotUsed(i)) { markSlotUsed(i, true); RecordId rid = new RecordId(pid, i); t.setRecordId(rid); tuples[i] = t; return; } } }
/** * 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; }
/** * 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); }