[BACK] Return to admin_executor_service.cpp CVS log [TXT][DIR] Up to Nevrax / code / nelns / admin_executor_service

Diff for /code/nelns/admin_executor_service/admin_executor_service.cpp between version 1.1 and 1.2

version 1.1, 2001/04/18 13:54:25 version 1.2, 2001/05/02 12:36:39
Line 2 
Line 2 
  * Admin Executor Service (AES)  * Admin Executor Service (AES)
  *  *
  * $Id$  * $Id$
   *
  */  */
  
 /* Copyright, 2000 Nevrax Ltd. /* Copyright, 2000 Nevrax Ltd.
  *  *
  * This file is part of NEVRAX NeL Network Services  * This file is part of NEVRAX D.T.C. SYSTEM.
  * NEVRAX NeL Network Services is free software; you can redistribute it and/or modify  * NEVRAX D.T.C. SYSTEM is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2, or (at your option)  * the Free Software Foundation; either version 2, or (at your option)
  * any later version.  * any later version.
  *  *
  * NEVRAX NeL Network Services is distributed in the hope that it will be useful, but  * NEVRAX D.T.C. SYSTEM is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  * General Public License for more details.  * General Public License for more details.
  *  *
  * You should have received a copy of the GNU General Public License  * You should have received a copy of the GNU General Public License
  * along with NEVRAX NeL Network Services; see the file COPYING. If not, write to the  * along with NEVRAX D.T.C. SYSTEM; see the file COPYING. If not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  * MA 02111-1307, USA.  * MA 02111-1307, USA.
  */  */
  
 #include <nel/misc/debug.h> #include <io.h>
 #include <nel/misc/log.h> #include <process.h>
 #include <nel/misc/common.h> #include <fcntl.h>
 #include <nel/net/service.h> #include <sys/stat.h>
 #include <nel/net/net_displayer.h> 
  #include <string>
 #include "sysload.h" #include <list>
 #include "sysmem.h" 
 #include "sysswap.h" #include "nel/misc/debug.h"
  #include "nel/misc/config_file.h"
  #include "nel/misc/thread.h"
  
  #include "nel/net/service.h"
  #include "nel/net/net_manager.h"
  
  
 using namespace std; using namespace std;
 using namespace NLMISC; using namespace NLMISC;
 using namespace NLNET; using namespace NLNET;
  
  
 static const char UNKNOW_VALUE[] = "<Unknown>"; 
  
  struct CService
  {
          CService(TSockId s) : ServiceSockId(s), ServiceId(NextServiceId++) { }
  
 CLog StatLog(CLog::LOG_STAT);         TSockId        ServiceSockId;        // socket number to communicate with
          uint32        ServiceId;                // id to identify it
          string        ShortName;
          string        LongName;
  
  private:
  
 /// Log Stat data (STT)         static        uint32 NextServiceId;
 void sendData (const char *str, TSenderId from) };
 { 
         StatLog.displayNL( str ); 
 } 
  
  uint32 CService::NextServiceId = 0;
  
 /// Log the last minute average load list<CService> Services;
 void cbLoad ( CMessage& message, TSenderId from ) typedef list<CService>::iterator sit;
 { 
         CSysLoad sysload = CSysLoad(); 
         double   load    = sysload.getLoadInfo(); 
         string   answer( "LOAD " ); 
  
         if ( load < 0 ) sit find (TSockId sid)
         {         {
                 answer.append( UNKNOW_VALUE );         sit it;
          for (it = Services.begin(); it != Services.end(); it++)
          {
                  if ((*it).ServiceSockId == sid) break;
         }         }
         else         return it;
  }
  
  sit find (uint32 sid)
  {
          sit it;
          for (it = Services.begin(); it != Services.end(); it++)
         {         {
                 char str[6];                 if ((*it).ServiceId == sid) break;
                 smprintf( str, 6, "%.2f", load ); 
                 answer.append( string(str) ); 
         }         }
          return it;
  }
  
                  
         sendData( answer.c_str(), from ); class CExecuteCommandThread : public IRunnable
  {
  public:
          string Command;
  
          CExecuteCommandThread (string command) : Command(command) { }
  
          void run ()
          {
                  nlinfo ("start executing: %s", Command.c_str());
                  system (Command.c_str());
                  nlinfo ("end executing: %s", Command.c_str());
 } }
  };
  
  
  void executeCommand (string command, bool background)
  {
          if (command.empty()) return;
  
 /// Log the total memory size and the used memory size (in B) /*
 void cbMemory ( CMessage& message, TSenderId from )         nlinfo ("start executing: %s", command.c_str());
          if (command[command.size()-1] == '&')
 { {
         CSysMemory sysmem   = CSysMemory();                 command.resize(command.size()-2);
         sint       memUsage = sysmem.getMemoryUsage(); 
         string     answer( "MEM " ); 
  
         if ( memUsage < 0 )                 if (spawnlp (_P_NOWAIT, cmd.c_str(), command.c_str(), NULL) == -1)
         {         {
                 answer.append( UNKNOW_VALUE );                         perror ("ca chie grave!!!!: ");
                  }
         }         }
         else         else
         {         {
                 char str[3];                 if (spawnlp (_P_WAIT, cmd.c_str(), command.c_str(), NULL) == -1)
                 smprintf( str, 3, "%d", memUsage );                 {
                 answer.append( string(str) );                         perror ("ca chie grave!!!!: ");
         }         }
          }
          nlinfo ("end executing: %s", command.c_str());
  */
                  
         sendData( answer.c_str(), from );         command += " >NUL:";
          if (background)
          {
                  IThread *thread = IThread::create (new CExecuteCommandThread (command));
                  thread->start ();
          }
          else
          {
                  CExecuteCommandThread cmdt (command);
                  cmdt.run ();
          }
 } }
  
  
 /// Log the swap size and the used swap space (in kB) /*
 void cbSwap ( CMessage& message, TSenderId from ) // execute without
  void executeCommand (string command, TSockId from, CCallbackNetBase &netbase)
 { {
         CSysSwap sysswap   = CSysSwap();         if (command.empty()) return;
         sint     swapUsage = sysswap.getSwapUsage(); 
         string   answer( "SWAP " );         #define STDOUT 1
          #define STDERR 2
          int nul, oldstdout, oldstderr;
          char *tmpfilename = tmpnam (NULL);
          nul = _open(tmpfilename, _O_RDWR | _O_CREAT | _O_TRUNC | _O_TEMPORARY | _O_SHORT_LIVED | _O_EXCL, _S_IREAD | _S_IWRITE);
          oldstdout = _dup(STDOUT);
          oldstderr = _dup(STDERR);
          _dup2(nul, STDOUT);
          _dup2(nul, STDERR);
          system(command.c_str());
          _dup2(oldstdout, STDOUT);
          _dup2(oldstderr, STDERR);
          _close(oldstdout);
          _close(oldstderr);
  
         if ( swapUsage < 0 )         _lseek (nul, 0L, SEEK_SET);
  
          while (!_eof(nul))
         {         {
                 answer.append( UNKNOW_VALUE );                 uint8 buffer[10000];
                  uint32 nbread = _read (nul, buffer, 10000);
  
                  CMessage msgout (netbase.getSIDA(), "ESCR");
                  msgout.serial (nbread);
                  msgout.serialBuffer (buffer, nbread);
                  netbase.send (msgout, from);
         }         }
         else         
          _close(nul);
  */
  /*
          FILE *fp = fopen ("test.txt", "r");
          do
         {         {
                 char str[3];                 char str[1024];
                 smprintf( str, 3, "%d", swapUsage );                 fgets (str, 1024, fp);
                 answer.append( string(str) );                 if (feof(fp)) break;
                  result.push_back (str);
         }         }
          while (true);
          fclose (fp);
  //      remove ("test.txt");
  *///}
                  
         sendData( answer.c_str(), from ); ////////////////////////////////////////////////////////////////////////////////////////////////////////
 } ////////////////////////////////////////////////////////////////////////////////////////////////////////
  ////////////////// CONNECTION TO THE SERVICES //////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////////////////////////////////
  
  static void cbServiceIdentification (CMessage& msgin, TSockId from, CCallbackNetBase &netbase)
  {
          CService *c = (CService*) from->appId();
  
          msgin.serial (c->ShortName);
          msgin.serial (c->LongName);
  
          nlinfo ("%s %s %s is identified", from->asString().c_str(), c->ShortName.c_str(), c->LongName.c_str());
  
          CMessage msgout (CNetManager::getSIDA ("AESAS"), "SID");
          msgout.serial (c->ShortName);
          msgout.serial (c->LongName);
          CNetManager::send ("AESAS", msgout);
  }
  
 // Log all the server informations. static void cbServiceReady (CMessage& msgin, TSockId from, CCallbackNetBase &netbase)
 void cbSystem ( CMessage& message, TSenderId from ) 
 { {
         cbLoad   ( message, from );         CService *c = (CService*) from->appId();
         cbMemory ( message, from ); 
         cbSwap   ( message, from );         nlinfo ("%s %s %s is ready", from->asString().c_str(), c->ShortName.c_str(), c->LongName.c_str());
  
          CMessage msgout (CNetManager::getSIDA ("AESAS"), "SR");
          msgout.serial (c->ShortName);
          msgout.serial (c->LongName);
          CNetManager::send ("AESAS", msgout);
 } }
  
  void serviceConnection (const string &serviceName, TSockId from, void *arg)
  {
          Services.push_back (CService(from));
          CService *c = &(Services.back());
          from->setAppId ((uint64)c);
  
 /**         nlinfo ("%s is connected", from->asString().c_str());
  * Callback Array         
  * Message types:         CMessage msgout (CNetManager::getSIDA ("AESAS"), "SC");
  *      LOAD:   log Load information         CNetManager::send ("AESAS", msgout);
  *      MEMORY: log Memory information }
  *      SWAP:   log Swap information 
  *      SYSTEM: log the Load, Memory, and Swap informations void serviceDisconnection (const string &serviceName, TSockId from, void *arg)
  */ 
 TCallbackItem CallbackArray[] = 
 { {
         { "LOAD",   cbLoad },         CService *c = (CService*) from->appId();
         { "MEMORY", cbMemory }, 
         { "SWAP",   cbSwap }, 
  
         { "SYSTEM", cbSystem }         nlinfo ("%s %s %s is disconnected", from->asString().c_str(), c->ShortName.c_str(), c->LongName.c_str());
 }; 
  
          CMessage msgout (CNetManager::getSIDA ("AESAS"), "SD");
          msgout.serial (c->ShortName);
          msgout.serial (c->LongName);
          CNetManager::send ("AESAS", msgout);
  }
  
  
 /** Admin Executor Service (AES). /** Callback Array
  * Log informations (load, memory usage, etc ...) about the server it's 
  * running on. 
  * These informations are used by the Admin Service (AS) and the Naming 
  * Service (NS) to watch the differents servers of the shard. 
  */  */
 class CAdminExecutorService : public NLNET::IService TCallbackItem ServicesCallbackArray[] =
 { {
 public:         { "SID", cbServiceIdentification },
          { "SR", cbServiceReady },
  };
  
         /// Initializes the service ////////////////////////////////////////////////////////////////////////////////////////////////////////
         void init () ////////////////////////////////////////////////////////////////////////////////////////////////////////
  ////////////////// CONNECTION TO THE AS ////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////////////////////////////////
  
  static void cbExecuteSystemCommand (CMessage& msgin, TSockId from, CCallbackNetBase &netbase)
         {         {
                 // Connect to the Log Service         string systemCommand;
                 StatLog.addDisplayer( new NLMISC::CStdDisplayer() );         uint8 background;
          msgin.serial (systemCommand);
          msgin.serial (background);
  
                 NLNET::CNetDisplayer *nd = new NLNET::CNetDisplayer;         nlinfo ("I have to execute '%s'", systemCommand.c_str());
  
                 if ( nd->connected() )         executeCommand (systemCommand, background==1);
                 { 
                         StatLog.addDisplayer( nd ); 
                 }                 }
                 else 
  static void cbStopService (CMessage& msgin, TSockId from, CCallbackNetBase &netbase)
                 {                 {
                         nlerror( "Coudn't connect to the Log Service." );         string service;
                 } 
          nlinfo ("I have to stop service");
  
         }         }
  
  
  TCallbackItem AESASCallbackArray[] =
  {
          { "ESC", cbExecuteSystemCommand },
          { "SS", cbStopService },
 }; };
  
  ////////////////////////////////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////////////////////////////////
  ////////////////// SERVICE IMPLEMENTATION //////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////////////////////////////////
  
  class CAdminExecutorService : public IService
  {
  public:
  
          /// Init the service, load the universal time.
          void                init ()
          {
                  CNetManager::setConnectionCallback ("AES", serviceConnection, NULL);
                  CNetManager::setDisconnectionCallback ("AES", serviceDisconnection, NULL);
  
                  // install the server for AS
                  CNetManager::addServer ("AESAS", 49996);
                  CNetManager::addCallbackArray ("AESAS", AESASCallbackArray, sizeof(AESASCallbackArray)/sizeof(AESASCallbackArray[0]));
          }
  
          bool                update ()
          {
                  return true;
          }
  };
  
 NLNET_SERVICE_MAIN( CAdminExecutorService, "AES", 50009 ); 
  
 // End of admin_executor_service.cpp /// Naming Service
  NLNET_SERVICE_MAIN (CAdminExecutorService, "AES", "admin_executor_service", 49997, ServicesCallbackArray);


Legend:
Removed from v.1.1 
changed lines
 Added in v.1.2