예제 #1
1
파일: HeapFile.java 프로젝트: ntgsx92/cs143
 // see DbFile.java for javadocs
 public Page readPage(PageId pid) {
   int offset = BufferPool.PAGE_SIZE * pid.pageNumber();
   byte[] b = new byte[BufferPool.PAGE_SIZE];
   try {
     InputStream is = new FileInputStream(m_file);
     is.skip(offset);
     is.read(b, 0, BufferPool.PAGE_SIZE);
     is.close();
     return new HeapPage((HeapPageId) pid, b);
   } catch (IOException ioe) {
     ioe.printStackTrace();
     return null;
   }
 }
예제 #2
0
  /**
   * Compares one PageId to another.
   *
   * @param o The object to compare against (must be a PageId)
   * @return true if the objects are equal (e.g., page numbers and table ids are the same)
   */
  public boolean equals(Object o) {
    if (!(o instanceof PageId)) return false;

    PageId other = (PageId) o;

    if (this.getTableId() != other.getTableId() || this.pageNumber() != other.pageNumber())
      return false;

    return true;
  }
예제 #3
0
  /**
   * You should implement the hashCode() so that two equal RecordId instances (with respect to
   * equals()) have the same hashCode().
   *
   * @return An int that is the same for equal RecordId objects.
   */
  @Override
  public int hashCode() {
    // some code goes here
    return Integer.parseInt(pid.hashCode() + Integer.toString(tupleno));
    // throw new UnsupportedOperationException("implement this");

  }
예제 #4
0
 @Override
 public int hashCode() {
   final int prime = 31;
   int result = 1;
   result = prime * result + ((pid == null) ? 0 : pid.hashCode());
   result = prime * result + tupleno;
   return result;
 }
예제 #5
0
  /**
   * Two RecordId objects are considered equal if they represent the same tuple.
   *
   * @return True if this and o represent the same tuple
   */
  @Override
  public boolean equals(Object o) {
    // some code goes here
    if (o instanceof RecordId) {
      RecordId tmp = (RecordId) o;

      return pid.equals(tmp.getPageId()) && tmp.tupleno == tupleno;
    }
    return false;
    // throw new UnsupportedOperationException("implement this");
  }
예제 #6
0
  // see DbFile.java for javadocs
  public Page readPage(PageId pid) {
    // some code goes here
    if (pid.pageNumber() >= numPages()) {
      throw new IllegalArgumentException("page not in file");
    }
    Page returnme = null;

    byte[] data = HeapPage.createEmptyPageData();
    long offset = (long) BufferPool.PAGE_SIZE * pid.pageNumber();
    try {
      raf.seek(offset);
      for (int i = 0; i < data.length; i++) {
        data[i] = raf.readByte();
      }
      returnme = new HeapPage((HeapPageId) pid, data);
    } catch (EOFException eofe) {
      eofe.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }
    return returnme;
  }
예제 #7
0
  /**
   * Retrieve the specified page with the associated permissions. Will acquire a lock and may block
   * if that lock is held by another transaction.
   *
   * <p>The retrieved page should be looked up in the buffer pool. If it is present, it should be
   * returned. If it is not present, it should be added to the buffer pool and returned. If there is
   * insufficient space in the buffer pool, an page should be evicted and the new page should be
   * added in its place.
   *
   * @param tid the ID of the transaction requesting the page
   * @param pid the ID of the requested page
   * @param perm the requested permissions on the page
   * @throws IOException
   * @throws NoSuchElementException
   */
  public Page getPage(TransactionId tid, PageId pid, Permissions perm)
      throws TransactionAbortedException, DbException, NoSuchElementException, IOException {

    if (this.deadPool.containsKey(pid)) {
      return this.deadPool.get(pid);
    } else {
      if (this.deadPool.size() >= this.numPages) {
        throw new DbException("Too many pages!");
      } else {
        this.deadPool.put(
            pid, Database.getCatalog().getDatabaseFile(pid.getTableId()).readPage(pid));
        return this.deadPool.get(pid);
      }
    }
  }
