blob: 66d8ec2e46e3a69a42fc0fa072afbed41484f880 [file] [log] [blame]
/*
* Copyright 2009-2012 by The Regents of the University of California
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* you may obtain a copy of the License from
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package edu.uci.ics.hyracks.storage.am.lsm.common.freepage;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
import edu.uci.ics.hyracks.api.io.FileReference;
import edu.uci.ics.hyracks.storage.am.lsm.common.api.IInMemoryBufferCache;
import edu.uci.ics.hyracks.storage.common.buffercache.ICacheMemoryAllocator;
import edu.uci.ics.hyracks.storage.common.buffercache.ICachedPage;
import edu.uci.ics.hyracks.storage.common.buffercache.ICachedPageInternal;
import edu.uci.ics.hyracks.storage.common.file.BufferedFileHandle;
import edu.uci.ics.hyracks.storage.common.file.IFileMapManager;
import edu.uci.ics.hyracks.storage.common.file.IFileMapProvider;
public class InMemoryBufferCache implements IInMemoryBufferCache {
protected final ICacheMemoryAllocator allocator;
protected final IFileMapManager fileMapManager;
protected final int pageSize;
protected final int numPages;
protected final List<CachedPage> overflowPages = new ArrayList<CachedPage>();
protected CachedPage[] pages;
public InMemoryBufferCache(ICacheMemoryAllocator allocator, int pageSize, int numPages,
IFileMapManager fileMapManager) {
this.allocator = allocator;
this.fileMapManager = fileMapManager;
this.pageSize = pageSize;
this.numPages = numPages;
}
public void open() {
pages = new CachedPage[numPages];
ByteBuffer[] buffers = allocator.allocate(pageSize, numPages);
for (int i = 0; i < buffers.length; ++i) {
pages[i] = new CachedPage(i, buffers[i]);
}
}
@Override
public ICachedPage pin(long dpid, boolean newPage) {
int pageId = BufferedFileHandle.getPageId(dpid);
if (pageId < pages.length) {
// Common case: Return regular page.
return pages[pageId];
} else {
// Rare case: Return overflow page, possibly expanding overflow array.
synchronized (overflowPages) {
int numNewPages = pageId - pages.length - overflowPages.size() + 1;
if (numNewPages > 0) {
ByteBuffer[] buffers = allocator.allocate(pageSize, numNewPages);
for (int i = 0; i < numNewPages; i++) {
CachedPage overflowPage = new CachedPage(pages.length + overflowPages.size(), buffers[i]);
overflowPages.add(overflowPage);
}
}
return overflowPages.get(pageId - pages.length);
}
}
}
@Override
public ICachedPage tryPin(long dpid) throws HyracksDataException {
return pin(dpid, false);
}
@Override
public int getPageSize() {
return pageSize;
}
@Override
public int getNumPages() {
return numPages;
}
@Override
public ICachedPageInternal getPage(int cpid) {
return pages[cpid];
}
public int getNumOverflowPages() {
return overflowPages.size();
}
@Override
public void createFile(FileReference fileRef) throws HyracksDataException {
synchronized (fileMapManager) {
fileMapManager.registerFile(fileRef);
}
}
@Override
public void openFile(int fileId) throws HyracksDataException {
// Do nothing.
}
@Override
public void closeFile(int fileId) throws HyracksDataException {
// Do nothing.
}
@Override
public void deleteFile(int fileId, boolean flushDirtyPages) throws HyracksDataException {
synchronized (fileMapManager) {
fileMapManager.unregisterFile(fileId);
}
}
@Override
public void unpin(ICachedPage page) throws HyracksDataException {
// Do Nothing.
}
@Override
public void close() {
for (int i = 0; i < numPages; ++i) {
pages[i] = null;
}
overflowPages.clear();
}
public class CachedPage implements ICachedPageInternal {
private final int cpid;
private final ByteBuffer buffer;
private final ReadWriteLock latch;
public CachedPage(int cpid, ByteBuffer buffer) {
this.cpid = cpid;
this.buffer = buffer;
latch = new ReentrantReadWriteLock(true);
}
@Override
public ByteBuffer getBuffer() {
return buffer;
}
@Override
public Object getReplacementStrategyObject() {
// Do nothing.
return null;
}
@Override
public boolean pinIfGoodVictim() {
// Do nothing.
return false;
}
@Override
public int getCachedPageId() {
return cpid;
}
@Override
public void acquireReadLatch() {
latch.readLock().lock();
}
@Override
public void acquireWriteLatch() {
latch.writeLock().lock();
}
@Override
public void releaseReadLatch() {
latch.readLock().unlock();
}
@Override
public void releaseWriteLatch() {
latch.writeLock().unlock();
}
}
@Override
public void force(int fileId, boolean metadata) throws HyracksDataException {
}
@Override
public void flushDirtyPage(ICachedPage page) throws HyracksDataException {
}
public IFileMapProvider getFileMapProvider() {
return fileMapManager;
}
}