Search code examples
aeron

Why in the case of Aeron Archive I am unable to specify directory for media driver?


I am trying to setup a standalone aeron archive media driver. This will be used by my publisher clients as well as subscribers. I intend to have two directional publish/subscribe agents per process that will connect to aeron.

While, setting up the mediadriver, if I let the mediadriver choose default directory (note: I am running locally on mac). It works fine. I am able to specify archive directory and that works.

Here is the code that works:

    public void init() {
        final String controlChannel = AERON_UDP_ENDPOINT + config.getHost() + ":" + config.getControlPort();
        final String replicationChannel = AERON_UDP_ENDPOINT + config.getHost() + ":" + config.getReplicationPort();
        final String recordingEventsChannel =
                "aeron:udp?control-mode=dynamic|control=" + config.getHost() + ":" + config.getEventsPort();

        LOGGER.info("Starting MediaDriver with control channel: {}, replication channel: {}, recording events channel: {}",
                controlChannel, replicationChannel, recordingEventsChannel);

        final var archiveContext = new Archive.Context()
                .deleteArchiveOnStart(true)
                .errorHandler(ArchieveMediaDriverService::errorHandler)
                .controlChannel(controlChannel)
                .replicationChannel(replicationChannel)
                .recordingEventsChannel(recordingEventsChannel)
                .idleStrategySupplier(SleepingMillisIdleStrategy::new)
                .threadingMode(ArchiveThreadingMode.SHARED)
                .archiveDir(new File(config.getAeronDirectoryName()));

        final var mediaDriverContext = new MediaDriver.Context()
                .spiesSimulateConnection(true)
                .errorHandler(ArchieveMediaDriverService::errorHandler)
                .threadingMode(ThreadingMode.SHARED)
                .sharedIdleStrategy(new SleepingMillisIdleStrategy())
                .dirDeleteOnStart(true);

        ArchivingMediaDriver.launch(mediaDriverContext, archiveContext);
        LOGGER.info("Media driver is ready.");

        aeron = Aeron.connect();
        LOGGER.info("Connected to Aeron {}", aeron.context());

        // Connect to AeronArchive
        aeronArchive = AeronArchive.connect(
                new AeronArchive.Context()
                        .aeron(aeron)
                        .controlRequestChannel(controlChannel)
                        .controlResponseChannel(replicationChannel)
        );
        LOGGER.info("MediaDriver is up and running");

        // Keep the MediaDriver running until the application is stopped
        Runtime.getRuntime().addShutdownHook(new Thread(this::stop));
    }

But if we set the directory to the same one as aeron archive directory, it gives a FATAL error saying cannot create CnC file.

        final var mediaDriverContext = new MediaDriver.Context()
                .spiesSimulateConnection(true)
                .aeronDirectoryName(config.getAeronDirectoryName())
                .errorHandler(ArchieveMediaDriverService::errorHandler)
                .threadingMode(ThreadingMode.SHARED)
                .sharedIdleStrategy(new SleepingMillisIdleStrategy())
                .dirDeleteOnStart(true);

The driver would timeout giving error: Caused by: io.aeron.exceptions.DriverTimeoutException: FATAL - CnC file not created: /Users/user/dev/optradex/optradex-engine/resources/archiveDataFolder/cnc.dat

However, if I change the directory to a different directory than the archive folder, it works. But there is a FATAL error. It turns out to be a warning as the system works.

Here is the exception:

Caused by: io.aeron.exceptions.DriverTimeoutException: FATAL - no driver heartbeat detected
    at io.aeron.Aeron$Context.connectToDriver(Aeron.java:1563) ~[aeron-all-1.37.0.jar:1.37.0]
    at io.aeron.Aeron$Context.conclude(Aeron.java:790) ~[aeron-all-1.37.0.jar:1.37.0]
    at io.aeron.Aeron.<init>(Aeron.java:83) ~[aeron-all-1.37.0.jar:1.37.0]
    at io.aeron.Aeron.connect(Aeron.java:139) ~[aeron-all-1.37.0.jar:1.37.0]
    at io.aeron.Aeron.connect(Aeron.java:121) ~[aeron-all-1.37.0.jar:1.37.0]
    at com.xac.archivemediadriver.service.ArchieveMediaDriverService.init(ArchieveMediaDriverService.java:71) ~[main/:na]
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMethod.invoke(InitDestroyAnnotationBeanPostProcessor.java:457) ~[spring-beans-6.0.17.jar:6.0.17]
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:401) ~[spring-beans-6.0.17.jar:6.0.17]
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:219) ~[spring-beans-6.0.17.jar:6.0.17]
    ... 17 common frames omitted

I am trying to configure the archive directory as well as the mediadriver cnc file directory. Normally, mediadriver allows me when it is not an archive instance. I am assuming I am missing some documentation here. Hence raising this question.

SOLUTION: I think I have found the solution. The directory for archive and aeron needs to be different. Otherwise we will get FATAL error that cnc file cannot be created. The second timeout issue was resolved when I pointed Aeron.connect to use the same directory.

aeron = Aeron.connect(new Aeron.Context().aeronDirectoryName(config.getAeronDirectoryName()));

Solution

  • For the best performance of the Media Driver you should make sure that the Aeron directory is using an in-memory filesystem, e.g. /dev/shm on Linux or a RAM disk on Mac. Storing the Aeron directory and the Archive directory in the same place is not recommended.