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

import static org.apache.geode.distributed.ConfigurationProperties.LOG_LEVEL;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.junit.Test;
import org.junit.experimental.categories.Category;

import org.apache.geode.LogWriter;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.EntryEvent;
import org.apache.geode.cache.InterestResultPolicy;
import org.apache.geode.cache.Operation;
import org.apache.geode.cache.PartitionAttributesFactory;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionFactory;
import org.apache.geode.cache.RegionShortcut;
import org.apache.geode.cache.client.ClientCache;
import org.apache.geode.cache.client.ClientCacheFactory;
import org.apache.geode.cache.client.ClientRegionShortcut;
import org.apache.geode.cache.server.CacheServer;
import org.apache.geode.cache.util.CacheListenerAdapter;
import org.apache.geode.internal.AvailablePortHelper;
import org.apache.geode.internal.cache.tier.InterestType;
import org.apache.geode.test.dunit.Assert;
import org.apache.geode.test.dunit.Host;
import org.apache.geode.test.dunit.LogWriterUtils;
import org.apache.geode.test.dunit.SerializableCallable;
import org.apache.geode.test.dunit.SerializableCallableIF;
import org.apache.geode.test.dunit.SerializableRunnable;
import org.apache.geode.test.dunit.VM;
import org.apache.geode.test.dunit.cache.internal.JUnit4CacheTestCase;
import org.apache.geode.test.junit.categories.ClientServerTest;

/**
 * This tests the fix for bug #43407 under a variety of configurations and also tests that
 * tombstones are treated in a similar manner. The ticket complains that a client that does a get(K)
 * does not end up with the entry in its cache if K is invalid on the server.
 */
@Category({ClientServerTest.class})
public class ClientServerInvalidAndDestroyedEntryDUnitTest extends JUnit4CacheTestCase {

  @Override
  public final void postSetUp() throws Exception {
    disconnectAllFromDS();
  }

  @Test
  public void testClientGetsInvalidEntry() throws Exception {
    final String regionName = getUniqueName() + "Region";
    doTestClientGetsInvalidEntry(regionName, false, false);
  }

  @Test
  public void testClientGetsInvalidEntryPR() throws Exception {
    final String regionName = getUniqueName() + "Region";
    doTestClientGetsInvalidEntry(regionName, true, false);
  }

  @Test
  public void testClientGetsTombstone() throws Exception {
    final String regionName = getUniqueName() + "Region";
    doTestClientGetsTombstone(regionName, false, false);
  }

  @Test
  public void testClientGetsTombstonePR() throws Exception {
    final String regionName = getUniqueName() + "Region";
    doTestClientGetsTombstone(regionName, true, false);
  }



  // same tests but with transactions...



  @Test
  public void testClientGetsInvalidEntryTX() throws Exception {
    final String regionName = getUniqueName() + "Region";
    doTestClientGetsInvalidEntry(regionName, false, true);
  }

  @Test
  public void testClientGetsInvalidEntryPRTX() throws Exception {
    final String regionName = getUniqueName() + "Region";
    doTestClientGetsInvalidEntry(regionName, true, true);
  }

  @Test
  public void testClientGetsTombstoneTX() throws Exception {
    final String regionName = getUniqueName() + "Region";
    doTestClientGetsTombstone(regionName, false, true);
  }

  @Test
  public void testClientGetsTombstonePRTX() throws Exception {
    final String regionName = getUniqueName() + "Region";
    doTestClientGetsTombstone(regionName, true, true);
  }


  // tests for bug #46780, tombstones left in client after RI

  @Test
  public void testRegisterInterestRemovesOldEntry() throws Exception {
    final String regionName = getUniqueName() + "Region";
    doTestRegisterInterestRemovesOldEntry(regionName, false);
  }

  @Test
  public void testRegisterInterestRemovesOldEntryPR() throws Exception {
    final String regionName = getUniqueName() + "Region";
    doTestRegisterInterestRemovesOldEntry(regionName, true);
  }

  /* this method creates a server cache and is used by all of the tests in this class */
  private SerializableCallableIF getCreateServerCallable(final String regionName,
      final boolean usePR) {
    return new SerializableCallable("create server and entries") {
      @Override
      public Object call() {
        Cache cache = getCache();
        List<CacheServer> servers = cache.getCacheServers();
        CacheServer server;
        if (servers.size() > 0) {
          server = servers.get(0);
        } else {
          server = cache.addCacheServer();
          int port = AvailablePortHelper.getRandomAvailableTCPPort();
          server.setPort(port);
          server.setHostnameForClients("localhost");
          try {
            server.start();
          } catch (IOException e) {
            Assert.fail("Failed to start server ", e);
          }
        }
        if (usePR) {
          RegionFactory factory = cache.createRegionFactory(RegionShortcut.PARTITION);
          PartitionAttributesFactory pf = new PartitionAttributesFactory();
          pf.setTotalNumBuckets(2);
          factory.setPartitionAttributes(pf.create());
          factory.create(regionName);
        } else {
          cache.createRegionFactory(RegionShortcut.REPLICATE).create(regionName);
        }
        return server.getPort();
      }
    };
  }


  /**
   * Bug #43407 - when a client does a get(k) and the entry is invalid in the server we want the
   * client to end up with an entry that is invalid.
   */
  private void doTestClientGetsInvalidEntry(final String regionName, final boolean usePR,
      boolean useTX) throws Exception {
    VM vm1 = Host.getHost(0).getVM(1);
    VM vm2 = Host.getHost(0).getVM(2);

    // here are the keys that will be used to validate behavior. Keys must be
    // colocated if using both a partitioned region in the server and transactions
    // in the client. All of these keys hash to bucket 0 in a two-bucket PR
    // except Object11 and IDoNotExist1
    final String notAffectedKey = "Object1";
    final String nonexistentKey = (usePR && useTX) ? "IDoNotExist2" : "IDoNotExist1";
    final String key1 = "Object10";
    final String key2 = (usePR && useTX) ? "Object12" : "Object11";

    SerializableCallableIF createServer = getCreateServerCallable(regionName, usePR);
    int serverPort = (Integer) vm1.invoke(createServer);
    vm2.invoke(createServer);
    vm1.invoke(new SerializableRunnable("populate server and create invalid entry") {
      @Override
      public void run() {
        Region myRegion = getCache().getRegion(regionName);
        for (int i = 1; i <= 20; i++) {
          myRegion.put("Object" + i, "Value" + i);
        }
        myRegion.invalidate(key1);
        myRegion.invalidate(key2);
      }
    });
    org.apache.geode.test.dunit.LogWriterUtils.getLogWriter().info("creating client cache");
    ClientCache c = new ClientCacheFactory().addPoolServer("localhost", serverPort)
        .set(LOG_LEVEL, LogWriterUtils.getDUnitLogLevel()).create();
    Region myRegion =
        c.createClientRegionFactory(ClientRegionShortcut.CACHING_PROXY).create(regionName);;
    if (useTX) {
      c.getCacheTransactionManager().begin();
    }

    // get of a valid entry should work
    assertNotNull(myRegion.get(notAffectedKey));

    // get of an invalid entry should return null and create the entry in an invalid state
    org.apache.geode.test.dunit.LogWriterUtils.getLogWriter()
        .info("getting " + key1 + " - should reach this cache and be INVALID");
    assertNull(myRegion.get(key1));
    assertTrue(myRegion.containsKey(key1));

    // since this might be a PR we also check the next key to force PR Get messaging
    assertNull(myRegion.get(key2));
    assertTrue(myRegion.containsKey(key2));

    // now try a key that doesn't exist anywhere
    assertNull(myRegion.get(nonexistentKey));
    assertFalse(myRegion.containsKey(nonexistentKey));

    if (useTX) {
      c.getCacheTransactionManager().commit();

      // test that the commit correctly created the entries in the region
      assertNotNull(myRegion.get(notAffectedKey));
      assertNull(myRegion.get(key1));
      assertTrue(myRegion.containsKey(key1));
      assertNull(myRegion.get(key2));
      assertTrue(myRegion.containsKey(key2));
    }

    myRegion.localDestroy(notAffectedKey);
    myRegion.localDestroy(key1);
    myRegion.localDestroy(key2);

    if (useTX) {
      c.getCacheTransactionManager().begin();
    }

    // check that getAll returns invalidated entries
    List keys = new LinkedList();
    keys.add(notAffectedKey);
    keys.add(key1);
    keys.add(key2);
    Map result = myRegion.getAll(keys);

    assertNotNull(result.get(notAffectedKey));
    assertNull(result.get(key1));
    assertNull(result.get(key2));
    assertTrue(result.containsKey(key1));
    assertTrue(result.containsKey(key2));
    assertTrue(myRegion.containsKey(key1));
    assertTrue(myRegion.containsKey(key2));

    if (useTX) {
      c.getCacheTransactionManager().commit();
      // test that the commit correctly created the entries in the region
      assertNotNull(myRegion.get(notAffectedKey));
      assertNull(myRegion.get(key1));
      assertTrue(myRegion.containsKey(key1));
      assertNull(myRegion.get(key2));
      assertTrue(myRegion.containsKey(key2));
    }

    // test that a listener is not invoked when there is already an invalidated
    // entry in the client cache
    UpdateListener listener = new UpdateListener();
    listener.log = org.apache.geode.test.dunit.LogWriterUtils.getLogWriter();
    myRegion.getAttributesMutator().addCacheListener(listener);
    myRegion.get(key1);
    assertEquals("expected no cache listener invocations", 0, listener.updateCount,
        listener.updateCount);

    myRegion.localDestroy(notAffectedKey);
    myRegion.getAll(keys);
    assertTrue("expected to find " + notAffectedKey, myRegion.containsKey(notAffectedKey));
    assertEquals("expected only one listener invocation for " + notAffectedKey, 1,
        listener.updateCount);
  }



