All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.aeron.cluster.IngressAdapter Maven / Gradle / Ivy

There is a newer version: 1.48.0
Show newest version
/*
 * 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.cluster;

import io.aeron.ControlledFragmentAssembler;
import io.aeron.Subscription;
import io.aeron.cluster.client.AeronCluster;
import io.aeron.cluster.codecs.*;
import io.aeron.logbuffer.ControlledFragmentHandler;
import io.aeron.logbuffer.Header;
import org.agrona.DirectBuffer;
import org.agrona.collections.ArrayUtil;

class IngressAdapter implements ControlledFragmentHandler, AutoCloseable
{
    private final int fragmentPollLimit;
    private final MessageHeaderDecoder messageHeaderDecoder = new MessageHeaderDecoder();
    private final SessionConnectRequestDecoder connectRequestDecoder = new SessionConnectRequestDecoder();
    private final SessionCloseRequestDecoder closeRequestDecoder = new SessionCloseRequestDecoder();
    private final SessionMessageHeaderDecoder sessionMessageHeaderDecoder = new SessionMessageHeaderDecoder();
    private final SessionKeepAliveDecoder sessionKeepAliveDecoder = new SessionKeepAliveDecoder();
    private final ChallengeResponseDecoder challengeResponseDecoder = new ChallengeResponseDecoder();
    private final AdminRequestDecoder adminRequestDecoder = new AdminRequestDecoder();
    private final ControlledFragmentAssembler fragmentAssembler = new ControlledFragmentAssembler(this);
    private final ConsensusModuleAgent consensusModuleAgent;
    private Subscription subscription;
    private Subscription ipcSubscription;

    IngressAdapter(final int fragmentPollLimit, final ConsensusModuleAgent consensusModuleAgent)
    {
        this.fragmentPollLimit = fragmentPollLimit;
        this.consensusModuleAgent = consensusModuleAgent;
    }

    public void close()
    {
        final Subscription subscription = this.subscription;
        final Subscription ipcSubscription = this.ipcSubscription;

        this.subscription = null;
        this.ipcSubscription = null;

        if (null != subscription)
        {
            subscription.close();
        }

        if (null != ipcSubscription)
        {
            ipcSubscription.close();
        }

        fragmentAssembler.clear();
    }

    @SuppressWarnings("MethodLength")
    public Action onFragment(final DirectBuffer buffer, final int offset, final int length, final Header header)
    {
        messageHeaderDecoder.wrap(buffer, offset);

        final int schemaId = messageHeaderDecoder.schemaId();
        final int templateId = messageHeaderDecoder.templateId();
        final int actingVersion = messageHeaderDecoder.version();
        final int actingBlockLength = messageHeaderDecoder.blockLength();
        if (schemaId != MessageHeaderDecoder.SCHEMA_ID)
        {
            return consensusModuleAgent.onExtensionMessage(
                actingBlockLength, templateId, schemaId, actingVersion, buffer, offset, length, header);
        }

        if (templateId == SessionMessageHeaderDecoder.TEMPLATE_ID)
        {
            sessionMessageHeaderDecoder.wrap(
                buffer,
                offset + MessageHeaderDecoder.ENCODED_LENGTH,
                messageHeaderDecoder.blockLength(),
                actingVersion);

            return consensusModuleAgent.onIngressMessage(
                sessionMessageHeaderDecoder.leadershipTermId(),
                sessionMessageHeaderDecoder.clusterSessionId(),
                buffer,
                offset + AeronCluster.SESSION_HEADER_LENGTH,
                length - AeronCluster.SESSION_HEADER_LENGTH);
        }

        switch (templateId)
        {
            case SessionConnectRequestDecoder.TEMPLATE_ID:
            {
                connectRequestDecoder.wrap(
                    buffer,
                    offset + MessageHeaderDecoder.ENCODED_LENGTH,
                    messageHeaderDecoder.blockLength(),
                    actingVersion);

                final String responseChannel = connectRequestDecoder.responseChannel();
                final int credentialsLength = connectRequestDecoder.encodedCredentialsLength();
                byte[] credentials = ArrayUtil.EMPTY_BYTE_ARRAY;
                if (credentialsLength > 0)
                {
                    credentials = new byte[credentialsLength];
                    connectRequestDecoder.getEncodedCredentials(credentials, 0, credentialsLength);
                }

                consensusModuleAgent.onSessionConnect(
                    connectRequestDecoder.correlationId(),
                    connectRequestDecoder.responseStreamId(),
                    connectRequestDecoder.version(),
                    responseChannel,
                    credentials);
                break;
            }

            case SessionCloseRequestDecoder.TEMPLATE_ID:
            {
                closeRequestDecoder.wrap(
                    buffer,
                    offset + MessageHeaderDecoder.ENCODED_LENGTH,
                    messageHeaderDecoder.blockLength(),
                    actingVersion);

                consensusModuleAgent.onSessionClose(
                    closeRequestDecoder.leadershipTermId(),
                    closeRequestDecoder.clusterSessionId());
                break;
            }

            case SessionKeepAliveDecoder.TEMPLATE_ID:
            {
                sessionKeepAliveDecoder.wrap(
                    buffer,
                    offset + MessageHeaderDecoder.ENCODED_LENGTH,
                    messageHeaderDecoder.blockLength(),
                    actingVersion);

                consensusModuleAgent.onSessionKeepAlive(
                    sessionKeepAliveDecoder.leadershipTermId(),
                    sessionKeepAliveDecoder.clusterSessionId());
                break;
            }

            case ChallengeResponseDecoder.TEMPLATE_ID:
            {
                challengeResponseDecoder.wrap(
                    buffer,
                    offset + MessageHeaderDecoder.ENCODED_LENGTH,
                    messageHeaderDecoder.blockLength(),
                    actingVersion);

                final byte[] credentials = new byte[challengeResponseDecoder.encodedCredentialsLength()];
                challengeResponseDecoder.getEncodedCredentials(credentials, 0, credentials.length);

                consensusModuleAgent.onIngressChallengeResponse(
                    challengeResponseDecoder.correlationId(),
                    challengeResponseDecoder.clusterSessionId(),
                    credentials);
                break;
            }

            case AdminRequestDecoder.TEMPLATE_ID:
            {
                adminRequestDecoder.wrap(
                    buffer,
                    offset + MessageHeaderDecoder.ENCODED_LENGTH,
                    messageHeaderDecoder.blockLength(),
                    actingVersion);

                final int payloadOffset = adminRequestDecoder.offset() +
                    adminRequestDecoder.encodedLength() +
                    AdminRequestDecoder.payloadHeaderLength();
                consensusModuleAgent.onAdminRequest(
                    adminRequestDecoder.leadershipTermId(),
                    adminRequestDecoder.clusterSessionId(),
                    adminRequestDecoder.correlationId(),
                    adminRequestDecoder.requestType(),
                    buffer,
                    payloadOffset,
                    adminRequestDecoder.payloadLength());
                break;
            }
        }

        return Action.CONTINUE;
    }

    void connect(final Subscription subscription, final Subscription ipcSubscription)
    {
        this.subscription = subscription;
        this.ipcSubscription = ipcSubscription;
    }

    int poll()
    {
        int fragmentsRead = 0;

        if (null != subscription)
        {
            fragmentsRead += subscription.controlledPoll(fragmentAssembler, fragmentPollLimit);
        }

        if (null != ipcSubscription)
        {
            fragmentsRead += ipcSubscription.controlledPoll(fragmentAssembler, fragmentPollLimit);
        }

        return fragmentsRead;
    }

    void freeSessionBuffer(final int imageSessionId)
    {
        fragmentAssembler.freeSessionBuffer(imageSessionId);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy