
io.aeron.archive.ArchiveMigration_2_3 Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aeron-all Show documentation
Show all versions of aeron-all Show documentation
Efficient reliable UDP unicast, UDP multicast, and IPC transport protocol.
/*
* Copyright 2014-2024 Real Logic Limited.
*
* 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 at
*
* https://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 io.aeron.archive;
import org.agrona.*;
import org.agrona.collections.MutableInteger;
import org.agrona.concurrent.UnsafeBuffer;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import static io.aeron.archive.Archive.Configuration.CATALOG_FILE_NAME;
import static io.aeron.archive.Catalog.DESCRIPTOR_HEADER_LENGTH;
import static io.aeron.archive.Catalog.MAX_CATALOG_LENGTH;
import static io.aeron.archive.MigrationUtils.fullVersionString;
import static java.nio.ByteOrder.LITTLE_ENDIAN;
import static java.nio.channels.FileChannel.MapMode.READ_WRITE;
import static java.nio.file.StandardOpenOption.*;
import static org.agrona.BitUtil.*;
class ArchiveMigration_2_3 implements ArchiveMigrationStep
{
private static final int MINIMUM_VERSION = SemanticVersion.compose(3, 0, 0);
/**
* {@inheritDoc}
*/
public int minimumVersion()
{
return MINIMUM_VERSION;
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("try")
public void migrate(
final PrintStream stream,
final ArchiveMarkFile markFile,
final Catalog catalog,
final File archiveDir)
{
final int version = minimumVersion();
try (FileChannel ignore = MigrationUtils.createMigrationTimestampFile(
archiveDir, markFile.decoder().version(), version))
{
final File newFile = new File(archiveDir, CATALOG_FILE_NAME + ".updated");
IoUtil.deleteIfExists(newFile);
final Path updatedCatalogFile = newFile.toPath();
try (FileChannel channel = FileChannel.open(updatedCatalogFile, READ, WRITE, CREATE_NEW))
{
final MappedByteBuffer mappedByteBuffer = channel.map(READ_WRITE, 0, MAX_CATALOG_LENGTH);
mappedByteBuffer.order(LITTLE_ENDIAN);
final int offset;
try
{
offset = migrateCatalogFile(catalog, version, mappedByteBuffer);
}
finally
{
BufferUtil.free(mappedByteBuffer);
}
channel.truncate(offset); // trim file to actual length used
}
catalog.close();
final Path catalogFilePath = updatedCatalogFile.resolveSibling(CATALOG_FILE_NAME);
Files.delete(catalogFilePath);
Files.move(updatedCatalogFile, catalogFilePath);
markFile.encoder().version(version);
}
catch (final IOException ex)
{
LangUtil.rethrowUnchecked(ex);
}
}
/**
* {@inheritDoc}
*/
public String toString()
{
return "to " + fullVersionString(minimumVersion());
}
private int migrateCatalogFile(final Catalog catalog, final int version, final MappedByteBuffer mappedByteBuffer)
{
final UnsafeBuffer buffer = new UnsafeBuffer(mappedByteBuffer);
final int alignment = CACHE_LINE_LENGTH;
// Create CatalogHeader for version 3.0.0
final int catalogHeaderLength =
writeCatalogHeader(buffer, version, catalog.nextRecordingId(), alignment);
final MutableInteger offset = new MutableInteger(catalogHeaderLength);
catalog.forEach(
(recordingDescriptorOffset, headerEncoder, headerDecoder, descriptorEncoder, descriptorDecoder) ->
{
final int strippedChannelLength = descriptorDecoder.strippedChannelLength();
descriptorDecoder.skipStrippedChannel();
final int originalChannelLength = descriptorDecoder.originalChannelLength();
descriptorDecoder.skipOriginalChannel();
final int sourceIdentityLength = descriptorDecoder.sourceIdentityLength();
final int frameLength =
align(DESCRIPTOR_HEADER_LENGTH + 7 * SIZE_OF_LONG + 6 * SIZE_OF_INT +
SIZE_OF_INT + strippedChannelLength +
SIZE_OF_INT + originalChannelLength +
SIZE_OF_INT + sourceIdentityLength,
alignment);
final DirectBuffer srcBuffer = headerDecoder.buffer();
final int headerLength = headerDecoder.encodedLength();
// Copy recording header
int index = offset.get();
buffer.putBytes(
index,
srcBuffer,
0,
headerLength);
index += headerLength;
// Correct length
buffer.putInt(offset.get(), frameLength - headerLength, LITTLE_ENDIAN);
// Copy recording descriptor
buffer.putBytes(
index,
srcBuffer,
headerLength,
frameLength - headerLength);
offset.addAndGet(frameLength);
});
return offset.get();
}
private int writeCatalogHeader(
final UnsafeBuffer buffer, final int version, final long nextRecordingId, final int alignment)
{
final int catalogHeaderLength = 32;
int index = 0;
buffer.putInt(index, version, LITTLE_ENDIAN); // version
index += SIZE_OF_INT;
buffer.putInt(index, catalogHeaderLength, LITTLE_ENDIAN); // length
index += SIZE_OF_INT;
buffer.putLong(index, nextRecordingId, LITTLE_ENDIAN); // nextRecordingId
index += SIZE_OF_LONG;
buffer.putInt(index, alignment, LITTLE_ENDIAN); // alignment
return catalogHeaderLength;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy