(file) Return to ServerRunStatus.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Service

  1 kumpf 1.1 //%2006////////////////////////////////////////////////////////////////////////
  2           //
  3           // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
  4           // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
  5           // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
  6           // IBM Corp.; EMC Corporation, The Open Group.
  7           // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
  8           // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
  9           // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 10           // EMC Corporation; VERITAS Software Corporation; The Open Group.
 11           // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 12           // EMC Corporation; Symantec Corporation; The Open Group.
 13           //
 14           // Permission is hereby granted, free of charge, to any person obtaining a copy
 15           // of this software and associated documentation files (the "Software"), to
 16           // deal in the Software without restriction, including without limitation the
 17           // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 18           // sell copies of the Software, and to permit persons to whom the Software is
 19           // furnished to do so, subject to the following conditions:
 20           // 
 21           // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 22 kumpf 1.1 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 23           // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 24           // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 25           // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 26           // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 27           // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 28           // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 29           //
 30           //==============================================================================
 31           //
 32           //%/////////////////////////////////////////////////////////////////////////////
 33           
 34           #include <Pegasus/Common/System.h>
 35           #include <Pegasus/Common/Signal.h>
 36           #include <Pegasus/Common/AutoPtr.h>
 37           #include <Service/PidFile.h>
 38           #include <Service/ServerRunStatus.h>
 39           
 40           #include <sys/types.h>
 41           #include <sys/stat.h>
 42           
 43 kumpf 1.1 #if defined(PEGASUS_OS_HPUX)
 44           # include <sys/pstat.h>
 45           # include <libgen.h>
 46           #endif
 47           
 48           #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
 49           # include <sys/ps.h>
 50           #endif
 51           
 52           #if defined(PEGASUS_OS_AIX)
 53           extern "C"
 54           {
 55           # include <procinfo.h>
 56           extern int getprocs(struct procsinfo *, int, struct fdsinfo *, int,pid_t *,int);
 57           # define PROCSIZE sizeof(struct procsinfo)
 58           }
 59           #endif
 60           
 61           #if defined(PEGASUS_OS_OS400)
 62           # include <Pegasus/Common/Logger.h>
 63           # include "OS400ConvertChar.h"
 64 kumpf 1.1 #endif
 65           
 66           PEGASUS_NAMESPACE_BEGIN
 67           
 68           #ifdef PEGASUS_OS_TYPE_WINDOWS
 69           
 70           //////////////////////////////////////
 71           //
 72           // Windows implementation
 73           //
 74           //////////////////////////////////////
 75           
 76           ServerRunStatus::ServerRunStatus(
 77               const char* serverName,
 78               const char* pidFilePath)
 79               : _serverName(serverName),
 80                 _pidFilePath(pidFilePath),
 81                 _parentPid(0),
 82                 _event(NULL),
 83                 _wasAlreadyRunning(false)
 84           {
 85 kumpf 1.1 }
 86           
 87           ServerRunStatus::~ServerRunStatus()
 88           {
 89               if (_event != NULL)
 90               {
 91                   CloseHandle(_event);
 92               }
 93           }
 94           
 95           Boolean ServerRunStatus::isServerRunning()
 96           {
 97               return _wasAlreadyRunning();
 98           }
 99           
