/************************************************************************* * * Copyright (C) 2003 Dr. Peter Baumann * * SOURCE: rasmgr_srv.cc * * MODULE: rasmgr * CLASS: RasServer, RasServerManager * * PURPOSE: * * * CHANGE HISTORY (append further entries): * when who what * ----------------------------------------------------------------------- * 05-Jan-01 schatz created * 2003-jun-06 PB symbolic constants for server flags * * COMMENTS: * * ***********************************************************************/ #include "rasmgr_srv.hh" #include "rasmgr_localsrv.hh" #include "rasmgr_comm.hh" #include "rasmgr_users.hh" // the following is a quick hack until the real rminit/debug stuff links properly: #if 0 #include "raslib/rminit.hh" #include "debug.hh" #else #ifdef DEBUG #define ENTER(a) { cout << "ENTER: " << a << endl; } #define LEAVE(a) { cout << "LEAVE: " << a << endl; } #define TALK(a) { cout << a << endl; } #define SET_OUTPUT(a) #else #define ENTER(a) { ; } #define LEAVE(a) { ; } #define TALK(a) { ; } #define SET_OUTPUT(a) #endif #endif // 0 RasServer::RasServer() { serverName[0]=0; extraParam[0]=0; ptrServerHost=NULL; ptrDatabaseHost=NULL; //connStr[0]=0; available=isup=isstarting=false; valid=false; downReq=false; initialCountDown=1000; currentCountDown=1000; // asa doreste management writeTransaction=false; // no clearTransaction!! readTransaction=false; connDatabase = NULL; activityExpected=false; crashCount = 0; activityCounter = 0; // will be changed in init() autorestart = true; strcpy(executableName,RASEXECUTABLE); } RasServer::~RasServer() { } const char* RasServer::getName() { return serverName; } const char* RasServer::getHostName() { if(ptrServerHost) { return ptrServerHost->getName(); } return "noValidHost!"; } const char* RasServer::getHostNetwName() { if(ptrServerHost) { return ptrServerHost->getNetworkName(); } return "noValidHost!"; } long RasServer::getPort() { return listenPort; } char RasServer::getType() { return serverType; } void RasServer::changeName(const char *newName) { strncpy( serverName, newName, sizeof(serverName) ); } void RasServer::changeType(const char newType) // char not char*!! { serverType=newType; } void RasServer::changePort(long newPort) { listenPort=newPort; } void RasServer::changeExtraParam(const char *xParam) { strncpy(this->extraParam,xParam,sizeof(extraParam) ); } void RasServer::changeCountDown(int newCountDown) { initialCountDown=newCountDown; currentCountDown=newCountDown; } void RasServer::changeAutoRestart(bool x) { autorestart = x; } const char* RasServer::getExtraParams() { return extraParam; } int RasServer::getCountDown() { return initialCountDown; } void RasServer::init(const char *srvName,const char* hostName,char serverType,long listenPort) { strcpy(this->serverName,srvName); ptrServerHost=&hostmanager[hostName];// should be valid! isinternal=ptrServerHost->isInternal(); available=isup=false; this->serverType=serverType; this->listenPort=listenPort; // RNP servers start with first action connectToDBMS() as opposed to the others, // therefore adapt counter. -- PB 2002-nov-23 switch (serverType) { case 'r': case 'h': activityCounter = 1; break: case 'n': activityCounter = 0; break: default: TALK( "Error: illegal server type specifier " << serverType << ", assuming 'n'." ); break; } valid=true; } bool RasServer::isValid() { return valid; } bool RasServer::isUp() { return isup; } bool RasServer::isStarting() { return isstarting; } bool RasServer::isAvailable() { return available; } bool RasServer::forceAvailable() { // this function is just for advanced system debug, not for production work if(isup) { available=true; clearPendingTransaction(); return true; } return false; } void RasServer::setNotAvailable() { available=false; regularSignalCounter = MAXREGULARCOUNTER; } bool RasServer::isAutoRestart() { return autorestart; } char* RasServer::getDescriptionHeader(char *destBuffer) { sprintf(destBuffer," %-20s %s %-20s %-20s %-4s %-2s %s %s","Server Name","Type","Host","Db Host","Stat","Av","Acc","Crc"); return destBuffer; } char* RasServer::getDescription(char *destBuffer) { char *sType="(none)"; if(serverType==SERVERTYPE_FLAG_RPC) sType="(RPC) "; if(serverType==SERVERTYPE_FLAG_HTTP) sType="(HTTP)"; if(serverType==SERVERTYPE_FLAG_RNP) sType="(RNP) "; const char* sUp= isup ? "UP ":"DOWN"; const char* sAv= available ? "YES":"NO "; const char* host= ptrServerHost->getName();//"(internal)"; const char* dbHost = getDBHostName(); //if(isinternal==false) // { host=ptrServerHost->getName(); // } sprintf(destBuffer,"%-20s %s %-20s %-20s %s %s %6ld %2d",serverName,sType,host,dbHost,sUp,sAv,activityCounter,crashCount); return destBuffer; } char* RasServer::getDescriptionPortHeader(char *destBuffer) { sprintf(destBuffer," %-20s %s %-20s %-10s %-3s %-3s","Server Name","Type","Host"," Port","Ars"," Icd"); return destBuffer; } char* RasServer::getDescriptionPort(char *destBuffer) { char *sType="(none)"; if(serverType==SERVERTYPE_FLAG_RPC) sType="(RPC) "; if(serverType==SERVERTYPE_FLAG_HTTP) sType="(HTTP)"; if(serverType==SERVERTYPE_FLAG_RNP) sType="(RNP) "; // const char* sUp= isup ? "UP ":"DOWN"; // const char* sAv= available ? "YES":"NO "; const char* host = ptrServerHost->getName(); const char *ars = autorestart ? "on":"off"; if(serverType==SERVERTYPE_FLAG_RPC) sprintf(destBuffer,"%-20s %s %-20s %#10x %-3s %3d/%-3d",serverName,sType,host,listenPort,ars,currentCountDown,initialCountDown); else sprintf(destBuffer,"%-20s %s %-20s %10d %-3s %3d/%-3d",serverName,sType,host,listenPort,ars,currentCountDown,initialCountDown); //countdown=%d InitialCountDown, return destBuffer; } char* RasServer::getDescriptionExecHeader(char *destBuffer) { sprintf(destBuffer," %-20s %-10s Executable Extraparameters","Server Name","Host"); return destBuffer; } char* RasServer::getDescriptionExec(char *destBuffer) { const char* host = ptrServerHost->getName(); sprintf(destBuffer,"%-20s %-10s %-15s %s",serverName,host,executableName,extraParam); return destBuffer; } bool RasServer::connectToDBHost(const char *dbHostName)//, const char *connString) { if(ptrDatabaseHost) return false; DatabaseHost &dbh=dbHostManager[dbHostName]; if(dbh.isValid()==false) return false; ptrDatabaseHost = &dbh; //removed dbh.incrConnServers(); //strcpy(connStr,connString); for(int i=0;igetName(); for(int i=0;idecrConnServers(); ptrDatabaseHost=NULL; return true; } const char* RasServer::getDBHostName() { if(ptrDatabaseHost) return ptrDatabaseHost->getName(); return "noDBHost!"; } bool RasServer::isConnectedToDBHost() { if(ptrDatabaseHost) return true; return false; } void RasServer::changeExecutableName(const char *newExecutable) { if(newExecutable == NULL) strcpy(executableName,RASEXECUTABLE); else strcpy(executableName,newExecutable); } const char* RasServer::getExecutableName() { return executableName; } int RasServer::startServerInDebugger(char *command) { // sorry for literals, I will change this soon if(ptrDatabaseHost==NULL) return -1; if(ptrServerHost->isUp()==false) return -5; if(ptrServerHost->mayStartServer()==false) return -2; downReq=false; const char *sTypeString= serverType==SERVERTYPE_FLAG_HTTP ? "--http":""; const char *rasmgrHost = ptrServerHost->useLocalHost() ? "localhost" : config.getHostName(); sprintf(command, "%s --rsn %s %s --lport %ld ",executableName,serverName,sTypeString,listenPort); sprintf(command+strlen(command),"--mgr %s --mgrport %ld --connect %s ",rasmgrHost,config.getListenPort(),ptrDatabaseHost->getConnectionString()); sprintf(command+strlen(command),"--sync %s %s",authorization.getSyncroString(),extraParam); currentCountDown=initialCountDown; activityExpected=true; activityCounter = 0; return 0; } int RasServer::startServer() { // sorry for literals, I will change this soon if(ptrDatabaseHost==NULL) return -1; if(ptrServerHost->isUp()==false) return -5; if(ptrServerHost->mayStartServer()==false) return -2; downReq=false; const char *sTypeString= serverType==SERVERTYPE_FLAG_HTTP ? "--http" : ""; sTypeString= serverType==SERVERTYPE_FLAG_RNP ? "--rnp" : sTypeString; const char *rasmgrHost = ptrServerHost->useLocalHost() ? "localhost" : config.getHostName(); char command[400]; sprintf(command, "%s %s %s --rsn %s %s --lport %ld ",serverName,executableName,executableName,serverName,sTypeString,listenPort); sprintf(command+strlen(command),"--mgr %s --mgrport %ld --connect %s ",rasmgrHost,config.getListenPort(),ptrDatabaseHost->getConnectionString()); sprintf(command+strlen(command)," %s",extraParam); if(isinternal) { TALK( "launching local server, command=" << command ); localServerManager.startNewServer(command); } else { TALK( "connecting to remote rasmgr" ); int socket=ptrServerHost->getConnectionSocket(); if(socket<0) return -3; char message[MAXMSG]="POST exec HTTP/1.1\r\nAccept: text/plain\r\nUserAgent: RasMGR/1.0\r\nContent-length: "; sprintf(message+strlen(message),"%d\r\n\r\n%s",strlen(command)+1,command); int nbytes=write(socket,message,strlen(message)+1); close(socket); if(nbytes<0) return -4; } currentCountDown=initialCountDown; activityExpected=true; isstarting=true; activityCounter = 0; return 0; } int RasServer::downServer(bool forced) { if(available==false && (forced == false || isstarting==true) ) { downReq=true; //std::cout<<"Down request, but working"<getConnectionSocket(); if(socket<0) return -2; char message[MAXMSG]="POST downserver HTTP/1.1\r\nAccept: text/plain\r\nUserAgent: RasMGR/1.0\r\nContent-length: "; sprintf(message+strlen(message),"%d\r\n\r\n%s",strlen(serverName)+1,serverName); int nbytes=write(socket,message,strlen(message)+1); close(socket); if(nbytes<0) return -3; } //ptrServerHost->regDownServer(); return 0; } int RasServer::killServer() { if(isup) { ptrServerHost->regDownServer(); if(ptrDatabaseHost) ptrDatabaseHost->regDownServer(); isup=available=0; activityExpected=false; } if(isinternal) { localServerManager.killServer(serverName); } else { int socket=ptrServerHost->getConnectionSocket(); if(socket<0) return -2; char message[MAXMSG]="POST killserver HTTP/1.1\r\nAccept: text/plain\r\nUserAgent: RasMGR/1.0\r\nContent-length: "; sprintf(message+strlen(message),"%d\r\n\r\n%s",strlen(serverName)+1,serverName); int nbytes=write(socket,message,strlen(message)+1); close(socket); if(nbytes<0) return -3; } return 0; } void RasServer::changeStatus(int newStatus,long infCount) { ENTER( "RasServer::changeStatus: enter. servername="<regStartServer(); if(ptrDatabaseHost) ptrDatabaseHost->regStartServer(); isstarting=false; } if(wasup==true && isup==false) { //then, ok, I'm down ptrServerHost->regDownServer(); if(ptrDatabaseHost) ptrDatabaseHost->regDownServer(); activityExpected=false; } clearPendingTransaction(); // when the server talks to RasMgr, is always clear, without client if(available) { activityCounter++; // just a counter } if(downReq && available) { downReq=false; available=false; //until it's really down it shouldn't get any clients TALK( "RasServer::changeStatus: srv down request, available - setting to unavailable and shutting down. "); downNow(); } if(crashed) { crashCount++; TALK( "server has crashed, current crash count is " << crashCount << ", activity count is " << activityCounter ); // restart if "work has started already" (see init() comment on different counting wrt. server types) // changed by PB 2003-nov-23 // if(activityCounter && autorestart) if (activityCounter>1 && autorestart) { // a crashed server doesn't autorestart if he crashes before starting work. TALK( "auto restart activated, restarting." ); startServer(); } } // commented out due to some error if(initialCountDown) { if(available) { currentCountDown--; if(currentCountDown==0) { available=false; std::cout<<"rasmgr: Countdown reached for "<endWriteTransaction(); if(readTransaction ) connDatabase->endReadTransaction(); writeTransaction=false; readTransaction =false; connDatabase = NULL; } //********************************************************************** RasServerManager::RasServerManager() { } RasServerManager::~RasServerManager() { } bool RasServerManager::insertNewServer(const char *srvName,const char* hostName,char serverType,long listenPort) { bool result = true; if(testUniqueness(srvName)==false) result = false; if( result == true && hostmanager[hostName].isValid()==false) result = false; if(result == true && serverType!=SERVERTYPE_FLAG_RPC && serverType!=SERVERTYPE_FLAG_HTTP && serverType!=SERVERTYPE_FLAG_RNP) { TALK( "RasServerManager::insertNewServer: server " << srvName << " has illegal type " << serverType ); result = false; } if (result == true) { RasServer tempRasServer; srvList.push_back(tempRasServer); RasServer &refRasServer=srvList.back(); refRasServer.init(srvName,hostName,serverType,listenPort); } return result; } bool RasServerManager::removeServer(const char *srvName) { list::iterator iter=srvList.begin(); for(int i=0;igetName(),srvName)==0) { if(iter->isUp()) return false; iter->disconnectFromDBHost(); //it's not up, so it fails only if it is not connected at all srvList.erase(iter); return true; } iter++; } return false; } bool RasServerManager::testUniqueness(const char* srvName) { list::iterator iter=srvList.begin(); for(int i=0;igetName(),srvName)==0) return false; iter++; } return true; } RasServer& RasServerManager::operator[](int x) { list::iterator iter=srvList.begin(); for(int i=0;i::iterator iter=srvList.begin(); for(int i=0;igetName(),srvName)==0) return *iter; iter++; } return protElem; } RasServer& RasServerManager::last() { return srvList.back(); } int RasServerManager::countServers() { return srvList.size(); } int RasServerManager::changeServerStatus(char *reqMessage) { char serverName[50]; int newstatus; long infCount; sscanf(reqMessage,"%s %d %ld",serverName,&newstatus,&infCount); TALK( "RasServerManager::changeServerStatus: Trying to change status of "<getDescription(buff); TALK( "\t" << i << ": " << buff ); iter++; } } bool RasServerManager::reset() { // test modus only if(config.isTestModus()==false) return false; list::iterator iter=srvList.begin(); for(int i=0;iisUp()) return false; } iter=srvList.begin(); for(int i=0;idisconnectFromDBHost(); //it's not up, so it fails only if it is not connected at all } while(srvList.size()) { srvList.pop_front(); } return true; } bool RasServerManager::acceptChangeName(const char *oldName,const char *newName) { if(strcmp(oldName,newName)==0) return true; // if someone really wants to change a name with the same, return testUniqueness(newName); }