<commit_before>/**
 * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */
package com.opengamma.engine.view;

import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.engine.marketdata.MarketDataInjector;
import com.opengamma.engine.marketdata.MarketDataPermissionProvider;
import com.opengamma.engine.value.ValueRequirement;
import com.opengamma.engine.view.calc.ViewCycleMetadata;
import com.opengamma.engine.view.calc.EngineResourceManagerInternal;
import com.opengamma.engine.view.calc.SingleComputationCycle;
import com.opengamma.engine.view.calc.ViewComputationJob;
import com.opengamma.engine.view.calc.ViewCycle;
import com.opengamma.engine.view.client.ViewDeltaResultCalculator;
import com.opengamma.engine.view.compilation.CompiledViewDefinitionWithGraphsImpl;
import com.opengamma.engine.view.execution.ViewCycleExecutionOptions;
import com.opengamma.engine.view.execution.ViewExecutionOptions;
import com.opengamma.engine.view.listener.ViewResultListener;
import com.opengamma.engine.view.permission.ViewPermissionProvider;
import com.opengamma.id.ObjectId;
import com.opengamma.id.UniqueId;
import com.opengamma.livedata.UserPrincipal;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.Lifecycle;

import javax.time.Instant;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock;


/**
 * Default implementation of {@link ViewProcess}.
 */
public class ViewProcessImpl implements ViewProcessInternal, Lifecycle {

  private static final Logger s_logger = LoggerFactory.getLogger(ViewProcess.class);

  private final UniqueId _viewProcessId;
  private final UniqueId _viewDefinitionId;
  private final ViewExecutionOptions _executionOptions;
  private final ViewProcessContext _viewProcessContext;
  private final ObjectId _cycleObjectId;
  private final EngineResourceManagerInternal<SingleComputationCycle> _cycleManager;

  private final AtomicLong _cycleVersion = new AtomicLong();

  /**
   * Manages access to critical regions of the process. Note that the use of {@link Semaphore} rather than, for example,
   * {@link ReentrantLock} allows one thread to acquire the lock and another thread to release it as part of the same
   * sequence of operations. This could be important for {@link #suspend()} and {@link #resume()}. 
   */
  private final Semaphore _processLock = new Semaphore(1);

  private final Set<ViewResultListener> _listeners = new HashSet<ViewResultListener>();

  private volatile ViewProcessState _state = ViewProcessState.STOPPED;

  private volatile ViewComputationJob _computationJob;
  private volatile Thread _computationThread;

  private final AtomicReference<Pair<CompiledViewDefinitionWithGraphsImpl, MarketDataPermissionProvider>> _latestCompiledViewDefinition =
      new AtomicReference<Pair<CompiledViewDefinitionWithGraphsImpl, MarketDataPermissionProvider>>();
  private final AtomicReference<ViewComputationResultModel> _latestResult = new AtomicReference<ViewComputationResultModel>();

  private ExecutorService _calcJobResultExecutorService = Executors.newSingleThreadExecutor();



  /**
   * Constructs an instance.
   *
   * @param viewProcessId  the unique identifier of the view process, not null
   * @param viewDefinitionId  the name of the view definition, not null
   * @param executionOptions  the view execution options, not null
   * @param viewProcessContext  the process context, not null
   * @param cycleManager  the view cycle manager, not null
   * @param cycleObjectId  the object identifier of cycles, not null
   */
  public ViewProcessImpl(UniqueId viewProcessId, UniqueId viewDefinitionId, ViewExecutionOptions executionOptions,
                         ViewProcessContext viewProcessContext, EngineResourceManagerInternal<SingleComputationCycle> cycleManager,
                         ObjectId cycleObjectId) {
    ArgumentChecker.notNull(viewProcessId, "viewProcessId");
    ArgumentChecker.notNull(viewDefinitionId, "viewDefinitionID");
    ArgumentChecker.notNull(executionOptions, "executionOptions");
    ArgumentChecker.notNull(viewProcessContext, "viewProcessContext");
    ArgumentChecker.notNull(cycleManager, "cycleManager");
    ArgumentChecker.notNull(cycleObjectId, "cycleObjectId");

    _viewProcessId = viewProcessId;
    _viewDefinitionId = viewDefinitionId;
    _executionOptions = executionOptions;
    _viewProcessContext = viewProcessContext;
    _cycleManager = cycleManager;
    _cycleObjectId = cycleObjectId;
  }

