/*
 * 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.processors.service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.internal.IgniteEx;
import org.apache.ignite.internal.util.lang.GridAbsPredicateX;
import org.apache.ignite.services.ServiceConfiguration;
import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
import org.apache.ignite.testframework.GridTestUtils;
import org.junit.Test;

/**
 * Single node services test.
 */
public class GridServiceProcessorMultiNodeConfigSelfTest extends GridServiceProcessorAbstractSelfTest {
    /** Cluster singleton name. */
    private static final String CLUSTER_SINGLE = "serviceConfigSingleton";

    /** Node singleton name. */
    private static final String NODE_SINGLE = "serviceConfigEachNode";

    /** Node singleton name. */
    private static final String NODE_SINGLE_BUT_CLIENT = "serviceConfigEachNodeButClient";

    /** Node singleton name. */
    private static final String NODE_SINGLE_WITH_LIMIT = "serviceConfigWithLimit";

    /** Affinity service name. */
    private static final String AFFINITY = "serviceConfigAffinity";

    /** Affinity key. */
    private static final Integer AFFINITY_KEY = 1;

    /** {@inheritDoc} */
    @Override protected int nodeCount() {
        return 4;
    }

    /** {@inheritDoc} */
    @Override protected ServiceConfiguration[] services() {

        ServiceConfiguration cfg = new ServiceConfiguration();

        cfg.setName(CLUSTER_SINGLE);
        cfg.setMaxPerNodeCount(1);
        cfg.setTotalCount(1);
        cfg.setService(new DummyService());

        List<ServiceConfiguration> cfgs = new ArrayList<>();

        cfgs.add(cfg);

        cfg = new ServiceConfiguration();

        cfg.setName(NODE_SINGLE_BUT_CLIENT);
        cfg.setMaxPerNodeCount(1);
        cfg.setService(new DummyService());

        cfgs.add(cfg);

        cfg = new ServiceConfiguration();

        cfg.setName(AFFINITY);
        cfg.setCacheName(CACHE_NAME);
        cfg.setAffinityKey(AFFINITY_KEY);
        cfg.setMaxPerNodeCount(1);
        cfg.setTotalCount(1);
        cfg.setService(new AffinityService(AFFINITY_KEY));

        cfgs.add(cfg);

        cfg = new ServiceConfiguration();

        cfg.setName(NODE_SINGLE);
        cfg.setMaxPerNodeCount(1);
        cfg.setNodeFilter(new CacheConfiguration.IgniteAllNodesPredicate());
        cfg.setService(new DummyService());

        cfgs.add(cfg);

        cfg = new ServiceConfiguration();

        cfg.setName(NODE_SINGLE_WITH_LIMIT);
        cfg.setMaxPerNodeCount(1);
        cfg.setTotalCount(nodeCount() + 1);
        cfg.setService(new DummyService());

        cfgs.add(cfg);

        return cfgs.toArray(new ServiceConfiguration[cfgs.size()]);
    }

    /** {@inheritDoc} */
    @Override protected IgniteConfiguration getConfiguration(final String igniteInstanceName) throws Exception {
        final IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);

        ((TcpCommunicationSpi)cfg.getCommunicationSpi()).setIdleConnectionTimeout(10000);

