//------------------------------------------------------------------------------
// File: EndpointDecider.hh
// Author: Georgios Bitzes - CERN
//------------------------------------------------------------------------------
/************************************************************************
* qclient - A simple redis C++ client with support for redirects *
* Copyright (C) 2016 CERN/Switzerland *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see .*
************************************************************************/
#ifndef QCLIENT_ENDPOINT_DECIDER_HH
#define QCLIENT_ENDPOINT_DECIDER_HH
#include "qclient/Logger.hh"
#include "qclient/Members.hh"
#include "qclient/GlobalInterceptor.hh"
#include "qclient/network/HostResolver.hh"
#include
namespace qclient {
class HostResolver;
class ServiceEndpoint;
//------------------------------------------------------------------------------
// In face of having multiple cluster members, each cluster member entry
// potentially pointing to several IP addresses, and on top of that redirections
// which might point to hosts which are not even part of the given members...
// How do we decide where to connect to? We need to somehow take into account
// if we just received a redirection, or previous connection attempts against
// an IP failed.
//
// This class gives an answer on where to connect to next.
//------------------------------------------------------------------------------
class EndpointDecider {
public:
//----------------------------------------------------------------------------
// Constructor provided with cluster members as per configuration. We may
// contact different clusters when issued a redirection, however, outside of
// the original list.
//----------------------------------------------------------------------------
EndpointDecider(Logger *log, HostResolver *resolver, const Members &memb);
//----------------------------------------------------------------------------
// We were just notified of a redirection.
//----------------------------------------------------------------------------
void registerRedirection(const Endpoint &redir);
//----------------------------------------------------------------------------
// The event loop needs to reconnect - which endpoint should we target?
//
// Returns non-resolved Endpoint, leaving the DNS resolution up to the
// caller.
//----------------------------------------------------------------------------
Endpoint getNext();
//----------------------------------------------------------------------------
// Get next fully resolved service endpoint, ready to be passed to connect().
// False means all DNS resolution attempts failed.
//----------------------------------------------------------------------------
bool getNextEndpoint(ServiceEndpoint &endpoint);
//----------------------------------------------------------------------------
// Have we made a full circle yet? That is, have we tried all possible
// ServiceEndpoints at least once? Including possible redirects.
//----------------------------------------------------------------------------
bool madeFullCircle() const;
private:
Logger *logger;
HostResolver *resolver;
size_t nextMember = 0u;
bool fullCircle = false;
Members members;
Endpoint redirection;
std::vector resolvedEndpoints;
//----------------------------------------------------------------------------
// Fetch one of the resolved endpoints, return true
//----------------------------------------------------------------------------
bool fetchServiceEndpoint(ServiceEndpoint &out);
};
}
#endif