package org.apache.helix.controller.stages;

/*
 * 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.HashMap;
import java.util.Map;

import org.apache.helix.HelixDefinedState;
import org.apache.helix.HelixManager;
import org.apache.helix.controller.LogUtil;
import org.apache.helix.controller.common.PartitionStateMap;
import org.apache.helix.controller.dataproviders.ResourceControllerDataProvider;
import org.apache.helix.controller.pipeline.AbstractAsyncBaseStage;
import org.apache.helix.controller.pipeline.AsyncWorkerType;
import org.apache.helix.model.BuiltInStateModelDefinitions;
import org.apache.helix.model.IdealState;
import org.apache.helix.model.MaintenanceSignal;
import org.apache.helix.model.Partition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MaintenanceRecoveryStage extends AbstractAsyncBaseStage {
  private static Logger LOG = LoggerFactory.getLogger(MaintenanceRecoveryStage.class);

  @Override
  public AsyncWorkerType getAsyncWorkerType() {
    return AsyncWorkerType.MaintenanceRecoveryWorker;
  }

  @Override
  public void execute(final ClusterEvent event) throws Exception {
    // Check the cache is there
    ResourceControllerDataProvider cache =
        event.getAttribute(AttributeName.ControllerDataProvider.name());
    if (cache == null) {
      return;
    }

    // Check if the maintenance signal has been changed during this pipeline run
    // If true, skip this stage because the Controller already changed the signal
    // The flag will be flipped in the next ReadClusterDataStage()
    if (cache.hasMaintenanceSignalChanged()) {
      return;
    }

    // Check for the maintenance signal
    // If it was entered manually or the signal is null (which shouldn't happen), skip this stage
    MaintenanceSignal maintenanceSignal = cache.getMaintenanceSignal();
    if (maintenanceSignal == null || maintenanceSignal
        .getTriggeringEntity() != MaintenanceSignal.TriggeringEntity.CONTROLLER) {
      return;
    }

    HelixManager manager = event.getAttribute(AttributeName.helixmanager.name());
    if (manager == null || !manager.isConnected()) {
      LogUtil.logInfo(LOG, _eventId,
          "MaintenanceRecoveryStage failed due to HelixManager being null or not connected!");
      return;
    }

    // At this point, the cluster entered maintenance mode automatically. Retrieve the
    // auto-triggering reason
    MaintenanceSignal.AutoTriggerReason internalReason = maintenanceSignal.getAutoTriggerReason();
    boolean shouldExitMaintenance;
    String reason;
    switch (internalReason) {
    case MAX_OFFLINE_INSTANCES_EXCEEDED:
      // Check on the number of offline/disabled instances
      int numOfflineInstancesForAutoExit =
          cache.getClusterConfig().getNumOfflineInstancesForAutoExit();
      if (numOfflineInstancesForAutoExit < 0) {
        return; // Config is not set, no auto-exit
      }
      // Get the count of all instances that are either offline or disabled
      int offlineDisabledCount =
          cache.getAllInstances().size() - cache.getEnabledLiveInstances().size();
      shouldExitMaintenance = offlineDisabledCount <= numOfflineInstancesForAutoExit;
      reason = String.format(
          "Auto-exiting maintenance mode for cluster %s; Num. of offline/disabled instances is %d, less than or equal to the exit threshold %d",
          event.getClusterName(), offlineDisabledCount, numOfflineInstancesForAutoExit);
      break;
    case MAX_PARTITION_PER_INSTANCE_EXCEEDED:
      IntermediateStateOutput intermediateStateOutput =
          event.getAttribute(AttributeName.INTERMEDIATE_STATE.name());
      if (intermediateStateOutput == null) {
        return;
      }
      shouldExitMaintenance = !violatesMaxPartitionsPerInstance(cache, intermediateStateOutput);
      reason = String.format(
          "Auto-exiting maintenance mode for cluster %s; All instances have fewer or equal number of partitions than maxPartitionsPerInstance threshold.",
          event.getClusterName());
      break;
    default:
      shouldExitMaintenance = false;
      reason = "";
    }
    if (shouldExitMaintenance) {
      // The cluster has recovered sufficiently, so proceed to exit the maintenance mode by removing
      // MaintenanceSignal. AutoTriggerReason won't be recorded
      manager.getClusterManagmentTool().autoEnableMaintenanceMode(manager.getClusterName(), false,
          reason, internalReason);
      cache.setMaintenanceSignalChanged(); // Set the flag so we do not double enable/disable
      LogUtil.logInfo(LOG, _eventId, reason);
    }
  }

  /**
   * Check that the intermediateStateOutput assignment does not violate maxPartitionPerInstance
   * threshold.
   * @param cache
   * @param intermediateStateOutput
   * @return true if violation is found, false otherwise.
   */
  private boolean violatesMaxPartitionsPerInstance(ResourceControllerDataProvider cache,
      IntermediateStateOutput intermediateStateOutput) {
    int maxPartitionPerInstance = cache.getClusterConfig().getMaxPartitionsPerInstance();
    if (maxPartitionPerInstance <= 0) {
      // Config is not set; return
      return false;
    }
    Map<String, PartitionStateMap> resourceStatesMap =
        intermediateStateOutput.getResourceStatesMap();
    Map<String, Integer> instancePartitionCounts = new HashMap<>();

    for (String resource : resourceStatesMap.keySet()) {
      IdealState idealState = cache.getIdealState(resource);
      if (idealState != null
          && idealState.getStateModelDefRef().equals(BuiltInStateModelDefinitions.Task.name())) {
        // Ignore task here. Task has its own throttling logic
        continue;
      }

      PartitionStateMap partitionStateMap = resourceStatesMap.get(resource);
      Map<Partition, Map<String, String>> stateMaps = partitionStateMap.getStateMap();
      for (Partition p : stateMaps.keySet()) {
        Map<String, String> stateMap = stateMaps.get(p);
        for (String instance : stateMap.keySet()) {
          // If this replica is in DROPPED state, do not count it in the partition count since it is
          // to be dropped
          String state = stateMap.get(instance);
          if (state.equals(HelixDefinedState.DROPPED.name())) {
            continue;
          }
          if (!instancePartitionCounts.containsKey(instance)) {
            instancePartitionCounts.put(instance, 0);
          }
          // Number of replicas (from different partitions) held in this instance
          int partitionCount = instancePartitionCounts.get(instance);
          partitionCount++;
          if (partitionCount > maxPartitionPerInstance) {
            // There exists an instance whose intermediate state assignment violates the maximum
            // partitions per instance threshold, return!
            return true;
          }
          instancePartitionCounts.put(instance, partitionCount);
        }
      }
    }
    // No violation found
    return false;
  }
}
