@Override
 public ExecutionPlanConfiguration getActiveExecutionPlanConfiguration(String name, int tenantId) {
   Map<String, ExecutionPlan> executionPlanMap = tenantSpecificExecutionPlans.get(tenantId);
   if (executionPlanMap != null) {
     ExecutionPlan executionPlan = executionPlanMap.get(name);
     if (executionPlan != null) {
       return executionPlan.getExecutionPlanConfiguration();
     }
   }
   return null;
 }
 @Override
 public void setStatisticsEnabled(
     String executionPlanName, boolean isEnabled, AxisConfiguration axisConfiguration)
     throws ExecutionPlanConfigurationException {
   int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
   Map<String, ExecutionPlan> executionPlans = tenantSpecificExecutionPlans.get(tenantId);
   if (executionPlans != null) {
     ExecutionPlan executionPlan = executionPlans.get(executionPlanName);
     executionPlan.getExecutionPlanConfiguration().setStatisticsEnabled(isEnabled);
     editExecutionPlanConfiguration(
         executionPlan.getExecutionPlanConfiguration(),
         executionPlanName,
         tenantId,
         axisConfiguration);
   }
 }
  private void removeExecutionPlanConfiguration(String name, int tenantId) {
    Map<String, ExecutionPlan> executionPlanMap = tenantSpecificExecutionPlans.get(tenantId);
    if (executionPlanMap != null && executionPlanMap.containsKey(name)) {
      ExecutionPlan executionPlan = executionPlanMap.remove(name);
      executionPlan.shutdown();

      ExecutionPlanConfiguration executionPlanConfiguration =
          executionPlan.getExecutionPlanConfiguration();

      // releasing junction listeners.
      for (SiddhiEventConsumer eventConsumer : executionPlan.getSiddhiEventConsumers()) {
        EventProcessorValueHolder.getEventStreamService().unsubscribe(eventConsumer, tenantId);
      }

      for (EventProducer eventProducer : executionPlan.getEventProducers()) {
        EventProcessorValueHolder.getEventStreamService().unsubscribe(eventProducer, tenantId);
      }
    }
  }
  public void deactivateActiveExecutionPlanConfigurations(String streamId, int tenantId) {

    List<String> toDeactivateExecutionPlan = new ArrayList<String>();
    Map<String, ExecutionPlan> executionPlanMap = tenantSpecificExecutionPlans.get(tenantId);
    if (executionPlanMap != null) {
      for (ExecutionPlan executionPlan : executionPlanMap.values()) {
        boolean done = false;
        for (EventProducer eventProducer : executionPlan.getEventProducers()) {
          if (eventProducer.getStreamId().equals(streamId)) {
            toDeactivateExecutionPlan.add(executionPlan.getName());
            done = true;
            break;
          }
        }

        if (!done) {
          for (SiddhiEventConsumer eventConsumer : executionPlan.getSiddhiEventConsumers()) {
            if (eventConsumer.getStreamId().equals(streamId)) {
              toDeactivateExecutionPlan.add(executionPlan.getName());
              break;
            }
          }
        }
      }
    }
    if (toDeactivateExecutionPlan.size() > 0) {
      for (String name : toDeactivateExecutionPlan) {
        ExecutionPlanConfigurationFile executionPlanConfigurationFile =
            getExecutionPlanConfigurationFileByPlanName(name, tenantId);
        try {
          EventProcessorConfigurationFilesystemInvoker.reload(
              executionPlanConfigurationFile.getFileName(),
              executionPlanConfigurationFile.getAxisConfiguration());
        } catch (Exception e) {
          log.error(
              "Exception occurred while trying to deploy the Execution Plan configuration file : "
                  + new File(executionPlanConfigurationFile.getFileName()).getName());
        }
      }
    }
  }
  public void addExecutionPlanConfiguration(
      ExecutionPlanConfiguration executionPlanConfiguration, AxisConfiguration axisConfiguration)
      throws ExecutionPlanDependencyValidationException, ExecutionPlanConfigurationException,
          ServiceDependencyValidationException {
    int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
    Map<String, ExecutionPlan> tenantExecutionPlans = tenantSpecificExecutionPlans.get(tenantId);
    if (tenantExecutionPlans == null) {
      tenantExecutionPlans = new ConcurrentHashMap<String, ExecutionPlan>();
      tenantSpecificExecutionPlans.put(tenantId, tenantExecutionPlans);
    } else if (tenantExecutionPlans.get(executionPlanConfiguration.getName()) != null) {
      // if an execution plan with the same name already exists, we are not going to override it
      // with this plan.
      throw new ExecutionPlanConfigurationException(
          "Execution plan with the same name already exists. Please remove it and retry.");
    }

    // This iteration exists only as a check. Actual usage of imported stream configs is further
    // down
    for (StreamConfiguration streamConfiguration :
        executionPlanConfiguration.getImportedStreams()) {
      try {
        StreamDefinition streamDefinition =
            EventProcessorValueHolder.getEventStreamService()
                .getStreamDefinition(streamConfiguration.getStreamId(), tenantId);
        if (streamDefinition == null) {
          throw new ExecutionPlanDependencyValidationException(
              streamConfiguration.getStreamId(),
              "Imported Stream " + streamConfiguration.getStreamId() + " does not exist");
        }
      } catch (EventStreamConfigurationException e) {
        throw new ExecutionPlanConfigurationException(
            "Error in retrieving stream ID : " + streamConfiguration.getStreamId());
      }
    }

    // This iteration exists only as a check. Actual usage of exported stream configs is further
    // down
    for (StreamConfiguration streamConfiguration :
        executionPlanConfiguration.getExportedStreams()) {
      try {
        StreamDefinition streamDefinition =
            EventProcessorValueHolder.getEventStreamService()
                .getStreamDefinition(streamConfiguration.getStreamId(), tenantId);
        if (streamDefinition == null) {
          throw new ExecutionPlanDependencyValidationException(
              streamConfiguration.getStreamId(),
              "Exported Stream " + streamConfiguration.getStreamId() + " does not exist");
        }
      } catch (EventStreamConfigurationException e) {
        throw new ExecutionPlanConfigurationException(
            "Error in retrieving stream ID : " + streamConfiguration.getStreamId());
      }
    }

    Map<String, InputHandler> inputHandlerMap =
        new ConcurrentHashMap<String, InputHandler>(
            executionPlanConfiguration.getImportedStreams().size());

    SiddhiConfiguration siddhiConfig =
        getSiddhiConfigurationFor(executionPlanConfiguration, tenantId);
    SiddhiManager siddhiManager =
        getSiddhiManagerFor(executionPlanConfiguration, siddhiConfig, inputHandlerMap);

    for (StreamConfiguration importedStreamConfiguration :
        executionPlanConfiguration.getImportedStreams()) {
      org.wso2.siddhi.query.api.definition.StreamDefinition siddhiStreamDefinition =
          new org.wso2.siddhi.query.api.definition.StreamDefinition();
      siddhiStreamDefinition.name(importedStreamConfiguration.getSiddhiStreamName());
      StreamDefinition streamDefinition = null;
      try {
        streamDefinition =
            EventProcessorValueHolder.getEventStreamService()
                .getStreamDefinition(importedStreamConfiguration.getStreamId(), tenantId);

        populateAttributes(
            siddhiStreamDefinition,
            streamDefinition.getMetaData(),
            EventProcessorConstants.META + EventProcessorConstants.ATTRIBUTE_SEPARATOR);
        populateAttributes(
            siddhiStreamDefinition,
            streamDefinition.getCorrelationData(),
            EventProcessorConstants.CORRELATION + EventProcessorConstants.ATTRIBUTE_SEPARATOR);
        populateAttributes(siddhiStreamDefinition, streamDefinition.getPayloadData(), "");
        InputHandler inputHandler = siddhiManager.defineStream(siddhiStreamDefinition);
        inputHandlerMap.put(streamDefinition.getStreamId(), inputHandler);
        log.debug("input handler created for " + siddhiStreamDefinition.getStreamId());
      } catch (EventStreamConfigurationException e) {
        // ignored as this will not happen
      }
    }

    for (StreamConfiguration exportedStreamConfiguration :
        executionPlanConfiguration.getExportedStreams()) {
      org.wso2.siddhi.query.api.definition.StreamDefinition siddhiStreamDefinition =
          new org.wso2.siddhi.query.api.definition.StreamDefinition();
      siddhiStreamDefinition.name(exportedStreamConfiguration.getSiddhiStreamName());
      StreamDefinition streamDefinition = null;
      try {
        streamDefinition =
            EventProcessorValueHolder.getEventStreamService()
                .getStreamDefinition(exportedStreamConfiguration.getStreamId(), tenantId);

        populateAttributes(
            siddhiStreamDefinition,
            streamDefinition.getMetaData(),
            EventProcessorConstants.META + EventProcessorConstants.ATTRIBUTE_SEPARATOR);
        populateAttributes(
            siddhiStreamDefinition,
            streamDefinition.getCorrelationData(),
            EventProcessorConstants.CORRELATION + EventProcessorConstants.ATTRIBUTE_SEPARATOR);
        populateAttributes(siddhiStreamDefinition, streamDefinition.getPayloadData(), "");
        siddhiManager.defineStream(siddhiStreamDefinition);
        log.debug("stream defined for " + siddhiStreamDefinition.getStreamId());
      } catch (EventStreamConfigurationException e) {
        // ignored as this will not happen
      }
    }

    HAManager haManager = null;
    String isDistributedProcessingEnabledString =
        executionPlanConfiguration
            .getSiddhiConfigurationProperties()
            .get(EventProcessorConstants.SIDDHI_DISTRIBUTED_PROCESSING);
    if (isDistributedProcessingEnabledString != null
        && isDistributedProcessingEnabledString.equalsIgnoreCase("RedundantNode")) {
      haManager =
          new HAManager(
              EventProcessorValueHolder.getHazelcastInstance(),
              executionPlanConfiguration.getName(),
              tenantId,
              siddhiManager,
              inputHandlerMap.size(),
              currentCepMembershipInfo);
    }

    try {
      siddhiManager.addExecutionPlan(executionPlanConfiguration.getQueryExpressions());
    } catch (Exception e) {
      throw new ExecutionPlanConfigurationException(
          "Invalid query specified, " + e.getMessage(), e);
    }

    ExecutionPlan executionPlan =
        new ExecutionPlan(
            executionPlanConfiguration.getName(),
            siddhiManager,
            executionPlanConfiguration,
            haManager);
    tenantExecutionPlans.put(executionPlanConfiguration.getName(), executionPlan);

    // subscribe output to junction
    SindhiStormOutputEventListener stormOutputListener = null;
    if (isRunningOnStorm) {
      stormOutputListener =
          new SindhiStormOutputEventListener(executionPlanConfiguration, tenantId);
    }
    for (StreamConfiguration exportedStreamConfiguration :
        executionPlanConfiguration.getExportedStreams()) {

      SiddhiOutputStreamListener streamCallback;

      if (haManager != null) {
        streamCallback =
            new SiddhiHAOutputStreamListener(
                exportedStreamConfiguration.getSiddhiStreamName(),
                exportedStreamConfiguration.getStreamId(),
                executionPlanConfiguration,
                tenantId);
        haManager.addStreamCallback((SiddhiHAOutputStreamListener) streamCallback);
      } else {
        streamCallback =
            new SiddhiOutputStreamListener(
                exportedStreamConfiguration.getSiddhiStreamName(),
                exportedStreamConfiguration.getStreamId(),
                executionPlanConfiguration,
                tenantId);

        if (isRunningOnStorm) {
          stormOutputListener.registerOutputStreamListener(
              exportedStreamConfiguration.getSiddhiStreamName(), streamCallback);
        }
      }
      siddhiManager.addCallback(exportedStreamConfiguration.getSiddhiStreamName(), streamCallback);
      try {
        EventProcessorValueHolder.getEventStreamService().subscribe(streamCallback, tenantId);
      } catch (EventStreamConfigurationException e) {
        // ignored as this will never happen
      }
      executionPlan.addProducer(streamCallback);
    }

    // subscribe input to junction
    for (StreamConfiguration importedStreamConfiguration :
        executionPlanConfiguration.getImportedStreams()) {
      InputHandler inputHandler = inputHandlerMap.get(importedStreamConfiguration.getStreamId());

      AbstractSiddhiInputEventDispatcher eventDispatcher = null;
      if (haManager != null) {
        eventDispatcher =
            new SiddhiHAInputEventDispatcher(
                importedStreamConfiguration.getStreamId(),
                inputHandler,
                executionPlanConfiguration,
                tenantId,
                haManager.getProcessThreadPoolExecutor(),
                haManager.getThreadBarrier());
        haManager.addInputEventDispatcher(
            importedStreamConfiguration.getStreamId(),
            (SiddhiHAInputEventDispatcher) eventDispatcher);
      } else if (isRunningOnStorm) {
        StreamDefinition streamDefinition = null;
        try {
          streamDefinition =
              EventProcessorValueHolder.getEventStreamService()
                  .getStreamDefinition(importedStreamConfiguration.getStreamId(), tenantId);
        } catch (EventStreamConfigurationException e) {
          // Ignore as this would never happen
        }
        eventDispatcher =
            new SiddhiStormInputEventDispatcher(
                streamDefinition,
                importedStreamConfiguration.getSiddhiStreamName(),
                executionPlanConfiguration,
                tenantId);
      } else {
        eventDispatcher =
            new SiddhiInputEventDispatcher(
                importedStreamConfiguration.getStreamId(),
                inputHandler,
                executionPlanConfiguration,
                tenantId);
      }

      try {
        EventProcessorValueHolder.getEventStreamService().subscribe(eventDispatcher, tenantId);
        executionPlan.addConsumer(eventDispatcher);

      } catch (EventStreamConfigurationException e) {
        // ignored as this will never happen
      }
    }

    if (haManager != null) {
      haManager.init();
    }
  }