/*
 * 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.hadoop.ozone.om;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.apache.hadoop.hdds.conf.OzoneConfiguration;
import org.apache.hadoop.hdds.scm.container.common.helpers.ExcludeList;
import org.apache.hadoop.hdds.server.ServerUtils;
import org.apache.hadoop.ozone.om.helpers.OmBucketInfo;
import org.apache.hadoop.ozone.om.helpers.OmKeyArgs;
import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs;
import org.apache.hadoop.ozone.om.helpers.OpenKeySession;
import org.apache.hadoop.ozone.om.request.TestOMRequestUtils;
import org.apache.hadoop.test.GenericTestUtils;
import org.apache.hadoop.hdds.utils.db.DBConfigFromFile;

import org.apache.commons.lang3.RandomStringUtils;
import static org.apache.hadoop.hdds.HddsConfigKeys.HDDS_CONTAINER_REPORT_INTERVAL;
import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_BLOCK_DELETING_SERVICE_INTERVAL;

import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

/**
 * Test Key Deleting Service.
 * <p>
 * This test does the following things.
 * <p>
 * 1. Creates a bunch of keys. 2. Then executes delete key directly using
 * Metadata Manager. 3. Waits for a while for the KeyDeleting Service to pick up
 * and call into SCM. 4. Confirms that calls have been successful.
 */
public class TestKeyDeletingService {
  @Rule
  public TemporaryFolder folder = new TemporaryFolder();

  private OzoneConfiguration createConfAndInitValues() throws IOException {
    OzoneConfiguration conf = new OzoneConfiguration();
    File newFolder = folder.newFolder();
    if (!newFolder.exists()) {
      Assert.assertTrue(newFolder.mkdirs());
    }
    System.setProperty(DBConfigFromFile.CONFIG_DIR, "/");
    ServerUtils.setOzoneMetaDirPath(conf, newFolder.toString());
    conf.setTimeDuration(OZONE_BLOCK_DELETING_SERVICE_INTERVAL, 100,
        TimeUnit.MILLISECONDS);
    conf.setTimeDuration(HDDS_CONTAINER_REPORT_INTERVAL, 200,
        TimeUnit.MILLISECONDS);
    conf.setQuietMode(false);

    return conf;
  }

  /**
   * In this test, we create a bunch of keys and delete them. Then we start the
   * KeyDeletingService and pass a SCMClient which does not fail. We make sure
   * that all the keys that we deleted is picked up and deleted by
   * OzoneManager.
   *
   * @throws IOException - on Failure.
   */

  @Test(timeout = 30000)
  public void checkIfDeleteServiceisDeletingKeys()
      throws IOException, TimeoutException, InterruptedException {
    OzoneConfiguration conf = createConfAndInitValues();
    OmMetadataManagerImpl metaMgr = new OmMetadataManagerImpl(conf);
    KeyManager keyManager =
        new KeyManagerImpl(
            new ScmBlockLocationTestingClient(null, null, 0),
            metaMgr, conf, UUID.randomUUID().toString(), null);
    keyManager.start(conf);
    final int keyCount = 100;
    createAndDeleteKeys(keyManager, keyCount, 1);
    KeyDeletingService keyDeletingService =
        (KeyDeletingService) keyManager.getDeletingService();
    GenericTestUtils.waitFor(
        () -> keyDeletingService.getDeletedKeyCount().get() >= keyCount,
        1000, 10000);
    Assert.assertTrue(keyDeletingService.getRunCount().get() > 1);
    Assert.assertEquals(
        keyManager.getPendingDeletionKeys(Integer.MAX_VALUE).size(), 0);
  }

