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

import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.cache.affinity.Affinity;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.NearCacheConfiguration;
import org.apache.ignite.testframework.GridTestUtils.SF;
import org.apache.ignite.testframework.MvccFeatureChecker;
import org.junit.Assume;
import org.junit.Test;

import static org.apache.ignite.IgniteSystemProperties.IGNITE_ATOMIC_CACHE_DELETE_HISTORY_SIZE;
import static org.apache.ignite.cache.CacheMode.PARTITIONED;
import static org.apache.ignite.cache.CacheRebalanceMode.SYNC;
import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;

/**
 *
 */
public abstract class GridCacheValueConsistencyAbstractSelfTest extends GridCacheAbstractSelfTest {
    /** Number of threads for test. */
    private static final int THREAD_CNT = 16;

    /** */
    private String sizePropVal;

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

    /** {@inheritDoc} */
    @Override protected long getTestTimeout() {
        return 5 * 60_000;
    }

    /** {@inheritDoc} */
    @Override protected CacheConfiguration cacheConfiguration(String igniteInstanceName) throws Exception {
        CacheConfiguration cCfg = super.cacheConfiguration(igniteInstanceName);

        cCfg.setCacheMode(PARTITIONED);
        cCfg.setAtomicityMode(atomicityMode());
        cCfg.setNearConfiguration(nearConfiguration());
        cCfg.setRebalanceMode(SYNC);
        cCfg.setWriteSynchronizationMode(FULL_SYNC);
        cCfg.setBackups(1);

        return cCfg;
    }

    /** {@inheritDoc} */
    @Override protected void beforeTestsStarted() throws Exception {
        // Need to increase value set in GridAbstractTest
        sizePropVal = System.getProperty(IGNITE_ATOMIC_CACHE_DELETE_HISTORY_SIZE);

        System.setProperty(IGNITE_ATOMIC_CACHE_DELETE_HISTORY_SIZE, "100000");

        super.beforeTestsStarted();
    }

    /** {@inheritDoc} */
    @Override protected void beforeTest() throws Exception {
        MvccFeatureChecker.skipIfNotSupported(MvccFeatureChecker.Feature.CACHE_STORE);

        if (nearEnabled())
            MvccFeatureChecker.skipIfNotSupported(MvccFeatureChecker.Feature.NEAR_CACHE);
    }

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

