blob: 80502eb4be5d5c554d09b4aa9aa5c8a092437d88 [file] [log] [blame]
package edu.uci.ics.hyracks.storage.common;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Test;
import edu.uci.ics.hyracks.api.context.IHyracksTaskContext;
import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
import edu.uci.ics.hyracks.api.io.FileReference;
import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
import edu.uci.ics.hyracks.storage.common.buffercache.ICachedPage;
import edu.uci.ics.hyracks.storage.common.file.BufferedFileHandle;
import edu.uci.ics.hyracks.storage.common.file.IFileMapProvider;
import edu.uci.ics.hyracks.test.support.TestStorageManagerComponentHolder;
import edu.uci.ics.hyracks.test.support.TestUtils;
public class BufferCacheTest {
protected static final List<String> openedFiles = new ArrayList<String>();
protected static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("ddMMyy-hhmmssSS");
protected static final String tmpDir = System.getProperty("java.io.tmpdir");
protected static final String sep = System.getProperty("file.separator");
private static final int PAGE_SIZE = 256;
private static final int NUM_PAGES = 10;
private static final int MAX_OPEN_FILES = 20;
private static final int HYRACKS_FRAME_SIZE = PAGE_SIZE;
private IHyracksTaskContext ctx = TestUtils.create(HYRACKS_FRAME_SIZE);
private static final Random rnd = new Random(50);
private String getFileName() {
String fileName = tmpDir + sep + simpleDateFormat.format(new Date()) + openedFiles.size();
openedFiles.add(fileName);
return fileName;
}
@Test
public void simpleOpenPinCloseTest() throws HyracksDataException {
TestStorageManagerComponentHolder.init(PAGE_SIZE, NUM_PAGES, MAX_OPEN_FILES);
IBufferCache bufferCache = TestStorageManagerComponentHolder.getBufferCache(ctx);
IFileMapProvider fmp = TestStorageManagerComponentHolder.getFileMapProvider(ctx);
String fileName = getFileName();
FileReference file = new FileReference(new File(fileName));
bufferCache.createFile(file);
int fileId = fmp.lookupFileId(file);
int num = 10;
int testPageId = 0;
bufferCache.openFile(fileId);
ICachedPage page = null;
// tryPin should fail
page = bufferCache.tryPin(BufferedFileHandle.getDiskPageId(fileId, testPageId));
Assert.assertNull(page);
// pin page should succeed
page = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, testPageId), true);
page.acquireWriteLatch();
try {
for (int i = 0; i < num; i++) {
page.getBuffer().putInt(i * 4, i);
}
// try pin should succeed
ICachedPage page2 = bufferCache.tryPin(BufferedFileHandle.getDiskPageId(fileId, testPageId));
Assert.assertNotNull(page2);
bufferCache.unpin(page2);
} finally {
page.releaseWriteLatch();
bufferCache.unpin(page);
}
bufferCache.closeFile(fileId);
boolean exceptionThrown = false;
// tryPin should fail since file is not open
try {
page = bufferCache.tryPin(BufferedFileHandle.getDiskPageId(fileId, testPageId));
} catch (HyracksDataException e) {
exceptionThrown = true;
}
Assert.assertTrue(exceptionThrown);
// pin should fail since file is not open
exceptionThrown = false;
try {
page = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, testPageId), false);
} catch (HyracksDataException e) {
exceptionThrown = true;
}
Assert.assertTrue(exceptionThrown);
// open file again
bufferCache.openFile(fileId);
// tryPin should succeed because page should still be cached
page = bufferCache.tryPin(BufferedFileHandle.getDiskPageId(fileId, testPageId));
Assert.assertNotNull(page);
page.acquireReadLatch();
try {
// verify contents of page
for (int i = 0; i < num; i++) {
Assert.assertEquals(page.getBuffer().getInt(i * 4), i);
}
} finally {
page.releaseReadLatch();
bufferCache.unpin(page);
}
bufferCache.closeFile(fileId);
bufferCache.close();
}
@Test
public void simpleMaxOpenFilesTest() throws HyracksDataException {
TestStorageManagerComponentHolder.init(PAGE_SIZE, NUM_PAGES, MAX_OPEN_FILES);
IBufferCache bufferCache = TestStorageManagerComponentHolder.getBufferCache(ctx);
IFileMapProvider fmp = TestStorageManagerComponentHolder.getFileMapProvider(ctx);
List<Integer> fileIds = new ArrayList<Integer>();
for (int i = 0; i < MAX_OPEN_FILES; i++) {
String fileName = getFileName();
FileReference file = new FileReference(new File(fileName));
bufferCache.createFile(file);
int fileId = fmp.lookupFileId(file);
bufferCache.openFile(fileId);
fileIds.add(fileId);
}
boolean exceptionThrown = false;
// since all files are open, next open should fail
try {
String fileName = getFileName();
FileReference file = new FileReference(new File(fileName));
bufferCache.createFile(file);
int fileId = fmp.lookupFileId(file);
bufferCache.openFile(fileId);
} catch (HyracksDataException e) {
exceptionThrown = true;
}
Assert.assertTrue(exceptionThrown);
// close a random file
int ix = Math.abs(rnd.nextInt()) % fileIds.size();
bufferCache.closeFile(fileIds.get(ix));
fileIds.remove(ix);
// now open should succeed again
exceptionThrown = false;
try {
String fileName = getFileName();
FileReference file = new FileReference(new File(fileName));
bufferCache.createFile(file);
int fileId = fmp.lookupFileId(file);
bufferCache.openFile(fileId);
fileIds.add(fileId);
} catch (HyracksDataException e) {
exceptionThrown = true;
}
Assert.assertFalse(exceptionThrown);
for (Integer i : fileIds) {
bufferCache.closeFile(i.intValue());
}
bufferCache.close();
}
@Test
public void contentCheckingMaxOpenFilesTest() throws HyracksDataException {
TestStorageManagerComponentHolder.init(PAGE_SIZE, NUM_PAGES, MAX_OPEN_FILES);
IBufferCache bufferCache = TestStorageManagerComponentHolder.getBufferCache(ctx);
IFileMapProvider fmp = TestStorageManagerComponentHolder.getFileMapProvider(ctx);
List<Integer> fileIds = new ArrayList<Integer>();
Map<Integer, ArrayList<Integer>> pageContents = new HashMap<Integer, ArrayList<Integer>>();
int num = 10;
int testPageId = 0;
// open max number of files and write some stuff into their first page
for (int i = 0; i < MAX_OPEN_FILES; i++) {
String fileName = getFileName();
FileReference file = new FileReference(new File(fileName));
bufferCache.createFile(file);
int fileId = fmp.lookupFileId(file);
bufferCache.openFile(fileId);
fileIds.add(fileId);
ICachedPage page = null;
page = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, testPageId), true);
page.acquireWriteLatch();
try {
ArrayList<Integer> values = new ArrayList<Integer>();
for (int j = 0; j < num; j++) {
int x = Math.abs(rnd.nextInt());
page.getBuffer().putInt(j * 4, x);
values.add(x);
}
pageContents.put(fileId, values);
} finally {
page.releaseWriteLatch();
bufferCache.unpin(page);
}
}
boolean exceptionThrown = false;
// since all files are open, next open should fail
try {
String fileName = getFileName();
FileReference file = new FileReference(new File(fileName));
bufferCache.createFile(file);
int fileId = fmp.lookupFileId(file);
bufferCache.openFile(fileId);
} catch (HyracksDataException e) {
exceptionThrown = true;
}
Assert.assertTrue(exceptionThrown);
// close a few random files
ArrayList<Integer> closedFileIds = new ArrayList<Integer>();
int filesToClose = 5;
for (int i = 0; i < filesToClose; i++) {
int ix = Math.abs(rnd.nextInt()) % fileIds.size();
bufferCache.closeFile(fileIds.get(ix));
closedFileIds.add(fileIds.get(ix));
fileIds.remove(ix);
}
// now open a few new files
for (int i = 0; i < filesToClose; i++) {
String fileName = getFileName();
FileReference file = new FileReference(new File(fileName));
bufferCache.createFile(file);
int fileId = fmp.lookupFileId(file);
bufferCache.openFile(fileId);
fileIds.add(fileId);
}
// since all files are open, next open should fail
try {
String fileName = getFileName();
FileReference file = new FileReference(new File(fileName));
bufferCache.createFile(file);
int fileId = fmp.lookupFileId(file);
bufferCache.openFile(fileId);
} catch (HyracksDataException e) {
exceptionThrown = true;
}
Assert.assertTrue(exceptionThrown);
// close a few random files again
for (int i = 0; i < filesToClose; i++) {
int ix = Math.abs(rnd.nextInt()) % fileIds.size();
bufferCache.closeFile(fileIds.get(ix));
closedFileIds.add(fileIds.get(ix));
fileIds.remove(ix);
}
// now open those closed files again and verify their contents
for (int i = 0; i < filesToClose; i++) {
int closedFileId = closedFileIds.get(i);
bufferCache.openFile(closedFileId);
fileIds.add(closedFileId);
// pin first page and verify contents
ICachedPage page = null;
page = bufferCache.pin(BufferedFileHandle.getDiskPageId(closedFileId, testPageId), false);
page.acquireReadLatch();
try {
ArrayList<Integer> values = pageContents.get(closedFileId);
for (int j = 0; j < values.size(); j++) {
Assert.assertEquals(values.get(j).intValue(), page.getBuffer().getInt(j * 4));
}
} finally {
page.releaseReadLatch();
bufferCache.unpin(page);
}
}
for (Integer i : fileIds) {
bufferCache.closeFile(i.intValue());
}
bufferCache.close();
}
@AfterClass
public static void cleanup() throws Exception {
for (String s : openedFiles) {
File f = new File(s);
f.deleteOnExit();
}
}
}