initial commit with everything

This commit is contained in:
2024-02-14 11:33:04 -05:00
parent 2c4360df9b
commit b011a30ab6
292 changed files with 606599 additions and 0 deletions
+17
View File
@@ -0,0 +1,17 @@
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
.mvn/wrapper/maven-wrapper.jar
# Eclipse m2e generated files
# Eclipse Core
.project
# JDT-specific (Eclipse Java Development Tools)
.classpath
+29
View File
@@ -0,0 +1,29 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "test",
"request": "launch",
"mainClass": "test",
"projectName": "cs448p1"
},
{
"type": "java",
"name": "Current File",
"request": "launch",
"mainClass": "${file}"
},
{
"type": "java",
"name": "App",
"request": "launch",
"mainClass": "cs448.App",
"projectName": "cs448p1",
"args": "./data_30MB.tsv 2 nm0000001"
}
]
}
+3
View File
@@ -0,0 +1,3 @@
{
"java.compile.nullAnalysis.mode": "disabled"
}
+32
View File
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: org.mapdb:mapdb:3.0.7" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib:1.2.71" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib-common:1.2.71" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains:annotations:13.0" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.collections:eclipse-collections-api:10.0.0" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.collections:eclipse-collections:10.0.0" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.collections:eclipse-collections-forkjoin:10.0.0" level="project" />
<orderEntry type="library" name="Maven: com.google.guava:guava:28.0-jre" level="project" />
<orderEntry type="library" name="Maven: com.google.guava:failureaccess:1.0.1" level="project" />
<orderEntry type="library" name="Maven: com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava" level="project" />
<orderEntry type="library" name="Maven: com.google.code.findbugs:jsr305:3.0.2" level="project" />
<orderEntry type="library" name="Maven: org.checkerframework:checker-qual:2.8.1" level="project" />
<orderEntry type="library" name="Maven: com.google.errorprone:error_prone_annotations:2.3.2" level="project" />
<orderEntry type="library" name="Maven: com.google.j2objc:j2objc-annotations:1.3" level="project" />
<orderEntry type="library" name="Maven: org.codehaus.mojo:animal-sniffer-annotations:1.17" level="project" />
<orderEntry type="library" name="Maven: net.jpountz.lz4:lz4:1.3.0" level="project" />
<orderEntry type="library" name="Maven: org.mapdb:elsa:3.0.0-M5" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.11" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
</component>
</module>
Binary file not shown.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+10
View File
@@ -0,0 +1,10 @@
nconst primaryName birthYear deathYear primaryProfession knownForTitles
nm0000001 Fred Astaire 1899 1987 soundtrack,actor,miscellaneous tt0072308,tt0053137,tt0043044,tt0050419
nm0000002 Lauren Bacall 1924 2014 actress,soundtrack tt0071877,tt0037382,tt0038355,tt0117057
nm0000003 Brigitte Bardot 1934 \N actress,soundtrack,producer tt0054452,tt0049189,tt0059956,tt0057345
nm0000004 John Belushi 1949 1982 actor,writer,soundtrack tt0078723,tt0072562,tt0077975,tt0080455
nm0000005 Ingmar Bergman 1918 2007 writer,director,actor tt0083922,tt0050976,tt0050986,tt0060827
nm0000006 Ingrid Bergman 1915 1982 actress,soundtrack,producer tt0034583,tt0071877,tt0038787,tt0038109
nm0000007 Humphrey Bogart 1899 1957 actor,soundtrack,producer tt0033870,tt0034583,tt0037382,tt0043265
nm0000008 Marlon Brando 1924 2004 actor,soundtrack,director tt0047296,tt0078788,tt0068646,tt0070849
nm0000009 Richard Burton 1925 1984 actor,producer,soundtrack tt0059749,tt0061184,tt0057877,tt0087803
1 nconst primaryName birthYear deathYear primaryProfession knownForTitles
2 nm0000001 Fred Astaire 1899 1987 soundtrack,actor,miscellaneous tt0072308,tt0053137,tt0043044,tt0050419
3 nm0000002 Lauren Bacall 1924 2014 actress,soundtrack tt0071877,tt0037382,tt0038355,tt0117057
4 nm0000003 Brigitte Bardot 1934 \N actress,soundtrack,producer tt0054452,tt0049189,tt0059956,tt0057345
5 nm0000004 John Belushi 1949 1982 actor,writer,soundtrack tt0078723,tt0072562,tt0077975,tt0080455
6 nm0000005 Ingmar Bergman 1918 2007 writer,director,actor tt0083922,tt0050976,tt0050986,tt0060827
7 nm0000006 Ingrid Bergman 1915 1982 actress,soundtrack,producer tt0034583,tt0071877,tt0038787,tt0038109
8 nm0000007 Humphrey Bogart 1899 1957 actor,soundtrack,producer tt0033870,tt0034583,tt0037382,tt0043265
9 nm0000008 Marlon Brando 1924 2004 actor,soundtrack,director tt0047296,tt0078788,tt0068646,tt0070849
10 nm0000009 Richard Burton 1925 1984 actor,producer,soundtrack tt0059749,tt0061184,tt0057877,tt0087803
Binary file not shown.
+94
View File
@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>edu.cs.purdue</groupId>
<artifactId>cs448p1</artifactId>
<version>1.0-SNAPSHOT</version>
<name>cs448p1</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.mapdb/mapdb -->
<dependency>
<groupId>org.mapdb</groupId>
<artifactId>mapdb</artifactId>
<version>3.0.7</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>cs448.App</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
@@ -0,0 +1,54 @@
package cs448;
import java.io.*;
public class App
{
public static void main( String[] args )
{
String input_file_path = args[0];
int backend = Integer.parseInt(args[1]);
String id = args[2];
project1 p = new project1();
long startts;
String[] column_names = {"nconst", "primaryName", "birthYear", "deathYear", "primaryProfession", "knownForTitles"};
try {
switch (backend){
case 0:
startts = System.nanoTime();
System.out.println(p.select_file(input_file_path,id,column_names));
System.out.println("Elapsed time in (ns): "+(System.nanoTime()-startts));
break;
case 1:
startts = System.nanoTime();
p.load_mainmemory(input_file_path);
System.out.println("Load: elapsed time in (ns): "+(System.nanoTime()-startts));
startts = System.nanoTime();
System.out.println(p.select_mainmemory(id,column_names));
System.out.println("Query: elapsed time in (ns): "+(System.nanoTime()-startts));
break;
case 2:
startts = System.nanoTime();
p.load_mapdb(input_file_path);
System.out.println("Load: elapsed time in (ns): "+(System.nanoTime()-startts));
startts = System.nanoTime();
System.out.println(p.select_mapdb(id,column_names));
System.out.println("Query: elapsed time in (ns): "+(System.nanoTime()-startts));
break;
default:
System.out.println("Syntax: project1 path/to/datafile 0|1|2 id");
}
}
catch(IOException e){
e.printStackTrace();
}
catch (OutOfMemoryError e){
System.gc();
e.printStackTrace();
}
finally {
p.db.close();
}
}
}
@@ -0,0 +1,171 @@
package cs448;
import org.mapdb.DB;
import org.mapdb.DBMaker;
import org.mapdb.Serializer;
import java.io.IOException;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Scanner;
import java.util.concurrent.ConcurrentMap;
import java.io.File;
import java.lang.StringBuilder;
/**
* A class to compare different storage backends.
*
* @author Sean Rettig
* @version January 22, 2024
*/
public class project1 {
/* Data structure for Main-memory back-end */
HashMap<String,Dictionary<String, String>> mm_map = new HashMap<String,Dictionary<String, String>>();
/* Data structure for MapDB persistent storage*/
String dbfile = "data.db";
DB db = DBMaker.fileDB(dbfile).make();
// use this for MapDB storage
ConcurrentMap mapdb = db.hashMap("map").make();
void load_mainmemory(String file_path) throws IOException {
Scanner sc = new Scanner((new File(file_path)));
String line = "";
while (sc.hasNextLine()) {
line = sc.nextLine();
String[] row = line.split("\t");
Dictionary<String, String> row_dict = new Hashtable<>();
row_dict.put("primaryName", row[1]);
row_dict.put("birthYear", row[2]);
row_dict.put("deathYear", row[3]);
row_dict.put("primaryProfession", row[4]);
row_dict.put("knownForTitles", row[5]);
mm_map.put(row[0], row_dict);
}
}
void load_mapdb(String file_path) throws IOException{
Scanner sc = new Scanner((new File(file_path)));
String line = "";
while (sc.hasNextLine()) {
line = sc.nextLine();
String[] row = line.split("\t");
Dictionary<String, String> row_dict = new Hashtable<>();
row_dict.put("primaryName", row[1]);
row_dict.put("birthYear", row[2]);
row_dict.put("deathYear", row[3]);
row_dict.put("primaryProfession", row[4]);
row_dict.put("knownForTitles", row[5]);
mapdb.put(row[0], row_dict);
}
}
String select_file(String file_path, String key, String[] column_names) throws IOException{
Scanner sc = new Scanner(new File(file_path));
String line = "";
while (sc.hasNextLine()) {
line = sc.nextLine();
if (line.contains(key)) {
sc.close();
break;
}
}
if (line != "") {
String[] row = line.split("\t");
StringBuilder sb = new StringBuilder();
for (String col_name : column_names) {
switch (col_name) {
case "nconst":
sb.append(row[0]);
break;
case "primaryName":
sb.append(row[1]);
break;
case "birthYear":
sb.append(row[2]);
break;
case "deathYear":
sb.append(row[3]);
break;
case "primaryProfession":
sb.append(row[4]);
break;
case "knownForTitles":
sb.append(row[5]);
break;
default:
break;
}
sb.append("\t");
}
line = sb.toString();
}
return line;
}
String select_mainmemory(String key, String[] column_names){
StringBuilder sb = new StringBuilder();
Dictionary<String, String> data = mm_map.get(key);
for (String col_name : column_names) {
if (col_name == "nconst") {
sb.append(key);
} else {
sb.append(data.get(col_name));
}
sb.append("\t");
}
return sb.toString();
}
String select_mapdb(String key, String[] column_names){
StringBuilder sb = new StringBuilder();
Dictionary<String, String> data = (Dictionary<String, String>) mapdb.get(key);
for (String col_name : column_names) {
if (col_name == "nconst") {
sb.append(key);
} else {
sb.append(data.get(col_name));
}
sb.append("\t");
}
return sb.toString();
}
int fastestLoad(){
// 1: Main-memory Load
// 2: MapDB Load
int fastest = 1;
return fastest;
}
int fastestSelect(){
// 0: File Select
// 1: Main-memory Select
// 2: MapDB Select
int fastest = 1;
return fastest;
}
}
Binary file not shown.
+99
View File
@@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>edu.cs.purdue</groupId>
<artifactId>cs448p2</artifactId>
<version>1.0-SNAPSHOT</version>
<name>cs448p2</name>
<url>https://www.cs.purdue.edu/homes/bb/cs448f19/</url>
<properties>
<java.version>10</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.mapdb/mapdb -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>minibase</groupId>
<artifactId>bufmgr-project</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${basedir}/lib/bufmgrAssign.jar</systemPath>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>${java.version}</release>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>test.TestDriver</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
@@ -0,0 +1,236 @@
package bufmgr;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import diskmgr.DiskMgrException;
import global.Minibase;
import global.Page;
import global.PageId;
/**
* <h3>Minibase Buffer Manager</h3>
* The buffer manager reads disk pages into a main memory page as needed. The
* collection of main memory pages (called frames) used by the buffer manager
* for this purpose is called the buffer pool. This is just an array of Page
* objects. The buffer manager is used by access methods, heap files, and
* relational operators to read, write, allocate, and de-allocate pages.
*/
public class BufMgr {
// INSTANCE VARIABLES
// Some of these are accessed during the test cases
// DO NOT CHANGE THE BELOW INSTANCE VARIABLE NAMES - you should use them as appropriate in your code
// You may add additional ones as you need to
/** bufPool: the buffer pool. An array of Page objects */
private Page[] bufPool = null;
/** frmDescr: An arracy of FrameDescriptor objects, holding information about the contents of each frame. */
private FrameDescriptor[] frmDescr = null;
/** numOfFrames: the number of frames used for the maximum capacity of the buffer pool */
private int numOfFrames = -1;
/** replacementPolicy: will be set to FIFO when the constructor is called. */
private static String replacementPolicy = "FIFO";
/** map: Hash table to track which frame in the buffer a page is in <Key: PageID, Value: Frame> */
private Map<Integer, Integer> pageMap = new HashMap<>();
//
/** fifo: queue for FIFO page replacement. All unpinned pages will be stored here, with the first element being
* the pageID that was unpinned the longest time ago */
private Queue<Integer> fifo = new LinkedList<>();
// END OF REQUIRED INSTANCE VARIABLES
/**
* Resets a FrameDescriptor to the default values with no pageID
*/
protected void resetFrameDescriptor(int frameId) {
resetFrameDescriptor(frameId, -1);
}
/**
* Resets a FrameDescriptor to the default values with the given pageID
*/
protected void resetFrameDescriptor(int frameId, int pageno) {
frmDescr[frameId].pageno = pageno;
frmDescr[frameId].pinCount = 0;
frmDescr[frameId].dirtyBit = false;
}
/**
* Create the BufMgr object. Allocate pages (frames) for the buffer pool in main
* memory and make the buffer manage aware that the replacement policy is
* specified by replacerArg (e.g., LH, Clock, LRU, MRU, LIRS, etc.).
*
* @param numbufs
* number of buffers in the buffer pool
* @param lookAheadSize
* number of pages to be looked ahead - can be ignored for this assignment
* @param replacementPolicy
* Name of the replacement policy
*/
public BufMgr(int numbufs, int lookAheadSize, String replacementPolicy) {
// we ignore replacementPolicy as there is only one policy implemented in the
// system
numOfFrames = numbufs;
bufPool = new Page[numOfFrames];
frmDescr = new FrameDescriptor[numOfFrames];
this.replacementPolicy = replacementPolicy;
for (int i = 0; i < numOfFrames; i++) {
bufPool[i] = new Page();
frmDescr[i] = new FrameDescriptor();
resetFrameDescriptor(i, -1);
fifo.add(i);
}
}
/**
* Pin a page. First check if this page is already in the buffer pool. If it is,
* increment the pin_count and return a pointer to this page. If the pin_count
* was 0 before the call, the page was a replacement candidate, but is no longer
* a candidate. If the page is not in the pool, choose a frame (from the set of
* replacement candidates) to hold this page, read the page (using the
* appropriate method from diskmgr package) and pin it. Also, must write out the
* old page in chosen frame if it is dirty before reading new page.(You can
* assume that emptyPage==false for this assignment.)
*
* @param pageno
* page number in the Minibase.
* @param page
* the pointer point to the page.
* @throws BufferPoolExceededException if there are no valid replacement candidates when attempting to pin a page not already in memory
* @throws DiskMgrException if there is an error from the DiskMgr layer. This is likely caused by incorrect implementations of other methods in the BufferManager
*/
public void pinPage(PageId pageno, Page page, boolean emptyPage)
throws BufferPoolExceededException, DiskMgrException {
// YOUR CODE HERE
}
/**
* Unpin a page specified by a pageId. This method should be called with
* dirty==true if the client has modified the page. If so, this call should set
* the dirty bit for this frame. Further, if pin_count>0, this method should
* decrement it. If pin_count=0 before this call, throw an exception to report
* error. (For testing purposes, we ask you to throw an exception named
* PageUnpinnedException in case of error.)
*
* @param pageno
* the PageID of the page
* @param dirty
* whether or not the page is dirty
* @throws PageNotFoundException the page is not in memory
* @throws PageUnpinnedException the page is already unpinned
*/
public void unpinPage(PageId pageno, boolean dirty)
throws PageNotFoundException, PageUnpinnedException {
// YOUR CODE HERE
}
/**
* Allocate new pages. Call DB object to allocate a run of new pages and find a
* frame in the buffer pool for the first page and pin it. (This call allows a
* client of the Buffer Manager to allocate pages on disk.) If buffer is full,
* i.e., you can't find a frame for the first page, ask DB to deallocate all
* these pages, and return null.
*
* @param firstpage
* the address of the first page.
* @param howmany
* total number of allocated new pages.
*
* @return the first page id of the new pages.__ null, if error.
* @throws DiskMgrException if there is an error from the DiskMgr layer. This is likely caused by incorrect implementations of other methods of the Buffer Manager
* @throws BufferPoolExceededException if the new page cannot be pinned after the run is allocated due to the buffer being full. If this exception is thrown, the newly allocated pages should be deallocated
*/
public PageId newPage(Page firstpage, int howmany) throws DiskMgrException, BufferPoolExceededException {
// YOUR CODE HERE
return new PageId();
}
/**
* This method should be called to delete a page that is on disk. This routine
* must call the method in diskmgr package to deallocate the page.
*
* @param pageno
* the page number in the data base.
* @throws PagePinnedException if the page is still pinned
* @throws DiskMgrException if there is an error in the DiskMgr layer. This is likely caused by incorrect implementations in other methods of the Buffer Manager
*/
public void freePage(PageId pageno) throws PagePinnedException, DiskMgrException {
// YOUR CODE HERE
}
/**
* Used to flush a particular page of the buffer pool to disk. This method calls
* the write_page method of the diskmgr package.
*
* @param pageid
* the page number in the database.
* @throws PageNotFoundException if the page is not in memory
* @throws DiskMgrException if there is an error in the DiskMgr layer. This is likely caused by incorrect implementations in other methods of the Buffer Manager
*/
public void flushPage(PageId pageid) throws PageNotFoundException, DiskMgrException {
// find the frame holding that page
Integer frameId = pageMap.get(pageid.pid);
if (frameId == null) {
throw new PageNotFoundException(
"BufMgr.flushPage: Page with id " + pageid.pid + " does not exist in the buffer bool.");
} else {
Minibase.DiskManager.write_page(pageid, bufPool[frameId]);
frmDescr[frameId].dirtyBit = false;
}
}
/**
* Used to flush all dirty pages in the buffer pool to disk
* @throws DiskMgrException if there is an error in the DiskMgr layer. This is likely caused by incorrect implementations in other methods of the Buffer Manager
*/
public void flushAllPages() throws DiskMgrException {
for (int i = 0; i < numOfFrames; i++) {
if (frmDescr[i].dirtyBit == true) {
Minibase.DiskManager.write_page(new PageId(frmDescr[i].pageno), bufPool[i]);
frmDescr[i].dirtyBit = false;
}
}
}
/**
* Returns the total number of buffer frames.
*/
public int getNumBuffers() {
return numOfFrames;
}
/**
* Returns the total number of unpinned buffer frames.
*/
public int getNumUnpinned() {
int numUnpinned = 0;
for (int i = 0; i < numOfFrames; i++) {
if (frmDescr[i].pinCount <= 0) {
numUnpinned++;
}
}
return numUnpinned;
}
//*** DO NOT CHANGE ANY EXISTING METHODS BELOW THIS LINE ***
// Accessor methods for use in test cases
public FrameDescriptor getFrameDesc(int frameNum) {
return frmDescr[frameNum];
}
public Page getPageFromFrame(int frameNum) {
return bufPool[frameNum];
}
public Integer getFrameFromPage(PageId pid) {
return pageMap.get(new Integer(pid.pid));
}
}
@@ -0,0 +1,15 @@
package bufmgr;
public class BufMgrException extends Throwable
{
/**
*
*/
private static final long serialVersionUID = -53906392083428894L;
public BufMgrException(String msg)
{
super(msg);
}
}
@@ -0,0 +1,15 @@
package bufmgr;
public class BufferPoolExceededException extends BufMgrException
{
/**
*
*/
private static final long serialVersionUID = -3879729988119933114L;
public BufferPoolExceededException(String msg)
{
super(msg);
}
}
@@ -0,0 +1,16 @@
package bufmgr;
/**
* A frame descriptor; contains info about each page in the buffer pool.
*/
public class FrameDescriptor
{
/** Identifies the frame's page. */
public int pageno = -1;
/** The frame's pin count. */
public int pinCount;
/** The frame's dirty status. */
public boolean dirtyBit;
}
@@ -0,0 +1,16 @@
package bufmgr;
public class PageNotFoundException extends BufMgrException
{
public PageNotFoundException(String msg)
{
super(msg);
}
/**
*
*/
private static final long serialVersionUID = 8527332129053870174L;
}
@@ -0,0 +1,16 @@
package bufmgr;
public class PagePinnedException extends BufMgrException
{
public PagePinnedException(String msg)
{
super(msg);
}
/**
*
*/
private static final long serialVersionUID = 2891505249472036297L;
}
@@ -0,0 +1,17 @@
package bufmgr;
public class PageUnpinnedException extends BufMgrException
{
public PageUnpinnedException(String msg)
{
super(msg);
}
/**
*
*/
private static final long serialVersionUID = 8366005988643934461L;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,21 @@
package diskmgr;
public class DiskMgrException extends Exception {
/**
*
*/
private static final long serialVersionUID = -6796603846181216651L;
public DiskMgrException(String name)
{
super(name);
}
}
@@ -0,0 +1,15 @@
package diskmgr;
public class DuplicateEntryException extends DiskMgrException {
/**
*
*/
private static final long serialVersionUID = -7360431299339776190L;
public DuplicateEntryException(String msg)
{
super(msg);
}
}
@@ -0,0 +1,22 @@
package diskmgr;
public class FileEntryNotFoundException extends DiskMgrException {
/**
*
*/
private static final long serialVersionUID = -5657953921202448803L;
public FileEntryNotFoundException(String msg)
{
super(msg);
}
}
@@ -0,0 +1,21 @@
package diskmgr;
public class FileIOException extends DiskMgrException {
/**
*
*/
private static final long serialVersionUID = 6320388561056052984L;
public FileIOException(String msg)
{
super(msg);
}
}
@@ -0,0 +1,19 @@
package diskmgr;
public class FileNameTooLongException extends DiskMgrException {
/**
*
*/
private static final long serialVersionUID = -4115614718485246811L;
public FileNameTooLongException(String msg)
{
super(msg);
}
}
@@ -0,0 +1,19 @@
package diskmgr;
public class InvalidPageNumberException extends DiskMgrException {
/**
*
*/
private static final long serialVersionUID = 5106265663568991693L;
public InvalidPageNumberException(String msg)
{
super(msg);
}
}
@@ -0,0 +1,18 @@
package diskmgr;
public class InvalidRunSizeException extends DiskMgrException {
/**
*
*/
private static final long serialVersionUID = 1663588077268780074L;
public InvalidRunSizeException(String msg)
{
super(msg);
}
}
@@ -0,0 +1,15 @@
package diskmgr;
public class OutOfSpaceException extends DiskMgrException {
/**
*
*/
private static final long serialVersionUID = 2560165916249758898L;
public OutOfSpaceException(String msg)
{
super(msg);
}
}
@@ -0,0 +1,952 @@
package tests;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import bufmgr.*;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import diskmgr.DiskMgrException;
import diskmgr.OutOfSpaceException;
import global.Convert;
import global.GlobalConst;
import global.Minibase;
import global.Page;
import global.PageId;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class BMTest implements GlobalConst {
public final static boolean OK = true;
public final static boolean FAIL = false;
/** Default database size (in pages). */
private final static int DB_SIZE = 10000;
/** Default buffer pool size (in pages) */
private final static int BUF_SIZE = 100;
/** Default number of pages to be looked ahead */
private final static int LAH_SIZE = 10;
// Filepaths
private static String dbpath;
private static String logpath;
private static final String REMOVE_CMD = "/bin/rm -rf ";
private static String remove_logcmd;
private static String remove_dbcmd;
// Instance variables for tests
private static int numPages;
private static Page pg;
private static PageId pid, first_pid, last_pid;
private void checkFDContents(FrameDescriptor fd, int pgid, int pinCount, boolean dirty) {
String failmsg = "Failed: - ";
boolean passed = true;
if (fd.pageno != pgid) {
failmsg += "FD pagenumber: " + fd.pageno + ", should be " + pgid + " - ";
passed = false;
}
if (fd.pinCount != pinCount) {
failmsg += "FD pincount: " + fd.pinCount + ", should be " + pinCount + " - ";
passed = false;
}
if (fd.dirtyBit != dirty) {
failmsg += "Fd dirty bit: " + fd.dirtyBit + ", should be " + dirty;
passed = false;
}
assertTrue(failmsg, passed);
}
@BeforeClass
public static void setUpBeforeClass() throws Exception {
// Set up remove commands and ensure nothing's left over
String remove_cmd = "/bin/rm -rf ";
dbpath = "/tmp/" + System.getProperty("user.name") + ".minibase-db";
logpath = "/tmp/" + System.getProperty("user.name") + ".minibase-log";
remove_logcmd = REMOVE_CMD + logpath;
remove_dbcmd = REMOVE_CMD + dbpath;
// Commands here is very machine dependent. We assume
// user are on UNIX system here
try {
Runtime.getRuntime().exec(remove_logcmd);
Runtime.getRuntime().exec(remove_dbcmd);
} catch (IOException e) {
System.err.println("" + e);
}
}
@Before
public void setUp() throws Exception {
new Minibase(dbpath, DB_SIZE, BUF_SIZE, LAH_SIZE, "FIFO", false);
numPages = Minibase.BufferManager.getNumUnpinned();
pg = new Page();
pid = new PageId();
first_pid = new PageId();
last_pid = new PageId();
}
@After
public void tearDown() throws Exception {
// Remove anything from previous tests
// Commands here are very machine dependent. We assume
// user are on UNIX system here
try {
Runtime.getRuntime().exec(remove_logcmd);
Runtime.getRuntime().exec(remove_dbcmd);
} catch (IOException e) {
System.err.println("" + e);
}
}
@Test
public void testA_PinPageNotInMemory() {
try {
first_pid = Minibase.BufferManager.newPage(pg, 1);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
// Allocated and pinned one page - check that it's in hash table
Integer fnum = Minibase.BufferManager.getFrameFromPage(first_pid);
if (fnum == null)
assertTrue("Failed: page not in hash table", false);
pg = Minibase.BufferManager.getPageFromFrame(fnum);
if (pg == null)
assertTrue("Failed: page not in frame", false);
FrameDescriptor fd = Minibase.BufferManager.getFrameDesc(fnum);
checkFDContents(fd, first_pid.pid, 1, false);
}
@Test
public void testB_PinPinnedPageInMemory() {
try {
first_pid = Minibase.BufferManager.newPage(pg, 1);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
try {
Minibase.BufferManager.pinPage(first_pid, pg, false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for repinning already pinned page", false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr pinning pinned page", false);
}
// Allocated and pinned one page twice - check that it's in hash table
Integer fnum = Minibase.BufferManager.getFrameFromPage(first_pid);
if (fnum == null)
assertTrue("Failed: page not in hash table", false);
pg = Minibase.BufferManager.getPageFromFrame(fnum);
if (pg == null)
assertTrue("Failed: page not in frame", false);
FrameDescriptor fd = Minibase.BufferManager.getFrameDesc(fnum);
checkFDContents(fd, first_pid.pid, 2, false);
}
@Test
public void testC_UnpinPinnedPageInMemory() {
try {
first_pid = Minibase.BufferManager.newPage(pg, 1);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
try {
Minibase.BufferManager.unpinPage(first_pid, false);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page not found in hash table when unpinning", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page already unpinned", false);
}
// Allocated and pinned one page, then unpinned it - check that it's in hash
// table
Integer fnum = Minibase.BufferManager.getFrameFromPage(first_pid);
if (fnum == null)
assertTrue("Failed: page not in hash table after unpinning", false);
pg = Minibase.BufferManager.getPageFromFrame(fnum);
if (pg == null)
assertTrue("Failed: page not in frame after unpinning", false);
FrameDescriptor fd = Minibase.BufferManager.getFrameDesc(fnum);
checkFDContents(fd, first_pid.pid, 0, false);
}
@Test
public void testD_PinUnpinnedPageInMemory() {
try {
first_pid = Minibase.BufferManager.newPage(pg, 1);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
try {
Minibase.BufferManager.unpinPage(first_pid, false);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page not found in hash table when unpinning", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page already unpinned", false);
}
try {
Minibase.BufferManager.pinPage(first_pid, pg, false);
} catch (BufferPoolExceededException bpe_ex) {
assertTrue("Unexpected Failure: Buffer Pool Full when attempting to repin unpinned page in buffer", false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr repinning page", false);
}
// Allocated and pinned one page, then unpinned it, then pinned it again
// check that it's in hash table
Integer fnum = Minibase.BufferManager.getFrameFromPage(first_pid);
if (fnum == null)
assertTrue("Failed: page not in hash table after repinning page", false);
pg = Minibase.BufferManager.getPageFromFrame(fnum);
if (pg == null)
assertTrue("Failed: page not in frame after repinning page", false);
FrameDescriptor fd = Minibase.BufferManager.getFrameDesc(fnum);
checkFDContents(fd, first_pid.pid, 1, false);
}
@Test
public void testE_UnpinUnpinnedPageInMemory() {
try {
first_pid = Minibase.BufferManager.newPage(pg, 1);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
try {
Minibase.BufferManager.unpinPage(first_pid, false);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page not found in hash table when unpinning", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page already unpinned", false);
}
// Unpin the page twice so that we will be unpinning an unpinned page
try {
Minibase.BufferManager.unpinPage(first_pid, false);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page not found in hash table when unpinning unpinned page", false);
} catch (PageUnpinnedException e) {
assertTrue(true);
return;
}
// If we get here, the expected exception was not returned
assertTrue("Failed: PageUnpinnedException not properly thrown", false);
}
@Test
public void testF_UnpinDirtyPage() {
try {
first_pid = Minibase.BufferManager.newPage(pg, 1);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
try {
Minibase.BufferManager.unpinPage(first_pid, true);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page not found in hash table when unpinning", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page already unpinned", false);
}
// Allocated and pinned one page, then unpinned it as dirty
// check that it's in hash table
Integer fnum = Minibase.BufferManager.getFrameFromPage(first_pid);
if (fnum == null)
assertTrue("Failed: page not in hash table after unpinning", false);
pg = Minibase.BufferManager.getPageFromFrame(fnum);
if (pg == null)
assertTrue("Failed: page not in frame after unpinning", false);
FrameDescriptor fd = Minibase.BufferManager.getFrameDesc(fnum);
checkFDContents(fd, first_pid.pid, 0, true);
}
@Test
public void testG_UnpinPageNotInMemory() {
try {
first_pid = Minibase.BufferManager.newPage(pg, 2);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
try {
Minibase.BufferManager.unpinPage(first_pid, false);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page not found in hash table while unpinning", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page already unpinned", false);
}
// Allocated two pages and pinned/unpinned first one
// Now attempt to unpin second, never-pinned page
pid = new PageId(first_pid.pid + 1);
try {
Minibase.BufferManager.unpinPage(pid, false);
} catch (PageNotFoundException e) {
assertTrue(true);
return;
} catch (PageUnpinnedException e) {
assertTrue(
"Unexpected Failure: PageUnpinnedException thrown, but should have returned HashNotFoundException",
false);
}
// If we get here, the expected exception was not returned
assertTrue("Failed: PageNotFoundException not properly thrown", false);
}
@Test
public void testH_PinPageNotInMemoryWithReplacement() {
try {
first_pid = Minibase.BufferManager.newPage(pg, numPages + 1);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
try {
Minibase.BufferManager.unpinPage(first_pid, false);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page not found in hash table when unpinning", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page already unpinned", false);
}
// Pin and unpin enough pages to fill buffer
for (pid.pid = first_pid.pid, last_pid.pid = pid.pid + numPages; pid.pid < last_pid.pid; pid.pid = pid.pid
+ 1) {
try {
Minibase.BufferManager.pinPage(pid, pg, false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: BufferPoolExceeded exception thrown for page " + pid.pid, false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: exception at disk manager for pinning page " + pid.pid, false);
}
try {
Minibase.BufferManager.unpinPage(pid, false);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page " + pid.pid + " not found in hash table", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page " + pid.pid + " already unpinned", false);
}
}
// Now attempt to bring another page into memory
try {
Minibase.BufferManager.pinPage(last_pid, pg, false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: BufferPoolExceeded exception thrown for last page " + last_pid.pid, false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: exception at disk manager when performing replacement", false);
}
// Pinned a page using replacement policy - verify that FD is correct
Integer fnum = Minibase.BufferManager.getFrameFromPage(last_pid);
if (fnum == null)
assertTrue("Failed: page not in hash table", false);
pg = Minibase.BufferManager.getPageFromFrame(fnum);
if (pg == null)
assertTrue("Failed: page not in frame", false);
FrameDescriptor fd = Minibase.BufferManager.getFrameDesc(fnum);
checkFDContents(fd, last_pid.pid, 1, false);
}
@Test
public void testI_PinPageReplaceDirtyPage() {
try {
first_pid = Minibase.BufferManager.newPage(pg, numPages + 1);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
try {
Minibase.BufferManager.unpinPage(first_pid, false);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page not found in hash table when unpinning", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page already unpinned", false);
}
// Pin and unpin enough pages to fill buffer
for (pid.pid = first_pid.pid, last_pid.pid = pid.pid + numPages; pid.pid < last_pid.pid; pid.pid = pid.pid
+ 1) {
try {
Minibase.BufferManager.pinPage(pid, pg, false);
// Write some data to each page
int data = pid.pid + 99999;
Convert.setIntValue(data, 0, pg.getpage());
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: BufferPoolExceeded exception thrown for page " + pid.pid, false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: exception at disk manager for page " + pid.pid, false);
} catch (IOException e) {
assertTrue("Unexpected Failure: could not write page data for page " + pid.pid, false);
}
// Unpin page - it's dirty
try {
Minibase.BufferManager.unpinPage(pid, true);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page " + pid.pid + " not found in hash table", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page " + pid.pid + " already unpinned", false);
}
}
// Now attempt to bring another page into memory, then unpin it
pid.pid = last_pid.pid + 1;
try {
Minibase.BufferManager.pinPage(pid, pg, false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: BufferPoolExceeded exception thrown for last page " + last_pid.pid + 1
+ " during replacement", false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: exception at disk manager when performing replacement", false);
}
// Pinned a page using replacement policy - FIFO should remove page with
// pid=first_pid
// Verify that page data in frame is overwritten
try {
Integer fnum = Minibase.BufferManager.getFrameFromPage(pid);
if (fnum == null)
assertTrue("Failed: page " + pid.pid + " not in hash table after replacement", false);
pg = Minibase.BufferManager.getPageFromFrame(fnum);
if (pg == null)
assertTrue("Failed: page " + pid.pid + " not in frame after replacement", false);
pg = Minibase.BufferManager.getPageFromFrame(fnum);
int data = Convert.getIntValue(0, pg.getpage());
if (data == first_pid.pid + 99999)
assertTrue("Failure: page stored in frame not overwritten when replaced", false);
} catch (IOException e) {
assertTrue("Unexpected Failure: reading from page " + pid.pid, false);
}
try {
Minibase.BufferManager.unpinPage(pid, true);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page " + pid.pid + " not found in hash table", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page " + pid.pid + " already unpinned", false);
}
// Bring in page with pid=first_pid again and see if its data is retrieved
try {
Minibase.BufferManager.pinPage(first_pid, pg, false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: BufferPoolExceeded bringing first page in from memory " + first_pid.pid
+ " during replacement", false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: exception at disk manager bringing first page in from memory", false);
}
// Verify contents of page after bringing back from disk
try {
Integer fnum = Minibase.BufferManager.getFrameFromPage(first_pid);
if (fnum == null)
assertTrue("Failed: page " + first_pid.pid + " not in hash table after replacement", false);
pg = Minibase.BufferManager.getPageFromFrame(fnum);
if (pg == null)
assertTrue("Failed: page " + first_pid.pid + " not in frame after replacement", false);
pg = Minibase.BufferManager.getPageFromFrame(fnum);
int data = Convert.getIntValue(0, pg.getpage());
// Finally, check page
assertTrue("Failure: page stored in frame not overwritten when replaced", data == first_pid.pid + 99999);
} catch (IOException e) {
assertTrue("Unexpected Failure: reading from page " + first_pid.pid, false);
}
}
@Test
public void testJ_FIFOBehavior() {
try {
first_pid = Minibase.BufferManager.newPage(pg, numPages + 1);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
try {
Minibase.BufferManager.unpinPage(first_pid, false);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page not found in hash table when unpinning", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page already unpinned", false);
}
// Pin enough pages to fill buffer
for (pid.pid = first_pid.pid, last_pid.pid = pid.pid + numPages; pid.pid < last_pid.pid; pid.pid = pid.pid + 1) {
try {
Minibase.BufferManager.pinPage(pid, pg, false);
// Write some data to each page
int data = pid.pid + 99999;
Convert.setIntValue(data, 0, pg.getpage());
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: BufferPoolExceeded exception thrown for page " + pid.pid, false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: exception at disk manager for page " + pid.pid, false);
} catch (IOException e) {
assertTrue("Unexpected Failure: cannot write data for page " + pid.pid, false);
}
}
// Pick three pages to unpin. Store the frames for reference later
PageId pg1 = new PageId(), pg2 = new PageId(), pg3 = new PageId();
int pageRange = last_pid.pid - first_pid.pid;
pg1.pid = first_pid.pid + (pageRange / 3);
Integer f1 = Minibase.BufferManager.getFrameFromPage(pg1);
pg2.pid = first_pid.pid + (pageRange / 3) * 2;
Integer f2 = Minibase.BufferManager.getFrameFromPage(pg2);
pg3.pid = first_pid.pid + pageRange-1;
Integer f3 = Minibase.BufferManager.getFrameFromPage(pg3);
// Unpin pages in order: pg2, pg1, pg3. FIFO should then select pg3 to evict
try {
Minibase.BufferManager.unpinPage(pg2, true);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: replacement page " + pg2.pid + " not found in hash table", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: replacement page " + pg2.pid + " already unpinned", false);
}
try {
Minibase.BufferManager.unpinPage(pg1, true);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: replacement page " + pg1.pid + " not found in hash table", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: replacement page " + pg1.pid + " already unpinned", false);
}
try {
Minibase.BufferManager.unpinPage(pg3, true);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: replacement page " + pg3.pid + " not found in hash table", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: replacement page " + pg3.pid + " already unpinned", false);
}
// Now attempt to bring another page into memory
pid.pid = last_pid.pid + 1;
try {
Minibase.BufferManager.pinPage(pid, pg, false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: BufferPoolExceeded exception thrown for last page " + last_pid.pid + 1
+ " during replacement", false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: exception at disk manager during replacement", false);
}
// Pinned a page using replacement policy - FIFO should remove page with pid=pg2
// Verify that page data in frame is overwritten
try {
Integer fnum = Minibase.BufferManager.getFrameFromPage(pid);
if (fnum == null)
assertTrue("Failed: page " + pid.pid + " not in hash table after replacement", false);
pg = Minibase.BufferManager.getPageFromFrame(fnum);
if (pg == null)
assertTrue("Failed: page " + pid.pid + " not in frame after replacement", false);
pg = Minibase.BufferManager.getPageFromFrame(fnum);
int data = Convert.getIntValue(0, pg.getpage());
if (data == pg2.pid + 99999)
assertTrue("Failure: page stored in frame not overwritten when replaced", false);
// Now that replacement policy has been used, verify we actually evicted pg3
assertTrue("Failed: wrong page evicted, should be page " + pg2.pid + " in frame " + f2, fnum == f2);
} catch (IOException e) {
assertTrue("Unexpected Failure: reading from page " + pid.pid, false);
}
}
@Test
public void testK_BufferFull() {
try {
first_pid = Minibase.BufferManager.newPage(pg, numPages + 1);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
try {
Minibase.BufferManager.unpinPage(first_pid, false);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page not found in hash table", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page already unpinned", false);
}
// Pin enough pages to fill buffer
for (pid.pid = first_pid.pid, last_pid.pid = pid.pid + numPages; pid.pid < last_pid.pid; pid.pid = pid.pid
+ 1) {
try {
Minibase.BufferManager.pinPage(pid, pg, false);
// Write some data to each page
int data = pid.pid + 99999;
Convert.setIntValue(data, 0, pg.getpage());
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: BufferPoolExceeded exception thrown for page " + pid.pid, false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: exception at disk manager for page " + pid.pid, false);
} catch (IOException e) {
assertTrue("Unexpected Failure: cannot write to page " + pid.pid, false);
}
}
// Now attempt to bring another page into memory, it should fail
pid.pid = last_pid.pid + 1;
try {
Minibase.BufferManager.pinPage(pid, pg, false);
} catch (BufferPoolExceededException bpe_ex) {
assertTrue(true);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: exception at disk manager for page " + pid.pid, false);
}
// If we reach here, expected exception was not thrown
assertTrue("Failure: expected BufferPoolExceeded exception not thrown thrown for page " + pid.pid, true);
}
@Test
public void testL_NewPageDeallocation()
{
//Allocate enough pages to fill the buffer
int numTestPages = numPages - 3; //-3 here is to account for required DiskMgr pages, which we will force to be pinned for this test
try {
first_pid = Minibase.BufferManager.newPage(pg, numTestPages);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
//Force all required DiskMgr pages to be pinned
for(pid.pid = 0; pid.pid < first_pid.pid; pid.pid = pid.pid + 1)
{
try {
Minibase.BufferManager.pinPage(pid, pg, false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: BufferPoolExceeded exception thrown for DiskMgr page " + pid.pid, false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: exception at disk manager for DiskMgr page " + pid.pid, false);
}
}
// Pin enough pages to fill buffer
for (pid.pid = first_pid.pid+1, last_pid.pid = first_pid.pid + numTestPages; pid.pid < last_pid.pid; pid.pid = pid.pid
+ 1) {
try {
Minibase.BufferManager.pinPage(pid, pg, false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: BufferPoolExceeded exception thrown for page " + pid.pid, false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: exception at disk manager for page " + pid.pid, false);
}
}
//Allocate enough pages to completely fill the database. However, we expect pinning the page to fail here
boolean pin = true;
try {
pid = Minibase.BufferManager.newPage(pg, DB_SIZE - last_pid.pid);
} catch (DiskMgrException e) {
e.printStackTrace();
assertTrue("Unexpected Failure: error with DiskMgr for allocation that fills the DB", false);
} catch (BufferPoolExceededException e) {
//Set a flag to show this exception was thrown successfully
pin = false;
}
if(pin)
assertTrue("Unexpected Failure: Page allocation with full buffer did not throw BufferPoolExceededException", false);
//Unpin all pages
for (pid.pid = 0; pid.pid < last_pid.pid; pid.pid = pid.pid + 1) {
try {
Minibase.BufferManager.unpinPage(pid, false);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page " + pid.pid + " not found in hash table", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page " + pid.pid + " already unpinned", false);
}
}
//Allocate new pages again - this should succeed now that the buffer is unpinned
try {
pid = Minibase.BufferManager.newPage(pg, DB_SIZE - last_pid.pid);
} catch (OutOfSpaceException e) {
assertTrue("Failure: disk pages not deallocated after failure to pin them", false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for allocation that fills the DB", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: buffer pool full when trying to allocate new pages", false);
}
//If we get here, then we have succeeded
assertTrue(true);
}
@Test //This is a simple test to demonstrate Freepage method. We create a new empty page, bring it to memory queue but do NOT pin it. It should be able to safely free the page.
public void testM_FreeAnEmptyPage()
{
try {
first_pid = Minibase.BufferManager.newPage(pg, 1);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
try {
Minibase.BufferManager.freePage(first_pid);
//assertTrue("freepage success", true);
} catch (PagePinnedException e) {
assertTrue("Test Failed: Page pinned already", true);
//System.out.println(" --> Failed as expected \n");
//status = FAIL; // what we want
} catch (Exception e) {
e.printStackTrace();
}
}
@Test //This test first creates a new emopty page, pins it and tries to Free it but as it is pinned already, we expect it to fail.
public void testN_FreeAPinnedPage(){
try {
first_pid = Minibase.BufferManager.newPage(pg, 1);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
try {
Minibase.BufferManager.pinPage(first_pid, pg, false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for repinning already pinned page", false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr pinning pinned page", false);
}
try {
Minibase.BufferManager.freePage(first_pid);
assertTrue("Unexpected behavior: Freepage was a success even though page was pinned", false);
} catch (PagePinnedException e) {
assertTrue("Test Success i.e. Failed as expected: Page pinned already - so Freepage will not suceed. This is the expected behavior.", true);
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void testO_FreePageOnWrittenPages() {
try {
first_pid = Minibase.BufferManager.newPage(pg, numPages + 1);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
try {
Minibase.BufferManager.unpinPage(first_pid, false);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page not found in hash table when unpinning", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page already unpinned", false);
}
// Pin enough pages to fill buffer
for (pid.pid = first_pid.pid, last_pid.pid = pid.pid + numPages; pid.pid < last_pid.pid; pid.pid = pid.pid + 1) {
try {
Minibase.BufferManager.pinPage(pid, pg, false);
// Write some data to each page
int data = pid.pid + 99999;
Convert.setIntValue(data, 0, pg.getpage());
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: BufferPoolExceeded exception thrown for page " + pid.pid, false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: exception at disk manager for page " + pid.pid, false);
} catch (IOException e) {
assertTrue("Unexpected Failure: cannot write data for page " + pid.pid, false);
}
}
// Pick three pages to unpin. But unpin only two and keep the third pinned
PageId pg1 = new PageId(), pg2 = new PageId(), pg3 = new PageId();
int pageRange = last_pid.pid - first_pid.pid;
pg1.pid = first_pid.pid + (pageRange / 3);
Integer f1 = Minibase.BufferManager.getFrameFromPage(pg1);
pg2.pid = first_pid.pid + (pageRange / 3) * 2;
Integer f2 = Minibase.BufferManager.getFrameFromPage(pg2);
pg3.pid = first_pid.pid + pageRange-1;
Integer f3 = Minibase.BufferManager.getFrameFromPage(pg3);
// Unpin pages in order: pg2, pg1, pg3 (as should be in FIFO policy). But for the test we do not unpin pg3
try {
Minibase.BufferManager.unpinPage(pg2, true);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: replacement page " + pg2.pid + " not found in hash table", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: replacement page " + pg2.pid + " already unpinned", false);
}
try {
Minibase.BufferManager.unpinPage(pg1, true);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: replacement page " + pg1.pid + " not found in hash table", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: replacement page " + pg1.pid + " already unpinned", false);
}
try {
Minibase.BufferManager.freePage(pg1);
assertTrue("Tests passed: PG1 was unpinned and should be able to be freed", true);
} catch (PagePinnedException e) {
assertTrue("Test Failed i.e. should be able to free an empty page", false);
} catch (Exception e) {
e.printStackTrace();
}
try {
Minibase.BufferManager.freePage(pg3);
assertTrue("Tests failed: PG3 was pinned (and written) and should NOT be able to be freed", false);
} catch (PagePinnedException e) {
assertTrue("Test passed i.e. should not be able to free a pinned page that was written on", true);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,17 @@
package tests;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
public class TestDriver {
public static void main(String[] args) {
Result result = JUnitCore.runClasses(tests.BMTest.class);
for (Failure failure : result.getFailures()) {
System.out.println(failure.toString());
}
System.out.println(result.wasSuccessful());
}
}