  /**
   * Similar to bug #43407 but not reported in a ticket, we want a client that does a get() on a
   * destroyed entry to end up with a tombstone for that entry. This was already the case but there
   * were no unit tests covering this for different server configurations and with/without
   * transactions.
   */
  private void doTestClientGetsTombstone(final String regionName, final boolean usePR,
      boolean useTX) throws Exception {
    VM vm1 = Host.getHost(0).getVM(1);
    VM vm2 = Host.getHost(0).getVM(2);

    // here are the keys that will be used to validate behavior. Keys must be
    // colocated if using both a partitioned region in the server and transactions
    // in the client. All of these keys hash to bucket 0 in a two-bucket PR
    // except Object11 and IDoNotExist1
    final String notAffectedKey = "Object1";
    final String nonexistentKey = (usePR && useTX) ? "IDoNotExist2" : "IDoNotExist1";
    final String key1 = "Object10";
    final String key2 = (usePR && useTX) ? "Object12" : "Object11";

    SerializableCallableIF createServer = getCreateServerCallable(regionName, usePR);
    int serverPort = (Integer) vm1.invoke(createServer);
    vm2.invoke(createServer);
    vm1.invoke(new SerializableRunnable("populate server and create invalid entry") {
      @Override
      public void run() {
        Region myRegion = getCache().getRegion(regionName);
        for (int i = 1; i <= 20; i++) {
          myRegion.put("Object" + i, "Value" + i);
        }
        myRegion.destroy(key1);
        myRegion.destroy(key2);
      }
    });
    org.apache.geode.test.dunit.LogWriterUtils.getLogWriter().info("creating client cache");
    ClientCache c = new ClientCacheFactory().addPoolServer("localhost", serverPort)
        .set(LOG_LEVEL, LogWriterUtils.getDUnitLogLevel()).create();
    Region myRegion =
        c.createClientRegionFactory(ClientRegionShortcut.CACHING_PROXY).create(regionName);;
    if (useTX) {
      c.getCacheTransactionManager().begin();
    }
    // get of a valid entry should work
    assertNotNull(myRegion.get(notAffectedKey));
    // get of an invalid entry should return null and create the entry in an invalid state
    org.apache.geode.test.dunit.LogWriterUtils.getLogWriter()
        .info("getting " + key1 + " - should reach this cache and be a TOMBSTONE");
    assertNull(myRegion.get(key1));
    assertFalse(myRegion.containsKey(key1));
    RegionEntry entry;
    if (!useTX) {
      entry = ((LocalRegion) myRegion).getRegionEntry(key1);
      assertNotNull(entry); // it should be there
      assertTrue(entry.isTombstone()); // it should be a destroyed entry with Token.TOMBSTONE
    }

    // since this might be a PR we also check the next key to force PR Get messaging
    assertNull(myRegion.get(key2));
    assertFalse(myRegion.containsKey(key2));
    if (!useTX) {
      entry = ((LocalRegion) myRegion).getRegionEntry(key2);
      assertNotNull(entry); // it should be there
      assertTrue(entry.isTombstone()); // it should be a destroyed entry with Token.TOMBSTONE
    }


    // now try a key that doesn't exist anywhere
    assertNull(myRegion.get(nonexistentKey));
    assertFalse(myRegion.containsKey(nonexistentKey));

    if (useTX) {
      c.getCacheTransactionManager().commit();

      // test that the commit correctly created the entries in the region
      assertNotNull(myRegion.get(notAffectedKey));
      assertNull(myRegion.get(key1));
      assertFalse(myRegion.containsKey(key1));
      entry = ((LocalRegion) myRegion).getRegionEntry(key1);
      assertNotNull(entry); // it should be there
      assertTrue(entry.isTombstone()); // it should be a destroyed entry with Token.TOMBSTONE

      assertNull(myRegion.get(key2));
      assertFalse(myRegion.containsKey(key2));
      entry = ((LocalRegion) myRegion).getRegionEntry(key2);
      assertNotNull(entry); // it should be there
      assertTrue(entry.isTombstone()); // it should be a destroyed entry with Token.TOMBSTONE
    }

    myRegion.localDestroy(notAffectedKey);

    if (useTX) {
      c.getCacheTransactionManager().begin();
    }

    // check that getAll returns invalidated entries
    List keys = new LinkedList();
    keys.add(notAffectedKey);
    keys.add(key1);
    keys.add(key2);
    Map result = myRegion.getAll(keys);

    org.apache.geode.test.dunit.LogWriterUtils.getLogWriter().info("result of getAll = " + result);
    assertNotNull(result.get(notAffectedKey));
    assertNull(result.get(key1));
    assertNull(result.get(key2));
    assertFalse(myRegion.containsKey(key1));
    assertFalse(myRegion.containsKey(key2));
    if (!useTX) {
      entry = ((LocalRegion) myRegion).getRegionEntry(key1);
      assertNotNull(entry); // it should be there
      assertTrue(entry.isTombstone()); // it should be a destroyed entry with Token.TOMBSTONE

      entry = ((LocalRegion) myRegion).getRegionEntry(key2);
      assertNotNull(entry); // it should be there
      assertTrue(entry.isTombstone()); // it should be a destroyed entry with Token.TOMBSTONE
    } else { // useTX
      c.getCacheTransactionManager().commit();
      // test that the commit correctly created the entries in the region
      assertNotNull(myRegion.get(notAffectedKey));

      assertNull(myRegion.get(key1));
      assertFalse(myRegion.containsKey(key1));
      entry = ((LocalRegion) myRegion).getRegionEntry(key1);
      assertNotNull(entry); // it should be there
      assertTrue(entry.isTombstone()); // it should be a destroyed entry with Token.TOMBSTONE

      assertNull(myRegion.get(key2));
      assertFalse(myRegion.containsKey(key2));
      entry = ((LocalRegion) myRegion).getRegionEntry(key2);
      assertNotNull(entry); // it should be there
      assertTrue(entry.isTombstone()); // it should be a destroyed entry with Token.TOMBSTONE
    }

  }