예제 #8
0
 /**
  * Flushes a certain page to disk
  *
  * @param pageId an ID indicating the page to flush
  */
 private synchronized void flushPage(PageId pageId) throws IOException {
   if (pageIdToPages.containsKey(pageId)) {
     Page page = pageIdToPages.get(pageId);
     // append an update record to the log, with
     // a before-image and after-image.
     TransactionId dirtier = page.isDirty();
     if (dirtier != null) {
       addDirtiedFlushedPage(dirtier, pageId);
       Database.getLogFile().logWrite(dirtier, page.getBeforeImage(), page);
       Database.getLogFile().force();
       Database.getCatalog().getDatabaseFile(pageId.getTableId()).writePage(page);
       page.markDirty(false, null);
     }
   }
 }
예제 #9
0
 // see DbFile.java for javadocs
 public Page readPage(PageId pid) {
   // some code goes here
   try {
     RandomAccessFile rAf = new RandomAccessFile(f, "r");
     int offset = pid.pageNumber() * BufferPool.PAGE_SIZE;
     byte[] b = new byte[BufferPool.PAGE_SIZE];
     rAf.seek(offset);
     rAf.read(b, 0, BufferPool.PAGE_SIZE);
     HeapPageId hpid = (HeapPageId) pid;
     rAf.close();
     return new HeapPage(hpid, b);
   } catch (IOException e) {
     e.printStackTrace();
   }
   return null;
 }
예제 #10
0
 /**
  * Retrieve the specified page with the associated permissions. Will acquire a lock and may block
  * if that lock is held by another transaction.
  *
  * <p>The retrieved page should be looked up in the buffer pool. If it is present, it should be
  * returned. If it is not present, it should be added to the buffer pool and returned. If there is
  * insufficient space in the buffer pool, an page should be evicted and the new page should be
  * added in its place.
  *
  * @param tid the ID of the transaction requesting the page
  * @param pid the ID of the requested page
  * @param perm the requested permissions on the page
  * @throws DbException
  * @throws TransactionAbortedException
  */
 public Page getPage(TransactionId tid, PageId pid, Permissions perm)
     throws DbException, TransactionAbortedException {
   lockManager.acquireLock(tid, pid, perm);
   if (pageIdToPages.containsKey(pid)) {
     return pageIdToPages.get(pid);
   }
   if (currentPages.get() == maxPages) {
     evictPage();
   }
   int tableId = pid.getTableId();
   Catalog catalog = Database.getCatalog();
   DbFile dbFile = catalog.getDatabaseFile(tableId);
   Page page = dbFile.readPage(pid);
   pageIdToPages.put(pid, page);
   currentPages.incrementAndGet();
   return page;
 }
예제 #11
0
 @Override
 public boolean equals(Object obj) {
   if (this == obj) {
     return true;
   }
   if (obj == null) {
     return false;
   }
   if (!(obj instanceof RecordId)) {
     return false;
   }
   RecordId other = (RecordId) obj;
   if (pid == null) {
     if (other.pid != null) {
       return false;
     }
   } else if (!pid.equals(other.pid)) {
     return false;
   }
   if (tupleno != other.tupleno) {
     return false;
   }
   return true;
 }
