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

import static java.lang.Thread.sleep;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.apache.geode.internal.cache.TombstoneService.EXPIRED_TOMBSTONE_LIMIT_DEFAULT;
import static org.apache.geode.internal.cache.TombstoneService.REPLICATE_TOMBSTONE_TIMEOUT_DEFAULT;
import static org.apache.geode.test.awaitility.GeodeAwaitility.await;
import static org.apache.geode.test.awaitility.GeodeAwaitility.getTimeout;
import static org.apache.geode.test.dunit.IgnoredException.addIgnoredException;
import static org.apache.geode.test.dunit.VM.getAllVMs;
import static org.apache.geode.test.dunit.VM.getController;
import static org.apache.geode.test.dunit.VM.getVM;
import static org.apache.geode.test.dunit.VM.toArray;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;

import junitparams.Parameters;
import junitparams.naming.TestCaseName;
import org.junit.After;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;

import org.apache.geode.DataSerializer;
import org.apache.geode.cache.AttributesFactory;
import org.apache.geode.cache.CacheClosedException;
import org.apache.geode.cache.DataPolicy;
import org.apache.geode.cache.DiskAccessException;
import org.apache.geode.cache.DiskStore;
import org.apache.geode.cache.DiskStoreFactory;
import org.apache.geode.cache.PartitionAttributesFactory;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionDestroyedException;
import org.apache.geode.cache.RegionFactory;
import org.apache.geode.cache.Scope;
import org.apache.geode.distributed.internal.ClusterDistributionManager;
import org.apache.geode.distributed.internal.DistributionMessage;
import org.apache.geode.distributed.internal.DistributionMessageObserver;
import org.apache.geode.internal.HeapDataOutputStream;
import org.apache.geode.internal.cache.CacheObserverAdapter;
import org.apache.geode.internal.cache.CacheObserverHolder;
import org.apache.geode.internal.cache.DiskRegion;
import org.apache.geode.internal.cache.DiskStoreFactoryImpl;
import org.apache.geode.internal.cache.DiskStoreImpl;
import org.apache.geode.internal.cache.DiskStoreObserver;
import org.apache.geode.internal.cache.EntrySnapshot;
import org.apache.geode.internal.cache.InitialImageOperation;
import org.apache.geode.internal.cache.InternalRegion;
import org.apache.geode.internal.cache.LocalRegion;
import org.apache.geode.internal.cache.NonTXEntry;
import org.apache.geode.internal.cache.RegionEntry;
import org.apache.geode.internal.cache.Token.Tombstone;
import org.apache.geode.internal.cache.TombstoneService;
import org.apache.geode.internal.cache.versions.RegionVersionVector;
import org.apache.geode.internal.cache.versions.VersionTag;
import org.apache.geode.test.dunit.AsyncInvocation;
import org.apache.geode.test.dunit.IgnoredException;
import org.apache.geode.test.dunit.LogWriterUtils;
import org.apache.geode.test.dunit.VM;
import org.apache.geode.test.dunit.Wait;
import org.apache.geode.test.dunit.rules.DistributedErrorCollector;
import org.apache.geode.test.dunit.rules.DistributedRestoreSystemProperties;
import org.apache.geode.test.junit.categories.PersistenceTest;
import org.apache.geode.test.junit.runners.GeodeParamsRunner;

@Category(PersistenceTest.class)
@RunWith(GeodeParamsRunner.class)
@SuppressWarnings("serial")
public class PersistentRVVRecoveryDUnitTest extends PersistentReplicatedTestBase {

  private static final int TEST_REPLICATED_TOMBSTONE_TIMEOUT = 1_000;
  private static final long TIMEOUT_MILLIS = getTimeout().toMillis();

  @Rule
  public DistributedRestoreSystemProperties restoreSystemProperties =
      new DistributedRestoreSystemProperties();

  @Rule
  public DistributedErrorCollector errorCollector = new DistributedErrorCollector();

