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

#include "util/thrift_client.h"

#include <thrift/transport/TTransport.h>
#include <thrift/transport/TTransportException.h>
// IWYU pragma: no_include <bits/chrono.h>
#include <chrono> // IWYU pragma: keep
#include <memory>
#include <string>
#include <thread>

#include "absl/strings/substitute.h"
#include "util/client_connection_provider.h"

namespace doris {

ThriftClientImpl::ThriftClientImpl(const std::string& ipaddress, int port)
        : _ipaddress(ipaddress),
          _port(port),
          _socket(doris::client::create_thrift_client_socket(ipaddress, port)) {}

Status ThriftClientImpl::open() {
    if (!_socket) {
        return Status::RpcError("socket not created");
    }

    try {
        if (!_transport->isOpen()) {
            _transport->open();
        }
    } catch (const apache::thrift::transport::TTransportException& e) {
        try {
            _transport->close();
        } catch (const apache::thrift::transport::TTransportException& e) {
            VLOG_CRITICAL << "Error closing socket to: " << ipaddress() << ":" << port()
                          << ", ignoring (" << e.what() << ")";
        }
        // In certain cases in which the remote host is overloaded, this failure can
        // happen quite frequently. Let's print this error message without the stack
        // trace as there aren't many callers of this function.
        const std::string& err_msg = absl::Substitute("Couldn't open transport for $0:$1 ($2)",
                                                      ipaddress(), port(), e.what());
        VLOG_CRITICAL << err_msg;
        return Status::RpcError(err_msg);
    }
    return Status::OK();
}

Status ThriftClientImpl::open_with_retry(int num_tries, int wait_ms) {
    DCHECK_GE(wait_ms, 0);
    Status status;
    int try_count = 0L;

    while (num_tries <= 0 || try_count < num_tries) {
        ++try_count;
        status = open();

        if (status.ok()) {
            return status;
        }

        LOG(INFO) << "Unable to connect to " << _ipaddress << ":" << _port;

        if (num_tries < 0) {
            LOG(INFO) << "(Attempt " << try_count << ", will retry indefinitely)";
        } else {
            LOG(INFO) << "(Attempt " << try_count << " of " << num_tries << ")";
        }

        std::this_thread::sleep_for(std::chrono::milliseconds(wait_ms));
    }

    return status;
}

void ThriftClientImpl::close() {
    try {
        if (_transport != nullptr && _transport->isOpen()) {
            _transport->close();
        }
    } catch (const apache::thrift::transport::TTransportException& e) {
        LOG(INFO) << "Error closing connection to: " << ipaddress() << ":" << port()
                  << ", ignoring (" << e.what() << ")";
        // Forcibly close the socket (since the transport may have failed to get that far
        // during close())
        try {
            if (_socket != nullptr) {
                _socket->close();
            }
        } catch (const apache::thrift::transport::TTransportException& e) {
            LOG(INFO) << "Error closing socket to: " << ipaddress() << ":" << port()
                      << ", ignoring (" << e.what() << ")";
        }
    }
}

} // namespace doris