예제 #12
0
  /**
   * overrides the test2 function in TestDriver. It tests whether illeagal operation can be caught.
   *
   * @return whether test2 has passed
   */
  protected boolean test2() {

    System.out.print("\n  Test 2 exercises some illegal buffer " + "manager operations:\n");

    // We choose this number to ensure that pinning this number of buffers
    // should fail.
    int numPages = SystemDefs.JavabaseBM.getNumUnpinnedBuffers() + 1;
    Page pg = new Page();
    PageId pid, lastPid;
    PageId firstPid = new PageId();
    boolean status = OK;

    System.out.print("  - Try to pin more pages than there are frames\n");
    try {
      firstPid = SystemDefs.JavabaseBM.newPage(pg, numPages);
    } catch (Exception e) {
      System.err.print("*** Could not allocate " + numPages);
      System.err.print(" new pages in the database.\n");
      e.printStackTrace();
      return false;
    }

    pid = new PageId();
    lastPid = new PageId();

    // First pin enough pages that there is no more room.
    for (pid.pid = firstPid.pid + 1, lastPid.pid = firstPid.pid + numPages - 1;
        status == OK && pid.pid < lastPid.pid;
        pid.pid = pid.pid + 1) {

      try {
        SystemDefs.JavabaseBM.pinPage(pid, pg, /*emptyPage:*/ true);
      } catch (Exception e) {
        status = FAIL;
        System.err.print("*** Could not pin new page " + pid.pid + "\n");
        e.printStackTrace();
      }
    }

    // Make sure the buffer manager thinks there's no more room.
    if (status == OK && SystemDefs.JavabaseBM.getNumUnpinnedBuffers() != 0) {
      status = FAIL;
      System.err.print(
          "*** The buffer manager thinks it has "
              + SystemDefs.JavabaseBM.getNumUnpinnedBuffers()
              + " available frames,\n"
              + "    but it should have none.\n");
    }

    // Now pin that last page, and make sure it fails.
    if (status == OK) {
      try {
        SystemDefs.JavabaseBM.pinPage(lastPid, pg, /*emptyPage:*/ true);
      } catch (ChainException e) {
        status = checkException(e, "bufmgr.BufferPoolExceededException");
        if (status == FAIL) {
          System.err.print("*** Pinning too many pages\n");
          System.out.println("  --> Failed as expected \n");
        }
      } catch (Exception e) {
        e.printStackTrace();
      }

      if (status == OK) {
        status = FAIL;
        System.err.print("The expected exception was not thrown\n");
      } else {
        status = OK;
      }
    }

    if (status == OK) {
      try {
        SystemDefs.JavabaseBM.pinPage(firstPid, pg, /*emptyPage:*/ true);
      } catch (Exception e) {
        status = FAIL;
        System.err.print("*** Could not acquire a second pin on a page\n");
        e.printStackTrace();
      }

      if (status == OK) {
        System.out.print("  - Try to free a doubly-pinned page\n");
        try {
          SystemDefs.JavabaseBM.freePage(firstPid);
        } catch (ChainException e) {
          status = checkException(e, "bufmgr.PagePinnedException");

          if (status == FAIL) {
            System.err.print("*** Freeing a pinned page\n");
            System.out.println("  --> Failed as expected \n");
          }
        } catch (Exception e) {
          e.printStackTrace();
        }

        if (status == OK) {
          status = FAIL;
          System.err.print("The expected exception was not thrown\n");
        } else {
          status = OK;
        }
      }

      if (status == OK) {
        try {
          SystemDefs.JavabaseBM.unpinPage(firstPid, false);
        } catch (Exception e) {
          status = FAIL;
          e.printStackTrace();
        }
      }
    }

    if (status == OK) {
      System.out.print("  - Try to unpin a page not in the buffer pool\n");
      try {
        SystemDefs.JavabaseBM.unpinPage(lastPid, false);
      } catch (ChainException e) {
        status = checkException(e, "bufmgr.HashEntryNotFoundException");

        if (status == FAIL) {
          System.err.print("*** Unpinning a page not in the buffer pool\n");
          System.out.println("  --> Failed as expected \n");
        }
      } catch (Exception e) {
        e.printStackTrace();
      }

      if (status == OK) {
        status = FAIL;
        System.err.print("The expected exception was not thrown\n");
      } else {
        status = OK;
      }
    }

    for (pid.pid = firstPid.pid; pid.pid <= lastPid.pid; pid.pid = pid.pid + 1) {
      try {
        SystemDefs.JavabaseBM.freePage(pid);
      } catch (Exception e) {
        status = FAIL;
        System.err.print("*** Error freeing page " + pid.pid + "\n");
        e.printStackTrace();
      }
    }

    if (status == OK) System.out.print("  Test 2 completed successfully.\n");

    return status;
  }