  private void doTestRegisterInterestRemovesOldEntry(final String regionName, final boolean usePR)
      throws Exception {
    VM vm1 = Host.getHost(0).getVM(1);
    VM vm2 = Host.getHost(0).getVM(2);

    // here are the keys that will be used to validate behavior. Keys must be
    // colocated if using both a partitioned region in the server and transactions
    // in the client. All of these keys hash to bucket 0 in a two-bucket PR
    // except Object11 and IDoNotExist1
    final String key10 = "Object10";
    final String interestPattern = "Object.*";

    SerializableCallableIF createServer = getCreateServerCallable(regionName, usePR);
    int serverPort = (Integer) vm1.invoke(createServer);
    vm2.invoke(createServer);
    vm1.invoke(new SerializableRunnable("populate server") {
      @Override
      public void run() {
        Region myRegion = getCache().getRegion(regionName);
        for (int i = 1; i <= 20; i++) {
          myRegion.put("Object" + i, "Value" + i);
        }
      }
    });
    org.apache.geode.test.dunit.LogWriterUtils.getLogWriter().info("creating client cache");
    ClientCache c = new ClientCacheFactory().addPoolServer("localhost", serverPort)
        .set(LOG_LEVEL, LogWriterUtils.getDUnitLogLevel()).setPoolSubscriptionEnabled(true)
        .create();

    Region myRegion =
        c.createClientRegionFactory(ClientRegionShortcut.CACHING_PROXY).create(regionName);;

    myRegion.registerInterestRegex(interestPattern);

    // make sure key1 is in the client because we're going to mess with it
    assertNotNull(myRegion.get(key10));

    // remove the entry for key1 on the servers and then simulate interest recovery
    // to show that the entry for key1 is no longer there in the client when recovery
    // finishes
    SerializableRunnable destroyKey10 =
        new SerializableRunnable("locally destroy " + key10 + " in the servers") {
          @Override
          public void run() {
            Region myRegion = getCache().getRegion(regionName);
            EntryEventImpl event = ((LocalRegion) myRegion).generateEvictDestroyEvent(key10);
            event.setOperation(Operation.LOCAL_DESTROY);
            if (usePR) {
              BucketRegion bucket = ((PartitionedRegion) myRegion).getBucketRegion(key10);
              if (bucket != null) {
                event.setRegion(bucket);
                org.apache.geode.test.dunit.LogWriterUtils.getLogWriter()
                    .info("performing local destroy in " + bucket + " ccEnabled="
                        + bucket.getConcurrencyChecksEnabled() + " rvv="
                        + bucket.getVersionVector());
                bucket.setConcurrencyChecksEnabled(false); // turn off cc so entry is removed
                bucket.mapDestroy(event, false, false, null);
                bucket.setConcurrencyChecksEnabled(true);
              }
            } else {
              ((LocalRegion) myRegion).setConcurrencyChecksEnabled(false); // turn off cc so entry
                                                                           // is
              // removed
              ((LocalRegion) myRegion).mapDestroy(event, false, false, null);
              ((LocalRegion) myRegion).setConcurrencyChecksEnabled(true);
            }
          }
        };

    vm1.invoke(destroyKey10);
    vm2.invoke(destroyKey10);

    myRegion.getCache().getLogger().info("clearing keys of interest");
    ((LocalRegion) myRegion).clearKeysOfInterest(interestPattern, InterestType.REGULAR_EXPRESSION,
        InterestResultPolicy.KEYS_VALUES);
    myRegion.getCache().getLogger().info("done clearing keys of interest");

    assertTrue("expected region to be empty but it has " + myRegion.size() + " entries",
        myRegion.size() == 0);

    RegionEntry entry;
    entry = ((LocalRegion) myRegion).getRegionEntry(key10);
    assertNull(entry); // it should have been removed

    // now register interest. At the end, finishRegisterInterest should clear
    // out the entry for key1 because it was stored in image-state as a
    // destroyed RI entry in clearKeysOfInterest
    myRegion.registerInterestRegex(interestPattern);

    entry = ((LocalRegion) myRegion).getRegionEntry(key10);
    assertNull(entry); // it should not be there
  }

  static class UpdateListener extends CacheListenerAdapter {
    int updateCount;
    LogWriter log;

    @Override
    public void afterUpdate(EntryEvent event) {
      // log.info("UpdateListener.afterUpdate invoked for " + event, new Exception("stack trace"));
      this.updateCount++;
    }

    @Override
    public void afterCreate(EntryEvent event) {
      // log.info("UpdateListener.afterCreate invoked for " + event, new Exception("stack trace"));
      this.updateCount++;
    }
  }

}