        return cfg;
    }

    /** {@inheritDoc} */
    @Override protected void beforeTestsStarted() throws Exception {
        super.beforeTestsStarted();

        GridTestUtils.waitForCondition(
            new GridAbsPredicateX() {
                @Override public boolean applyx() {
                    return
                        DummyService.started(CLUSTER_SINGLE) == 1 &&
                        DummyService.cancelled(CLUSTER_SINGLE) == 0 &&
                        DummyService.started(NODE_SINGLE) == nodeCount() &&
                        DummyService.cancelled(NODE_SINGLE) == 0 &&
                        DummyService.started(NODE_SINGLE_BUT_CLIENT) == nodeCount() &&
                        DummyService.cancelled(NODE_SINGLE_BUT_CLIENT) == 0 &&
                        DummyService.started(NODE_SINGLE_WITH_LIMIT) >= nodeCount() &&
                        DummyService.cancelled(NODE_SINGLE_WITH_LIMIT) == 0 &&
                        actualCount(AFFINITY, randomGrid().services().serviceDescriptors()) == 1;
                }
            },
            2000
        );
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testSingletonUpdateTopology() throws Exception {
        checkSingletonUpdateTopology(CLUSTER_SINGLE);
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testDeployOnEachNodeUpdateTopology() throws Exception {
        checkDeployOnEachNodeUpdateTopology(NODE_SINGLE);
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testDeployOnEachNodeButClientUpdateTopology() throws Exception {
        checkDeployOnEachNodeButClientUpdateTopology(NODE_SINGLE_BUT_CLIENT);
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testAll() throws Exception {
        checkSingletonUpdateTopology(CLUSTER_SINGLE);

        DummyService.reset();

        checkDeployOnEachNodeButClientUpdateTopology(NODE_SINGLE_BUT_CLIENT);

        DummyService.reset();

        checkDeployOnEachNodeUpdateTopology(NODE_SINGLE);

        DummyService.reset();
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testAffinityUpdateTopology() throws Exception {
        IgniteEx g = randomGrid();

        checkCount(AFFINITY, g, 1);

        checkAffinityServiceDeployment(g, AFFINITY);

        int nodeCnt = 2;

        startExtraNodes(nodeCnt);

        try {
            checkCount(AFFINITY, g, 1);

            checkAffinityServiceDeployment(g, AFFINITY);
        }
        finally {
            stopExtraNodes(nodeCnt);
        }

        checkCount(AFFINITY, g, 1);

        checkAffinityServiceDeployment(g, AFFINITY);
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testDeployLimits() throws Exception {
        final IgniteEx g = randomGrid();

        final String name = NODE_SINGLE_WITH_LIMIT;

        waitForDeployment(name, nodeCount());

        checkCount(name, g, nodeCount());

        CountDownLatch latch = new CountDownLatch(1);

        DummyService.exeLatch(name, latch);

        int extraNodes = 2;

        startExtraNodes(extraNodes);

        try {
            latch.await();

            waitForDeployment(name, nodeCount() + 1);

            checkCount(name, g, nodeCount() + 1);
        }
        finally {
            stopExtraNodes(extraNodes);
        }

        waitForDeployment(name, nodeCount());

        // Service can be redeployed when nodes is stopping one-by-one.
        assertEquals(0, DummyService.started(name) - DummyService.cancelled(name));

        checkCount(name, g, nodeCount());
    }

    /**
     * @param name Name.
     * @throws Exception If failed.
     */
    private void checkSingletonUpdateTopology(String name) throws Exception {
        IgniteEx g = randomGrid();

        startExtraNodes(2, 2);

        try {
            assertEquals(name, 0, DummyService.started(name));
            assertEquals(name, 0, DummyService.cancelled(name));

            info(">>> Passed checks.");

            checkCount(name, g, 1);
        }
        finally {
            stopExtraNodes(4);
        }
    }

    /**
     * @param name Name.
     * @throws Exception If failed.
     */
    private void checkDeployOnEachNodeUpdateTopology(String name) throws Exception {
        IgniteEx g = randomGrid();

        int newNodes = 4;

        CountDownLatch latch = new CountDownLatch(newNodes);

        DummyService.exeLatch(name, latch);

        startExtraNodes(2, 2);

        try {
            latch.await();

            waitForDeployment(name, nodeCount() + newNodes);

            // Since we start extra nodes, there may be extra start and cancel events,
            // so we check only the difference between start and cancel and
            // not start and cancel events individually.
            assertEquals(name, newNodes, DummyService.started(name) - DummyService.cancelled(name));

            checkCount(name, g, nodeCount() + newNodes);
        }
        finally {
            stopExtraNodes(newNodes);
        }

        waitForDeployment(name, nodeCount());

        checkCount(name, g, nodeCount());
    }

    /**
     * @param name Name.
     * @throws Exception If failed.
     */
    private void checkDeployOnEachNodeButClientUpdateTopology(String name) throws Exception {
        IgniteEx g = randomGrid();

        int servers = 2;

        CountDownLatch latch = new CountDownLatch(servers);

        DummyService.exeLatch(name, latch);

        int clients = 2;

        startExtraNodes(servers, clients);

        try {
            latch.await();

            waitForDeployment(name, nodeCount() + servers);

            // Since we start extra nodes, there may be extra start and cancel events,
            // so we check only the difference between start and cancel and
            // not start and cancel events individually.
            assertEquals(name, servers, DummyService.started(name) - DummyService.cancelled(name));

            checkCount(name, g, nodeCount() + servers);
        }
        finally {
            stopExtraNodes(servers + clients);
        }

        waitForDeployment(name, nodeCount());

        checkCount(name, g, nodeCount());
    }
}