예제 #13
0
  /**
   * overrides the test1 function in TestDriver. It tests some simple normal buffer manager
   * operations.
   *
   * @return whether test1 has passed
   */
  protected boolean test1() {

    System.out.print("\n  Test 1 does a simple test of normal buffer ");
    System.out.print("manager operations:\n");

    // We choose this number to ensure that at least one page will have to be
    // written during this test.
    boolean status = OK;
    int numPages = SystemDefs.JavabaseBM.getNumUnpinnedBuffers() + 1;
    Page pg = new Page();
    PageId pid;
    PageId lastPid;
    PageId firstPid = new PageId();

    System.out.print("  - Allocate a bunch of new pages\n");

    try {
      firstPid = SystemDefs.JavabaseBM.newPage(pg, numPages);
    } catch (Exception e) {
      System.err.print("*** Could not allocate " + numPages);
      System.err.print(" new pages in the database.\n");
      e.printStackTrace();
      return false;
    }

    // Unpin that first page... to simplify our loop.
    try {
      SystemDefs.JavabaseBM.unpinPage(firstPid, false /*not dirty*/);
    } catch (Exception e) {
      System.err.print("*** Could not unpin the first new page.\n");
      e.printStackTrace();
      status = FAIL;
    }

    System.out.print("  - Write something on each one\n");

    pid = new PageId();
    lastPid = new PageId();

    for (pid.pid = firstPid.pid, lastPid.pid = pid.pid + numPages;
        status == OK && pid.pid < lastPid.pid;
        pid.pid = pid.pid + 1) {

      try {
        SystemDefs.JavabaseBM.pinPage(pid, pg, /*emptyPage:*/ true);
      } catch (Exception e) {
        status = FAIL;
        System.err.print("*** Could not pin new page " + pid.pid + "\n");
        e.printStackTrace();
      }

      if (status == OK) {

        // Copy the page number + 99999 onto each page.  It seems
        // unlikely that this bit pattern would show up there by
        // coincidence.
        int data = pid.pid + 99999;

        try {
          Convert.setIntValue(data, 0, pg.getpage());
        } catch (IOException e) {
          System.err.print("*** Convert value failed\n");
          status = FAIL;
        }

        if (status == OK) {
          try {
            SystemDefs.JavabaseBM.unpinPage(pid, /*dirty:*/ true);
          } catch (Exception e) {
            status = FAIL;
            System.err.print("*** Could not unpin dirty page " + pid.pid + "\n");
            e.printStackTrace();
          }
        }
      }
    }

    if (status == OK)
      System.out.print(
          "  - Read that something back from each one\n"
              + "   (because we're buffering, this is where "
              + "most of the writes happen)\n");

    for (pid.pid = firstPid.pid; status == OK && pid.pid < lastPid.pid; pid.pid = pid.pid + 1) {

      try {
        SystemDefs.JavabaseBM.pinPage(pid, pg, /*emptyPage:*/ false);
      } catch (Exception e) {
        status = FAIL;
        System.err.print("*** Could not pin page " + pid.pid + "\n");
        e.printStackTrace();
      }

      if (status == OK) {

        int data = 0;

        try {
          data = Convert.getIntValue(0, pg.getpage());
        } catch (IOException e) {
          System.err.print("*** Convert value failed \n");
          status = FAIL;
        }

        if (status == OK) {
          if (data != (pid.pid) + 99999) {
            status = FAIL;
            System.err.print("*** Read wrong data back from page " + pid.pid + "\n");
          }
        }

        if (status == OK) {
          try {
            SystemDefs.JavabaseBM.unpinPage(pid, /*dirty:*/ true);
          } catch (Exception e) {
            status = FAIL;
            System.err.print("*** Could not unpin page " + pid.pid + "\n");
            e.printStackTrace();
          }
        }
      }
    }

    if (status == OK) System.out.print("  - Free the pages again\n");

    for (pid.pid = firstPid.pid; pid.pid < lastPid.pid; pid.pid = pid.pid + 1) {

      try {
        SystemDefs.JavabaseBM.freePage(pid);
      } catch (Exception e) {
        status = FAIL;
        System.err.print("*** Error freeing page " + pid.pid + "\n");
        e.printStackTrace();
      }
    }

    if (status == OK) System.out.print("  Test 1 completed successfully.\n");

    return status;
  }