public int backup(BackupAwareOperation backupAwareOp) throws Exception {
    int requestedSyncBackups = requestedSyncBackups(backupAwareOp);
    int requestedAsyncBackups = requestedAsyncBackups(backupAwareOp);
    int requestedTotalBackups = requestedTotalBackups(backupAwareOp);
    if (requestedTotalBackups == 0) {
      return 0;
    }

    Operation op = (Operation) backupAwareOp;
    InternalPartitionService partitionService = node.getPartitionService();
    long[] replicaVersions =
        partitionService.incrementPartitionReplicaVersions(
            op.getPartitionId(), requestedTotalBackups);

    boolean syncForced = backpressureRegulator.isSyncForced(backupAwareOp);

    int syncBackups = syncBackups(requestedSyncBackups, requestedAsyncBackups, syncForced);
    int asyncBackups = asyncBackups(requestedSyncBackups, requestedAsyncBackups, syncForced);

    // TODO: This could cause a problem with back pressure
    if (!op.returnsResponse()) {
      asyncBackups += syncBackups;
      syncBackups = 0;
    }

    if (syncBackups + asyncBackups == 0) {
      return 0;
    }

    return makeBackups(
        backupAwareOp, op.getPartitionId(), replicaVersions, syncBackups, asyncBackups);
  }
  public OperationServiceImpl(NodeEngineImpl nodeEngine) {
    this.nodeEngine = nodeEngine;
    this.node = nodeEngine.getNode();
    this.thisAddress = node.getThisAddress();
    this.logger = node.getLogger(OperationService.class);
    this.serializationService = (InternalSerializationService) nodeEngine.getSerializationService();

    this.backpressureRegulator =
        new BackpressureRegulator(
            node.getProperties(), node.getLogger(BackpressureRegulator.class));

    int coreSize = Runtime.getRuntime().availableProcessors();
    boolean reallyMultiCore = coreSize >= CORE_SIZE_CHECK;
    int concurrencyLevel = reallyMultiCore ? coreSize * CORE_SIZE_FACTOR : CONCURRENCY_LEVEL;

    this.invocationRegistry =
        new InvocationRegistry(
            node.getLogger(OperationServiceImpl.class),
            backpressureRegulator.newCallIdSequence(),
            concurrencyLevel);

    this.invocationMonitor =
        new InvocationMonitor(
            nodeEngine,
            thisAddress,
            node.getHazelcastThreadGroup(),
            node.getProperties(),
            invocationRegistry,
            node.getLogger(InvocationMonitor.class),
            serializationService,
            nodeEngine.getServiceManager());

    this.operationBackupHandler = new OperationBackupHandler(this);

    this.responseHandler =
        new ResponseHandler(
            node.getLogger(ResponseHandler.class),
            node.getSerializationService(),
            invocationRegistry,
            nodeEngine);
    this.asyncResponseHandler =
        new AsyncResponseHandler(
            node.getHazelcastThreadGroup(),
            node.getLogger(AsyncResponseHandler.class),
            responseHandler,
            node.getProperties());

    this.operationExecutor =
        new OperationExecutorImpl(
            node.getProperties(),
            node.loggingService,
            thisAddress,
            new OperationRunnerFactoryImpl(this),
            node.getHazelcastThreadGroup(),
            node.getNodeExtension());

    this.slowOperationDetector =
        new SlowOperationDetector(
            node.loggingService,
            operationExecutor.getGenericOperationRunners(),
            operationExecutor.getPartitionOperationRunners(),
            node.getProperties(),
            node.getHazelcastThreadGroup());
  }