  @After
  public void tearDown() {
    for (VM vm : toArray(getAllVMs(), getController())) {
      vm.invoke(() -> {
        LocalRegion.ISSUE_CALLBACKS_TO_CACHE_OBSERVER = false;
        CacheObserverHolder.setInstance(null);
        DiskStoreObserver.setInstance(null);
        TombstoneService.REPLICATE_TOMBSTONE_TIMEOUT = REPLICATE_TOMBSTONE_TIMEOUT_DEFAULT;
        TombstoneService.EXPIRED_TOMBSTONE_LIMIT = EXPIRED_TOMBSTONE_LIMIT_DEFAULT;
      });
    }
  }

  @Test
  public void testNoConcurrencyChecks() {
    getCache();

    RegionFactory regionFactory = new RegionFactory();
    regionFactory.setDataPolicy(DataPolicy.PERSISTENT_REPLICATE);
    regionFactory.setConcurrencyChecksEnabled(false);

    Throwable thrown = catchThrowable(() -> regionFactory.create(regionName));
    assertThat(thrown).isInstanceOf(IllegalStateException.class);
  }

  /**
   * Test that we can recover the RVV information.
   */
  @Test
  @Parameters({"true", "false"})
  @TestCaseName("{method}({params})")
  public void testRecoveryWithOrWithoutKRF(boolean deleteKRFs) throws Exception {
    VM vm0 = getVM(0);
    VM vm1 = getVM(1);
    VM vm2 = getVM(2);

    // Create the region in few members to test recovery
    createPersistentRegion(vm0);
    createPersistentRegion(vm1);
    createPersistentRegion(vm2);

    // Create and delete some keys (to update the RVV)
    createData(vm0, 0, 5, "value1");
    createData(vm1, 3, 8, "value2");
    createData(vm2, 6, 11, "value3");

    delete(vm1, 0, 1);
    delete(vm0, 10, 11);

    // Make sure the RVVs are the same in the members
    RegionVersionVector vm0RVV = getRVV(vm0);
    RegionVersionVector vm1RVV = getRVV(vm1);
    RegionVersionVector vm2RVV = getRVV(vm2);

    assertSameRVV(vm0RVV, vm1RVV);
    assertSameRVV(vm0RVV, vm2RVV);

    // Closing the cache will ensure the disk store is closed
    closeCache(vm2);
    closeCache(vm1);
    closeCache(vm0);

    if (deleteKRFs) {
      deleteKRFs(getVM(0));
    }

    // Make sure we can recover the RVV
    createPersistentRegion(vm0);

    RegionVersionVector new0RVV = getRVV(vm0);
    assertSameRVV(vm0RVV, new0RVV);
    assertThat(new0RVV.getOwnerId()).isEqualTo(vm0RVV.getOwnerId());

    createData(vm0, 12, 15, "value");

    // Make sure we can GII the RVV
    new0RVV = getRVV(vm0);
    assertSameRVV(new0RVV, getDiskRVV(vm0));
    createPersistentRegion(vm1);
    assertSameRVV(new0RVV, getRVV(vm1));
    assertSameRVV(new0RVV, getDiskRVV(vm1));

    closeCache(vm0);
    closeCache(vm1);

    if (deleteKRFs) {
      deleteKRFs(getVM(0));
    }

    // Make the sure member that GII'd the RVV can also recover it
    createPersistentRegion(vm1);
    assertSameRVV(new0RVV, getRVV(vm1));
  }

