/*
 * 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.cache.EvictionAlgorithm.NONE;
import static org.apache.geode.cache.EvictionAttributes.createLRUEntryAttributes;
import static org.apache.geode.cache.PartitionAttributesFactory.RECOVERY_DELAY_DEFAULT;
import static org.apache.geode.internal.cache.PartitionedRegion.RETRY_TIMEOUT_PROPERTY;
import static org.apache.geode.internal.cache.PartitionedRegionHelper.BYTES_PER_MB;
import static org.apache.geode.test.dunit.Host.getHost;
import static org.assertj.core.api.Assertions.assertThat;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

import org.apache.geode.cache.EvictionAction;
import org.apache.geode.cache.EvictionAttributes;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionAttributes;
import org.apache.geode.test.dunit.VM;
import org.apache.geode.test.dunit.cache.CacheTestCase;
import org.apache.geode.test.dunit.rules.DistributedRestoreSystemProperties;

/**
 * This class is to test LOCAL_MAX_MEMORY property of partition region while creation of bucket.
 */

@SuppressWarnings("serial")
public class PartitionedRegionLocalMaxMemoryDUnitTest extends CacheTestCase {

  private static final String RETRY_TIMEOUT_PROPERTY_VALUE = "20000";
  private static final int LOCAL_MAX_MEMORY = 1;
  private static final long EXPECTED_LOCAL_MAX_MEMORY = LOCAL_MAX_MEMORY * BYTES_PER_MB;
  private static final int REDUNDANCY = 1;

  private String regionName;
  private boolean evict;

  private VM vm0;
  private VM vm1;

  @Rule
  public DistributedRestoreSystemProperties restoreSystemProperties =
      new DistributedRestoreSystemProperties();

  @Before
  public void setUp() {
    vm0 = getHost(0).getVM(0);
    vm1 = getHost(0).getVM(1);

    regionName = getUniqueName();
    evict = false;
  }

  protected RegionAttributes<?, ?> createRegionAttrsForPR(int redundancy, int localMaxMemory,
      long recoveryDelay, EvictionAttributes evictionAttributes) {
    return PartitionedRegionTestHelper.createRegionAttrsForPR(redundancy, localMaxMemory,
        recoveryDelay, evictionAttributes, null);
  }

  /**
   * This test performs following operations <br>
   * 1. Create Partition region with LOCAL_MAX_MEMORY = 1MB on all the VMs <br>
   * 2. Put objects in partition region so that only one bucket gets created and size of that bucket
   * exceeds LOCAL_MAX_MEMORY <br>
   * 3. Put object such that new bucket gets formed <br>
   * 4. Test should create a new bucket
   */
  @Test
  public void testLocalMaxMemoryInPartitionedRegion() {
    evict = false;

    vm0.invoke(() -> createMultiplePartitionRegion(evict));
    vm1.invoke(() -> createMultiplePartitionRegion(evict));

    vm0.invoke(() -> validateEvictionIsEnabled(evict));
    vm1.invoke(() -> validateEvictionIsEnabled(evict));

    // puts to one bucket to use up LOCAL_MAX_MEMORY
    vm0.invoke(() -> fillDataStoreWithPutsToOneBucket(10));
    long currentAllocatedMemory = vm0.invoke(() -> validateDataStoreExceedsLocalMaxMemory());

    // exceed LOCAL_MAX_MEMORY
    vm0.invoke(() -> putOneObjectInPartitionedRegion(21));
    vm0.invoke(() -> validateDataStoreExceeds(currentAllocatedMemory));
  }

  /**
   * This test makes sure that we don't enforce the LOCAL_MAX_MEMORY setting when eviction is
   * enabled.
   */
  @Test
  public void testLocalMaxMemoryInPartitionedRegionWithEviction() {
    evict = true;

    vm0.invoke(() -> createMultiplePartitionRegion(evict));
    vm1.invoke(() -> createMultiplePartitionRegion(evict));

    vm0.invoke(() -> validateEvictionIsEnabled(evict));
    vm1.invoke(() -> validateEvictionIsEnabled(evict));

    // puts to one bucket to use up LOCAL_MAX_MEMORY
    vm0.invoke(() -> fillDataStoreWithPutsToOneBucket(10));

    // exceed LOCAL_MAX_MEMORY
    vm0.invoke(() -> putOneObjectInPartitionedRegion(21));
    vm0.invoke(() -> validateDataStoreExceeds(EXPECTED_LOCAL_MAX_MEMORY));
  }

