mirror of https://github.com/apache/cassandra
Switch CommitLogSegment from RandomAccessFile to nio
Patch by jmckenzie; reviewed by belliottsmith for CASSANDRA-8308
This commit is contained in:
parent
028fd29501
commit
2b4029a763
|
|
@ -1,4 +1,5 @@
|
|||
3.0
|
||||
* Switch CommitLogSegment from RandomAccessFile to nio (CASSANDRA-8308)
|
||||
* Allow mixing token and partition key restrictions (CASSANDRA-7016)
|
||||
* Support index key/value entries on map collections (CASSANDRA-8473)
|
||||
* Modernize schema tables (CASSANDRA-8261)
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import java.io.RandomAccessFile;
|
|||
import java.nio.ByteBuffer;
|
||||
import java.nio.MappedByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
|
|
@ -104,7 +105,7 @@ public class CommitLogSegment
|
|||
public final long id;
|
||||
|
||||
private final File logFile;
|
||||
private final RandomAccessFile logFileAccessor;
|
||||
private final FileChannel channel;
|
||||
private final int fd;
|
||||
|
||||
private final MappedByteBuffer buffer;
|
||||
|
|
@ -134,7 +135,6 @@ public class CommitLogSegment
|
|||
id = getNextId();
|
||||
descriptor = new CommitLogDescriptor(id);
|
||||
logFile = new File(DatabaseDescriptor.getCommitLogLocation(), descriptor.fileName());
|
||||
boolean isCreating = true;
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -147,25 +147,37 @@ public class CommitLogSegment
|
|||
logger.debug("Re-using discarded CommitLog segment for {} from {}", id, filePath);
|
||||
if (!oldFile.renameTo(logFile))
|
||||
throw new IOException("Rename from " + filePath + " to " + id + " failed");
|
||||
isCreating = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.debug("Creating new CommitLog segment: " + logFile);
|
||||
}
|
||||
}
|
||||
|
||||
// Open the initial the segment file
|
||||
logFileAccessor = new RandomAccessFile(logFile, "rw");
|
||||
// Extend or truncate the file size to the standard segment size as we may have restarted after a segment
|
||||
// size configuration change, leaving "incorrectly" sized segments on disk.
|
||||
// NOTE: while we're using RAF to allow extension of file on disk w/out sparse, we need to avoid using RAF
|
||||
// for grabbing the FileChannel due to FILE_SHARE_DELETE flag bug on windows.
|
||||
// See: https://bugs.openjdk.java.net/browse/JDK-6357433 and CASSANDRA-8308
|
||||
if (logFile.length() != DatabaseDescriptor.getCommitLogSegmentSize())
|
||||
{
|
||||
try (RandomAccessFile raf = new RandomAccessFile(logFile, "rw"))
|
||||
{
|
||||
raf.setLength(DatabaseDescriptor.getCommitLogSegmentSize());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new FSWriteError(e, logFile);
|
||||
}
|
||||
}
|
||||
|
||||
if (isCreating)
|
||||
logger.debug("Creating new commit log segment {}", logFile.getPath());
|
||||
channel = FileChannel.open(logFile.toPath(), StandardOpenOption.WRITE, StandardOpenOption.READ);
|
||||
|
||||
// Map the segment, extending or truncating it to the standard segment size.
|
||||
// (We may have restarted after a segment size configuration change, leaving "incorrectly"
|
||||
// sized segments on disk.)
|
||||
logFileAccessor.setLength(DatabaseDescriptor.getCommitLogSegmentSize());
|
||||
fd = CLibrary.getfd(logFileAccessor.getFD());
|
||||
fd = CLibrary.getfd(channel);
|
||||
buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, DatabaseDescriptor.getCommitLogSegmentSize());
|
||||
|
||||
buffer = logFileAccessor.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, DatabaseDescriptor.getCommitLogSegmentSize());
|
||||
// write the header
|
||||
CommitLogDescriptor.writeHeader(buffer, descriptor);
|
||||
|
||||
// mark the initial sync marker as uninitialised
|
||||
buffer.putInt(CommitLogDescriptor.HEADER_SIZE, 0);
|
||||
buffer.putLong(CommitLogDescriptor.HEADER_SIZE + 4, 0);
|
||||
|
|
@ -415,7 +427,7 @@ public class CommitLogSegment
|
|||
{
|
||||
if (FileUtils.isCleanerAvailable())
|
||||
FileUtils.clean(buffer);
|
||||
logFileAccessor.close();
|
||||
channel.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ package org.apache.cassandra.utils;
|
|||
import java.io.FileDescriptor;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.channels.FileChannel;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
|
@ -276,6 +277,24 @@ public final class CLibrary
|
|||
}
|
||||
}
|
||||
|
||||
public static int getfd(FileChannel channel)
|
||||
{
|
||||
Field field = FBUtilities.getProtectedField(channel.getClass(), "fd");
|
||||
|
||||
if (field == null)
|
||||
return -1;
|
||||
|
||||
try
|
||||
{
|
||||
return getfd((FileDescriptor)field.get(channel));
|
||||
}
|
||||
catch (IllegalArgumentException|IllegalAccessException e)
|
||||
{
|
||||
logger.warn("Unable to read fd field from FileChannel");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get system file descriptor from FileDescriptor object.
|
||||
* @param descriptor - FileDescriptor objec to get fd from
|
||||
|
|
@ -295,7 +314,7 @@ public final class CLibrary
|
|||
catch (Exception e)
|
||||
{
|
||||
JVMStabilityInspector.inspectThrowable(e);
|
||||
logger.warn("unable to read fd field from FileDescriptor");
|
||||
logger.warn("Unable to read fd field from FileDescriptor");
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -419,6 +419,7 @@ public class SchemaLoader
|
|||
|
||||
public static void cleanupAndLeaveDirs()
|
||||
{
|
||||
CommitLog.instance.resetUnsafe(); // unmap CLS before attempting to delete or Windows complains
|
||||
mkdirs();
|
||||
cleanup();
|
||||
mkdirs();
|
||||
|
|
@ -434,7 +435,11 @@ public class SchemaLoader
|
|||
File dir = new File(dirName);
|
||||
if (!dir.exists())
|
||||
throw new RuntimeException("No such directory: " + dir.getAbsolutePath());
|
||||
FileUtils.deleteRecursive(dir);
|
||||
|
||||
// Leave the folder around as Windows will complain about directory deletion w/handles open to children files
|
||||
String[] children = dir.list();
|
||||
for (String child : children)
|
||||
FileUtils.deleteRecursive(new File(dir, child));
|
||||
}
|
||||
|
||||
cleanupSavedCaches();
|
||||
|
|
@ -445,7 +450,9 @@ public class SchemaLoader
|
|||
File dir = new File(dirName);
|
||||
if (!dir.exists())
|
||||
throw new RuntimeException("No such directory: " + dir.getAbsolutePath());
|
||||
FileUtils.deleteRecursive(dir);
|
||||
String[] children = dir.list();
|
||||
for (String child : children)
|
||||
FileUtils.deleteRecursive(new File(dir, child));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue