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

import javax.cache.Cache;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.cache.CacheAtomicityMode;
import org.apache.ignite.cache.CacheMode;
import org.apache.ignite.cache.CacheWriteSynchronizationMode;
import org.apache.ignite.cache.eviction.fifo.FifoEvictionPolicy;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.configuration.NearCacheConfiguration;
import org.apache.ignite.configuration.TransactionConfiguration;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.testframework.MvccFeatureChecker;
import org.apache.ignite.testframework.MvccFeatureChecker.Feature;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.apache.ignite.transactions.Transaction;
import org.apache.ignite.transactions.TransactionConcurrency;
import org.apache.ignite.transactions.TransactionIsolation;
import org.junit.Test;

/**
 *
 */
public class IgniteCacheTxIteratorSelfTest extends GridCommonAbstractTest {
    /** */
    public static final String CACHE_NAME = "testCache";

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

        final TransactionConfiguration txCfg = new TransactionConfiguration();

        txCfg.setDefaultTxIsolation(TransactionIsolation.READ_COMMITTED);

        cfg.setTransactionConfiguration(txCfg);

        return cfg;
    }

    /**
     * @return Cache configuration.
     */
    private CacheConfiguration<String, TestClass> cacheConfiguration(
        CacheMode mode,
        CacheAtomicityMode atomMode,
        boolean nearEnabled,
        boolean useEvictPlc
    ) {
        final CacheConfiguration<String, TestClass> ccfg = new CacheConfiguration<>(CACHE_NAME);

        ccfg.setAtomicityMode(atomMode);
        ccfg.setCacheMode(mode);
        ccfg.setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC);

        if (nearEnabled)
            ccfg.setNearConfiguration(new NearCacheConfiguration<String, TestClass>());

        if (useEvictPlc) {
            ccfg.setEvictionPolicy(new FifoEvictionPolicy(50));
            ccfg.setOnheapCacheEnabled(true);
        }

        return ccfg;
    }

    /**
     * @throws Exception if failed.
     */
    @Test
    public void testModesSingleNode() throws Exception {
        checkModes(1);
    }

    /**
     * @throws Exception if failed.
     */
    @Test
    public void testModesMultiNode() throws Exception {
        checkModes(3);
    }

    /**
     * @throws Exception if failed.
     */
    public void checkModes(int gridCnt) throws Exception {
        startGrids(gridCnt);

        try {
            for (CacheMode mode : CacheMode.values()) {
                for (CacheAtomicityMode atomMode : CacheAtomicityMode.values()) {
                    if (mode == CacheMode.PARTITIONED) {
                        // Near cache makes sense only for partitioned cache.
                        checkTxCache(CacheMode.PARTITIONED, atomMode, true, false);
                    }

                    checkTxCache(mode, atomMode, false, true);

                    checkTxCache(mode, atomMode, false, false);
                }
            }
        }
        finally {
            stopAllGrids();
        }
    }

    /**
     * @throws Exception If failed.
     */
    private void checkTxCache(
        CacheMode mode,
        CacheAtomicityMode atomMode,
        boolean nearEnabled,
        boolean useEvicPlc
    ) throws Exception {
        if (atomMode == CacheAtomicityMode.TRANSACTIONAL_SNAPSHOT) {
            if ((nearEnabled && !MvccFeatureChecker.isSupported(Feature.NEAR_CACHE)) ||
                (useEvicPlc && !MvccFeatureChecker.isSupported(Feature.EVICTION)))
                return; // Nothing to do. Mode is not supported.
        }

        final Ignite ignite = grid(0);

        final CacheConfiguration<String, TestClass> ccfg = cacheConfiguration(
            mode,
            atomMode,
            nearEnabled,
            useEvicPlc);

        final IgniteCache<String, TestClass> cache = ignite.createCache(ccfg).withAllowAtomicOpsInTx();

        info("Checking cache [mode=" + mode + ", atomMode=" + atomMode + ", near=" + nearEnabled +
            ", evict=" + useEvicPlc + ']');

        try {
            for (int i = 0; i < 30; i++) {
                final TestClass val = new TestClass("data");
                final String key = "key-" + i;

                cache.put(key, val);

                assertEquals(i + 1, cache.size());

                for (TransactionIsolation iso : TransactionIsolation.values()) {
                    for (TransactionConcurrency con : TransactionConcurrency.values()) {
                        if (atomMode == CacheAtomicityMode.TRANSACTIONAL_SNAPSHOT &&
                            !MvccFeatureChecker.isSupported(con, iso))
                            continue; // Mode not supported.

                        try (Transaction transaction = ignite.transactions().txStart(con, iso)) {
                            assertEquals(val, cache.get(key));

                            transaction.commit();
                        }

                        int cnt = iterateOverKeys(cache);

                        assertEquals("Failed [con=" + con + ", iso=" + iso + ']', i + 1, cnt);

                        assertEquals("Failed [con=" + con + ", iso=" + iso + ']', i + 1, cache.size());
                    }
                }
            }
        }
        finally {
            grid(0).destroyCache(CACHE_NAME);
        }
    }

    /**
     * @param cache Cache.
     */
    @SuppressWarnings("TypeMayBeWeakened")
    private int iterateOverKeys(final IgniteCache<String, TestClass> cache) {
        int cnt = 0;

        for (final Cache.Entry<String, TestClass> ignore : cache)
            cnt++;

        return cnt;
    }

    /**
     *
     */
    private static class TestClass {
        /** */
        private String data;

        /**
         * @param data Data.
         */
        private TestClass(String data) {
            this.data = data;
        }

        /** {@inheritDoc} */
        @Override public boolean equals(final Object o) {
            if (this == o)
                return true;
            if (o == null || getClass() != o.getClass())
                return false;

            final TestClass testCls = (TestClass)o;

            return data != null ? data.equals(testCls.data) : testCls.data == null;

        }

        /** {@inheritDoc} */
        @Override public int hashCode() {
            return data != null ? data.hashCode() : 0;
        }

        /** {@inheritDoc} */
        @Override public String toString() {
            return S.toString(TestClass.class, this);
        }
    }
}
