/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 * * http://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 org.apache.ignite.internal.util.nio.impl; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.util.concurrent.atomic.AtomicReference; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteException; import org.apache.ignite.internal.util.lang.GridMetadataAwareAdapter; import org.apache.ignite.internal.util.nio.GridNioFilterAdapter; import org.apache.ignite.internal.util.nio.GridNioFilterChain; import org.apache.ignite.internal.util.nio.GridNioFinishedFuture; import org.apache.ignite.internal.util.nio.GridNioFuture; import org.apache.ignite.internal.util.nio.GridNioRecoveryDescriptor; import org.apache.ignite.internal.util.nio.GridNioServerListener; import org.apache.ignite.internal.util.nio.GridNioServerListenerAdapter; import org.apache.ignite.internal.util.nio.GridNioSession; import org.apache.ignite.lang.IgniteInClosure; import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; import org.jetbrains.annotations.Nullable; /** * Tests filter chain event processing. */ public class GridNioFilterChainSelfTest extends GridCommonAbstractTest { /** Session opened event meta name. */ private static final int OPENED_META_NAME = 11; /** Session closed event meta name. */ private static final int CLOSED_META_NAME = 12; /** Exception caught. */ private static final int EXCEPTION_CAUGHT_META_NAME = 13; /** Message received event meta name. */ private static final int MESSAGE_RECEIVED_META_NAME = 14; /** Message write event meta name. */ private static final int MESSAGE_WRITE_META_NAME = 15; /** Session close event meta name. */ private static final int CLOSE_META_NAME = 16; /** Session idle timeout meta name. */ private static final int IDLE_META_NAME = 17; /** Session write timeout meta name. */ private static final int WRITE_TIMEOUT_META_NAME = 18; /** * @throws Exception If failed. */ public void testChainEvents() throws Exception { final AtomicReference<String> connectedEvt = new AtomicReference<>(); final AtomicReference<String> disconnectedEvt = new AtomicReference<>(); final AtomicReference<String> msgEvt = new AtomicReference<>(); final AtomicReference<String> idleEvt = new AtomicReference<>(); final AtomicReference<String> writeTimeoutEvt = new AtomicReference<>(); final AtomicReference<String> sndEvt = new AtomicReference<>(); final AtomicReference<String> closeEvt = new AtomicReference<>(); final AtomicReference<ByteBuffer> rcvdMsgObj = new AtomicReference<>(); final AtomicReference<Object> sndMsgObj = new AtomicReference<>(); GridNioServerListener<Object> testLsnr = new GridNioServerListenerAdapter<Object>() { @Override public void onConnected(GridNioSession ses) { connectedEvt.compareAndSet(null, ses.<String>meta(OPENED_META_NAME)); } @Override public void onDisconnected(GridNioSession ses, @Nullable Exception e) { disconnectedEvt.compareAndSet(null, ses.<String>meta(CLOSED_META_NAME)); } @Override public void onMessage(GridNioSession ses, Object msg) { msgEvt.compareAndSet(null, ses.<String>meta(MESSAGE_RECEIVED_META_NAME)); rcvdMsgObj.compareAndSet(null, (ByteBuffer)msg); } @Override public void onSessionWriteTimeout(GridNioSession ses) { writeTimeoutEvt.compareAndSet(null, ses.<String>meta(WRITE_TIMEOUT_META_NAME)); } @Override public void onSessionIdleTimeout(GridNioSession ses) { idleEvt.compareAndSet(null, ses.<String>meta(IDLE_META_NAME)); } }; GridNioFilterAdapter testHead = new GridNioFilterAdapter("TestHead") { @Override public void onSessionOpened(GridNioSession ses) throws IgniteCheckedException { proceedSessionOpened(ses); } @Override public void onSessionClosed(GridNioSession ses) throws IgniteCheckedException { proceedSessionClosed(ses); } @Override public void onExceptionCaught(GridNioSession ses, IgniteCheckedException ex) throws IgniteCheckedException { proceedExceptionCaught(ses, ex); } @Override public GridNioFuture<?> onSessionWrite(GridNioSession ses, Object msg, boolean fut, IgniteInClosure<IgniteException> ackC) { sndEvt.compareAndSet(null, ses.<String>meta(MESSAGE_WRITE_META_NAME)); sndMsgObj.compareAndSet(null, msg); return null; } @Override public void onMessageReceived(GridNioSession ses, Object msg) throws IgniteCheckedException { proceedMessageReceived(ses, msg); } @Override public GridNioFuture<Boolean> onSessionClose(GridNioSession ses) { closeEvt.compareAndSet(null, ses.<String>meta(CLOSE_META_NAME)); return null; } @Override public void onSessionIdleTimeout(GridNioSession ses) throws IgniteCheckedException { proceedSessionIdleTimeout(ses); } @Override public void onSessionWriteTimeout(GridNioSession ses) throws IgniteCheckedException { proceedSessionWriteTimeout(ses); } }; GridNioFilterChain<Object> chain = new GridNioFilterChain<>(log, testLsnr, testHead, new AppendingFilter("A"), new AppendingFilter("B"), new AppendingFilter("C"), new AppendingFilter("D")); GridNioSession ses = new MockNioSession(); ByteBuffer snd = ByteBuffer.wrap(new byte[1]); ByteBuffer rcvd = ByteBuffer.wrap(new byte[1]); chain.onSessionOpened(ses); chain.onSessionClosed(ses); chain.onMessageReceived(ses, rcvd); chain.onSessionIdleTimeout(ses); chain.onSessionWriteTimeout(ses); assertNull(chain.onSessionClose(ses)); assertNull(chain.onSessionWrite(ses, snd, true, null)); assertEquals("DCBA", connectedEvt.get()); assertEquals("DCBA", disconnectedEvt.get()); assertEquals("DCBA", msgEvt.get()); assertEquals("DCBA", idleEvt.get()); assertEquals("DCBA", writeTimeoutEvt.get()); assertEquals("ABCD", sndEvt.get()); assertEquals("ABCD", closeEvt.get()); assertTrue(snd == sndMsgObj.get()); assertTrue(rcvd == rcvdMsgObj.get()); } /** * */ private static class AppendingFilter extends GridNioFilterAdapter { /** Param that will be appended to event trace. */ private String param; /** * Constructs test filter. * * @param param Filter parameter. */ private AppendingFilter(String param) { super(AppendingFilter.class.getSimpleName()); this.param = param; } /** {@inheritDoc} */ @Override public void onSessionOpened(GridNioSession ses) throws IgniteCheckedException { chainMeta(ses, OPENED_META_NAME); proceedSessionOpened(ses); } /** {@inheritDoc} */ @Override public void onSessionClosed(GridNioSession ses) throws IgniteCheckedException { chainMeta(ses, CLOSED_META_NAME); proceedSessionClosed(ses); } /** {@inheritDoc} */ @Override public void onExceptionCaught(GridNioSession ses, IgniteCheckedException ex) throws IgniteCheckedException { chainMeta(ses, EXCEPTION_CAUGHT_META_NAME); proceedExceptionCaught(ses, ex); } /** {@inheritDoc} */ @Override public GridNioFuture<?> onSessionWrite(GridNioSession ses, Object msg, boolean fut, IgniteInClosure<IgniteException> ackC) throws IgniteCheckedException { chainMeta(ses, MESSAGE_WRITE_META_NAME); return proceedSessionWrite(ses, msg, fut, ackC); } /** {@inheritDoc} */ @Override public void onMessageReceived(GridNioSession ses, Object msg) throws IgniteCheckedException { chainMeta(ses, MESSAGE_RECEIVED_META_NAME); proceedMessageReceived(ses, msg); } /** {@inheritDoc} */ @Override public GridNioFuture<Boolean> onSessionClose(GridNioSession ses) throws IgniteCheckedException { chainMeta(ses, CLOSE_META_NAME); return proceedSessionClose(ses); } /** {@inheritDoc} */ @Override public void onSessionIdleTimeout(GridNioSession ses) throws IgniteCheckedException { chainMeta(ses, IDLE_META_NAME); proceedSessionIdleTimeout(ses); } /** {@inheritDoc} */ @Override public void onSessionWriteTimeout(GridNioSession ses) throws IgniteCheckedException { chainMeta(ses, WRITE_TIMEOUT_META_NAME); proceedSessionWriteTimeout(ses); } /** {@inheritDoc} */ public String toString() { return "AppendingFilter [param=" + param + ']'; } /** * Appends parameter of this filter to a meta with specified name. * * @param ses Session. * @param metaKey Meta key. */ private void chainMeta(GridNioSession ses, int metaKey) { String att = ses.meta(metaKey); att = (att == null ? "" : att) + param; ses.addMeta(metaKey, att); } } /** */ public class MockNioSession extends GridMetadataAwareAdapter implements GridNioSession { /** Local address */ private InetSocketAddress locAddr = new InetSocketAddress(0); /** Remote address. */ private InetSocketAddress rmtAddr = new InetSocketAddress(0); /** * Creates empty mock session. */ public MockNioSession() { // No-op. } /** * Creates new mock session with given addresses. * * @param locAddr Local address. * @param rmtAddr Remote address. */ public MockNioSession(InetSocketAddress locAddr, InetSocketAddress rmtAddr) { this(); this.locAddr = locAddr; this.rmtAddr = rmtAddr; } /** {@inheritDoc} */ @Override public InetSocketAddress localAddress() { return locAddr; } /** {@inheritDoc} */ @Override public InetSocketAddress remoteAddress() { return rmtAddr; } /** {@inheritDoc} */ @Override public long bytesSent() { return 0; } /** {@inheritDoc} */ @Override public long bytesReceived() { return 0; } /** {@inheritDoc} */ @Override public long createTime() { return 0; } /** {@inheritDoc} */ @Override public long closeTime() { return 0; } /** {@inheritDoc} */ @Override public long lastReceiveTime() { return 0; } /** {@inheritDoc} */ @Override public long lastSendTime() { return 0; } /** {@inheritDoc} */ @Override public long lastSendScheduleTime() { return 0; } /** {@inheritDoc} */ @Override public GridNioFuture<Boolean> close() { return new GridNioFinishedFuture<>(true); } /** {@inheritDoc} */ @Override public GridNioFuture<?> send(Object msg) { return new GridNioFinishedFuture<>(true); } /** {@inheritDoc} */ @Override public void sendNoFuture(Object msg, IgniteInClosure<IgniteException> ackC) { // No-op. } /** {@inheritDoc} */ @Override public GridNioFuture<Object> resumeReads() { return null; } /** {@inheritDoc} */ @Override public GridNioFuture<Object> pauseReads() { return null; } /** {@inheritDoc} */ @Override public boolean accepted() { return false; } /** {@inheritDoc} */ @Override public boolean readsPaused() { return false; } /** {@inheritDoc} */ @Override public void outRecoveryDescriptor(GridNioRecoveryDescriptor recoveryDesc) { // No-op. } /** {@inheritDoc} */ @Nullable @Override public GridNioRecoveryDescriptor outRecoveryDescriptor() { return null; } /** {@inheritDoc} */ @Override public void inRecoveryDescriptor(GridNioRecoveryDescriptor recoveryDesc) { // No-op. } /** {@inheritDoc} */ @Nullable @Override public GridNioRecoveryDescriptor inRecoveryDescriptor() { return null; } /** {@inheritDoc} */ @Override public void systemMessage(Object msg) { // No-op. } } }