438 lines
13 KiB
C++
438 lines
13 KiB
C++
// Matt Wells, Copyright Nov 2000
|
|
|
|
// . every host (aka server) has a unique positive 32 bit hostId
|
|
// . to get the groupId of a hostId we must reverse the bits and then
|
|
// AND the result with g_hostdb.m_groupMask
|
|
// . host record is about 32 bytes
|
|
// . we keep a list of all hosts in the conf file
|
|
// . this new model is much easier to work with
|
|
// . format of hosts in the xml conf file
|
|
// . <host0> <ip> 1.2.3.4 </> <port> 1234 </>
|
|
|
|
#ifndef GB_HOSTDB_H
|
|
#define GB_HOSTDB_H
|
|
|
|
#include "types.h"
|
|
#include "rdbid_t.h"
|
|
#include "collnum_t.h"
|
|
#include "msgtype_t.h"
|
|
#include "Sanity.h"
|
|
#include "GbMutex.h"
|
|
#include <atomic>
|
|
|
|
/// @note ALC there used to be a sync host functionality that was removed
|
|
/// in commit 08e8eeb2a53b41763b5d7f97a0b953bebb04517a because it wasn't working
|
|
|
|
#define HT_GRUNT 0x01
|
|
#define HT_SPARE 0x02
|
|
#define HT_PROXY 0x04
|
|
#define HT_QCPROXY 0x08
|
|
#define HT_SCPROXY 0x10
|
|
|
|
int32_t *getLocalIps ( ) ;
|
|
|
|
|
|
//information about a running host/instance
|
|
struct HostRuntimeInformation {
|
|
bool m_valid; //is this information valid, i.e. have we received it or is it fake?
|
|
|
|
uint32_t m_flags; //updated by InstanceInfoExchange and PingServer
|
|
|
|
collnum_t m_dailyMergeCollnum;
|
|
|
|
char m_gbVersionStr[21];
|
|
|
|
int32_t m_totalDocsIndexed;
|
|
|
|
int32_t m_hostsConfCRC;
|
|
|
|
int8_t m_repairMode;
|
|
};
|
|
|
|
|
|
class Host {
|
|
public:
|
|
int32_t getInternalHttpPort() const { return m_httpPort; }
|
|
int32_t getInternalHttpsPort() const { return m_httpsPort; }
|
|
int32_t getExternalHttpPort() const { return m_httpPort; }
|
|
int32_t getExternalHttpsPort() const { return m_httpsPort; }
|
|
|
|
int32_t m_hostId ;
|
|
|
|
// shards and groups are basically the same, but let's keep it simple.
|
|
// since we use m_map in Hostdb.cpp to map the bits of a key to
|
|
// the shard # now (not a groupId anymore, since groupId does not
|
|
// work for non binary powers of shards)
|
|
uint32_t m_shardNum;
|
|
|
|
uint32_t m_ip ; // used for internal communcation (udp)
|
|
|
|
// what stripe are we in? i.e. what twin number are we?
|
|
int32_t m_stripe;
|
|
|
|
// this ip is now the shotgun ip. the problem with an "external" ip
|
|
// is that people internal to the network cannot usually see it!!
|
|
// so now this is just a secondary regular ip address for servers with
|
|
// dual gigabit ethernet ports. make performance much better.
|
|
uint32_t m_ipShotgun;
|
|
|
|
uint16_t m_port ; // Mattster Protocol (MP) UDP port
|
|
|
|
bool m_isAlive;
|
|
HostRuntimeInformation m_runtimeInformation;
|
|
|
|
// send to eth 0 or 1 when sending to this host?
|
|
char m_preferEth;
|
|
|
|
// we now include the working dir in the hosts.conf file
|
|
// so main.cpp can do gb --install and gb --allstart
|
|
char m_dir[256];
|
|
char m_mergeDir[256];
|
|
char m_mergeLockDir[256];
|
|
|
|
char m_hostname[16];
|
|
|
|
// the secondary ethernet interface hostname
|
|
char m_hostname2[16];
|
|
|
|
// client port
|
|
uint16_t m_dnsClientPort;
|
|
|
|
// was host in gk0 cluster and retired because its twin got
|
|
// ssds, so it was no longer really needed.
|
|
bool m_retired;
|
|
|
|
// how many total error replies we got from this host
|
|
int32_t m_errorReplies;
|
|
|
|
// now include a note for every host
|
|
char m_note[128];
|
|
|
|
bool m_isProxy;
|
|
|
|
// used for compressing spidered docs before sending back to local
|
|
// network to save on local loop bandwidth costs
|
|
char m_type;
|
|
|
|
bool isProxy() { return (m_type == HT_PROXY); }
|
|
bool isGrunt() { return (m_type == HT_GRUNT); }
|
|
|
|
bool isHostsConfCRCKnown() const { return m_runtimeInformation.m_hostsConfCRC!=0; }
|
|
inline bool hasSameHostsConfCRC() const;
|
|
|
|
// for m_type == HT_QCPROXY, we forward the query to the regular proxy
|
|
// at this Ip:Port. we should receive a compressed 0xfd reply and
|
|
// we uncompress it and return it to the browser.
|
|
int32_t m_forwardIp;
|
|
int16_t m_forwardPort;
|
|
|
|
std::atomic<int64_t> m_dgramsTo;
|
|
std::atomic<int64_t> m_dgramsFrom;
|
|
|
|
std::atomic<int32_t> m_totalResends; //how many UDP packets has been resent
|
|
std::atomic<int32_t> m_etryagains; //how many times a request got an ETRYAGAIN
|
|
|
|
// for timing how long the msg39 takes from this host
|
|
int32_t m_splitsDone;
|
|
int64_t m_splitTimes;
|
|
|
|
// . used by Parms.cpp for broadcasting parm change requests
|
|
// . each parm change request has an id
|
|
// . this let's us know which id is in progress and what the last
|
|
// id completed was
|
|
int32_t m_currentParmIdInProgress;
|
|
int32_t m_lastParmIdCompleted;
|
|
class ParmNode *m_currentNodePtr;
|
|
int32_t m_lastTryError;
|
|
int32_t m_lastTryTime;
|
|
|
|
bool m_spiderEnabled;
|
|
bool m_queryEnabled;
|
|
|
|
void updateLastResponseReceiveTimestamp(uint64_t t) { m_lastResponseReceiveTimestamp=t; }
|
|
void updateLastRequestSendTimestamp(uint64_t t) { m_lastRequestSendTimestamp=t; }
|
|
uint64_t getLastResponseReceiveTimestamp() const { return m_lastResponseReceiveTimestamp; }
|
|
uint64_t getLastRequestSendTimestamp() const { return m_lastRequestSendTimestamp; }
|
|
|
|
private:
|
|
uint64_t m_lastResponseReceiveTimestamp;
|
|
std::atomic<uint64_t> m_lastRequestSendTimestamp;
|
|
|
|
friend class Hostdb;
|
|
uint16_t m_httpPort ; // http port
|
|
uint16_t m_httpsPort;
|
|
};
|
|
|
|
#include "max_hosts.h"
|
|
#define MAX_SPARES 64
|
|
#define MAX_PROXIES 6
|
|
|
|
// for table for mapping key to a groupid
|
|
#define MAX_KSLOTS 8192
|
|
|
|
class Hostdb {
|
|
|
|
public:
|
|
|
|
// . set up our Hostdb
|
|
// . sets itself from g_conf (our configuration class)
|
|
// . returns false on fatal error
|
|
// . gets filename from Conf.h class
|
|
bool init(int32_t hostId, bool proxyHost=false, bool useTempCluster=false, bool initMyHost=true, const char *cwd=NULL);
|
|
|
|
// if config changes this *should* change
|
|
int32_t getCRC();
|
|
|
|
Hostdb();
|
|
~Hostdb();
|
|
void reset();
|
|
|
|
uint32_t getMyIp ( ) { return m_myIp; }
|
|
uint16_t getMyPort ( ) { return m_myPort; }
|
|
int32_t getMyHostId ( ) { return m_myHostId; }
|
|
uint32_t getLoopbackIp ( ) { return m_loopbackIp; }
|
|
Host *getMyHost ( ) { return m_myHost; }
|
|
bool amProxy ( ) { return m_myHost->isProxy(); }
|
|
Host *getMyShard ( ) { return m_myShard; }
|
|
int32_t getMyShardNum ( ) { return m_myHost->m_shardNum; }
|
|
|
|
// we consider the host dead if we didn't get a ping reply back
|
|
// after 10 seconds
|
|
bool isDead(int32_t hostId) const;
|
|
|
|
bool isDead(const Host *h) const;
|
|
|
|
bool hasDeadHost() const;
|
|
bool hasDeadHostCached() const;
|
|
|
|
int getNumHostsDead() const;
|
|
|
|
int64_t getNumGlobalRecs ( );
|
|
|
|
bool isShardDead(int32_t shardNum) const;
|
|
|
|
Host *getLeastLoadedInShard ( uint32_t shardNum , char niceness );
|
|
int32_t getHostIdWithSpideringEnabled ( uint32_t shardNum, bool answerRequired );
|
|
Host *getHostWithSpideringEnabled ( uint32_t shardNum );
|
|
Host *getHostWithQueryingEnabled(uint32_t shardNum);
|
|
bool mayWeSendRequestToHost(const Host *host, msg_type_t msgType); //spider/query split: send requests between classes of hosts?
|
|
|
|
// in the entire cluster. return host #0 if its alive, otherwise
|
|
// host #1, etc.
|
|
Host *getFirstAliveHost ();
|
|
|
|
// . returns false if blocks and will call your callback later
|
|
// . returns true if doesn't block
|
|
// . sets errno on error
|
|
// . used to get array of hosts in 1 group usually for transmitting to
|
|
// . returned group includes all hosts in host "hostId"'s group
|
|
// . RdbList will be populated with the hosts in that group
|
|
// . we do not create an RdbList, you must do that
|
|
// . callback passes your RdbList back to you
|
|
Host *getShard ( uint32_t shardNum , int32_t *numHosts = NULL ) {
|
|
if(shardNum>=(unsigned)m_numShards) gbshutdownLogicError();
|
|
if ( numHosts ) *numHosts = m_numHostsPerShard;
|
|
return &m_hosts[shardNum * m_numHostsPerShard];
|
|
}
|
|
const Host *getShard( uint32_t shardNum , int32_t *numHosts = NULL) const {
|
|
return const_cast<Hostdb*>(this)->getShard(shardNum,numHosts);
|
|
}
|
|
|
|
// get the host that has this path/ip
|
|
Host *getHost2 ( const char *cwd , int32_t *localIps ) ;
|
|
Host *getProxy2 ( const char *cwd , int32_t *localIps ) ;
|
|
|
|
// . like above but just gets one host
|
|
Host *getHost ( int32_t hostId ) {
|
|
if ( hostId < 0 ) { gbshutdownAbort(true); }
|
|
return m_hostPtrs[hostId];
|
|
}
|
|
const Host *getHost(int32_t hostId) const {
|
|
return const_cast<Hostdb*>(this)->getHost(hostId);
|
|
}
|
|
|
|
Host *getSpare ( int32_t spareId ) {
|
|
return m_spareHosts[spareId]; }
|
|
|
|
Host *getProxy ( int32_t proxyId ) {
|
|
return m_proxyHosts[proxyId]; }
|
|
|
|
int32_t getNumHosts() const { return m_numHosts; }
|
|
int32_t getNumProxy() const { return m_numProxyHosts; }
|
|
int32_t getNumProxies() const { return m_numProxyHosts; }
|
|
int32_t getNumGrunts() const { return m_numHosts; }
|
|
|
|
// how many of the hosts are non-dead?
|
|
int32_t getNumHostsAlive() const { return m_numHostsAlive; }
|
|
int32_t getNumProxyAlive() const { return m_numProxyAlive; }
|
|
int32_t getNumShards() const { return m_numShards; }
|
|
int32_t getNumIndexSplits() const { return m_indexSplits; }
|
|
|
|
// how many hosts in this group?
|
|
int32_t getNumHostsPerShard() const { return m_numHostsPerShard; }
|
|
|
|
// goes with Host::m_stripe
|
|
int32_t getNumStripes() const {
|
|
// BR 20160316: Make sure noquery hosts are not used when dividing
|
|
// docIds for querying (Msg39)
|
|
return m_numStripeHostsPerShard;
|
|
}
|
|
|
|
// hash the hosts into the hash tables for lookup
|
|
bool hashHosts(bool initMyHost=true);
|
|
bool hashHost ( bool udp , Host *h , uint32_t ip , uint16_t port ) ;
|
|
int32_t getHostId ( uint32_t ip , uint16_t port ) ;
|
|
Host *getHostByIp ( uint32_t ip ) ;
|
|
Host *getUdpHost ( uint32_t ip , uint16_t port ) ;
|
|
Host *getTcpHost ( uint32_t ip , uint16_t port ) ;
|
|
bool isIpInNetwork ( uint32_t ip ) ;
|
|
Host *getHostFromTable ( bool udp , uint32_t ip , uint16_t port ) ;
|
|
|
|
// sets the note for a host
|
|
bool setNote ( int32_t hostId, const char *note, int32_t noteLen );
|
|
bool setSpareNote ( int32_t spareId, const char *note, int32_t noteLen );
|
|
|
|
// replace a host with a spare
|
|
bool replaceHost ( int32_t origHostId, int32_t spareHostId );
|
|
|
|
// write a hosts.conf file
|
|
bool saveHostsConf ( );
|
|
|
|
int32_t getBestIp(const Host *h);
|
|
|
|
Host *getBestSpiderCompressionProxy ( int32_t *key ) ;
|
|
|
|
// only used by 'gb scale <hostdb.conf>' cmd for now
|
|
void resetPortTables ();
|
|
|
|
// returns best IP to use for "h" which is a host in hosts2.conf
|
|
int32_t getBestHosts2IP(const Host *h);
|
|
|
|
void updateAliveHosts(const int32_t alive_hosts_ids[], size_t n);
|
|
void updateHostRuntimeInformation(int hostId, const HostRuntimeInformation &hri);
|
|
|
|
void setOurFlags();
|
|
void setOurTotalDocsIndexed();
|
|
|
|
const Host *getMinRepairModeHost() const { return m_minRepairModeHost; }
|
|
int32_t getMinRepairMode() const { return m_minRepairMode; }
|
|
int32_t getMinRepairModeBesides0() const { return m_minRepairModeBesides0; }
|
|
|
|
// our host's info used by Udp* classes for internal communication
|
|
uint32_t m_myIp;
|
|
uint16_t m_myPort;
|
|
Host *m_myHost;
|
|
Host *m_myShard;
|
|
|
|
// the loopback ip (127.0.0.1)
|
|
uint32_t m_loopbackIp;
|
|
|
|
// . the hosts are stored from g_conf in xml to here
|
|
// . m_hosts[i] is the ith Host entry
|
|
Host *m_hosts;
|
|
int32_t m_numHosts;
|
|
|
|
int32_t m_allocSize;
|
|
|
|
// . this maps a hostId to the appropriate host!
|
|
// . we can't use m_hosts[i] because we sort it by groupId for getGroup
|
|
Host *m_hostPtrs[MAX_HOSTS];
|
|
|
|
// we must have the same number of hosts in each group
|
|
int32_t m_numHostsPerShard;
|
|
|
|
// Number of hosts per shared not counting noquery hosts
|
|
int32_t m_numStripeHostsPerShard;
|
|
|
|
// store the file in m_buf
|
|
char m_buf [MAX_HOSTS * 128];
|
|
int32_t m_bufSize;
|
|
|
|
// this maps shard # to the array of hosts in that shard
|
|
Host *m_shards[MAX_HOSTS];
|
|
|
|
// the hash table of the ips in hosts.conf
|
|
int32_t *m_ips;
|
|
int32_t m_numIps;
|
|
|
|
// . our group info
|
|
int32_t m_myHostId; // our hostId
|
|
int32_t m_numShards;
|
|
char m_dir[256];
|
|
|
|
char m_httpRootDir[sizeof(m_dir)+128];
|
|
char m_logFilename[sizeof(m_dir)+128];
|
|
|
|
int32_t m_indexSplits;
|
|
|
|
// spare hosts list
|
|
Host *m_spareHosts[MAX_SPARES];
|
|
int32_t m_numSpareHosts;
|
|
|
|
// proxy host list
|
|
Host *m_proxyHosts[MAX_PROXIES];
|
|
int32_t m_numProxyHosts;
|
|
int32_t m_numProxyAlive;
|
|
|
|
int32_t m_numTotalHosts;
|
|
|
|
bool m_initialized;
|
|
|
|
bool createHostsConf( const char *cwd );
|
|
bool m_created;
|
|
|
|
int32_t m_crc;
|
|
bool m_crcValid;
|
|
|
|
bool m_useTmpCluster;
|
|
|
|
uint32_t getShardNum(rdbid_t rdbId, const void *key) const;
|
|
|
|
uint32_t getShardNumFromDocId (int64_t d) const;
|
|
|
|
// assume to be for posdb here
|
|
uint32_t getShardNumByTermId(const void *key) const;
|
|
|
|
uint32_t m_map[MAX_KSLOTS];
|
|
|
|
bool hostsConfInDisagreement() const { return m_hostsConfInDisagreement; }
|
|
bool hostsConfInAgreement() const { return m_hostsConfInAgreement; }
|
|
|
|
private:
|
|
bool isDead_unlocked(const Host *h) const;
|
|
|
|
int32_t m_numHostsAlive;
|
|
mutable GbMutex m_mtxPinginfo; //protects the pinginfo in the hosts
|
|
bool m_hostsConfInAgreement;
|
|
bool m_hostsConfInDisagreement;
|
|
|
|
int32_t m_minRepairMode;
|
|
int32_t m_minRepairModeBesides0;
|
|
const Host *m_minRepairModeHost;
|
|
};
|
|
|
|
extern class Hostdb g_hostdb;
|
|
|
|
|
|
static inline uint32_t getShardNum(rdbid_t rdbId, const void *key) {
|
|
return g_hostdb.getShardNum ( rdbId , key );
|
|
}
|
|
|
|
inline uint32_t getMyShardNum ( ) {
|
|
return g_hostdb.m_myHost->m_shardNum;
|
|
}
|
|
|
|
inline int32_t getMyHostId() {
|
|
return g_hostdb.m_myHost->m_hostId;
|
|
}
|
|
|
|
inline uint32_t getShardNumFromDocId ( int64_t d ) {
|
|
return g_hostdb.getShardNumFromDocId ( d );
|
|
}
|
|
|
|
inline bool Host::hasSameHostsConfCRC() const {
|
|
return m_runtimeInformation.m_hostsConfCRC == g_hostdb.getCRC();
|
|
}
|
|
|
|
#endif // GB_HOSTDB_H
|