        System.setProperty(IGNITE_ATOMIC_CACHE_DELETE_HISTORY_SIZE, sizePropVal != null ? sizePropVal : "");
    }

    /**
     * @return Distribution mode.
     */
    @Override protected NearCacheConfiguration nearConfiguration() {
        return null;
    }

    /**
     * @return Consistency test iteration count.
     */
    protected abstract int iterationCount();

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testPutRemove() throws Exception {
        awaitPartitionMapExchange();

        IgniteCache<String, Integer> cache = jcache();

        int keyCnt = 10;

        for (int i = 0; i < keyCnt; i++)
            cache.put("key" + i, i);

        for (int g = 0; g < gridCount(); g++) {
            IgniteCache<String, Integer> cache0 = jcache(g);
            ClusterNode locNode = grid(g).localNode();

            for (int i = 0; i < keyCnt; i++) {
                String key = "key" + i;

                if (ignite(0).affinity(DEFAULT_CACHE_NAME).mapKeyToPrimaryAndBackups(key).contains(locNode)) {
                    info("Node is reported as affinity node for key [key=" + key + ", nodeId=" + locNode.id() + ']');

                    assertEquals((Integer)i, cache0.localPeek(key));
                }
                else {
                    info("Node is reported as NOT affinity node for key [key=" + key +
                        ", nodeId=" + locNode.id() + ']');

                    if (nearEnabled() &&
                        ((IgniteCacheProxy)cache).context().equals(((IgniteCacheProxy)cache0).context()))
                        assertEquals((Integer)i, cache0.localPeek(key));
                    else
                        assertNull(cache0.localPeek(key));
                }

                assertEquals((Integer)i, cache0.get(key));
            }
        }

        info("Removing values from cache.");

        for (int i = 0; i < keyCnt; i++)
            assertEquals((Integer)i, cache.getAndRemove("key" + i));

        for (int g = 0; g < gridCount(); g++) {
            IgniteCache<String, Integer> cache0 = jcache(g);

            for (int i = 0; i < keyCnt; i++) {
                String key = "key" + i;

                assertNull(cache0.localPeek(key));

                assertNull(cache0.get(key));
            }
        }
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testPutRemoveAll() throws Exception {
        awaitPartitionMapExchange();

        IgniteCache<String, Integer> cache = jcache();

        int keyCnt = 10;

        for (int i = 0; i < keyCnt; i++) {
            info("Putting value to cache: " + i);

            cache.put("key" + i, i);
        }

        for (int g = 0; g < gridCount(); g++) {
            IgniteCache<String, Integer> cache0 = jcache(g);
            ClusterNode locNode = grid(g).localNode();

            for (int i = 0; i < keyCnt; i++) {
                String key = "key" + i;

                if (ignite(0).affinity(DEFAULT_CACHE_NAME).mapKeyToPrimaryAndBackups(key).contains(grid(g).localNode())) {
                    info("Node is reported as affinity node for key [key=" + key + ", nodeId=" + locNode.id() + ']');

                    assertEquals((Integer)i, cache0.localPeek(key));
                }
                else {
                    info("Node is reported as NOT affinity node for key [key=" + key +
                        ", nodeId=" + locNode.id() + ']');

                    if (nearEnabled() &&
                        ((IgniteCacheProxy)cache).context().equals(((IgniteCacheProxy)cache0).context()))
                        assertEquals((Integer)i, cache0.localPeek(key));
                    else
                        assertNull(cache0.localPeek(key));
                }

                assertEquals((Integer)i, cache0.get(key));
            }
        }

        for (int g = 0; g < gridCount(); g++) {
            info(">>>> Removing all values form cache: " + g);

            jcache(g).removeAll();
        }

        info(">>>> Starting values check");

        for (int g = 0; g < gridCount(); g++) {
            IgniteCache<String, Integer> cache0 = jcache(g);

            for (int i = 0; i < keyCnt; i++) {
                String key = "key" + i;

                assertNull(cache0.localPeek(key));
                assertNull(cache0.get(key));
            }
        }
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testPutConsistencyMultithreaded() throws Exception {
        Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-627", nearEnabled());

        for (int i = 0; i < 20; i++) {
            log.info("Iteration: " + i);

            final int range = 100;

            final int iterCnt = 100;

            final AtomicInteger threadId = new AtomicInteger();

            final AtomicInteger iters = new AtomicInteger();

            multithreadedAsync(new Callable<Object>() {
                @Override public Object call() throws Exception {
                    Random rnd = new Random();

                    int g = threadId.getAndIncrement();

                    Ignite ignite = grid(g);

                    IgniteCache<Object, Object> cache = ignite.cache(DEFAULT_CACHE_NAME);

                    log.info("Update thread: " + ignite.name());

                    Thread.currentThread().setName("UpdateThread-" + ignite.name());

                    Long val = (long)g;

                    while (true) {
                        int i = iters.getAndIncrement();

                        if (i >= iterCnt)
                            break;

                        int k = rnd.nextInt(range);

                        cache.put(k, val);
                    }

                    return null;
                }
            }, gridCount()).get();

            checkConsistency(range);
        }
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testPutRemoveConsistencyMultithreaded() throws Exception {
        Assume.assumeFalse("https://issues.apache.org/jira/browse/IGNITE-627", nearEnabled());

        for (int i = 0; i < SF.applyLB(10, 2); i++) {
            log.info("Iteration: " + i);

            putRemoveConsistencyMultithreaded();
        }
    }

    /**
     * @throws Exception If failed.
     */
    private void putRemoveConsistencyMultithreaded() throws Exception {
        final int range = 10_000;

        final int iterCnt = iterationCount();

        final AtomicInteger iters = new AtomicInteger();

        multithreadedAsync(new Callable<Object>() {
            @Override public Object call() throws Exception {
                Random rnd = new Random();

                while (true) {
                    int i = iters.getAndIncrement();

                    if (i >= iterCnt)
                        break;

                    int g = rnd.nextInt(gridCount());

                    Ignite ignite = grid(g);

                    IgniteCache<Object, Object> cache = ignite.cache(DEFAULT_CACHE_NAME);

                    int k = rnd.nextInt(range);

                    boolean rmv = rnd.nextBoolean();

                    if (!rmv)
                        cache.put(k, Thread.currentThread().getId());
                    else
                        cache.remove(k);

                    if (i > 0 && i % 5000 == 0)
                        info("Completed: " + i);
                }

                return null;
            }
        }, THREAD_CNT).get();

        checkConsistency(range);
    }

    /**
     * @param range Key range.
     */
    private void checkConsistency(int range) {
        int present = 0;
        int absent = 0;

        Affinity<Integer> aff = ignite(0).affinity(DEFAULT_CACHE_NAME);

        boolean invalidVal = false;

        for (int i = 0; i < range; i++) {
            Long firstVal = null;

            for (int g = 0; g < gridCount(); g++) {
                Ignite ignite = grid(g);

                Long val = (Long)ignite.cache(DEFAULT_CACHE_NAME).localPeek(i);

                if (firstVal == null && val != null)
                    firstVal = val;

                if (val != null) {
                    if (!firstVal.equals(val)) {
                        invalidVal = true;

                        boolean primary = aff.isPrimary(ignite.cluster().localNode(), i);
                        boolean backup = aff.isBackup(ignite.cluster().localNode(), i);

                        log.error("Invalid value detected [key=" + i +
                            ", val=" + val +
                            ", firstVal=" + firstVal +
                            ", node=" + g +
                            ", primary=" + primary +
                            ", backup=" + backup + ']');

                        log.error("All values: ");

                        printValues(aff, i);

                        break;
                    }
                }
            }

            if (firstVal == null)
                absent++;
            else
                present++;
        }

        assertFalse("Inconsistent value found.", invalidVal);

        info("Finished check [present=" + present + ", absent=" + absent + ']');

        info("Checking keySet consistency");

    }

    /**
     * @param aff Affinity.
     * @param key Key.
     */
    private void printValues(Affinity<Integer> aff, int key) {
        for (int g = 0; g < gridCount(); g++) {
            Ignite ignite = grid(g);

            boolean primary = aff.isPrimary(ignite.cluster().localNode(), key);
            boolean backup = aff.isBackup(ignite.cluster().localNode(), key);

            Object val = ignite.cache(DEFAULT_CACHE_NAME).localPeek(key);

            log.error("Node value [key=" + key +
                ", val=" + val +
                ", node=" + g +
                ", primary=" + primary +
                ", backup=" + backup + ']');
        }
    }
}