  @Test(timeout = 30000)
  public void checkIfDeleteServiceWithFailingSCM()
      throws IOException, TimeoutException, InterruptedException {
    OzoneConfiguration conf = createConfAndInitValues();
    OmMetadataManagerImpl metaMgr = new OmMetadataManagerImpl(conf);
    //failCallsFrequency = 1 , means all calls fail.
    KeyManager keyManager =
        new KeyManagerImpl(
            new ScmBlockLocationTestingClient(null, null, 1),
            metaMgr, conf, UUID.randomUUID().toString(), null);
    keyManager.start(conf);
    final int keyCount = 100;
    createAndDeleteKeys(keyManager, keyCount, 1);
    KeyDeletingService keyDeletingService =
        (KeyDeletingService) keyManager.getDeletingService();
    keyManager.start(conf);
    Assert.assertEquals(
        keyManager.getPendingDeletionKeys(Integer.MAX_VALUE).size(), keyCount);
    // Make sure that we have run the background thread 5 times more
    GenericTestUtils.waitFor(
        () -> keyDeletingService.getRunCount().get() >= 5,
        100, 1000);
    // Since SCM calls are failing, deletedKeyCount should be zero.
    Assert.assertEquals(keyDeletingService.getDeletedKeyCount().get(), 0);
    Assert.assertEquals(
        keyManager.getPendingDeletionKeys(Integer.MAX_VALUE).size(), keyCount);
  }

  @Test(timeout = 30000)
  public void checkDeletionForEmptyKey()
      throws IOException, TimeoutException, InterruptedException {
    OzoneConfiguration conf = createConfAndInitValues();
    OmMetadataManagerImpl metaMgr = new OmMetadataManagerImpl(conf);
    //failCallsFrequency = 1 , means all calls fail.
    KeyManager keyManager =
        new KeyManagerImpl(
            new ScmBlockLocationTestingClient(null, null, 1),
            metaMgr, conf, UUID.randomUUID().toString(), null);
    keyManager.start(conf);
    final int keyCount = 100;
    createAndDeleteKeys(keyManager, keyCount, 0);
    KeyDeletingService keyDeletingService =
        (KeyDeletingService) keyManager.getDeletingService();
    keyManager.start(conf);

    // Since empty keys are directly deleted from db there should be no
    // pending deletion keys. Also deletedKeyCount should be zero.
    Assert.assertEquals(
        keyManager.getPendingDeletionKeys(Integer.MAX_VALUE).size(), 0);
    // Make sure that we have run the background thread 2 times or more
    GenericTestUtils.waitFor(
        () -> keyDeletingService.getRunCount().get() >= 2,
        100, 1000);
    Assert.assertEquals(keyDeletingService.getDeletedKeyCount().get(), 0);
  }

  private void createAndDeleteKeys(KeyManager keyManager, int keyCount,
      int numBlocks) throws IOException {
    for (int x = 0; x < keyCount; x++) {
      String volumeName = String.format("volume%s",
          RandomStringUtils.randomAlphanumeric(5));
      String bucketName = String.format("bucket%s",
          RandomStringUtils.randomAlphanumeric(5));
      String keyName = String.format("key%s",
          RandomStringUtils.randomAlphanumeric(5));
      String volumeBytes =
          keyManager.getMetadataManager().getVolumeKey(volumeName);
      String bucketBytes =
          keyManager.getMetadataManager().getBucketKey(volumeName, bucketName);
      // cheat here, just create a volume and bucket entry so that we can
      // create the keys, we put the same data for key and value since the
      // system does not decode the object
      TestOMRequestUtils.addVolumeToOM(keyManager.getMetadataManager(),
          OmVolumeArgs.newBuilder()
              .setOwnerName("o")
              .setAdminName("a")
              .setVolume(volumeName)
              .build());

      TestOMRequestUtils.addBucketToOM(keyManager.getMetadataManager(),
          OmBucketInfo.newBuilder().setVolumeName(volumeName)
              .setBucketName(bucketName)
              .build());

      OmKeyArgs arg =
          new OmKeyArgs.Builder()
              .setVolumeName(volumeName)
              .setBucketName(bucketName)
              .setKeyName(keyName)
              .setAcls(Collections.emptyList())
              .setLocationInfoList(new ArrayList<>())
              .build();
      //Open, Commit and Delete the Keys in the Key Manager.
      OpenKeySession session = keyManager.openKey(arg);
      for (int i = 0; i < numBlocks; i++) {
        arg.addLocationInfo(
            keyManager.allocateBlock(arg, session.getId(), new ExcludeList()));
      }
      keyManager.commitKey(arg, session.getId());
      keyManager.deleteKey(arg);
    }
  }
}