<commit_before>/**
 * 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 "HandlerBase.h"
#include <boost/bind.hpp>

#include <cassert>

#include "LogUtils.h"

DECLARE_LOG_OBJECT()

namespace pulsar {

HandlerBase::HandlerBase(const ClientImplPtr& client, const std::string& topic)
        : client_(client),
          topic_(topic),
          connection_(),
          mutex_(),
          creationTimestamp_(now()),
          operationTimeut_(seconds(client->conf().getOperationTimeoutSeconds())),
          state_(Pending),
          backoff_(milliseconds(100), seconds(60)),
          timer_(client->getIOExecutorProvider()->get()->createDeadlineTimer()) {
}

HandlerBase::~HandlerBase() {
    timer_->cancel();
}

void HandlerBase::start() {
    grabCnx();
}

void HandlerBase::grabCnx() {
    if (connection_.lock()) {
        LOG_INFO(getName() << "Ignoring reconnection request since we're already connected");
        return;
    }

    LOG_INFO(getName() << "Getting connection from pool");
    ClientImplPtr client = client_.lock();
    Future<Result, ClientConnectionWeakPtr> future = client->getConnection(topic_);
    future.addListener(
            boost::bind(&HandlerBase::handleNewConnection, _1, _2, get_weak_from_this()));
}

void HandlerBase::handleNewConnection(Result result, ClientConnectionWeakPtr connection,
                                      HandlerBaseWeakPtr weakHandler) {
    HandlerBasePtr handler = weakHandler.lock();
    if (!handler) {
        LOG_DEBUG("HandlerBase Weak reference is not valid anymore");
        return;
    }
    if (result == ResultOk) {
        ClientConnectionPtr conn = connection.lock();
        if (conn) {
            LOG_DEBUG(handler->getName() << "Connected to broker: " << conn->cnxString());
            handler->connectionOpened(conn);
            return;
        }
        // TODO - look deeper into why the connection is null while the result is ResultOk
        LOG_INFO(handler->getName() << "ClientConnectionPtr is no longer valid");
    }
    handler->connectionFailed(result);
    scheduleReconnection(handler);
}

void HandlerBase::handleDisconnection(Result result, ClientConnectionWeakPtr connection,
                                      HandlerBaseWeakPtr weakHandler) {
    HandlerBasePtr handler = weakHandler.lock();
    if (!handler) {
        LOG_DEBUG("HandlerBase Weak reference is not valid anymore");
        return;
    }

    Lock lock(handler->mutex_);
    State state = handler->state_;

    ClientConnectionPtr currentConnection = handler->connection_.lock();
    if (currentConnection && connection.lock().get() != currentConnection.get()) {
        LOG_WARN(
                handler->getName() << "Ignoring connection closed since we are already attached to a newer connection");
        return;
    }

    if (currentConnection) {
        currentConnection.reset();
    }

    switch (state) {
        case Pending:
        case Ready:
            scheduleReconnection(handler);
            break;

        case Closing:
        case Closed:
        case Failed:
            LOG_DEBUG(handler->getName() <<
                    "Ignoring connection closed event since the handler is not used anymore");
            break;
    }
}<commit_msg>Fix for Problems in lookup flow in C++ Client (#551) - Issue 1 (#553)<commit_after>/**
 * 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 "HandlerBase.h"
#include <boost/bind.hpp>

#include <cassert>

#include "LogUtils.h"

DECLARE_LOG_OBJECT()

namespace pulsar {

HandlerBase::HandlerBase(const ClientImplPtr& client, const std::string& topic)
        : client_(client),
          topic_(topic),
          connection_(),
          mutex_(),
          creationTimestamp_(now()),
          operationTimeut_(seconds(client->conf().getOperationTimeoutSeconds())),
          state_(Pending),
          backoff_(milliseconds(100), seconds(60)),
          timer_(client->getIOExecutorProvider()->get()->createDeadlineTimer()) {
}

HandlerBase::~HandlerBase() {
    timer_->cancel();
}

void HandlerBase::start() {
    grabCnx();
}

void HandlerBase::grabCnx() {
    if (connection_.lock()) {
        LOG_INFO(getName() << "Ignoring reconnection request since we're already connected");
        return;
    }

    LOG_INFO(getName() << "Getting connection from pool");
    ClientImplPtr client = client_.lock();
    Future<Result, ClientConnectionWeakPtr> future = client->getConnection(topic_);
    future.addListener(
            boost::bind(&HandlerBase::handleNewConnection, _1, _2, get_weak_from_this()));
}

void HandlerBase::handleNewConnection(Result result, ClientConnectionWeakPtr connection,
                                      HandlerBaseWeakPtr weakHandler) {
    HandlerBasePtr handler = weakHandler.lock();
    if (!handler) {
        LOG_DEBUG("HandlerBase Weak reference is not valid anymore");
        return;
    }
    if (result == ResultOk) {
        ClientConnectionPtr conn = connection.lock();
        if (conn) {
            LOG_DEBUG(handler->getName() << "Connected to broker: " << conn->cnxString());
            handler->connectionOpened(conn);
            return;
        }
        // TODO - look deeper into why the connection is null while the result is ResultOk
        LOG_INFO(handler->getName() << "ClientConnectionPtr is no longer valid");
    }
    handler->connectionFailed(result);
    scheduleReconnection(handler);
}

void HandlerBase::handleDisconnection(Result result, ClientConnectionWeakPtr connection,
                                      HandlerBaseWeakPtr weakHandler) {
    HandlerBasePtr handler = weakHandler.lock();
    if (!handler) {
        LOG_DEBUG("HandlerBase Weak reference is not valid anymore");
        return;
    }

    Lock lock(handler->mutex_);
    State state = handler->state_;

    ClientConnectionPtr currentConnection = handler->connection_.lock();
    if (currentConnection && connection.lock().get() != currentConnection.get()) {
        LOG_WARN(
                handler->getName() << "Ignoring connection closed since we are already attached to a newer connection");
        return;
    }

    handler->connection_.reset();

    switch (state) {
        case Pending:
        case Ready:
            scheduleReconnection(handler);
            break;

        case Closing:
        case Closed:
        case Failed:
            LOG_DEBUG(handler->getName() <<
                    "Ignoring connection closed event since the handler is not used anymore");
            break;
    }
}
{'fraction_non_alphanumeric': 0.10266966067864272, 'fraction_numerical': 0.0036177644710578844, 'mean_word_length': 2.926052889324192, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 42, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4423545', 'n_tokens_mistral': 2052, 'n_tokens_neox': 1976, 'n_words': 628}