use of io.atomix.storage.StorageException in project atomix by atomix.
the class FileChannelJournalSegmentWriter method truncate.
@Override
@SuppressWarnings("unchecked")
public void truncate(long index) {
// If the index is greater than or equal to the last index, skip the truncate.
if (index >= getLastIndex()) {
return;
}
// Reset the last entry.
lastEntry = null;
try {
// Truncate the index.
this.index.truncate(index);
if (index < segment.index()) {
channel.position(JournalSegmentDescriptor.BYTES);
channel.write(zero());
channel.position(JournalSegmentDescriptor.BYTES);
} else {
// Reset the writer to the given index.
reset(index);
// Zero entries after the given index.
long position = channel.position();
channel.write(zero());
channel.position(position);
}
} catch (IOException e) {
throw new StorageException(e);
}
}
use of io.atomix.storage.StorageException in project atomix by atomix.
the class SegmentedJournal method loadSegment.
/**
* Loads a segment.
*/
private JournalSegment<E> loadSegment(long segmentId) {
File segmentFile = JournalSegmentFile.createSegmentFile(name, directory, segmentId);
ByteBuffer buffer = ByteBuffer.allocate(JournalSegmentDescriptor.BYTES);
try (FileChannel channel = openChannel(segmentFile)) {
channel.read(buffer);
buffer.flip();
JournalSegmentDescriptor descriptor = new JournalSegmentDescriptor(buffer);
JournalSegment<E> segment = newSegment(new JournalSegmentFile(segmentFile), descriptor);
log.debug("Loaded disk segment: {} ({})", descriptor.id(), segmentFile.getName());
return segment;
} catch (IOException e) {
throw new StorageException(e);
}
}
use of io.atomix.storage.StorageException in project atomix by atomix.
the class SegmentedJournal method loadSegments.
/**
* Loads all segments from disk.
*
* @return A collection of segments for the log.
*/
protected Collection<JournalSegment<E>> loadSegments() {
// Ensure log directories are created.
directory.mkdirs();
TreeMap<Long, JournalSegment<E>> segments = new TreeMap<>();
// Iterate through all files in the log directory.
for (File file : directory.listFiles(File::isFile)) {
// If the file looks like a segment file, attempt to load the segment.
if (JournalSegmentFile.isSegmentFile(name, file)) {
JournalSegmentFile segmentFile = new JournalSegmentFile(file);
ByteBuffer buffer = ByteBuffer.allocate(JournalSegmentDescriptor.BYTES);
try (FileChannel channel = openChannel(file)) {
channel.read(buffer);
buffer.flip();
} catch (IOException e) {
throw new StorageException(e);
}
JournalSegmentDescriptor descriptor = new JournalSegmentDescriptor(buffer);
// Load the segment.
JournalSegment<E> segment = loadSegment(descriptor.id());
// Add the segment to the segments list.
log.debug("Found segment: {} ({})", segment.descriptor().id(), segmentFile.file().getName());
segments.put(segment.index(), segment);
}
}
// Verify that all the segments in the log align with one another.
JournalSegment<E> previousSegment = null;
boolean corrupted = false;
Iterator<Map.Entry<Long, JournalSegment<E>>> iterator = segments.entrySet().iterator();
while (iterator.hasNext()) {
JournalSegment<E> segment = iterator.next().getValue();
if (previousSegment != null && previousSegment.lastIndex() != segment.index() - 1) {
log.warn("Journal is inconsistent. {} is not aligned with prior segment {}", segment.file().file(), previousSegment.file().file());
corrupted = true;
}
if (corrupted) {
segment.close();
segment.delete();
iterator.remove();
}
previousSegment = segment;
}
return segments.values();
}
use of io.atomix.storage.StorageException in project atomix by atomix.
the class FileChannelJournalSegmentReader method readNext.
/**
* Reads the next entry in the segment.
*/
@SuppressWarnings("unchecked")
private void readNext() {
// Compute the index of the next entry in the segment.
final long index = getNextIndex();
try {
// Read more bytes from the segment if necessary.
if (memory.remaining() < maxEntrySize) {
long position = channel.position() + memory.position();
channel.position(position);
memory.clear();
channel.read(memory);
channel.position(position);
memory.flip();
}
// Mark the buffer so it can be reset if necessary.
memory.mark();
try {
// Read the length of the entry.
final int length = memory.getInt();
// If the buffer length is zero then return.
if (length <= 0 || length > maxEntrySize) {
memory.reset().limit(memory.position());
nextEntry = null;
return;
}
// Read the checksum of the entry.
long checksum = memory.getInt() & 0xFFFFFFFFL;
// Compute the checksum for the entry bytes.
final Checksum crc32 = new CRC32();
crc32.update(memory.array(), memory.position(), length);
// If the stored checksum equals the computed checksum, return the entry.
if (checksum == crc32.getValue()) {
int limit = memory.limit();
memory.limit(memory.position() + length);
E entry = namespace.deserialize(memory);
memory.limit(limit);
nextEntry = new Indexed<>(index, entry, length);
} else {
memory.reset().limit(memory.position());
nextEntry = null;
}
} catch (BufferUnderflowException e) {
memory.reset().limit(memory.position());
nextEntry = null;
}
} catch (IOException e) {
throw new StorageException(e);
}
}
use of io.atomix.storage.StorageException in project atomix by atomix.
the class FileChannelJournalSegmentReader method reset.
@Override
public void reset() {
try {
channel.position(JournalSegmentDescriptor.BYTES);
} catch (IOException e) {
throw new StorageException(e);
}
memory.clear().limit(0);
currentEntry = null;
nextEntry = null;
readNext();
}
Aggregations