/*
* This file is part of rasdaman community.
*
* Rasdaman community 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.
*
* Rasdaman community 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 rasdaman community. If not, see .
*
* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
rasdaman GmbH.
*
* For more information please see
* or contact Peter Baumann via .
/
/**
* SOURCE: rasmgr_host.cc
*
* MODULE: rasmgr
* CLASS: ServerHost, HostManager
*
* COMMENTS:
* - undefine TALK_SECRET fpr production release!!!
*
*/
#include "rasmgr_host.hh"
#include "rasmgr_srv.hh"
#include "rasmgr_master.hh"
#include "debug.hh"
// clear this def for production release!!!
#define TALK_SECRET(a) TALK(a)
#ifndef DEBUG
#undef TALK_SECRET
#define TALK_SECRET(a) { /* TALK(a) */ }
#endif // DEBUG
#ifdef SOLARIS
#define PORTMAP // define to use function declarations for old interfaces
#include
#include
#else
#include
#include
#endif
typedef unsigned long r_Ptr;
//int _rpcpmstart = 0;
// function prototype with C linkage
//extern "C" int gethostname(char *name, int namelen);
extern bool hostCmp( const char *h1, const char *h2);
ServerHost::ServerHost()
{
hostName[0]=0;
netwName[0]=0;
setNotUp();
isinternal=false;
valid=false;
startedServers=0;
isuseLocalHost=true;
TALK( "ServerHost::ServerHost(): hostName=" << this->hostName << ", netwName=" << this->netwName << ", listenPort=" << this->listenPort << ", isinternal=" << this->isinternal << ", valid=" << valid );
}
ServerHost::~ServerHost()
{
}
bool ServerHost::isValid() // used for the protection element
{
TALK( "ServerHost::isValid() -> " << valid );
return valid;
}
const char* ServerHost::getName()
{
return hostName;
}
const char* ServerHost::getNetworkName()
{
return netwName;
}
long ServerHost::getListenPort()
{
return listenPort;
}
bool ServerHost::isInternal()
{
return isinternal;
}
void ServerHost::init(const char* hostName,const char* netwName,int listenPort,bool isinternal)
{
strcpy(this->hostName,hostName);
strcpy(this->netwName,netwName);
this->listenPort=listenPort;
this->isinternal=isinternal;
isup = isinternal;
valid=true;
TALK( "ServerHost::init(): hostName=" << this->hostName << ", netwName=" << this->netwName << ", listenPort=" << this->listenPort << ", isinternal=" << this->isinternal << ", valid=" << valid );
}
char* ServerHost::getDescriptionHeader(char *destBuffer)
{
sprintf(destBuffer," %-10s %-32s %-4s %-4s %-10s ulh","Host Name","Netw. Addr","Port","Stat","Servers");
return destBuffer;
}
char* ServerHost::getDescription(char *destBuffer)
{
const char* sUp= isup ? "UP ":"DOWN";
const char* uLh= " -";
long lPort = listenPort;
if(isinternal)
{
uLh = useLocalHost() ? "on":"off";
lPort = config.getListenPort();
}
sprintf(destBuffer,"%-10s %-32s %4ld %-4s %2d %s",hostName,netwName,lPort,sUp,startedServers,uLh);
return destBuffer;
}
bool ServerHost::isUp()
{
return isup;
}
bool ServerHost::downHost()
{
// you can't stop the master with this
if(isinternal)
return false;
int socket=getConnectionSocket();
if(socket<0)
{
setNotUp();
//close(socket);
return false;
}
const char *text="POST downhost HTTP/1.1\r\nAccept: text/plain\r\nUserAgent: RasMGR/1.0\r\n\r\nRasMGR";
int nbytes=write(socket,text,strlen(text)+1);
isup=false;
return true;
}
bool ServerHost::checkStatus()
{
if(isinternal)
{
isup=true;
return true;
}
int socket=getConnectionSocket();
if(socket<0)
{
setNotUp();
//close(socket);
TALK( "ServerHost::checkStatus() -> false (no socket)" );
return false;
}
const char *text="POST getstatus HTTP/1.1\r\nAccept: text/plain\r\nUserAgent: RasMGR/1.0\r\n\r\nRasMGR";
int nbytes=write(socket,text,strlen(text)+1);
if(nbytes<0)
{
setNotUp();
close(socket);
TALK( "ServerHost::checkStatus() -> false (cannot write socket)" );
return false;
}
char message[200];
nbytes=read(socket,message,200);
close(socket);
if(nbytes<0)
{
setNotUp();
TALK( "ServerHost::checkStatus() -> false (cannot read socket)" );
return false;
}
char *body=strstr(message,"\r\n\r\n");
if(body==NULL)
{
setNotUp();
TALK( "ServerHost::checkStatus() -> false (null body)" );
return false;
}
int localStartedServers; //not sure that we will provide this info
sscanf(body,"%d ",&localStartedServers);
isup=true;
TALK( "ServerHost::checkStatus() -> true (all done)" );
return true;
} // checkStatus()
int ServerHost::countDefinedServers()
{
TALK_SECRET( "ServerHost::countDefinedServers enter." );
int count=0;
for(int i=0;i " << count );
return count;
}
int ServerHost::getConnectionSocket()
{
TALK_SECRET( "ServerHost::getConnectionSocket enter." );
// create socket
int sock;
struct protoent *getprotoptr;
getprotoptr=getprotobyname("tcp");
sock=socket(PF_INET,SOCK_STREAM,getprotoptr->p_proto);
int tempErrno = errno;
TALK_SECRET( "ServerHost::getConnectionSocket socket(PF_INET,SOCK_STREAM," << getprotoptr->p_proto << ") -> " << sock );
if (sock < 0)
{
TALK_SECRET( "ServerHost::getConnectionSocket cannot create socket: " << strerror( tempErrno ) );
return -1;
}
// init sockaddr
sockaddr_in servername;
struct hostent *hostinfo;
servername.sin_family=AF_INET;
servername.sin_port=htons(listenPort);
hostinfo=gethostbyname(netwName);
if(hostinfo==NULL)
{
close(sock);
TALK_SECRET( "ServerHost::getConnectionSocket leave (invalid hostinfo) -> -1" );
return -1;
}
servername.sin_addr=*(struct in_addr*)hostinfo->h_addr;
// connect to slave-manager
int connectResult = connect(sock,(struct sockaddr*)&servername,sizeof(servername));
TALK_SECRET( "ServerHost::getConnectionSocket connect() to host=" << hostinfo->h_name << ", listen port=" << servername.sin_port << " -> " << connectResult );
if(connectResult < 0)
{
close(sock);
if (errno)
{
tempErrno = errno;
TALK_SECRET( "ServerHost::getConnectionSocket close(" << sock << ") -> " << strerror(tempErrno) );
}
TALK_SECRET( "ServerHost::getConnectionSocket leave (cannot connect to slave mgr " << hostinfo << ") -> -1" );
return -1;
}
TALK_SECRET( "ServerHost::getConnectionSocket leave -> " << sock );
return sock;
}
void ServerHost::setNotUp()
{
isup=false;
startedServers=0;
}
void ServerHost::setIsUp(bool x)
{
isup=x;
}
void ServerHost::regStartServer()
{
startedServers++;
}
void ServerHost::regDownServer()
{
startedServers--;
}
int ServerHost::getStartedServers()
{
return startedServers;
}
void ServerHost::useLocalHost(bool how)
{
isuseLocalHost=how;
}
bool ServerHost::useLocalHost()
{
return isinternal ? isuseLocalHost : false;
}
void ServerHost::changeName(const char *newName)
{
strcpy(hostName,newName);
}
void ServerHost::changeNetName(const char *newNetName)
{
strcpy(netwName,newNetName);
}
void ServerHost::changeListenPort(int newListenPort)
{
listenPort=newListenPort;
}
//**********************************************************************
HostManager::HostManager()
{
TALK( "HostManager::HostManager()" );
}
HostManager::~HostManager()
{
TALK( "HostManager::~HostManager()" );
}
bool HostManager::insertInternalHost()
{
ENTER( "HostManager::insertInternalHost()" );
bool result = false; // function result
ServerHost tempServerHost;
if(hostList.empty()==false)
result = false;
else
{
//put the internal host, which is always defined, even if it has no servers attached
hostList.push_back(tempServerHost);
ServerHost &refServerHost=hostList.back();
const char *myhostName=config.getHostName();
const char *myPublicHostName=config.getPublicHostName();
refServerHost.init(myhostName,myPublicHostName,-1,true);
result = true;
}
LEAVE( "HostManager::insertInternalHost() -> " << result );
return result;
}
bool HostManager::insertNewHost(const char* hostName,const char *netwName,int listenport)
{
bool result = true; // function result
ENTER( "HostManager::insertNewHost( hostName=" << hostName << ", netwName=" << netwName << ", listenport=" << listenport << " )" );
if(testUniqueness(hostName)==false)
result = false;
if (result == true)
{
ServerHost tempServerHost;
if(hostList.empty())
insertInternalHost(); // just protection, but shouldn't be necessary
hostList.push_back(tempServerHost);
ServerHost &refServerHost=hostList.back();
refServerHost.init(hostName,netwName,listenport,false); //always external
result = true;
}
LEAVE( "HostManager::insertNewHost() -> " << result );
return result;
}
bool HostManager::removeHost(const char *hostName)
{
ENTER( "HostManager::removeHost( hostName=" << hostName << " )" );
list::iterator iter=hostList.begin();
for(int i=0;igetName(),hostName))
{
if(iter->countDefinedServers()>0)
{
LEAVE( "HostManager::removeHost() -> false" );
return false;
}
hostList.erase(iter);
break;
}
iter++;
}
LEAVE( "HostManager::removeHost() -> true" );
return true;
}
// FIXME: check for end of list
ServerHost& HostManager::operator[](int x)
{
ENTER( "HostManager::operator[] ( x=" << x << " )" );
list::iterator iter=hostList.begin();
for(int i=0;i::iterator iter=hostList.begin();
for(int i=0;igetName(),hostName))
{
LEAVE( "HostManager::operator[] -> found" );
return *iter;
}
iter++;
}
LEAVE( "HostManager::operator[] -> not found" );
return protElem;
}
int HostManager::countHosts()
{
return hostList.size();
}
int HostManager::countUpHosts()
{
int count=0;
list::iterator iter=hostList.begin();
for(int i=0;iisUp())
count++;
iter++;
}
return count;
}
bool HostManager::testUniqueness(const char* hostName)
{
list::iterator iter=hostList.begin();
for(int i=0;igetName(),hostName))
return false;
iter++;
}
return true;
}
int HostManager::postSlaveMGR(char *body,char *outBuffer)
{
char answBuffer[100];
do
{ // so we can break
if(body==NULL)
{
strcpy(answBuffer,"Missing identification, this is not a valid rasmgr."); // no rasmgr or soft error
break;
}
char name[100];
int licServ;
sscanf(body,"%s %d",name,&licServ);
TALK_SECRET( "HostManager::postSlaveMGR: name="< false" );
return false;
}
list::iterator iter=hostList.begin();
for(int i=0;icountDefinedServers()>0)
{
LEAVE( "HostManager::reset() -> false" );
return false;
}
}
while(hostList.size())
{
hostList.pop_front();
}
LEAVE( "HostManager::reset() -> true" );
return true;
}
bool HostManager::acceptChangeName(const char *oldName,const char *newName)
{
if(hostCmp(oldName,newName))
return true; // if someone really wants to change a name with the same,
return testUniqueness(newName);
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void rpcif_1(struct svc_req *rqstp, register SVCXPRT *transp)
{ // this function is registered by rpc-system. No one can use it, because it's never called
//(we do not have a svc_run() - call, thus it's not doing anything
}