  /**
   * Test that we correctly recover and expire recovered tombstones, with compaction enabled
   */
  @Test
  public void testLotsOfTombstones() throws Exception {
    VM vm0 = getVM(0);

    // I think we just need to assert the number of tombstones, maybe?
    // Bruce has code that won't even let the tombstones expire for 10 minutes
    // That means on recovery we need to recover them all? Or do we need to recover
    // any? We're doing a GII. Won't we GII tombstones anyway? Ahh, but we need
    // to know that we don't need to record the new tombstones.

    InternalRegion region = createRegion(vm0);

    int initialCount = getTombstoneCount(region);
    assertThat(initialCount).isEqualTo(0);

    int entryCount = 20;
    for (int i = 0; i < entryCount; i++) {
      region.put(i, new byte[100]);
      region.destroy(i);
    }

    assertThat(getTombstoneCount(region)).isEqualTo(entryCount);

    // roll to a new oplog
    region.getDiskStore().forceRoll();

    // Force a compaction. This should do nothing, because the tombstones are not garbage, so only
    // 50% of the oplog is garbage (the creates).
    region.getDiskStore().forceCompaction();

    assertThat(region.getDiskStore().numCompactableOplogs()).isEqualTo(0);
    assertThat(getTombstoneCount(region)).isEqualTo(entryCount);

    getCache().close();

    region = createRegion(vm0);

    assertThat(getTombstoneCount(region)).isEqualTo(entryCount);

    TombstoneService tombstoneService = getCache().getTombstoneService();

    // Before expiring tombstones, no oplogs are available for compaction
    assertThat(region.getDiskStore().numCompactableOplogs()).isEqualTo(0);

    region.getDiskStore().forceCompaction();

    assertThat(
        tombstoneService.forceBatchExpirationForTests(entryCount / 2, TIMEOUT_MILLIS, MILLISECONDS))
            .isTrue();
    assertThat(getTombstoneCount(region)).isEqualTo(entryCount / 2);

    // After expiring, we should have an oplog available for compaction.
    assertThat(region.getDiskStore().numCompactableOplogs()).isEqualTo(1);

    // Test after restart the tombstones are still missing
    getCache().close();
    region = createRegion(vm0);
    assertThat(getTombstoneCount(region)).isEqualTo(entryCount / 2);

    // Should have an oplog available for compaction, because the tombstones were garbage collected
    assertThat(region.getDiskStore().numCompactableOplogs()).isEqualTo(1);

    // This should compact some oplogs
    region.getDiskStore().forceCompaction();
    assertThat(region.getDiskStore().numCompactableOplogs()).isEqualTo(0);

    // Restart again, and make sure the compaction didn't mess up our tombstone count
    getCache().close();
    region = createRegion(vm0);
    assertThat(getTombstoneCount(region)).isEqualTo(entryCount / 2);

    // Add a test hook that will shutdown the system as soon as we write a GC RVV record
    DiskStoreObserver.setInstance(new DiskStoreObserver() {

      @Override
      public void afterWriteGCRVV(DiskRegion dr) {
        // This will cause the disk store to shut down, preventing us from writing any other records
        throw new DiskAccessException();
      }
    });

    addIgnoredException(DiskAccessException.class);
    addIgnoredException(RegionDestroyedException.class);

    // Force expiration, with our test hook that should close the cache
    tombstoneService = getCache().getTombstoneService();
    assertThat(
        tombstoneService.forceBatchExpirationForTests(entryCount / 4, TIMEOUT_MILLIS, MILLISECONDS))
            .isTrue();

    getCache().close();

    // Restart again, and make sure the tombstones are in fact removed
    region = createRegion(vm0);
    assertThat(getTombstoneCount(region)).isEqualTo(entryCount / 4);
  }

  /**
   * Test that we correctly recover and expire recovered tombstones, with compaction enabled.
   *
   * This test differs from above test in that we need to make sure tombstones start expiring based
   * on their original time-stamp, NOT the time-stamp assigned during scheduling for expiration
   * after recovery.
   */
  @Ignore
  @Test
  public void testLotsOfTombstonesExpiration() {
    VM vm0 = getVM(0);

    vm0.invoke(() -> {
      InternalRegion region = createRegion(vm0);

      int initialCount = getTombstoneCount(region);
      assertThat(initialCount).isEqualTo(0);

      int entryCount = 20;
      for (int i = 0; i < entryCount; i++) {
        region.put(i, new byte[100]);
        region.destroy(i);
      }

      assertThat(getTombstoneCount(region)).isEqualTo(entryCount);

      // roll to a new oplog
      region.getDiskStore().forceRoll();

      // Force a compaction. This should do nothing, because the tombstones are not garbage, so
      // only 50% of the oplog is garbage (the creates).
      region.getDiskStore().forceCompaction();

      assertThat(region.getDiskStore().numCompactableOplogs()).isEqualTo(0);
      assertThat(getTombstoneCount(region)).isEqualTo(entryCount);

      getCache().close();

      // We should wait for timeout time so that tombstones are expired
      // right away when they are gIId based on their original timestamp.
      Wait.pause(TEST_REPLICATED_TOMBSTONE_TIMEOUT);

      TombstoneService.REPLICATE_TOMBSTONE_TIMEOUT = TEST_REPLICATED_TOMBSTONE_TIMEOUT;
      TombstoneService.EXPIRED_TOMBSTONE_LIMIT = entryCount;

      // Do region GII
      region = createRegion(vm0);

      assertThat(getTombstoneCount(region)).isEqualTo(entryCount);

      // maximumSleepTime+500 in TombstoneSweeper GC thread
      Wait.pause(10_000);

      // Tombstones should have been expired and garbage collected by now by TombstoneService.
      assertThat(getTombstoneCount(region)).isEqualTo(0);

      // This should compact some oplogs
      region.getDiskStore().forceCompaction();
      assertThat(region.getDiskStore().numCompactableOplogs()).isEqualTo(0);

      // Test after restart the tombstones are still missing
      getCache().close();
      region = createRegion(vm0);
      assertThat(getTombstoneCount(region)).isEqualTo(0);

      // should have an oplog available for compaction because the tombstones were garbage collected
      assertThat(region.getDiskStore().numCompactableOplogs()).isEqualTo(0);

      getCache().close();
    });
  }