100           void ServerRunStatus::setServerRunning()
101           {
102               if (_event == NULL)
103               {
104                   _event = CreateEvent(NULL, TRUE, TRUE, _serverName);
105                   if ((_event != NULL) && (GetLastError() != ERROR_ALREADY_EXISTS))
106 kumpf 1.1         {
107                       _wasAlreadyRunning = false;
108                   }
109               }
110           }
111           
112           void ServerRunStatus::setParentPid(PEGASUS_PID_T parentPid)
113           {
114           }
115           
116           Boolean ServerRunStatus::kill()
117           {
118               return true;
119           }
120           
121           #elif defined(PEGASUS_OS_TYPE_UNIX)
122           
123           //////////////////////////////////////
124           //
125           // Unix and OpenVMS implementation
126           //
127 kumpf 1.1 //////////////////////////////////////
128           
129           ServerRunStatus::ServerRunStatus(
130               const char* serverName,
131               const char* pidFilePath)
132               : _serverName(serverName),
133                 _pidFilePath(pidFilePath),
134                 _parentPid(0)
135           {
136           }
137           
138           ServerRunStatus::~ServerRunStatus()
139           {
140           }
141           
142           Boolean ServerRunStatus::isServerRunning()
143           {
144               PidFile pidFile(_pidFilePath);
145               PEGASUS_PID_T pid = (PEGASUS_PID_T) pidFile.getPid();
146           
147               if (pid == 0)
148 kumpf 1.1     {
149                   return false;
150               }
151           
152               return (pid != (PEGASUS_PID_T) System::getPID()) &&
153                      (pid != _parentPid) &&
154                      _isServerProcess(pid);
155           }
156           
157           void ServerRunStatus::setServerRunning()
158           {
159               PidFile pidFile(_pidFilePath);
160               pidFile.setPid(System::getPID());
161           }
162           
163           void ServerRunStatus::setParentPid(PEGASUS_PID_T parentPid)
164           {
165               _parentPid = parentPid;
166           }
167           
168           Boolean ServerRunStatus::kill()
169 kumpf 1.1 {
170               PidFile pidFile(_pidFilePath);
171               PEGASUS_PID_T pid = (PEGASUS_PID_T) pidFile.getPid();
172           
173               if ((pid == 0) ||
174                   (pid == (PEGASUS_PID_T) System::getPID()) ||
175                   (pid == _parentPid) ||
176                   !_isServerProcess(pid))
177               {
178                   pidFile.remove();
179                   return false;
180               }
181           
182           #if defined(PEGASUS_OS_HPUX) || \
183               defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || \
184               defined(PEGASUS_OS_SOLARIS) || \
185               defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM) || \
186               defined(PEGASUS_OS_AIX)
187           
188               ::kill(pid, SIGKILL);
189           
190 kumpf 1.1 #endif
191           
192               pidFile.remove();
193               return true;
194           }
195           
196           # if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
197           
198           ///////////////////////////////////////////////////////
199           // z/OS implementation of _isServerProcess
200           ///////////////////////////////////////////////////////
201           Boolean ServerRunStatus::_isServerProcess(PEGASUS_PID_T pid)
202           {
203               W_PSPROC buf;
204               int token = 0;
205               memset(&buf, 0x00, sizeof(buf));
206               buf.ps_conttyptr =(char *) malloc(buf.ps_conttylen =PS_CONTTYBLEN);
207               buf.ps_pathptr   =(char *) malloc(buf.ps_pathlen   =PS_PATHBLEN);
208               buf.ps_cmdptr    =(char *) malloc(buf.ps_cmdlen    =PS_CMDBLEN);
209               Boolean returnValue = false;
210           
211 kumpf 1.1     while ((token = w_getpsent(token, &buf, sizeof(buf))) > 0)
212               {
213                   if (buf.ps_pid == pid)
214                   {
215                       // If the process id is associated with the server program,
216                       // then a server is still running.
217                       if (strstr(buf.ps_pathptr, _serverName) != NULL)
218                       {
219                           returnValue = true;
220                       }
221                       // else the pid was not associated with the server
222                       break;
223                   }
224               }
225           
226               free(buf.ps_conttyptr);
227               free(buf.ps_pathptr);
228               free(buf.ps_cmdptr);
229               return returnValue;
230           }
231           
232 kumpf 1.1 # elif defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || \
233               defined(PEGASUS_OS_SOLARIS)
234           
235           ///////////////////////////////////////////////////////
236           // Linux and Solaris implementation of _isServerProcess
237           ///////////////////////////////////////////////////////
238           /*
239              Opens the 'stat' file in the /proc/<pid> directory to
240              verify that the process name is that of the server.
241           */
242           static Boolean _isServerPidDir(
243               const char *directory,
244               const char* serverProcessName)
245           {
246               static char filename[80];
247               static char buffer[512];
248               int fd, bytesRead;
249           
250               // generate the name of the stat file in the process's /proc directory,
251               // and open it
252               sprintf(filename, "%s/%s", directory, "stat");
253 kumpf 1.1     if ( (fd = open(filename, O_RDONLY, 0)) == -1 )
254               {
255                   return false;
256               }
257           
258               // read the contents
259               if ( (bytesRead = read( fd, buffer, (sizeof buffer) - 1 )) <= 0 )
260               {
261                   close(fd);
262                   return false;
263               }
264           
265               // null terminate the file contents
266               buffer[bytesRead] = 0;
267           
268               close(fd);
269           
270               // the process name is the second element of the file contents and
271               // is surrounded by parentheses.
272               //
273               // find the positions of the parentheses in the file contents
274 kumpf 1.1     const char* openParen;
275               const char* closeParen;
276           
277               openParen = strchr(buffer, '(');
278               closeParen = strchr(buffer, ')');
279               if (openParen == NULL || closeParen == NULL || closeParen < openParen)
280               {
281                   return false;
282               }
283           
284               // allocate memory for the result
285               AutoArrayPtr<char> processName(new char[closeParen - openParen]);
286           
287               // copy the process name into the result
288               strncpy(processName.get(), openParen + 1, closeParen - openParen -1);
289           
290               // strncpy doesn't NULL-terminate the result, so do it here
291               processName[closeParen - openParen -1] = '\0';
292           
293               return strcmp(processName.get(), serverProcessName) == 0;
294           }
295 kumpf 1.1 
296           Boolean ServerRunStatus::_isServerProcess(PEGASUS_PID_T pid)
297           {
298               // This method makes a stat() system call on the directory in /proc
299               // with a name that matches the pid of the server.  It returns true
300               // if it successfully located the process dir and verified that the
301               // process name matches that of the server.
302           
303               static char path[32];
304               static struct stat statBuffer;
305           
306               sprintf(path, "/proc/%d", pid);
307               if (stat(path, &statBuffer) == -1)          // process stopped running
308               {
309                   return false;
310               }
311           
312               // get the process name to make sure it is the cimserver process
313           // ATTN: skip verify for Solaris
314           #  if !defined(PEGASUS_OS_SOLARIS)
315               if (!_isServerPidDir(path, _serverName))
316 kumpf 1.1     {
317                   return false;
318               }
319           #  endif
320           
321               return true;
322           }
323           
324           # elif defined(PEGASUS_OS_AIX)
325           
326           ///////////////////////////////////////////////////////
327           // AIX implementation of _isServerProcess
328           ///////////////////////////////////////////////////////
329           /*
330              Calls subroutine getprocs() to get information about all processes.
331              If successful, an array of procsinfo structures filled with process table
332              entries is returned.  Otherwise, a null pointer is returned.
333              The output parameter cnt specifies the number of the processes in the
334              returned table.
335           */
336           static struct procsinfo* _getProcessData(int& cnt)
337 kumpf 1.1 {
338               struct procsinfo* proctable = NULL;
339               struct procsinfo* rtnp = NULL;
340               int count = 1048576;
341               int rtncnt;
342               int repeat = 1;
343               int nextp = 0;
344           
345               cnt = 0;
346               while (repeat &&
347                      (rtncnt = getprocs(rtnp, PROCSIZE, 0, 0, &nextp, count) > 0))
348               {
349                   if (!rtnp)
350                   {
351                       count=rtncnt;
352                       proctable = (struct procsinfo*) malloc((size_t) PROCSIZE*count);
353                       if (!proctable)
354                       {
355                           return NULL;
356                       }
357                       rtnp = proctable;
358 kumpf 1.1             nextp = 0;
359                   }
360                   else
361                   {
362                       cnt += rtncnt;
363                       if (rtncnt >= count)
364                       {
365                           proctable=(struct procsinfo *) realloc(
366                               (void*)proctable, (size_t) (PROCSIZE*(cnt+count)));
367                           if (!proctable)
368                           {
369                               return NULL;
370                           }
371                           rtnp = proctable+(cnt);
372                       }
373                       else
374                       {
375                           repeat = 0;
376                       }
377                   } // end of if(!rtnp)
378               } //end of while
379 kumpf 1.1     return proctable;
380           }
381           
382           Boolean ServerRunStatus::_isServerProcess(PEGASUS_PID_T pid)
383           {
384               int count;
385               struct procsinfo* proctable;
386           
387               proctable = _getProcessData(count);
388               if (proctable == NULL)
389               {
390                   return false;
391               }
392           
393               for (int i=0; i < count; i++)
394               {
395                   if (!strcmp(proctable[i].pi_comm, _serverName) && \
396                       proctable[i].pi_pid == pid)
397                   {
398                       free(proctable);
399                       return true;
400 kumpf 1.1         }
401               }
402           
403               free(proctable);
404               return false;
405           }
406           
407           # elif defined(PEGASUS_OS_HPUX)
408           
409           ///////////////////////////////////////////////////////
410           // HP-UX implementation of _isServerProcess
411           ///////////////////////////////////////////////////////
412           Boolean ServerRunStatus::_isServerProcess(PEGASUS_PID_T pid)
413           {
414               struct pst_status pstru;
415           
416               if (pstat_getproc(&pstru, sizeof(struct pst_status), (size_t)0, pid) != -1)
417               {
418                   //
419                   // Gets the command basename disregarding the command parameters
420                   //
421 kumpf 1.1         char *execName = strchr(pstru.pst_cmd,' ');
422                   if (execName)
423                   {
424                       *execName = '\0';
425                   }
426                   execName = basename(pstru.pst_cmd);
427           
428                   if (strcmp(execName, _serverName) == 0)
429                   {
430                       return true;
431                   }
432               }
433           
434               return false;
435           }
436           
437           # else
438           
439           ///////////////////////////////////////////////////////
440           // Generic implementation of _isServerProcess
441           ///////////////////////////////////////////////////////
442 kumpf 1.1 Boolean ServerRunStatus::_isServerProcess(PEGASUS_PID_T pid)
443           {
444               return false;
445           }
446           
447           # endif
448           
449           #elif defined(PEGASUS_OS_OS400)
450           
451           //////////////////////////////////////
452           //
453           // OS/400 implementation
454           //
455           //////////////////////////////////////
456           
457           ServerRunStatus::ServerRunStatus(
458               const char* serverName,
459               const char* pidFilePath)
460               : _serverName(serverName),
461                 _pidFilePath(pidFilePath),
462                 _parentPid(0)
463 kumpf 1.1 {
464           }
465           
466           ServerRunStatus::~ServerRunStatus()
467           {
468           }
469           
470           /*
471              NOTE: This implementation is specific to the CIM Server.
472           */
473           Boolean ServerRunStatus::isServerRunning()
474           {
475           #pragma convert(37)
476               // Construct a ycmJob object
477               ycmJob cppJob(YCMJOB_SRVNAME_10, YCMJOB_SRVUSER_10);
478           
479               // Find the QYCMCIMOM job
480               char cppStatus  = cppJob.find(YCMJOB_ALL_NUMBERS);
481           
482               if (cppStatus == YCMJOB_FOUND)       // CIMOM Server is Running
483               {
484 kumpf 1.1         return true;
485               }
486           
487               return false;
488           #pragma convert(0)
489           }
490           
491           void ServerRunStatus::setServerRunning()
492           {
493           }
494           
495           void ServerRunStatus::setParentPid(PEGASUS_PID_T parentPid)
496           {
497           }
498           
499           /*
500              The iSeries qycmctlcimCimomServer.C (QYCMCTLCIM program) code has
501              already checked that the server is already running prior to calling
502              the CIMOM server (QYCMCIMOM) and telling it to shutdown.
503              However, a check is still made in this method because we have to
504              find the job number in order to kill the job.
505 kumpf 1.1   
506              For iSeries, this method is called regardless of whether we took
507              errors trying to connect to the server - if the CIMOM server job
508              is anywhere on the system, in any state, this method will find it
509              and kill it dead!!
510             
511              NEVER call this method unless the server is unable to be shut down
512              gracefully.
513           
514              NOTE: This implementation is specific to the CIM Server.
515           */
516           Boolean ServerRunStatus::kill()
517           {
518           #pragma convert(37)
519               char rc2[3] = "02"; // CIMOM server failed to end
520               char cppServ[10] = "QYCMCIMOM";
521           
522               // Construct a ycmJob object
523               ycmJob cppJob(YCMJOB_SRVNAME_10, YCMJOB_SRVUSER_10);
524               // Find the QYCMCIMOM job
525               char cppStatus  = cppJob.find(YCMJOB_ALL_NUMBERS);
526 kumpf 1.1 
527               if (cppStatus == YCMJOB_FOUND)       // CIMOM Server is Running
528               {
529                   if (cppJob.end((char *)cppJob.getNumber().c_str(), 'C', 30) ==
530                           YCMJOB_END_FAILED)
531                   {
532                       char chData[sizeof(rc2)+sizeof(cppServ)];
533                       strcpy((char *)&chData,rc2);
534                       strcat(chData,cppServ);
535           
536                       ycmMessage message(
537                           "CPDDF81",
538                           chData,
539                           strlen(chData),
540                           "cimserver_os400::cimserver_kill()",
541                           ycmCTLCIMID,
542                           utf8);
543                       message.joblogIt(UserError,ycmMessage::Diagnostic);
544           
545           #pragma convert(0)
546           
547 kumpf 1.1             Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
548                           "src.Server.cimserver_os400.FAILED_TO_END_JOB",
549                           "$0 FAILED to end the $1 job!!",
550                           "cimserver_os400::cimserver_kill -",
551                           "QYCMCIMOM");
552           
553                       return false; // Note: this return code is ignored
554                   }
555               }
556           
557               // The case of the job not found is already handled in QYCMCTLCIM program
558               return true;
559           }
560           
561           #endif
562           
563           PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2