* change picture to word * change picture to word * SHOW FULL TABLES WHERE Table_type != VIEW sql can not execute * change license description
419 lines
19 KiB
C++
419 lines
19 KiB
C++
// Copyright (c) 2017, Baidu.com, Inc. All Rights Reserved
|
|
|
|
// Licensed 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.
|
|
|
|
#ifndef BDG_PALO_BE_SRC_RPC_HANDLER_MAP_H
|
|
#define BDG_PALO_BE_SRC_RPC_HANDLER_MAP_H
|
|
|
|
#include "comm_address.h"
|
|
#include "comm_buf.h"
|
|
#include "io_handler_data.h"
|
|
#include "io_handler_datagram.h"
|
|
#include "io_handler_raw.h"
|
|
#include "proxy_map.h"
|
|
#include "error.h"
|
|
#include "common/logging.h"
|
|
#include "sock_addr_map.h"
|
|
|
|
#include "timer.h"
|
|
#include <condition_variable>
|
|
#include <cassert>
|
|
#include <memory>
|
|
#include <mutex>
|
|
|
|
namespace palo {
|
|
class IOHandlerAccept;
|
|
|
|
/** Data structure for mapping socket addresses to I/O handlers.
|
|
* An I/O handler is associated with each socket connection and is used
|
|
* to handle polling events on the socket descriptor. Examples incude
|
|
* writing a message to the socket, reading a message from the socket,
|
|
* or completing a connection request. This class maintains three maps,
|
|
* one for TCP socket connections, UDP socket connections, and one for
|
|
* accept sockets. The Comm methods use this map to locate the I/O
|
|
* handler for a given address.
|
|
*/
|
|
class HandlerMap {
|
|
public:
|
|
|
|
/** Constructor. */
|
|
HandlerMap() : m_proxies_loaded(false) { }
|
|
|
|
/** Inserts an accept handler.
|
|
* Uses IOHandler#m_local_addr as the key
|
|
* @param handler Accept I/O handler to insert
|
|
*/
|
|
void insert_handler(IOHandlerAccept *handler);
|
|
|
|
/** Inserts a data (TCP) handler.
|
|
* Uses IOHandler#m_addr as the key. If program is the proxy master,
|
|
* a proxy map update message with the new mapping is broadcast to
|
|
* all connections.
|
|
* @param handler Data (TCP) I/O handler to insert
|
|
* @param checkout Atomically checkout handler
|
|
*/
|
|
void insert_handler(IOHandlerData *handler, bool checkout=false);
|
|
|
|
/** Inserts a datagram (UDP) handler.
|
|
* Uses IOHandler#m_local_addr as the key.
|
|
* @param handler Datagram (UDP) I/O handler to insert
|
|
*/
|
|
void insert_handler(IOHandlerDatagram *handler);
|
|
|
|
/** Inserts a raw handler.
|
|
* Uses IOHandler#m_addr as the key.
|
|
* @param handler Raw I/O handler to insert
|
|
*/
|
|
void insert_handler(IOHandlerRaw *handler);
|
|
|
|
/** Checks out accept I/O handler associated with <code>addr</code>.
|
|
* Looks up <code>addr</code> in accept map. If an entry is found,
|
|
* then its reference count is incremented and it is returned
|
|
* in <code>handler</code>.
|
|
* @param addr Connection address
|
|
* @param handler Address of handler pointer returned
|
|
* @return error::OK on success, or error::COMM_NOT_CONNECTED if no mapping
|
|
* found for <code>addr</code>.
|
|
*/
|
|
int checkout_handler(const CommAddress &addr, IOHandlerAccept **handler);
|
|
|
|
/** Checks out data (TCP) I/O handler associated with <code>addr</code>.
|
|
* First translates <code>addr</code> to socket address and then
|
|
* looks up translated address in data map. If an entry is found,
|
|
* then its reference count is incremented and it is returned
|
|
* in <code>handler</code>.
|
|
* @param addr Connection address
|
|
* @param handler Address of handler pointer returned
|
|
* @return error::OK on success, error::COMM_INVALID_PROXY if
|
|
* <code>addr</code> is of type CommAddress::PROXY and no translation
|
|
* exists, or error::COMM_NOT_CONNECTED if no mapping found for
|
|
* translated address.
|
|
*/
|
|
int checkout_handler(const CommAddress &addr, IOHandlerData **handler);
|
|
|
|
/** Checks out datagram (UDP) I/O handler associated with <code>addr</code>.
|
|
* Looks up <code>addr</code> in datagram map. If an entry is found,
|
|
* then its reference count is incremented and it is returned
|
|
* in <code>handler</code>.
|
|
* @param addr Connection address
|
|
* @param handler Address of handler pointer returned
|
|
* @return error::OK on success, or error::COMM_NOT_CONNECTED if no mapping
|
|
* found for <code>addr</code>.
|
|
*/
|
|
int checkout_handler(const CommAddress &addr, IOHandlerDatagram **handler);
|
|
|
|
/** Checks out raw I/O handler associated with <code>addr</code>.
|
|
* Looks up <code>addr</code> in raw map. If an entry is found,
|
|
* then its reference count is incremented and it is returned
|
|
* in <code>handler</code>.
|
|
* @param addr Connection address
|
|
* @param handler Address of handler pointer returned
|
|
* @return error::OK on success, or error::COMM_NOT_CONNECTED if no mapping
|
|
* found for <code>addr</code>.
|
|
*/
|
|
int checkout_handler(const CommAddress &addr, IOHandlerRaw **handler);
|
|
|
|
/** Checks to see if <code>addr</code> is contained in map.
|
|
* First translates <code>addr</code> to socket address and then
|
|
* looks up translated address in data map.
|
|
* @param addr Connection address
|
|
* @return error::OK if found, error::COMM_INVALID_PROXY if
|
|
* <code>addr</code> is of type CommAddress::PROXY and no translation
|
|
* exists, or error::COMM_NOT_CONNECTED if no mapping found for
|
|
* translated address.
|
|
*/
|
|
int contains_data_handler(const CommAddress &addr);
|
|
|
|
/** Decrements the reference count of <code>handler</code>.
|
|
* The decrementing of a handler's reference count is done by this method
|
|
* with #m_mutex locked which avoids a race condition between checking
|
|
* out handlers and purging them.
|
|
* @param handler Pointer to I/O handler for which to decrement reference
|
|
* count
|
|
*/
|
|
void decrement_reference_count(IOHandler *handler);
|
|
|
|
/** Sets an alias address for an existing TCP address in map.
|
|
* RangeServers listen on a well-known port defined by the
|
|
* <code>palo.RangeServer.Port</code> configuration property
|
|
* (default = 15865). However, RangeServers connect to the master using
|
|
* an ephemeral port due to a bind conflict with its listen socket. So that
|
|
* the Master can refer to the RangeServer using the well-known port, an
|
|
* alias address can be registered and subsequently used to reference the
|
|
* connection. This method adds an entry to the data (TCP) map for
|
|
* <code>alias</code> which references the IOHandlerData object previously
|
|
* registered under <code>addr</code>.
|
|
* @param addr Address of previously registered data handler
|
|
* @param alias Alias address to add
|
|
* @return error::OK on success, or error::COMM_CONFLICTING_ADDRESS if
|
|
* <code>alias</code> is already in the data map, or
|
|
* error::COMM_NOT_CONNECTED if <code>addr</code> is not found in the data
|
|
* map.
|
|
*/
|
|
int set_alias(const InetAddr &addr, const InetAddr &alias);
|
|
|
|
/** Removes <code>handler</code> from map. This method removes
|
|
* <code>handler</code> from the data, datagram, or accept map, depending
|
|
* on the type of handler. If <code>handler</code> refers to a data
|
|
* handler, then its alias address entry is also removed from the data map.
|
|
* @param handler IOHandler to remove
|
|
* @return error::OK on success, or error::COMM_NOT_CONNECTED if
|
|
* <code>handler</code> is not found in any of the maps.
|
|
*/
|
|
int remove_handler(IOHandler *handler);
|
|
|
|
/** Decomissions <code>handler</code>. Since handler pointers are passed
|
|
* into the polling mechanism and asynchronously referenced by reactor
|
|
* threads, care must be taken to not delete a handler until it has
|
|
* be removed from the polling mechanism. This is accomplished by
|
|
* introducing a two-step removal process. First a handler is decomissioned
|
|
* (by this method) by removing it from the associated map, adding it to the
|
|
* #m_decomissioned_handlers set and marking it decomissioned. Once there
|
|
* are no more references to the handler, it may be safely removed. The
|
|
* removal is accomplished via #purge_handler which is called by the reactor
|
|
* thread after it has been removed from the polling interface.
|
|
* @param handler Pointer to IOHandler to decomission
|
|
*/
|
|
void decomission_handler_unlocked(IOHandler *handler);
|
|
|
|
/** Decomissions <code>handler</code> with #m_mutex locked.
|
|
* This method locks #m_mutex and calls #decomission_handler_unlocked
|
|
* @param handler Pointer to IOHandler to decomission
|
|
*/
|
|
void decomission_handler(IOHandler *handler) {
|
|
std::lock_guard<std::mutex> lock(m_mutex);
|
|
|
|
decomission_handler_unlocked(handler);
|
|
|
|
}
|
|
/** Decomissions all handlers. This method is called by the ~Comm to
|
|
* decomission all of the handlers in the map.
|
|
* @note It doesn't look like the Comm object ever gets deleted and
|
|
* therefore this method never gets called. See issue 1031.
|
|
*/
|
|
void decomission_all();
|
|
|
|
/** Determines if <code>handler</code> can be destoryed.
|
|
* @return <i>true</i> if <code>handler</code> is decomissioned and
|
|
* has a reference count of 0.
|
|
*/
|
|
bool destroy_ok(IOHandler *handler);
|
|
|
|
/** Translates <code>proxy_addr</code> to its corresponding IPV4 address.
|
|
* This method fetches the mapping for <code>proxy_addr</code> from
|
|
* #m_proxy_map and returns the associated IPV4 address in
|
|
* <code>addr</code>. If <code>addr</code> is NULL, then no translation
|
|
* occurs but the return value can be checked to see if the proxy name
|
|
* contains a mapping.
|
|
* @param proxy_addr Reference to proxy address
|
|
* @param addr Pointer to return IPV4 address
|
|
* @return <i>true</i> if mapping found, <i>false</i> otherwise
|
|
*/
|
|
bool translate_proxy_address(const CommAddress &proxy_addr, InetAddr *addr);
|
|
|
|
/** Purges (removes) <code>handler</code>. This method removes
|
|
* <code>handler</code> from the #m_decomissioned_handlers set, signals
|
|
* #m_cond if #m_decomissioned_handlers becomes empty, calls
|
|
* <code>hander->disconnect()</code>, and then deletes the handler.
|
|
* This method must only be called from a reactor thread after the handler
|
|
* has been removed from the polling interface and #destroy_ok returns
|
|
* true for the handler.
|
|
* @param handler Handler to purge
|
|
*/
|
|
void purge_handler(IOHandler *handler);
|
|
|
|
/** Waits for map to become empty. This method assumes that all of the
|
|
* handlers in the map have been decomissioned. It waits for the
|
|
* #m_decomissioned_handlers set to become empty, waiting on #m_cond
|
|
* until it does.
|
|
*/
|
|
void wait_for_empty();
|
|
|
|
/** Adds or updates proxy information. This method adds or updates proxy
|
|
* information in #m_proxy_map. For the data handler to which
|
|
* <code>addr</code> refers, it updates its proxy name via a call to
|
|
* IOHandler::set_proxy and then calls #propagate_proxy_map with the newly
|
|
* added/updated proxy information to update all active data connections
|
|
* with the new proxy information.
|
|
* @note This method should only be called by the proxy master.
|
|
* @param proxy Proxy name of new/updated mapping
|
|
* @param hostname Hostname of new/updated mapping
|
|
* @param addr InetAddr of new/updated mapping
|
|
* @return error::OK on success, or one of the errors returned by
|
|
* #propagate_proxy_map
|
|
*/
|
|
int add_proxy(const std::string &proxy, const std::string &hostname, const InetAddr &addr);
|
|
|
|
/** Removes a proxy name from the proxy map. This method removes
|
|
* <code>proxy</code> from #m_proxy_map and then calls #propagate_proxy_map
|
|
* to propagate the removed mapping information to all connections.
|
|
* @note This method should only be called by the proxy master.
|
|
* @param proxy Proxy name to remove
|
|
* @return error::OK if <code>proxy</code> not found in proxy map or if
|
|
* it was successfully removed, or one of the errors returned by
|
|
* #propagate_proxy_map
|
|
*/
|
|
int remove_proxy(const std::string &proxy);
|
|
|
|
/** Returns the proxy map
|
|
* @param proxy_map reference to returned proxy map
|
|
*/
|
|
void get_proxy_map(ProxyMapT &proxy_map);
|
|
|
|
/** Updates the proxy map with a proxy map update message received from the
|
|
* proxy master. Calls ProxyMap::update_mappings with <code>message</code>
|
|
* to update the proxy map. If any of the proxy names have changed, the
|
|
* corresponding data handlers are updated with a call to
|
|
* IOHandler::set_proxy. For each mapping in <code>message</code> that has
|
|
* the hostname set to <code>--DELETED--</code>, the associated data handler
|
|
* is decomissioned. After the proxy map has been successfuly updated, the
|
|
* #m_proxies_loaded flag is set to <i>true</i> and the #m_cond_proxy
|
|
* condition variable is signalled.
|
|
* @param message Pointer to proxy map update message
|
|
* @param message_len Length of proxy map update message
|
|
*/
|
|
void update_proxy_map(const char *message, size_t message_len);
|
|
|
|
/** Sends the current proxy map over connection identified by
|
|
* <code>handler</code>. This method must only be called by the proxy
|
|
* master, otherwise it will assert.
|
|
* @param handler Connection over which to send proxy map
|
|
* @return Same set of error codes returned by IOHandlerData#send_message
|
|
*/
|
|
int32_t propagate_proxy_map(IOHandlerData *handler);
|
|
|
|
/** Waits for proxy map to get updated from a proxy map update message
|
|
* received from the master. This method waits on #m_cond_proxy for
|
|
* #m_proxies_loaded to become <i>true</i> or <code>timer</code> expires.
|
|
* @param timer Deadline timer
|
|
* @return <i>true</i> if proxy map was loaded, <i>false</i> if
|
|
* <code>timer</code> expired before proxy map was loaded.
|
|
*/
|
|
bool wait_for_proxy_map(Timer &timer);
|
|
|
|
private:
|
|
/** Propagates proxy map information in <code>mappings</code> to
|
|
* all active data (TCP) connections. This method creates a proxy
|
|
* map update message from the mappings in <code>mappings</code>.
|
|
* The update message is just a list of mapping entries in the
|
|
* following format:
|
|
* @verbatim <proxy> '\t' <hostname> '\t' <addr> '\n' @endverbatim
|
|
* Then the proxy map update message is sent via each of the handlers in
|
|
* the data (TCP) handler map. If an error is encountered on a
|
|
* handler when trying to send the proxy map, it will be decomissioned.
|
|
* @param mappings Proxy map information to propagate.
|
|
* @return error::OK if proxy map update message was successfully
|
|
* sent across all data handlers, otherwise one of the error
|
|
* codes returned by IOHandlerData#send_message
|
|
*/
|
|
int propagate_proxy_map(ProxyMapT &mappings);
|
|
|
|
/** Translates <code>addr</code> to an InetAddr (IP address).
|
|
* If <code>addr</code> is of type CommAddress::PROXY, then the
|
|
* #m_proxy_map is consulted to translate the proxy name to an IP address,
|
|
* otherwise if <code>addr</code> is of type CommAddress::INET, the IP
|
|
* address held in <code>addr</code> is copied to <code>inet_addr</code>.
|
|
* @param addr Address to translate
|
|
* @param inet_addr Pointer to valid InetAddr object to hold translated
|
|
* address
|
|
* @return error::OK on success, error::COMM_INVALID_PROXY if
|
|
* <code>addr</code> is of type CommAddress::PROXY and no mapping is found.
|
|
*/
|
|
int translate_address(const CommAddress &addr, InetAddr *inet_addr);
|
|
|
|
/** Removes <code>handler</code> from map without locking #m_mutex. This
|
|
* method removes <code>handler</code> from the data, datagram, or accept
|
|
* map, depending on the type of handler. If <code>handler</code> refers to
|
|
* a data handler, then its alias address entry is also removed from the
|
|
* data map.
|
|
* @param handler IOHandler to remove
|
|
* @return error::OK on success, or error::COMM_NOT_CONNECTED if
|
|
* <code>handler</code> is not found in any of the maps.
|
|
*/
|
|
int remove_handler_unlocked(IOHandler *handler);
|
|
|
|
/** Finds <i>accept</i> I/O handler associated with <code>addr</code>.
|
|
* This method looks up <code>addr</code> in #m_accept_handler_map and
|
|
* returns the handler, if found.
|
|
* @param addr Address of accept handler to locate
|
|
* @return Pointer to IOHandlerAccept object associated with
|
|
* <code>addr</code>, or 0 if not found.
|
|
*/
|
|
IOHandlerAccept *lookup_accept_handler(const InetAddr &addr);
|
|
|
|
/** Finds <i>data (TCP)</i> I/O handler associated with <code>addr</code>.
|
|
* This method looks up <code>addr</code> in #m_data_handler_map and
|
|
* returns the handler, if found.
|
|
* @param addr Address of data handler to locate
|
|
* @return Pointer to IOHandlerData object associated with
|
|
* <code>addr</code>, or 0 if not found.
|
|
*/
|
|
IOHandlerData *lookup_data_handler(const InetAddr &addr);
|
|
|
|
/** Finds <i>datagram</i> I/O handler associated with <code>addr</code>.
|
|
* This method looks up <code>addr</code> in #m_datagram_handler_map and
|
|
* returns the handler, if found.
|
|
* @param addr Address of datagram handler to locate
|
|
* @return Pointer to IOHandlerDatagram object associated with
|
|
* <code>addr</code>, or 0 if not found.
|
|
*/
|
|
IOHandlerDatagram *lookup_datagram_handler(const InetAddr &addr);
|
|
|
|
/** Finds <i>raw</i> I/O handler associated with <code>addr</code>.
|
|
* This method looks up <code>addr</code> in #m_raw_handler_map and
|
|
* returns the handler, if found.
|
|
* @param addr Address of raw handler to locate
|
|
* @return Pointer to IOHandlerRaw object associated with
|
|
* <code>addr</code>, or nullptr if not found.
|
|
*/
|
|
IOHandlerRaw *lookup_raw_handler(const InetAddr &addr);
|
|
|
|
/// %Mutex for serializing concurrent access
|
|
std::mutex m_mutex;
|
|
|
|
/// Condition variable for signalling empty map
|
|
std::condition_variable m_cond;
|
|
|
|
/// Condition variable for signalling proxy map load
|
|
std::condition_variable m_cond_proxy;
|
|
|
|
/// Accept map (InetAddr-to-IOHandlerAccept)
|
|
SockAddrMap<IOHandlerAccept *> m_accept_handler_map;
|
|
|
|
/// Data (TCP) map (InetAddr-to-IOHandlerData)
|
|
SockAddrMap<IOHandlerData *> m_data_handler_map;
|
|
|
|
/// Datagram (UDP) map (InetAddr-to-IOHandlerDatagram)
|
|
SockAddrMap<IOHandlerDatagram *> m_datagram_handler_map;
|
|
|
|
/// Raw map (InetAddr-to-IOHandlerRaw)
|
|
SockAddrMap<IOHandlerRaw *> m_raw_handler_map;
|
|
|
|
/// Decomissioned handler set
|
|
std::set<IOHandler *> m_decomissioned_handlers;
|
|
|
|
/// Proxy map
|
|
ProxyMap m_proxy_map;
|
|
|
|
/// Flag indicating if proxy map has been loaded
|
|
bool m_proxies_loaded;
|
|
|
|
};
|
|
|
|
/// Smart pointer to HandlerMap
|
|
typedef std::shared_ptr<HandlerMap> HandlerMapPtr;
|
|
|
|
} //namespace palo
|
|
#endif //BDG_PALO_BE_SRC_RPC_HANDLER_MAP_H
|