// 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.

#pragma once

#include <vector>

#include "common/status.h"
#include "gen-cpp/Types_types.h"

namespace impala {

/// Categorisation of causes of cancellation.
enum class CancellationWorkCause {
  // The Impala Server terminated the query, e.g. because it exceeded a timeout or
  // resource limit.
  TERMINATED_BY_SERVER,
  // The query is being terminated because a backend failed. We can skip cancelling the
  // query if the fragment instances running on that backend all completed.
  BACKEND_FAILED
};

/// Work item for ImpalaServer::cancellation_thread_pool_.
/// This class needs to support move construction and assignment for use in ThreadPool.
class CancellationWork {
 public:
  // Empty constructor needed to make ThreadPool happy.
  CancellationWork()
    : cause_(CancellationWorkCause::TERMINATED_BY_SERVER), unregister_(false) {}

  // Construct a TERMINATED_BY_SERVER CancellationWork instance.
  static CancellationWork TerminatedByServer(
      const TUniqueId& query_id, const Status& error, bool unregister) {
    return CancellationWork(
        query_id, CancellationWorkCause::TERMINATED_BY_SERVER, error, {}, unregister);
  }

  // Construct a BACKEND_FAILURE CancellationWork instance.
  static CancellationWork BackendFailure(const TUniqueId& query_id,
      const std::vector<TNetworkAddress>& failed_backends) {
    return CancellationWork(query_id, CancellationWorkCause::BACKEND_FAILED, Status::OK(),
        failed_backends, false);
  }

  const TUniqueId& query_id() const { return query_id_; }
  CancellationWorkCause cause() const { return cause_; }
  const Status& error() const {
    DCHECK_ENUM_EQ(cause_, CancellationWorkCause::TERMINATED_BY_SERVER);
    return error_;
  }
  const std::vector<TNetworkAddress>& failed_backends() const {
    DCHECK_ENUM_EQ(cause_, CancellationWorkCause::BACKEND_FAILED);
    return failed_backends_;
  }
  bool unregister() const { return unregister_; }

 private:
  CancellationWork(const TUniqueId& query_id, CancellationWorkCause cause,
      const Status& error, const std::vector<TNetworkAddress>& failed_backends,
      bool unregister)
    : query_id_(query_id),
      cause_(cause),
      error_(error),
      failed_backends_(failed_backends),
      unregister_(unregister) {
    DCHECK(cause_ != CancellationWorkCause::TERMINATED_BY_SERVER || !error.ok());
    DCHECK(cause_ != CancellationWorkCause::BACKEND_FAILED || !failed_backends.empty());
  }

  // ID of query to be cancelled.
  TUniqueId query_id_;

  // Cause of the expiration.
  CancellationWorkCause cause_;

  // If 'cause_' is TERMINATED_BY_SERVER, the error containing human-readable explanation
  // of the cancellation. Otherwise not used.
  Status error_;

  // If cause is BACKEND_FAILED, all of the backend that were detected to fail. Otherwise
  // not used.
  std::vector<TNetworkAddress> failed_backends_;

  // If true, unregister the query after cancelling it.
  bool unregister_;
};
} // namespace impala
