/* * 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.client; import java.net.InetAddress; import java.net.UnknownHostException; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.UUID; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteLogger; import org.apache.ignite.internal.client.marshaller.GridClientMarshaller; import org.apache.ignite.internal.client.marshaller.optimized.GridClientOptimizedMarshaller; import org.apache.ignite.internal.processors.rest.client.message.GridClientAuthenticationRequest; import org.apache.ignite.internal.processors.rest.client.message.GridClientHandshakeRequest; import org.apache.ignite.internal.processors.rest.client.message.GridClientHandshakeResponse; import org.apache.ignite.internal.processors.rest.client.message.GridClientMessage; import org.apache.ignite.internal.processors.rest.client.message.GridClientNodeBean; import org.apache.ignite.internal.processors.rest.client.message.GridClientPingPacket; import org.apache.ignite.internal.processors.rest.client.message.GridClientResponse; import org.apache.ignite.internal.processors.rest.client.message.GridClientTopologyRequest; import org.apache.ignite.internal.processors.rest.protocols.tcp.GridTcpRestParser; import org.apache.ignite.internal.util.nio.GridNioAsyncNotifyFilter; import org.apache.ignite.internal.util.nio.GridNioCodecFilter; import org.apache.ignite.internal.util.nio.GridNioServer; import org.apache.ignite.internal.util.nio.GridNioServerListenerAdapter; import org.apache.ignite.internal.util.nio.GridNioSession; import org.jetbrains.annotations.Nullable; /** * */ public class ClientTestRestServer { /** */ public static final int FIRST_SERVER_PORT = 11000; /** */ public static final int SERVERS_CNT = 5; /** */ private static final byte[] EMPTY_SES_TOKEN = new byte[] {}; /** */ private static final Collection<GridClientNodeBean> top = new ArrayList<>(); /** * */ static { for (int port = FIRST_SERVER_PORT; port < FIRST_SERVER_PORT + SERVERS_CNT; port++) { GridClientNodeBean node = new GridClientNodeBean(); node.setNodeId(UUID.randomUUID()); node.setConsistentId("127.0.0.1:" + port); node.setTcpPort(port); node.setTcpAddresses(Arrays.asList("127.0.0.1")); top.add(node); } } /** */ private final int port; /** */ private volatile boolean failOnConnect; /** */ private final IgniteLogger log; /** */ private final AtomicInteger connCnt = new AtomicInteger(); /** */ private final AtomicInteger succConnCnt = new AtomicInteger(); /** */ private final AtomicInteger disconnCnt = new AtomicInteger(); /** */ private GridNioServer<GridClientMessage> srv; /** */ private volatile GridNioSession lastSes; /** * @param port Port to listen on. * @param failOnConnect If {@code true} than server will close connection immediately after connect. * @param log Log. */ public ClientTestRestServer(int port, boolean failOnConnect, IgniteLogger log) { this.port = port; this.failOnConnect = failOnConnect; this.log = log; } /** * @return Port number. */ public int getPort() { return port; } /** * Starts the server. * * @throws IgniteCheckedException If failed. */ public void start() throws IgniteCheckedException { try { String igniteInstanceName = "test"; srv = GridNioServer.<GridClientMessage>builder() .address(InetAddress.getByName("127.0.0.1")) .port(port) .listener(new TestListener()) .logger(log) .selectorCount(2) .igniteInstanceName(igniteInstanceName) .byteOrder(ByteOrder.nativeOrder()) .tcpNoDelay(true) .directBuffer(false) .filters( new GridNioAsyncNotifyFilter(igniteInstanceName, Executors.newFixedThreadPool(2), log), new GridNioCodecFilter(new TestParser(), log, false) ) .build(); } catch (UnknownHostException e) { throw new IgniteCheckedException("Failed to determine localhost address.", e); } srv.start(); } /** * Stops the server. */ public void stop() { assert srv != null; srv.stop(); } /** * @return Number of connections opened to this server. */ public int getConnectCount() { return connCnt.get(); } /** * @return Number of successful connections opened to this server. */ public int getSuccessfulConnectCount() { return succConnCnt.get(); } /** * @return Number of connections with this server closed by clients. */ public int getDisconnectCount() { return disconnCnt.get(); } /** * Closes all opened connections. */ public void fail() { assert lastSes != null; lastSes.close(); failOnConnect = true; resetCounters(); } /** * */ public void repair() { failOnConnect = false; } /** * Resets all counters. */ public void resetCounters() { connCnt.set(0); succConnCnt.set(0); disconnCnt.set(0); } /** * Prepares response stub. * @param msg Mesage to respond to. * @return Response. */ private static GridClientResponse makeResponseFor(GridClientMessage msg) { GridClientResponse res = new GridClientResponse(); res.clientId(msg.clientId()); res.requestId(msg.requestId()); res.successStatus(GridClientResponse.STATUS_SUCCESS); res.sessionToken(EMPTY_SES_TOKEN); return res; } /** * Test listener. */ private class TestListener extends GridNioServerListenerAdapter<GridClientMessage> { /** {@inheritDoc} */ @Override public void onConnected(GridNioSession ses) { lastSes = ses; connCnt.incrementAndGet(); if (failOnConnect) ses.close(); else succConnCnt.incrementAndGet(); } /** {@inheritDoc} */ @Override public void onDisconnected(GridNioSession ses, @Nullable Exception e) { disconnCnt.incrementAndGet(); } /** {@inheritDoc} */ @Override public void onMessage(GridNioSession ses, GridClientMessage msg) { if (msg == GridClientPingPacket.PING_MESSAGE) ses.send(GridClientPingPacket.PING_MESSAGE); else if (msg instanceof GridClientAuthenticationRequest) ses.send(makeResponseFor(msg)); else if (msg instanceof GridClientTopologyRequest) { GridClientResponse res = makeResponseFor(msg); res.result(top); ses.send(res); } else if (msg instanceof GridClientHandshakeRequest) ses.send(GridClientHandshakeResponse.OK); } /** {@inheritDoc} */ @Override public void onSessionWriteTimeout(GridNioSession ses) { ses.close(); } /** {@inheritDoc} */ @Override public void onSessionIdleTimeout(GridNioSession ses) { ses.close(); } } /** */ private static class TestParser extends GridTcpRestParser { /** */ private final GridClientMarshaller marsh = new GridClientOptimizedMarshaller(); /** */ public TestParser() { super(false); } /** {@inheritDoc} */ @Override protected GridClientMarshaller marshaller(GridNioSession ses) { return marsh; } } }