package org.apache.commons.jcs3;

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

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.jcs3.access.GroupCacheAccess;
import org.apache.commons.jcs3.access.exception.CacheException;

import junit.framework.TestCase;

/**
 * Test Case for JCS-73, modeled after the Groovy code by Alexander Kleymenov
 *
 * @author Thomas Vandahl
 *
 */
public class JCSConcurrentCacheAccessUnitTest extends TestCase
{
    private final static int THREADS = 20;
    private final static int LOOPS = 10000;

    /**
     * the cache instance
     */
    protected GroupCacheAccess<Integer, String> cache;

    /**
     * the group name
     */
    protected String group = "group";

    /**
     * the error count
     */
    protected AtomicInteger errcount;

    /**
     * Collect all value mismatches
     */
    protected List<String> valueMismatchList;

    @Override
	protected void setUp() throws Exception
	{
        super.setUp();
        JCS.setConfigFilename( "/TestJCS-73.ccf" );
        cache = JCS.getGroupCacheInstance( "cache" );
        errcount = new AtomicInteger(0);
        valueMismatchList = new CopyOnWriteArrayList<>();
	}

    @Override
    protected void tearDown()
        throws Exception
    {
        super.tearDown();
        cache.clear();
        cache.dispose();
    }

    /**
     * Worker thread
     */
    protected class Worker extends Thread
    {
    	@Override
		public void run()
		{
			String name = getName();

			for (int idx = 0; idx < LOOPS; idx++)
			{
				if (idx > 0)
				{
					// get previously stored value
		            String res = cache.getFromGroup(Integer.valueOf(idx-1), group);

		            if (res == null)
		            {
		                // null value got inspite of the fact it was placed in cache!
		                System.out.println("ERROR: for " + idx + " in " + name);
		                errcount.incrementAndGet();

		                // try to get the value again:
		                int n = 5;
		                while (n-- > 0)
		                {
		                    res = cache.getFromGroup(Integer.valueOf(idx-1), group);
		                    if (res != null)
		                    {
		                        // the value finally appeared in cache
		                    	System.out.println("ERROR FIXED for " + idx + ": " + res + " " + name);
		                    	errcount.decrementAndGet();
		                        break;
		                    }

		                    System.out.println("ERROR STILL PERSISTS for " + idx + " in " + name);
		                    try
		                    {
								Thread.sleep(1000);
							}
		                    catch (InterruptedException e)
							{
								// continue
							}
		                }
		            }

		            if (!String.valueOf(idx-1).equals(res))
		            {
		                valueMismatchList.add(String.format("Values do not match: %s - %s", String.valueOf(idx-1), res));
		            }
				}

				 // put value in the cache
		        try
		        {
					cache.putInGroup(Integer.valueOf(idx), group, String.valueOf(idx));
				}
		        catch (CacheException e)
		        {
		        	// continue
				}

//		        if ((idx % 1000) == 0)
//		        {
//		        	System.out.println(name + " " + idx);
//		        }
			}

		}
    }

	/**
     *
     * @throws Exception
     */
    public void testConcurrentAccess()
        throws Exception
    {
    	Worker[] worker = new Worker[THREADS];

        for (int i = 0; i < THREADS; i++)
        {
        	worker[i] = new Worker();
        	worker[i].start();
        }

        for (int i = 0; i < THREADS; i++)
        {
        	worker[i].join();
        }

        assertEquals("Error count should be 0",  0, errcount.intValue());
        for (String msg : valueMismatchList)
        {
            System.out.println(msg);
        }
        assertEquals("Value mismatch count should be 0",  0, valueMismatchList.size());
    }

}