  /**
   * This test creates 2 VMs in a distributed system with a persistent PartitionedRegion and one VM
   * (VM1) puts an entry in region. Second VM (VM2) starts later and does a delta GII. During Delta
   * GII in VM2 a DESTROY operation happens in VM1 and gets propagated to VM2 concurrently with GII.
   * At this point if entry version is greater than the once received from GII then it must not get
   * applied. Which is Bug #45921.
   */
  @Test
  public void testConflictChecksDuringConcurrentDeltaGIIAndOtherOp() throws Exception {
    VM vm0 = getVM(0);
    VM vm1 = getVM(1);

    vm0.invoke(() -> {
      getCache();

      PartitionAttributesFactory<String, String> partitionAttributesFactory =
          new PartitionAttributesFactory<>();
      partitionAttributesFactory.setRedundantCopies(1);
      partitionAttributesFactory.setTotalNumBuckets(1);

      AttributesFactory<String, String> attributesFactory = new AttributesFactory<>();
      attributesFactory.setPartitionAttributes(partitionAttributesFactory.create());

      RegionFactory<String, String> regionFactory =
          getCache().createRegionFactory(attributesFactory.create());

      Region<String, String> region = regionFactory.create("prRegion");

      region.put("testKey", "testValue");
      assertThat(region.size()).isEqualTo(1);
    });

    // Create a cache and region, do an update to change the version no. and
    // restart the cache and region.
    vm1.invoke(() -> {
      getCache();

      PartitionAttributesFactory<String, String> partitionAttributesFactory =
          new PartitionAttributesFactory<>();
      partitionAttributesFactory.setRedundantCopies(1);
      partitionAttributesFactory.setTotalNumBuckets(1);

      AttributesFactory<String, String> attributesFactory = new AttributesFactory<>();
      attributesFactory.setPartitionAttributes(partitionAttributesFactory.create());

      RegionFactory<String, String> regionFactory =
          getCache().createRegionFactory(attributesFactory.create());
      Region<String, String> region = regionFactory.create("prRegion");

      region.put("testKey", "testValue2");

      getCache().close();

      // Restart
      regionFactory = getCache().createRegionFactory(attributesFactory.create());
      regionFactory.create("prRegion");
    });

    // Do a DESTROY in vm0 when delta GII is in progress in vm1 (Hopefully, Not guaranteed).
    AsyncInvocation<Void> destroyDuringDeltaGiiInVM0 = vm0.invokeAsync(() -> {
      Region<String, String> region = getCache().getRegion("prRegion");

      await().until(() -> region.get("testKey").equals("testValue2"));

      region.destroy("testKey");
    });

    destroyDuringDeltaGiiInVM0.await();

    vm1.invoke(() -> {
      InternalRegion region = (InternalRegion) getCache().getRegion("prRegion");

      Region.Entry entry = region.getEntry("testKey", true);
      RegionEntry regionEntry = ((EntrySnapshot) entry).getRegionEntry();
      assertThat(regionEntry.getValueInVM(region)).isInstanceOf(Tombstone.class);

      VersionTag tag = regionEntry.getVersionStamp().asVersionTag();
      assertThat(tag.getEntryVersion()).isEqualTo(3 /* Two puts and a Destroy */);
    });

    closeCache(vm0);
    closeCache(vm1);
  }

