// 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 <cstdint>
#include <functional>
#include <string>
#include <vector>

#include "kudu/master/master.pb.h"
#include "kudu/rpc/response_callback.h"
#include "kudu/rpc/rpc.h"
#include "kudu/rpc/rpc_controller.h"
#include "kudu/util/status_callback.h"

namespace kudu {

class MonoTime;
class Status;

namespace master {
class MasterServiceProxy;
} // namespace master

namespace client {

class KuduClient;

namespace internal {

// Encapsulates RPCs that target the leader master, handling retries and
// reconnection to the master(s).
template <class ReqClass, class RespClass>
class AsyncLeaderMasterRpc : public rpc::Rpc {
 public:
  // The input 'client' will be used to call the asynchonous master proxy
  // function 'func' on the currently-known leader master, sending over 'req',
  // and expecting the features specified by 'required_feature_flags' to be
  // present on the master. Upon successful completion of the RPC, 'resp' is
  // populated with the RPC response. Various errors (e.g. from the RPC layer
  // or from the application layer) will direct the RPC to be retried until
  // 'deadline' is reached. If the final result is an error, 'resp' may not be
  // set, or may have an application error set.
  //
  // 'user_cb' will be called on the final result of the RPC (either OK,
  // TimedOut, or some other non-retriable error).
  //
  // 'rpc_name' is a descriptor for the RPC used to add more context to logs
  // and error messages.
  //
  // Retries will be done according to the backoff type specified by 'backoff'.
  AsyncLeaderMasterRpc(const MonoTime& deadline,
                       KuduClient* client,
                       rpc::BackoffType backoff,
                       const ReqClass& req,
                       RespClass* resp,
                       const std::function<void(master::MasterServiceProxy*,
                                                const ReqClass&, RespClass*,
                                                rpc::RpcController*,
                                                const rpc::ResponseCallback&)>& func,
                       std::string rpc_name,
                       StatusCallback user_cb,
                       std::vector<uint32_t> required_feature_flags);

  // Sends the RPC using the master proxy's asynchonous API, ensuring that
  // neither the per-RPC deadline nor the overall deadline has passed.
  //
  // Resets the RPC controller before sending out a new RPC.
  void SendRpc() override;

  std::string ToString() const override;

  // Uses 'status' and the contents of the RPC controller and RPC response to
  // determine whether reconnections or retries should be performed, and if so,
  // performs them. Additionally, updates 'status' to include more information
  // based on the state of the RPC.
  //
  // Retries take the following kinds of errors into account:
  // - TimedOut errors that indicate the operation retrier has passed its
  //   deadline (distinct from TimedOut errors that surface in the RPC layer)
  // - RPC errors that come from a failed connection, in which case the
  //   controller status will be non-OK
  // - generic RPC errors, in which case the controller status will be a
  //   RemoteError and the controller will have an error response
  // - generic Master application errors, in which case the controller status
  //   will be OK, and the response will have an ErrorStatusPB
  //
  // Returns true if a reconnection and/or retry was required and has been
  // scheduled, in which case callers should ensure that this object remains
  // alive.
  bool RetryOrReconnectIfNecessary(Status* status);

 protected:
  // Handles 'status', retrying if necessary, and calling the user-provided
  // callback as appropriate.
  void SendRpcCb(const Status& status) override;

  // Attempts to reconnect with the masters and find the leader master, and
  // attempts to retry the RPC.
  virtual void ResetMasterLeaderAndRetry(rpc::CredentialsPolicy creds_policy);

  // With a new leader found, resends the RPC. 'creds_policy' is the policy
  // with which the reconnection was attempted.
  void NewLeaderMasterDeterminedCb(rpc::CredentialsPolicy creds_policy,
                                   const Status& status);

  KuduClient* client_;
  const ReqClass* req_;
  RespClass* resp_;

  // Asynchronous function that sends an RPC to the master.
  const std::function<void(master::MasterServiceProxy*,
                           const ReqClass&, RespClass*,
                           rpc::RpcController*,
                           const rpc::ResponseCallback&)> func_;

  // Name of the RPC being sent. Since multiple template instantiations may
  // exist for the same proxy function, this need not be exactly the proxy
  // function name.
  const std::string rpc_name_;

  // Callback to call upon completion of the operation (whether the RPC itself
  // was successful or not).
  const StatusCallback user_cb_;

  // List of master-side feature flags required to send this RPC. If the
  // master(s) is missing any of these flags, the RPC will yield an error.
  const std::vector<uint32_t> required_feature_flags_;
};

} // namespace internal
} // namespace client
} // namespace kudu
