/*
 * 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;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import org.apache.ignite.GridTestTask;
import org.apache.ignite.Ignite;
import org.apache.ignite.cluster.ClusterGroupEmptyException;
import org.apache.ignite.cluster.ClusterMetrics;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.events.DiscoveryEvent;
import org.apache.ignite.events.Event;
import org.apache.ignite.events.EventType;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.G;
import org.apache.ignite.lang.IgnitePredicate;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.apache.ignite.testframework.junits.common.GridCommonTest;
import org.junit.Test;

import static org.apache.ignite.events.EventType.EVT_JOB_FINISHED;
import static org.apache.ignite.events.EventType.EVT_NODE_METRICS_UPDATED;

/**
 * Tests for projection metrics.
 */
@GridCommonTest(group = "Kernal Self")
public class ClusterMetricsSelfTest extends GridCommonAbstractTest {
    /** */
    private static final int NODES_CNT = 4;

    /** */
    private static final int ITER_CNT = 10;

    /** {@inheritDoc} */
    @Override protected void beforeTestsStarted() throws Exception {
        for (int i = 0; i < NODES_CNT; i++)
            startGrid(i);
    }

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

        cfg.setCacheConfiguration();
        cfg.setIncludeProperties();
        cfg.setIncludeEventTypes(EventType.EVTS_ALL);

        return cfg;
    }

    /**
     * @throws Exception In case of error.
     */
    @Test
    public void testEmptyProjection() throws Exception {
        try {
            grid(0).cluster().forPredicate(F.<ClusterNode>alwaysFalse()).metrics();

            assert false;
        }
        catch (ClusterGroupEmptyException e) {
            info("Caught expected exception: " + e);
        }
    }

    /**
     *
     */
    @Test
    public void testTaskExecution() {
        for (int i = 0; i < ITER_CNT; i++) {
            info("Starting new iteration: " + i);

            try {
                performTaskExecutionTest();
            }
            catch (Throwable t) {
                error("Iteration failed: " + i, t);

                fail("Test failed (see logs for details).");
            }
        }
    }

    /**
     * @throws Exception In case of error.
     */
    private void performTaskExecutionTest() throws Exception {
        Ignite g = grid(0);

        JobFinishLock jobFinishLock = new JobFinishLock();

        MetricsUpdateLock metricsUpdLock = new MetricsUpdateLock();

        try {
            for (Ignite g0 : G.allGrids())
                g0.events().localListen(jobFinishLock, EVT_JOB_FINISHED);

            g.compute().execute(new GridTestTask(), "testArg");

            // Wait until all nodes fire JOB FINISH event.
            jobFinishLock.await();

            g.events().localListen(metricsUpdLock, EVT_NODE_METRICS_UPDATED);

            // Wait until local node will have updated metrics.
            metricsUpdLock.await();

            ClusterMetrics m = g.cluster().metrics();

            checkMetrics(m);
        }
        finally {
            for (Ignite g0 : G.allGrids())
                g0.events().stopLocalListen(jobFinishLock);

            g.events().stopLocalListen(metricsUpdLock);
        }
    }

    /**
     * @param m Metrics.
     */
    @SuppressWarnings({"FloatingPointEquality"})
    private void checkMetrics(ClusterMetrics m) {
        assert m.getTotalNodes() == NODES_CNT;

        assert m.getMaximumActiveJobs() >= 0;
        assert m.getAverageActiveJobs() >= 0;

        assert m.getMaximumCancelledJobs() == 0;
        assert m.getAverageCancelledJobs() == 0;

        assert m.getMaximumRejectedJobs() == 0;
        assert m.getAverageRejectedJobs() == 0;

        assert m.getMaximumWaitingJobs() == 0;
        assert m.getAverageWaitingJobs() == 0;

        assert m.getMaximumJobExecuteTime() >= 0;
        assert m.getAverageJobExecuteTime() >= 0;

        assert m.getAverageJobExecuteTime() <= m.getMaximumJobExecuteTime();

        assert m.getMaximumJobWaitTime() >= 0;
        assert m.getAverageJobWaitTime() >= 0;

        assert m.getAverageJobWaitTime() <= m.getMaximumJobWaitTime();

        assert m.getMaximumThreadCount() > 0;
        assert m.getIdleTimePercentage() >= 0;
        assert m.getIdleTimePercentage() <= 100;

        assert m.getAverageCpuLoad() >= 0 || m.getAverageCpuLoad() == -1.0;

        assert m.getTotalCpus() > 0;
    }

    /**
     *
     */
    private static class JobFinishLock implements IgnitePredicate<Event> {
        /** Latch. */
        private final CountDownLatch latch = new CountDownLatch(NODES_CNT);

        /** {@inheritDoc} */
        @Override public boolean apply(Event evt) {
            assert evt.type() == EVT_JOB_FINISHED;

            latch.countDown();

            return true;
        }

        /**
         * Waits until all nodes fire EVT_JOB_FINISHED.
         *
         * @throws InterruptedException If interrupted.
         */
        public void await() throws InterruptedException {
            latch.await();
        }
    }

    /**
     *
     */
    private static class MetricsUpdateLock implements IgnitePredicate<Event> {
        /** Latch. */
        private final CountDownLatch latch = new CountDownLatch(NODES_CNT * 2);

        /** */
        private final Map<UUID, Integer> metricsRcvdCnt = new HashMap<>();

        /** {@inheritDoc} */
        @Override public boolean apply(Event evt) {
            DiscoveryEvent discoEvt = (DiscoveryEvent)evt;

            Integer cnt = F.addIfAbsent(metricsRcvdCnt, discoEvt.eventNode().id(), 0);

            assert cnt != null;

            if (cnt < 2) {
                latch.countDown();

                metricsRcvdCnt.put(discoEvt.eventNode().id(), ++cnt);
            }

            return true;
        }

        /**
         * Waits until all metrics will be received twice from all nodes in
         * topology.
         *
         * @throws InterruptedException If interrupted.
         */
        public void await() throws InterruptedException {
            latch.await();
        }
    }
}