  /**
   * Test that we skip conflict checks with entries that are on disk compared to entries that come
   * in as part of a GII
   */
  @Test
  public void testSkipConflictChecksForGIIdEntries() throws Exception {
    VM vm0 = getVM(0);
    VM vm1 = getVM(1);

    // Create the region in few members to test recovery
    createPersistentRegion(vm0);
    createPersistentRegion(vm1);

    // Create an update some entries in vm0 and vm1.
    createData(vm0, 0, 1, "value1");
    createData(vm0, 0, 2, "value2");

    closeCache(vm1);

    // Reset the entry version in vm0.
    // This means that if we did a conflict check, vm0's key will have a lower entry version than
    // vm1, which would cause us to prefer vm1's value

    vm0.invoke(() -> {
      InternalRegion region = (InternalRegion) getCache().getRegion(regionName);
      region.put(0, "value3");
      RegionEntry regionEntry = region.getRegionEntry(0);
      // Sneak in and change the version number for an entry to generate a conflict.
      VersionTag tag = regionEntry.getVersionStamp().asVersionTag();
      tag.setEntryVersion(tag.getEntryVersion() - 2);
      regionEntry.getVersionStamp().setVersions(tag);
    });

    // Create vm1, doing a GII
    createPersistentRegion(vm1);

    checkData(vm0, 0, 1, "value3");
    // If we did a conflict check, this would be value2
    checkData(vm1, 0, 1, "value3");
  }

  /**
   * Test that we skip conflict checks with entries that are on disk compared to entries that come
   * in as part of a concurrent operation
   */
  @Test
  public void testSkipConflictChecksForConcurrentOps() throws Exception {
    VM vm0 = getVM(0);
    VM vm1 = getVM(1);

    // Create the region in few members to test recovery
    createPersistentRegion(vm0);
    createPersistentRegion(vm1);

    // Create an update some entries in vm0 and vm1.
    createData(vm0, 0, 1, "value1");
    createData(vm0, 0, 1, "value2");
    createData(vm0, 0, 1, "value2");

    closeCache(vm1);

    // Update the keys in vm0 until the entry version rolls over. This means that if we did a
    // conflict check, vm0's key will have a lower entry version than vm1, which would cause us to
    // prefer vm1's value
    vm0.invoke(() -> {
      InternalRegion region = (InternalRegion) getCache().getRegion(regionName);
      region.put(0, "value3");
      RegionEntry regionEntry = region.getRegionEntry(0);
      // Sneak in and change the version number for an entry to generate a conflict.
      VersionTag tag = regionEntry.getVersionStamp().asVersionTag();
      tag.setEntryVersion(tag.getEntryVersion() - 2);
      regionEntry.getVersionStamp().setVersions(tag);
    });

    // Add an observer to vm0 which will perform a concurrent operation during the GII. If we do a
    // conflict check, this operation will be rejected because it will have a lower entry version
    // that what vm1 recovered from disk
    vm0.invoke(() -> {
      DistributionMessageObserver.setInstance(new DistributionMessageObserver() {

        @Override
        public void beforeProcessMessage(ClusterDistributionManager dm, DistributionMessage msg) {
          if (msg instanceof InitialImageOperation.RequestImageMessage) {
            if (((InitialImageOperation.RequestImageMessage) msg).regionPath.contains(regionName)) {
              createData(vm0, 0, 1, "value4");
              DistributionMessageObserver.setInstance(null);
            }
          }
        }
      });
    });

    // Create vm1, doing a GII
    createPersistentRegion(vm1);

    // If we did a conflict check, this would be value2
    checkData(vm0, 0, 1, "value4");
    checkData(vm1, 0, 1, "value4");
  }

