/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package com.github.geophile.erdo.segmentfilemanager;
import com.github.geophile.erdo.Configuration;
import com.github.geophile.erdo.util.FileUtil;
import com.github.geophile.erdo.util.IdGenerator;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.logging.Level;
import java.util.logging.Logger;
public class SegmentFileManager extends AbstractSegmentFileManager
{
// AbstractSegmentFileManager interface
@Override
public boolean delete(File file, long treeId, long segmentId)
{
FileUtil.deleteFile(file);
return true;
}
@Override
public void create(File file, long treeId, long segmentId) throws IOException
{
FileUtil.createFile(file);
if (!file.createNewFile()) {
throw new IOException(String.format("Unable to create file %s.", file));
}
}
@Override
public void register(File source, long treeId, long segmentId)
{
throw new UnsupportedOperationException();
}
@Override
public void write(File file, long position, ByteBuffer buffer) throws IOException, InterruptedException
{
long start = System.currentTimeMillis();
RandomAccessFile randomAccessFile = randomAccessFile(file);
try {
FileChannel channel = randomAccessFile.getChannel();
channel.position(position);
channel.write(buffer);
if (Thread.interrupted()) {
throw new InterruptedException();
}
long stop = System.currentTimeMillis();
if (LOG.isLoggable(Level.FINE)) {
LOG.log(Level.FINE,
"Wrote page at {0} of {1}: {2} msec",
new Object[]{position, file, stop - start});
}
} finally {
randomAccessFile.close();
}
}
@Override
public ByteBuffer readPage(File file, long position, ByteBuffer pageBuffer)
throws IOException, InterruptedException
{
long start = System.currentTimeMillis();
RandomAccessFile randomAccessFile = randomAccessFile(file);
try {
randomAccessFile.seek(position);
randomAccessFile.readFully(pageBuffer.array(), pageBuffer.arrayOffset(), pageSizeBytes);
if (Thread.interrupted()) {
throw new InterruptedException();
}
long stop = System.currentTimeMillis();
if (LOG.isLoggable(Level.FINE)) {
LOG.log(Level.FINE,
"Read page at {0} of {1}: {2} msec",
new Object[]{position, file, stop - start});
}
} catch (EOFException e) {
LOG.log(Level.SEVERE,
"Caught EOFException while reading {0}, position {1}",
new Object[]{file, position});
LOG.log(Level.SEVERE, "stack", e);
throw e;
} finally {
randomAccessFile.close();
}
return pageBuffer;
}
@Override
public void flush(File file) throws IOException
{
long start = System.currentTimeMillis();
RandomAccessFile randomAccessFile = randomAccessFile(file);
try {
FileChannel channel = randomAccessFile.getChannel();
channel.force(true);
if (LOG.isLoggable(Level.FINE)) {
long stop = System.currentTimeMillis();
LOG.log(Level.FINE,
"Flushed {0}: {1} msec",
new Object[]{file, stop - start});
}
} finally {
randomAccessFile.close();
}
}
@Override
public long newSegmentId()
{
return segmentIdGenerator.nextId();
}
@Override
public void restoreSegmentIdGenerator(long lastSegmentId)
{
segmentIdGenerator.restore(lastSegmentId);
}
@Override
public void resetStats()
{
}
@Override
public void resetForTesting()
{
}
// SegmentFileManager interface
public SegmentFileManager(Configuration configuration)
{
super(configuration);
}
// For use by this class
private RandomAccessFile randomAccessFile(File file)
throws FileNotFoundException
{
return new RandomAccessFile(file, MODE);
}
// Class state
private static final String MODE = "rwd"; // Flush content but not metadata on each write.
private static final Logger LOG = Logger.getLogger(SegmentFileManager.class.getName());
// Object state
private final IdGenerator segmentIdGenerator = new IdGenerator(0);
}