  //-------------------------------------------------------------------------
  @Override
  public UniqueId getUniqueId() {
    return _viewProcessId;
  }

  @Override
  public UniqueId getDefinitionId() {
    return _viewDefinitionId;
  }

  @Override
  public ViewDefinition getLatestViewDefinition() {
    return getProcessContext().getViewDefinitionRepository().getDefinition(getDefinitionId());
  }

  @Override
  public MarketDataInjector getLiveDataOverrideInjector() {
    return getProcessContext().getLiveDataOverrideInjector();
  }

  @Override
  public ViewProcessState getState() {
    return _state;
  }

  @Override
  public void shutdown() {
    if (getState() == ViewProcessState.TERMINATED) {
      return;
    }
    shutdownCore();
  }

  public void triggerCycle() {
    getComputationJob().triggerCycle();
  }

  //-------------------------------------------------------------------------
  // Lifecycle
  //-------------------------------------------------------------------------

  @Override
  public void start() {
    // Lifecycle method - nothing to start
  }

  @Override
  public void stop() {
    shutdown();
  }

  @Override
  public boolean isRunning() {
    // This is 'running' from a Lifecycle perspective, not whether the job is running.
    return getState() != ViewProcessState.TERMINATED;
  }

  @Override
  public void suspend() {
    s_logger.info("Suspending view process {}", getUniqueId());
    lock();
    if (getComputationJob() != null) {
      s_logger.debug("Suspending calculation job");
      getComputationJob().terminate();
      if (getComputationThread().getState() == Thread.State.TIMED_WAITING) {
        // In this case it might be waiting on a recalculation pass. Interrupt it.
        s_logger.debug("Interrupting calculation job thread");
        getComputationThread().interrupt();
      }
      setComputationJob(null);
      try {
        s_logger.debug("Waiting for calculation thread to finish");
        getComputationThread().wait();<commit_msg>Should use join, not "wait" to wait for thread completion.<commit_after>/**
 * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */
package com.opengamma.engine.view;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock;

import javax.time.Instant;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.Lifecycle;

import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.engine.marketdata.MarketDataInjector;
import com.opengamma.engine.marketdata.MarketDataPermissionProvider;
import com.opengamma.engine.value.ValueRequirement;
import com.opengamma.engine.view.calc.EngineResourceManagerInternal;
import com.opengamma.engine.view.calc.SingleComputationCycle;
import com.opengamma.engine.view.calc.ViewComputationJob;
import com.opengamma.engine.view.calc.ViewCycle;
import com.opengamma.engine.view.calc.ViewCycleMetadata;
import com.opengamma.engine.view.client.ViewDeltaResultCalculator;
import com.opengamma.engine.view.compilation.CompiledViewDefinitionWithGraphsImpl;
import com.opengamma.engine.view.execution.ViewCycleExecutionOptions;
import com.opengamma.engine.view.execution.ViewExecutionOptions;
import com.opengamma.engine.view.listener.ViewResultListener;
import com.opengamma.engine.view.permission.ViewPermissionProvider;
import com.opengamma.id.ObjectId;
import com.opengamma.id.UniqueId;
import com.opengamma.livedata.UserPrincipal;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.tuple.Pair;


/**
 * Default implementation of {@link ViewProcess}.
 */
public class ViewProcessImpl implements ViewProcessInternal, Lifecycle {

  private static final Logger s_logger = LoggerFactory.getLogger(ViewProcess.class);

  private final UniqueId _viewProcessId;
  private final UniqueId _viewDefinitionId;
  private final ViewExecutionOptions _executionOptions;
  private final ViewProcessContext _viewProcessContext;
  private final ObjectId _cycleObjectId;
  private final EngineResourceManagerInternal<SingleComputationCycle> _cycleManager;

  private final AtomicLong _cycleVersion = new AtomicLong();

  /**
   * Manages access to critical regions of the process. Note that the use of {@link Semaphore} rather than, for example,
   * {@link ReentrantLock} allows one thread to acquire the lock and another thread to release it as part of the same
   * sequence of operations. This could be important for {@link #suspend()} and {@link #resume()}. 
   */
  private final Semaphore _processLock = new Semaphore(1);

  private final Set<ViewResultListener> _listeners = new HashSet<ViewResultListener>();

  private volatile ViewProcessState _state = ViewProcessState.STOPPED;

  private volatile ViewComputationJob _computationJob;
  private volatile Thread _computationThread;

  private final AtomicReference<Pair<CompiledViewDefinitionWithGraphsImpl, MarketDataPermissionProvider>> _latestCompiledViewDefinition =
      new AtomicReference<Pair<CompiledViewDefinitionWithGraphsImpl, MarketDataPermissionProvider>>();
  private final AtomicReference<ViewComputationResultModel> _latestResult = new AtomicReference<ViewComputationResultModel>();

  private ExecutorService _calcJobResultExecutorService = Executors.newSingleThreadExecutor();



  /**
   * Constructs an instance.
   *
   * @param viewProcessId  the unique identifier of the view process, not null
   * @param viewDefinitionId  the name of the view definition, not null
   * @param executionOptions  the view execution options, not null
   * @param viewProcessContext  the process context, not null
   * @param cycleManager  the view cycle manager, not null
   * @param cycleObjectId  the object identifier of cycles, not null
   */
  public ViewProcessImpl(UniqueId viewProcessId, UniqueId viewDefinitionId, ViewExecutionOptions executionOptions,
                         ViewProcessContext viewProcessContext, EngineResourceManagerInternal<SingleComputationCycle> cycleManager,
                         ObjectId cycleObjectId) {
    ArgumentChecker.notNull(viewProcessId, "viewProcessId");
    ArgumentChecker.notNull(viewDefinitionId, "viewDefinitionID");
    ArgumentChecker.notNull(executionOptions, "executionOptions");
    ArgumentChecker.notNull(viewProcessContext, "viewProcessContext");
    ArgumentChecker.notNull(cycleManager, "cycleManager");
    ArgumentChecker.notNull(cycleObjectId, "cycleObjectId");

    _viewProcessId = viewProcessId;
    _viewDefinitionId = viewDefinitionId;
    _executionOptions = executionOptions;
    _viewProcessContext = viewProcessContext;
    _cycleManager = cycleManager;
    _cycleObjectId = cycleObjectId;
  }

  //-------------------------------------------------------------------------
  @Override
  public UniqueId getUniqueId() {
    return _viewProcessId;
  }

  @Override
  public UniqueId getDefinitionId() {
    return _viewDefinitionId;
  }

  @Override
  public ViewDefinition getLatestViewDefinition() {
    return getProcessContext().getViewDefinitionRepository().getDefinition(getDefinitionId());
  }

  @Override
  public MarketDataInjector getLiveDataOverrideInjector() {
    return getProcessContext().getLiveDataOverrideInjector();
  }

  @Override
  public ViewProcessState getState() {
    return _state;
  }

  @Override
  public void shutdown() {
    if (getState() == ViewProcessState.TERMINATED) {
      return;
    }
    shutdownCore();
  }

  public void triggerCycle() {
    getComputationJob().triggerCycle();
  }

  //-------------------------------------------------------------------------
  // Lifecycle
  //-------------------------------------------------------------------------

  @Override
  public void start() {
    // Lifecycle method - nothing to start
  }

  @Override
  public void stop() {
    shutdown();
  }

  @Override
  public boolean isRunning() {
    // This is 'running' from a Lifecycle perspective, not whether the job is running.
    return getState() != ViewProcessState.TERMINATED;
  }

  @Override
  public void suspend() {
    s_logger.info("Suspending view process {}", getUniqueId());
    lock();
    if (getComputationJob() != null) {
      s_logger.debug("Suspending calculation job");
      getComputationJob().terminate();
      if (getComputationThread().getState() == Thread.State.TIMED_WAITING) {
        // In this case it might be waiting on a recalculation pass. Interrupt it.
        s_logger.debug("Interrupting calculation job thread");
        getComputationThread().interrupt();
      }
      setComputationJob(null);
      try {
        s_logger.debug("Waiting for calculation thread to finish");
        getComputationThread().join();
{'fraction_non_alphanumeric': 0.11305789891124089, 'fraction_numerical': 0.0010094455259932224, 'mean_word_length': 4.056507473569085, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3437207', 'n_tokens_mistral': 3715, 'n_tokens_neox': 3614, 'n_words': 896}