  /**
   * Test that with concurrent updates to an async disk region, we correctly update the RVV On disk
   */
  @Test
  public void testUpdateRVVWithAsyncPersistence() throws Exception {
    VM vm1 = getVM(1);

    // Create a region with async persistence
    vm1.invoke(() -> createRegionWithAsyncPersistence(vm1));

    // In two different threads, perform updates to the same key on the same region
    AsyncInvocation<Void> doPutsInThread1InVM0 = vm1.invokeAsync(() -> {
      Region<String, String> region = getCache().getRegion(regionName);
      for (int i = 0; i < 500; i++) {
        region.put("A", "vm0-" + i);
      }
    });

    AsyncInvocation<Void> doPutsInThread2InVM0 = vm1.invokeAsync(() -> {
      Region<String, String> region = getCache().getRegion(regionName);
      for (int i = 0; i < 500; i++) {
        region.put("A", "vm1-" + i);
      }
    });

    // Wait for the update threads to finish.
    doPutsInThread1InVM0.await();
    doPutsInThread2InVM0.await();

    // Make sure the async queue is flushed to disk
    vm1.invoke(() -> {
      DiskStore diskStore = getCache().findDiskStore(regionName);
      diskStore.flush();
    });

    // Assert that the disk has seen all of the updates
    RegionVersionVector rvv = getRVV(vm1);
    RegionVersionVector diskRVV = getDiskRVV(vm1);
    assertSameRVV(rvv, diskRVV);

    // Bounce the cache and make the same assertion
    closeCache(vm1);

    vm1.invoke(() -> createRegionWithAsyncPersistence(vm1));

    // Assert that the recovered RVV is the same as before the restart
    RegionVersionVector rvv2 = getRVV(vm1);
    assertSameRVV(rvv, rvv2);

    // The disk RVV should also match.
    RegionVersionVector diskRVV2 = getDiskRVV(vm1);
    assertSameRVV(rvv2, diskRVV2);
  }

  /**
   * Test that when we generate a krf, we write the version tag that matches the entry in the crf.
   */
  @Test
  public void testWriteCorrectVersionToKrf() throws Exception {
    VM vm1 = getVM(1);

    InternalRegion region = (InternalRegion) createAsyncRegionWithSmallQueue(vm1);

    // The idea here is to do a bunch of puts with async persistence
    // At some point the oplog will switch. At that time, we wait for a krf
    // to be created and then throw an exception to shutdown the disk store.
    //
    // This should cause us to create a krf with some entries that have been
    // modified since the crf was written and are still in the async queue.
    //
    // To avoid deadlocks, we need to mark that the oplog was switched,
    // and then do the wait in the flusher thread.

    // Setup the callbacks to wait for krf creation and throw an exception
    LocalRegion.ISSUE_CALLBACKS_TO_CACHE_OBSERVER = true;
    try (IgnoredException e = addIgnoredException(DiskAccessException.class)) {
      CountDownLatch krfCreated = new CountDownLatch(1);
      AtomicBoolean oplogSwitched = new AtomicBoolean(false);

      CacheObserverHolder.setInstance(new CacheObserverAdapter() {

        @Override
        public void afterKrfCreated() {
          krfCreated.countDown();
        }

        @Override
        public void afterWritingBytes() {
          if (oplogSwitched.get()) {
            errorCollector
                .checkSucceeds(() -> assertThat(krfCreated.await(3_000, SECONDS)).isTrue());

            throw new DiskAccessException();
          }
        }

        @Override
        public void afterSwitchingOplog() {
          oplogSwitched.set(true);
        }
      });

      // This is just to make sure the first oplog is not completely garbage.
      region.put("testkey", "key");

      // Do some puts to trigger an oplog roll.
      try {
        // Starting with a value of 1 means the value should match
        // the region version for easier debugging.
        int i = 1;
        while (krfCreated.getCount() > 0) {
          i++;
          region.put("key" + (i % 3), i);
          sleep(2);
        }
      } catch (CacheClosedException | DiskAccessException expected) {
        // do nothing
      }

      // Wait for the region to be destroyed. The region won't be destroyed
      // until the async flusher thread ends up switching oplogs
      await().until(region::isDestroyed);
      closeCache();
    } finally {
      LocalRegion.ISSUE_CALLBACKS_TO_CACHE_OBSERVER = false;
      CacheObserverHolder.setInstance(null);
    }

    // Get the version tags from the krf
    InternalRegion recoveredRegion = (InternalRegion) createAsyncRegionWithSmallQueue(vm1);
    VersionTag[] tagsFromKrf = new VersionTag[3];
    for (int i = 0; i < 3; i++) {
      NonTXEntry entry = (NonTXEntry) recoveredRegion.getEntry("key" + i);
      tagsFromKrf[i] = entry.getRegionEntry().getVersionStamp().asVersionTag();
      LogWriterUtils.getLogWriter()
          .info("krfTag[" + i + "]=" + tagsFromKrf[i] + ",value=" + entry.getValue());
    }

    closeCache();

    // Set a system property to skip recovering from the krf so we can
    // get the version tag from the crf.
    System.setProperty(DiskStoreImpl.RECOVER_VALUES_SYNC_PROPERTY_NAME, "true");

    // Get the version tags from the crf
    recoveredRegion = (InternalRegion) createAsyncRegionWithSmallQueue(vm1);
    VersionTag[] tagsFromCrf = new VersionTag[3];
    for (int i = 0; i < 3; i++) {
      NonTXEntry entry = (NonTXEntry) recoveredRegion.getEntry("key" + i);
      tagsFromCrf[i] = entry.getRegionEntry().getVersionStamp().asVersionTag();
      LogWriterUtils.getLogWriter()
          .info("crfTag[" + i + "]=" + tagsFromCrf[i] + ",value=" + entry.getValue());
    }

    // Make sure the version tags from the krf and the crf match.
    for (int i = 0; i < 3; i++) {
      assertThat(tagsFromKrf[i]).isEqualTo(tagsFromCrf[i]);
    }
  }