  private void putOneObjectInPartitionedRegion(final int objectId) {
    Region<TestObjectWithIdentifier, TestObjectWithIdentifier> region =
        getCache().getRegion(regionName);
    TestObjectWithIdentifier kv =
        new TestObjectWithIdentifier("TestObjectWithIdentifier-" + 0, objectId);
    region.put(kv, kv);
  }

  private void fillDataStoreWithPutsToOneBucket(final int objectId) {
    Region<TestObjectWithIdentifier, TestObjectWithIdentifier> region =
        getCache().getRegion(regionName);
    fillAllMemoryWithPuts(region, objectId);

    PartitionedRegionDataStore dataStore = ((PartitionedRegion) region).getDataStore();
    assertThat(dataStore.getLocalBucket2RegionMap()).hasSize(1);
  }

  private void fillAllMemoryWithPuts(
      final Region<TestObjectWithIdentifier, TestObjectWithIdentifier> region, final int objectId) {
    PartitionedRegion partitionedRegion = (PartitionedRegion) region;
    assertThat(partitionedRegion.getLocalMaxMemory()).isEqualTo(LOCAL_MAX_MEMORY);

    PartitionedRegionDataStore dataStore = partitionedRegion.getDataStore();
    for (int i = 0; dataStore.currentAllocatedMemory() <= EXPECTED_LOCAL_MAX_MEMORY; i++) {
      TestObjectWithIdentifier id =
          new TestObjectWithIdentifier("TestObjectWithIdentifier-" + i, objectId);
      region.put(id, id);
    }
    assertThat(dataStore.getLocalBucket2RegionMap()).hasSize(1);
  }

  private long validateDataStoreExceedsLocalMaxMemory() {
    Region<TestObjectWithIdentifier, TestObjectWithIdentifier> region =
        getCache().getRegion(regionName);
    PartitionedRegion partitionedRegion = (PartitionedRegion) region;
    assertThat(partitionedRegion.getLocalMaxMemory()).isEqualTo(LOCAL_MAX_MEMORY);

    PartitionedRegionDataStore dataStore = partitionedRegion.getDataStore();
    assertThat(dataStore.currentAllocatedMemory())
        .isGreaterThanOrEqualTo(EXPECTED_LOCAL_MAX_MEMORY);

    return dataStore.currentAllocatedMemory();
  }

  private void validateDataStoreExceeds(final long memory) {
    Region<TestObjectWithIdentifier, TestObjectWithIdentifier> region =
        getCache().getRegion(regionName);
    PartitionedRegion partitionedRegion = (PartitionedRegion) region;

    PartitionedRegionDataStore dataStore = partitionedRegion.getDataStore();
    assertThat(dataStore.currentAllocatedMemory()).isGreaterThanOrEqualTo(memory);
  }

  private void validateEvictionIsEnabled(final boolean evict) {
    Region<TestObjectWithIdentifier, TestObjectWithIdentifier> region =
        getCache().getRegion(regionName);
    RegionAttributes regionAttributes = region.getAttributes();
    if (evict) {
      assertThat(regionAttributes.getEvictionAttributes().getAlgorithm()).isNotEqualTo(NONE);
    } else {
      assertThat(regionAttributes.getEvictionAttributes().getAlgorithm()).isEqualTo(NONE);
    }
  }

  private void createMultiplePartitionRegion(final boolean evict) {
    String value = setSystemProperty(RETRY_TIMEOUT_PROPERTY, RETRY_TIMEOUT_PROPERTY_VALUE);
    try {
      EvictionAttributes evictionAttributes = getEvictionAttributes(evict);
      getCache().createRegion(regionName, createRegionAttrsForPR(REDUNDANCY, LOCAL_MAX_MEMORY,
          RECOVERY_DELAY_DEFAULT, evictionAttributes));
    } finally {
      setSystemProperty(RETRY_TIMEOUT_PROPERTY, value);
    }
  }

  private EvictionAttributes getEvictionAttributes(final boolean evict) {
    if (evict) {
      return createLRUEntryAttributes(Integer.MAX_VALUE, EvictionAction.LOCAL_DESTROY);
    } else {
      return null;
    }
  }

  private String setSystemProperty(final String property, final String value) {
    if (value == null) {
      return System.clearProperty(property);
    } else {
      return System.setProperty(property, value);
    }
  }
}