  private void createRegionWithAsyncPersistence(VM vm) {
    getCache();

    File dir = getDiskDirForVM(vm);
    dir.mkdirs();

    DiskStoreFactory diskStoreFactory = getCache().createDiskStoreFactory();
    diskStoreFactory.setDiskDirs(new File[] {dir});
    diskStoreFactory.setMaxOplogSize(1);
    diskStoreFactory.setQueueSize(100);
    diskStoreFactory.setTimeInterval(1000);

    DiskStore diskStore = diskStoreFactory.create(regionName);

    RegionFactory regionFactory = new RegionFactory();
    regionFactory.setDiskStoreName(diskStore.getName());
    regionFactory.setDataPolicy(DataPolicy.PERSISTENT_REPLICATE);
    regionFactory.setScope(Scope.DISTRIBUTED_ACK);
    regionFactory.setDiskSynchronous(false);

    regionFactory.create(regionName);
  }

  private InternalRegion createRegion(VM vm0) {
    getCache();

    File dir = getDiskDirForVM(vm0);
    dir.mkdirs();

    DiskStoreFactory diskStoreFactory = getCache().createDiskStoreFactory();
    diskStoreFactory.setDiskDirs(new File[] {dir});
    diskStoreFactory.setMaxOplogSize(1);
    // Turn off automatic compaction
    diskStoreFactory.setAllowForceCompaction(true);
    diskStoreFactory.setAutoCompact(false);
    // The compaction javadocs seem to be wrong. This is the amount of live data in the oplog
    diskStoreFactory.setCompactionThreshold(40);

    DiskStore diskStore = diskStoreFactory.create(regionName);

    RegionFactory regionFactory = new RegionFactory();
    regionFactory.setDiskStoreName(diskStore.getName());
    regionFactory.setDiskSynchronous(true);
    regionFactory.setDataPolicy(DataPolicy.PERSISTENT_REPLICATE);
    regionFactory.setScope(Scope.DISTRIBUTED_ACK);

    return (InternalRegion) regionFactory.create(regionName);
  }

  private int getTombstoneCount(InternalRegion region) {
    int regionCount = region.getTombstoneCount();
    int actualCount = 0;
    for (RegionEntry entry : region.getRegionMap().regionEntries()) {
      if (entry.isTombstone()) {
        actualCount++;
      }
    }

    assertThat(actualCount).isEqualTo(regionCount);

    return actualCount;
  }

  private Region createAsyncRegionWithSmallQueue(VM vm0) {
    getCache();

    File dir = getDiskDirForVM(vm0);
    dir.mkdirs();

    DiskStoreFactoryImpl diskStoreFactory =
        (DiskStoreFactoryImpl) getCache().createDiskStoreFactory();
    diskStoreFactory.setDiskDirs(new File[] {dir});
    diskStoreFactory.setMaxOplogSizeInBytes(500);
    diskStoreFactory.setQueueSize(1000);
    diskStoreFactory.setTimeInterval(1000);

    DiskStore diskStore = diskStoreFactory.create(regionName);

    RegionFactory regionFactory = new RegionFactory();
    regionFactory.setDiskStoreName(diskStore.getName());
    regionFactory.setDataPolicy(DataPolicy.PERSISTENT_REPLICATE);
    regionFactory.setScope(Scope.DISTRIBUTED_ACK);
    regionFactory.setDiskSynchronous(false);

    return regionFactory.create(regionName);
  }

  private void deleteKRFs(VM vm) {
    vm.invoke(() -> {
      File file = getDiskDirForVM(vm);
      File[] krfs = file.listFiles((dir, name) -> name.endsWith(".krf"));

      assertThat(krfs.length).isGreaterThan(0);
      for (File krf : krfs) {
        assertThat(krf.delete()).isTrue();
      }
    });
  }

  private void assertSameRVV(RegionVersionVector expectedRVV, RegionVersionVector actualRVV) {
    assertThat(expectedRVV.sameAs(actualRVV))
        .as("Expected " + expectedRVV + " but was " + actualRVV)
        .isTrue();
  }

  private void createData(VM vm, int startKey, int endKey, String value) {
    vm.invoke(() -> {
      Region<Integer, String> region = getCache().getRegion(regionName);

      for (int i = startKey; i < endKey; i++) {
        region.put(i, value);
      }
    });
  }

  private void checkData(VM vm, int startKey, int endKey, String value) {
    vm.invoke(() -> {
      Region<Integer, String> region = getCache().getRegion(regionName);

      for (int i = startKey; i < endKey; i++) {
        assertThat(region.get(i)).as("Value for key " + i).isEqualTo(value);
      }
    });
  }

  protected void delete(VM vm, int startKey, int endKey) {
    vm.invoke(() -> {
      Region<Integer, String> region = getCache().getRegion(regionName);

      for (int i = startKey; i < endKey; i++) {
        region.destroy(i);
      }
    });
  }

  private RegionVersionVector getRVV(VM vm) throws IOException, ClassNotFoundException {
    byte[] result = vm.invoke(() -> {
      InternalRegion region = (InternalRegion) getCache().getRegion(regionName);

      RegionVersionVector rvv = region.getVersionVector();
      rvv = rvv.getCloneForTransmission();
      HeapDataOutputStream hdos = new HeapDataOutputStream(2048);

      // Using gemfire serialization because RegionVersionVector is not java serializable
      DataSerializer.writeObject(rvv, hdos);
      return hdos.toByteArray();
    });

    ByteArrayInputStream bais = new ByteArrayInputStream(result);
    return DataSerializer.readObject(new DataInputStream(bais));
  }

  private RegionVersionVector getDiskRVV(VM vm) throws IOException, ClassNotFoundException {
    byte[] result = vm.invoke(() -> {
      InternalRegion region = (InternalRegion) getCache().getRegion(regionName);

      RegionVersionVector rvv = region.getDiskRegion().getRegionVersionVector();
      rvv = rvv.getCloneForTransmission();
      HeapDataOutputStream hdos = new HeapDataOutputStream(2048);

      // Using gemfire serialization because RegionVersionVector is not java serializable
      DataSerializer.writeObject(rvv, hdos);
      return hdos.toByteArray();
    });

    ByteArrayInputStream bais = new ByteArrayInputStream(result);
    return DataSerializer.readObject(new DataInputStream(bais));
  }
}
