(file) Return to StressTestController.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / test / StressTestController

   1 j.alex 1.1.2.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 j.alex 1.1.2.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                // Author: John Alex
  33                //
  34                // Modified By:
  35                //
  36                //%/////////////////////////////////////////////////////////////////////////////
  37                
  38                #include <iostream>
  39                #include <Pegasus/Common/Config.h>
  40                #include <Pegasus/Common/Constants.h>
  41                #include <Pegasus/Common/System.h>
  42                #include <Pegasus/Common/PegasusVersion.h>
  43 j.alex 1.1.2.1 #include <Pegasus/Common/SSLContext.h>
  44                #include <Pegasus/getoopt/getoopt.h>
  45                #include <Pegasus/Common/String.h>
  46                #include <Pegasus/Client/CIMClient.h>
  47                #include <Pegasus/Common/FileSystem.h>
  48                #include <Pegasus/Common/TimeValue.h>
  49                #include <time.h>
  50                #include <signal.h>
  51                #include "StressTestController.h"
  52                #include "StressTestControllerException.h"
  53                //
  54                //Windows
  55                //
  56 j.alex 1.1.2.3 #ifdef PEGASUS_OS_TYPE_WINDOWS
  57 j.alex 1.1.2.4  // for DWORD etc.
  58                 #include <windows.h>  
  59                 // getpid() and others 
  60                 typedef DWORD pid_t;     
  61 j.alex 1.1.2.3  #include <process.h>
  62 j.alex 1.1.2.1 #elif !defined(PEGASUS_OS_OS400)
  63 j.alex 1.1.2.3  #include <unistd.h>
  64 j.alex 1.1.2.1 #endif
  65                
  66                //#define DEBUG
  67                
  68                #define SIXTYSECONDS 60
  69                #define MILLISECONDS 1000
  70                #define CHECKUP_INTERVAL 1
  71                #define STOP_DELAY 1 
  72 j.alex 1.1.2.2 #define SHUTDOWN_DELAY 5 
  73 j.alex 1.1.2.1 #define RUN_DELAY 1 
  74                #define DEFAULT_INSTANCE "5"
  75                
  76                #define convertmin2millisecs(x) (x * SIXTYSECONDS * MILLISECONDS)
  77                #define getToleranceInPercent(x,y) (100 - (((y-x)/y) * 100))
  78                
  79                
  80                
  81                static void endAllTests(int signum);
  82                
  83 j.alex 1.1.2.3 static void cleanupProcess();
  84 j.alex 1.1.2.1 
  85                static String convertUint64toString(Uint64 x);
  86                
  87                
  88                PEGASUS_NAMESPACE_BEGIN
  89 j.alex 1.1.2.4 PEGASUS_USING_PEGASUS;
  90                PEGASUS_USING_STD;
  91                
  92 j.alex 1.1.2.1 
  93                
  94                /**
  95                  Log file descripter
  96                */
  97                
  98                /**
  99                   variable for Signal handler 
 100                */
 101 j.alex 1.1.2.3 static Boolean Quit = false;
 102 j.alex 1.1.2.1 
 103                /**
 104                    The command name.
 105                 */
 106 j.alex 1.1.2.3 const char StressTestControllerCommand::COMMAND_NAME [] = 
 107                              "TestStressTestController";
 108 j.alex 1.1.2.1 
 109                
 110                /**
 111                   StressTest Configuration file details 
 112                */
 113 j.alex 1.1.2.3 char StressTestControllerCommand::FILENAME[] = "default_stresstest.conf";
 114                char StressTestControllerCommand::TESTDIR[] = "/test/";
 115                char StressTestControllerCommand::STRESSTESTDIR[] = "StressTestController/";
 116                char StressTestControllerCommand::LOGDIR[] = "log/";
 117                char StressTestControllerCommand::BINDIR[] = "/bin/";
 118                char StressTestControllerCommand::DEFAULT_CFGDIR[] = 
 119                      STRESSTEST_DEFAULTCFGDIR;
 120                char StressTestControllerCommand::DEFAULT_LOGDIR[] =
 121                         "/test/StressTestController/log/";
 122                char StressTestControllerCommand::DEFAULT_TMPDIR[] =
 123                         "/test/StressTestController/tmp/";
 124                
 125                String DEFAULT_BINDIR = String::EMPTY;
 126                
 127                static Uint32 DEFAULT_CLIENTS = 2;
 128                static Uint32 Total_Clients = DEFAULT_CLIENTS;
 129                static Uint32 Total_vClients = DEFAULT_CLIENTS;
 130                static Uint32 NEW_CLIENTS = 5;
 131 j.alex 1.1.2.1 
 132 j.alex 1.1.2.3 static char MODELWALK_CLIENT[] = "TestModelWalkStressClient";
 133                static char WRAPPER_CLIENT[] = "TestWrapperStressClient";
 134 j.alex 1.1.2.1 
 135                /**
 136                  StressTest Client Status types
 137                */
 138                enum CStatus{
 139 j.alex 1.1.2.3     VALID_RESPONSE,
 140                    INVALID_RESPONSE,
 141                    NO_RESPONSE};
 142 j.alex 1.1.2.1 
 143                
 144                /**
 145                  Temporary arrays to store client information
 146                */
 147 j.alex 1.1.2.4 
 148 j.alex 1.1.2.1 /**
 149                  Client PID's
 150                */
 151 j.alex 1.1.2.3 static pid_t *clientPIDs;
 152 j.alex 1.1.2.1 
 153                /**
 154                  Client Status
 155                */
 156 j.alex 1.1.2.3 static int *clientStatus;
 157 j.alex 1.1.2.1 
 158                
 159                /**
 160                  Client Status
 161                */
 162 j.alex 1.1.2.3 static int *prev_clientStatus;
 163 j.alex 1.1.2.1 
 164                /**
 165                  Client Instance
 166                */
 167 j.alex 1.1.2.3 static int *clientInstance;
 168 j.alex 1.1.2.1 
 169                /**
 170                  Indicates if client is Active
 171                */
 172                static Boolean *clientActive;
 173                
 174                /**
 175                  Client status time stamp 
 176                */
 177 j.alex 1.1.2.3 static Uint64 *clientTimeStamp;
 178 j.alex 1.1.2.1 
 179                /**
 180                  Previous client status time stamp 
 181                */
 182 j.alex 1.1.2.3 static Uint64 *prev_clientTimeStamp;
 183 j.alex 1.1.2.1 
 184                /**
 185                    DEFAULT VALUES:
 186                */
 187                
 188                /**
 189                    Default duration for the stress tests
 190                */
 191 j.alex 1.1.2.3 double StressTestControllerCommand::_duration = 180;
 192 j.alex 1.1.2.1 
 193                /**
 194                    Label for the usage string for this command.
 195                 */
 196 j.alex 1.1.2.3 const char StressTestControllerCommand::_USAGE [] = "Usage: ";
 197 j.alex 1.1.2.1 
 198                /**
 199                    The option character used to specify the hostname.
 200                 */
 201 j.alex 1.1.2.3 const char StressTestControllerCommand::_OPTION_HOSTNAME = 'h';
 202 j.alex 1.1.2.1 
 203                /**
 204                    The option character used to specify the port number.
 205                 */
 206 j.alex 1.1.2.3 const char StressTestControllerCommand::_OPTION_PORTNUMBER = 'p';
 207 j.alex 1.1.2.1 
 208                /**
 209                    The option character used to specify SSL usage.
 210                 */
 211 j.alex 1.1.2.3 const char StressTestControllerCommand::_OPTION_SSL = 's';
 212 j.alex 1.1.2.1 
 213                /**
 214                    The option character used to specify the username.
 215                 */
 216 j.alex 1.1.2.3 const char StressTestControllerCommand::_OPTION_USERNAME = 'u';
 217 j.alex 1.1.2.1 
 218                /**
 219                    The option character used to specify the password.
 220                 */
 221 j.alex 1.1.2.3 const char StressTestControllerCommand::_OPTION_PASSWORD = 'w';
 222 j.alex 1.1.2.1 
 223                /**
 224                    The minimum valid portnumber.
 225                 */
 226 j.alex 1.1.2.3 const Uint32 StressTestControllerCommand::_MIN_PORTNUMBER = 0;
 227 j.alex 1.1.2.1 
 228                /**
 229                    The maximum valid portnumber.
 230                 */
 231 j.alex 1.1.2.3 const Uint32 StressTestControllerCommand::_MAX_PORTNUMBER = 65535;
 232 j.alex 1.1.2.1 
 233                /**
 234                    The minimum Duration.
 235                 */
 236 j.alex 1.1.2.3 const Uint32 StressTestControllerCommand::_MIN_DURATION = 0;
 237 j.alex 1.1.2.1 
 238                /**
 239                    The minimum valid Tolerance Level.
 240                 */
 241 j.alex 1.1.2.3 const Uint32 StressTestControllerCommand::_MIN_TOLERANCE = 0;
 242 j.alex 1.1.2.1 
 243                /**
 244                    The maximum valid Tolerance Level.
 245                 */
 246 j.alex 1.1.2.3 const Uint32 StressTestControllerCommand::_MAX_TOLERANCE = 100;
 247 j.alex 1.1.2.1 
 248                /**
 249                    The variable used to specify the hostname.
 250                 */
 251 j.alex 1.1.2.3 static const char HOSTNAME[] = "hostname";
 252 j.alex 1.1.2.1 
 253                /**
 254                    The variable used to specify the port number.
 255                 */
 256 j.alex 1.1.2.3 static const char PORTNUMBER[] = "port";
 257 j.alex 1.1.2.1 
 258                /**
 259                    The variable used to specify SSL usage.
 260                 */
 261 j.alex 1.1.2.3 static const char SSL [] = "ssl";
 262 j.alex 1.1.2.1 
 263                /**
 264                    The variable used to specify the username.
 265                 */
 266 j.alex 1.1.2.3 static const char USERNAME[] = "username";
 267 j.alex 1.1.2.1 
 268                /**
 269                    The variable used to specify the password.
 270                 */
 271 j.alex 1.1.2.3 static const char PASSWORD[] = "password";
 272 j.alex 1.1.2.1 
 273                /**
 274                    The variable used to specify the duration of the tests.
 275                 */
 276 j.alex 1.1.2.3 static const char DURATION[] = "duration";
 277 j.alex 1.1.2.1 
 278                /**
 279                    The variable used to specify the duration of the Client tests.
 280                 */
 281 j.alex 1.1.2.3 static const char CLIENTDURATION[] = "ClientDuration";
 282 j.alex 1.1.2.1 
 283                /**
 284                    The variable used to specify the ToleranceLevel for the tests.
 285                 */
 286 j.alex 1.1.2.3 static const char TOLERANCELEVEL[] = "TOLERANCELEVEL";
 287 j.alex 1.1.2.1 
 288                /**
 289                    The variable used to specify the NameSpace for the tests.
 290                 */
 291 j.alex 1.1.2.3 static const char NAMESPACE[] = "namespace";
 292 j.alex 1.1.2.1 
 293                /**
 294                    The variable used to specify the ClassName for the tests.
 295                 */
 296 j.alex 1.1.2.3 static const char CLASSNAME[] = "classname";
 297 j.alex 1.1.2.1 
 298                /**
 299                    The variable used to specify the Name for the tests.
 300                 */
 301 j.alex 1.1.2.3 static const char NAME[] = "NAME";
 302 j.alex 1.1.2.1 
 303                /**
 304                    The variable used to specify the Clientname for the tests.
 305                 */
 306 j.alex 1.1.2.3 static const char CLIENTNAME[] = "clientname";
 307 j.alex 1.1.2.1 
 308                /**
 309                    The variable used to specify the Clientname for the tests.
 310                 */
 311 j.alex 1.1.2.3 static const char OPTIONS[] = "options";
 312 j.alex 1.1.2.1 
 313                /**
 314                    The variable used to specify the Clientname for the tests.
 315                 */
 316 j.alex 1.1.2.3 static const char INSTANCE[] = "INSTANCE";
 317 j.alex 1.1.2.1 
 318                /**
 319                    The variable used to specify the Clientname for the tests.
 320                 */
 321 j.alex 1.1.2.3 static const char CLIENTWAIT[] = "CLIENTWAIT";
 322 j.alex 1.1.2.1 
 323                
 324                
 325                /**
 326                 * Message resource name
 327                 */
 328 j.alex 1.1.2.3 static const char PASSWORD_PROMPT [] =
 329                                    "Please enter your password: ";
 330 j.alex 1.1.2.1 static const char PASSWORD_BLANK []                          =
 331 j.alex 1.1.2.3                     "Password cannot be blank. Please re-enter your password.";
 332                static const char LONG_HELP[] = "help";
 333                static const char LONG_VERSION[] = "version";
 334                static const char LONG_VERBOSE[] = "verbose";
 335 j.alex 1.1.2.1 
 336 j.alex 1.1.2.3 static Boolean IsAClient = false;
 337 j.alex 1.1.2.1 
 338 j.alex 1.1.2.3 static Boolean IsClientOptions = false;
 339 j.alex 1.1.2.1 
 340 j.alex 1.1.2.3 static Boolean IgnoreLine = false;
 341 j.alex 1.1.2.1 
 342                /**
 343                
 344                    Constructs a StressTestControllerCommand and initializes instance variables.
 345                
 346                 */
 347                StressTestControllerCommand::StressTestControllerCommand ()
 348                {
 349                
 350 j.alex 1.1.2.3     _hostName = String ();
 351                    _hostNameSpecified = false;
 352                    _portNumber = WBEM_DEFAULT_HTTP_PORT;
 353 j.alex 1.1.2.1     _portNumberSpecified = false;
 354                
 355                    char buffer[32];
 356                    sprintf(buffer, "%lu", (unsigned long) _portNumber);
 357                
 358 j.alex 1.1.2.3     _portNumberStr = buffer;
 359 j.alex 1.1.2.1 
 360 j.alex 1.1.2.3     _timeout = DEFAULT_TIMEOUT_MILLISECONDS;
 361                    _userName = String ();
 362                    _userNameSpecified = false;
 363                    _password = String ();
 364                    _passwordSpecified = false;
 365                    _useSSL = false;
 366 j.alex 1.1.2.4 
 367                    //
 368 j.alex 1.1.2.1     // initialize
 369 j.alex 1.1.2.4     //
 370 j.alex 1.1.2.3     _clientCount = 0;
 371                    _currClientCount = 0;
 372 j.alex 1.1.2.1     
 373                    //
 374                    // Set up tables for client properties.
 375                    //
 376 j.alex 1.1.2.3     _clientTable = new Table[Total_Clients];
 377 j.alex 1.1.2.1 
 378                    // 
 379                    // Allocate one table to collect all the common properties Thy use AutoPtr
 380                    //
 381 j.alex 1.1.2.3     _propertyTable = new Table;
 382 j.alex 1.1.2.1 
 383 j.alex 1.1.2.4     //
 384 j.alex 1.1.2.1     // Client Information
 385 j.alex 1.1.2.4     //
 386 j.alex 1.1.2.3     _clientCommands = 0;
 387                    _clientDurations = 0;
 388                    _clientDelays = 0;
 389 j.alex 1.1.2.1 
 390 j.alex 1.1.2.4     //
 391 j.alex 1.1.2.1     // Get environment variables:
 392                    //
 393 j.alex 1.1.2.3     pegasusHome = getenv("PEGASUS_HOME");
 394 j.alex 1.1.2.1 
 395 j.alex 1.1.2.3     DEFAULT_BINDIR = String(pegasusHome);
 396 j.alex 1.1.2.1     DEFAULT_BINDIR.append(BINDIR);
 397                
 398 j.alex 1.1.2.3     _stressTestLogFile = String::EMPTY;
 399 j.alex 1.1.2.1 
 400 j.alex 1.1.2.3     _stressTestClientPIDFile = String::EMPTY;
 401 j.alex 1.1.2.1 
 402 j.alex 1.1.2.3     _stressTestClientLogFile = String::EMPTY;
 403 j.alex 1.1.2.1 
 404 j.alex 1.1.2.3     _tmpStressTestClientPIDFile = String::EMPTY;
 405 j.alex 1.1.2.1 
 406                
 407                
 408 j.alex 1.1.2.3     _usage = String (_USAGE);
 409 j.alex 1.1.2.1 
 410 j.alex 1.1.2.3     _usage.append (COMMAND_NAME);
 411 j.alex 1.1.2.1 #ifndef DISABLE_SUPPORT_FOR_REMOTE_CONNECTIONS
 412 j.alex 1.1.2.3     _usage.append (" [ -");
 413                    _usage.append (_OPTION_SSL);
 414                    _usage.append (" ] [ -");
 415                    _usage.append (_OPTION_HOSTNAME);
 416                    _usage.append (" hostname ] [ -");
 417                    _usage.append (_OPTION_PORTNUMBER);
 418                    _usage.append (" portnumber ]\n                            [ -");
 419                    _usage.append (_OPTION_USERNAME);
 420                    _usage.append (" username ] [ -");
 421                    _usage.append (_OPTION_PASSWORD);
 422                    _usage.append (" password ]");
 423 j.alex 1.1.2.1 #endif
 424 j.alex 1.1.2.3     _usage.append (" [ --");
 425                    _usage.append (LONG_HELP);
 426                    _usage.append(" ]\n");
 427                    _usage.append("                            ");
 428                    _usage.append("[ --").append(LONG_VERSION).append(" ]");
 429                    _usage.append(" [ --").append(LONG_VERBOSE).append(" ]").append(\
 430                        " [<config_filename>] \n");
 431                
 432                    _usage.append("Options : \n");
 433                    _usage.append("    -h         - Connect to CIM Server on specified ");
 434                    _usage.append("hostname. \n");
 435                    _usage.append("    --help     - Display this help message.\n");
 436                    _usage.append("    -p         - Connect to CIM Server on specified ");
 437                    _usage.append("portnumber.\n");
 438                    _usage.append("    -s         - Use SSL protocol between Stress Test ");
 439                    _usage.append("Client\n");
 440                    _usage.append("                 and the CIM Server\n");
 441                    _usage.append("    -u         - Connect to CIM Server using the specified");
 442                    _usage.append(" username\n");
 443                    _usage.append("    --version  - Display CIM Server version number\n");
 444                    _usage.append("    --verbose  - Display verbose information\n");
 445 j.alex 1.1.2.3     _usage.append("    -w         - Connect to CIM Server using the specified");
 446                    _usage.append(" password\n");
 447                    _usage.append("\nOperands : \n");
 448                    _usage.append("   <config_filename>\n");
 449                    _usage.append("               - Specifies the name of the configuration ");
 450                    _usage.append("file that is to be used \n");
 451                    _usage.append("                 for the tests.\n");
 452 j.alex 1.1.2.1 
 453 j.alex 1.1.2.3     setUsage(_usage);
 454 j.alex 1.1.2.1 
 455                } /* StressTestControllerCommand  */
 456                
 457                /**
 458                
 459                    Parses the command line, validates the options, and sets instance
 460                    variables based on the option arguments.
 461                
 462                    @param   argc  the number of command line arguments
 463                    @param   argv  the string vector of command line arguments
 464                
 465                    @exception  CommandFormatException  if an error is encountered in parsing
 466                                                        the command line
 467                
 468                 */
 469                void StressTestControllerCommand::setCommand (Uint32 argc, char* argv [])
 470                {
 471 j.alex 1.1.2.3     Uint32 i = 0;
 472                    Uint32 c = 0;
 473                    String GetOptString = String ();
 474                    getoopt getOpts;
 475                    _toleranceLevel = 0;
 476                    _configFilePath = String ();
 477                    _configFilePathSpecified = false;
 478 j.alex 1.1.2.1 
 479 j.alex 1.1.2.3     _operationType = OPERATION_TYPE_UNINITIALIZED;
 480 j.alex 1.1.2.1 
 481                
 482 j.alex 1.1.2.3     ofstream log_file;
 483 j.alex 1.1.2.1 
 484 j.alex 1.1.2.4     //
 485 j.alex 1.1.2.1     // opens  the log file
 486 j.alex 1.1.2.4     //
 487 j.alex 1.1.2.3     OpenAppend(log_file,_stressTestLogFile);
 488 j.alex 1.1.2.1 
 489                    if (!log_file)
 490                    {
 491 j.alex 1.1.2.3         if(verboseEnabled)
 492                        {
 493                            cout<<StressTestControllerCommand::COMMAND_NAME<<
 494                                "::Cannot get file "<<_stressTestLogFile<<endl;
 495                        }
 496 j.alex 1.1.2.1        
 497                    }
 498 j.alex 1.1.2.3     log_file<<StressTestControllerCommand::COMMAND_NAME<<
 499                        ":: Preparing to set up parameters: "<<endl;
 500 j.alex 1.1.2.1 
 501                    //
 502                    //  Construct GetOptString
 503                    //
 504                    GetOptString.append (_OPTION_HOSTNAME);
 505                    GetOptString.append (getoopt::GETOPT_ARGUMENT_DESIGNATOR);
 506                    GetOptString.append (_OPTION_PORTNUMBER);
 507                    GetOptString.append (getoopt::GETOPT_ARGUMENT_DESIGNATOR);
 508                    GetOptString.append (_OPTION_SSL);
 509                    GetOptString.append (_OPTION_USERNAME);
 510                    GetOptString.append (getoopt::GETOPT_ARGUMENT_DESIGNATOR);
 511                    GetOptString.append (_OPTION_PASSWORD);
 512                    GetOptString.append (getoopt::GETOPT_ARGUMENT_DESIGNATOR);
 513                
 514                    //
 515                    //  Initialize and parse getOpts
 516                    //
 517                    getOpts = getoopt ();
 518                    getOpts.addFlagspec (GetOptString);
 519                
 520 j.alex 1.1.2.4     //
 521 j.alex 1.1.2.1     // per PEP#167
 522 j.alex 1.1.2.4     //
 523 j.alex 1.1.2.1     getOpts.addLongFlagspec(LONG_HELP,getoopt::NOARG);
 524                    getOpts.addLongFlagspec(LONG_VERSION,getoopt::NOARG);
 525                    getOpts.addLongFlagspec(LONG_VERBOSE,getoopt::NOARG);
 526                
 527                    getOpts.parse (argc, argv);
 528                
 529                    if (getOpts.hasErrors ())
 530                    {
 531                        log_file.close();
 532 j.alex 1.1.2.3         CommandFormatException e(getOpts.getErrorStrings () [0]);
 533 j.alex 1.1.2.1         throw e;
 534                    }
 535                
 536                    //
 537                    //  Get options and arguments from the command line
 538                    //
 539 j.alex 1.1.2.3     for (i = getOpts.first(); i <  getOpts.last (); i++)
 540 j.alex 1.1.2.1     {
 541 j.alex 1.1.2.3         if (getOpts[i].getType() == Optarg::LONGFLAG)
 542 j.alex 1.1.2.1         {
 543 j.alex 1.1.2.3             if (getOpts[i].getopt() == LONG_HELP)
 544 j.alex 1.1.2.1             {
 545                               _operationType = OPERATION_TYPE_HELP;
 546                            }
 547 j.alex 1.1.2.3             else if (getOpts[i].getopt() == LONG_VERSION)
 548 j.alex 1.1.2.1             {
 549                                _operationType = OPERATION_TYPE_VERSION;
 550                            }
 551 j.alex 1.1.2.3             if (getOpts[i].getopt() == LONG_VERBOSE)
 552 j.alex 1.1.2.1             {
 553                                verboseEnabled = true;
 554                            }
 555                        }
 556 j.alex 1.1.2.3         else if (getOpts [i].getType() == Optarg::REGULAR)
 557 j.alex 1.1.2.1         {
 558                            //
 559                            // _configFilePath is the only non-option argument
 560                            //
 561                            if (_configFilePathSpecified)
 562                            {
 563                                //
 564                                // more than one _configFilePath argument was found
 565                                //
 566 j.alex 1.1.2.3                 log_file<<StressTestControllerCommand::COMMAND_NAME<<
 567                                    "::More than one arguement was found "<<endl;
 568 j.alex 1.1.2.1                 log_file.close();
 569 j.alex 1.1.2.3                 UnexpectedArgumentException e(getOpts[i].Value());
 570 j.alex 1.1.2.1                 throw e;
 571                            }
 572 j.alex 1.1.2.3             _configFilePath = getOpts[i].Value();
 573 j.alex 1.1.2.1             _configFilePathSpecified = true;
 574                        }
 575 j.alex 1.1.2.3         else /* getOpts[i].getType() == FLAG */
 576 j.alex 1.1.2.1         {
 577 j.alex 1.1.2.3             c = getOpts[i].getopt()[0];
 578                            switch(c)
 579 j.alex 1.1.2.1             {
 580                                case _OPTION_HOSTNAME:
 581                                {
 582 j.alex 1.1.2.3                     if (getOpts.isSet(_OPTION_HOSTNAME) > 1)
 583 j.alex 1.1.2.1                     {
 584                                        //
 585                                        // More than one hostname option was found
 586                                        //
 587                                        log_file.close();
 588 j.alex 1.1.2.3                         DuplicateOptionException e(_OPTION_HOSTNAME);
 589 j.alex 1.1.2.1                         throw e;
 590                                    }
 591                                    _hostName = getOpts [i].Value ();
 592                                    _hostNameSpecified = true;
 593                                    if (!_propertyTable->insert("hostname", _hostName))
 594                                    {
 595                                         // shouldn't get here
 596                                         if(verboseEnabled)
 597                                         {
 598                                             cout<<StressTestControllerCommand::COMMAND_NAME;
 599 j.alex 1.1.2.3                              cout<<"::Property Name name already saved: "<<
 600                                                 "hostname"<<endl;
 601 j.alex 1.1.2.1                          }
 602                                    }
 603                                    break;
 604                                }
 605                                case _OPTION_PORTNUMBER:
 606                                {
 607 j.alex 1.1.2.3                     if (getOpts.isSet(_OPTION_PORTNUMBER) > 1)
 608 j.alex 1.1.2.1                     {
 609                                        //
 610                                        // More than one portNumber option was found
 611                                        //
 612                                        log_file.close();
 613 j.alex 1.1.2.3                         DuplicateOptionException e(_OPTION_PORTNUMBER);
 614 j.alex 1.1.2.1                         throw e;
 615                                    }
 616                                    _portNumberStr = getOpts [i].Value ();
 617                                    try
 618                                    {
 619 j.alex 1.1.2.3                         getOpts[i].Value(_portNumber);
 620 j.alex 1.1.2.1                     }
 621                                    catch (const TypeMismatchException&)
 622                                    {
 623                                        log_file.close();
 624 j.alex 1.1.2.3                         InvalidOptionArgumentException e(
 625                                            _portNumberStr,
 626                                            _OPTION_PORTNUMBER);
 627 j.alex 1.1.2.1                         throw e;
 628                                    }
 629                                    _portNumberSpecified = true;
 630                                    if (!_propertyTable->insert("port", _portNumberStr))
 631                                    {
 632                                        if(verboseEnabled)
 633                                        {
 634                                           cout<<StressTestControllerCommand::COMMAND_NAME;
 635 j.alex 1.1.2.3                            cout<<"::Property Name:duplicate name already saved:"
 636                                               <<"port"<<endl;
 637 j.alex 1.1.2.1                         }
 638                                    }
 639                                    break;
 640                                }
 641                                case _OPTION_SSL:
 642                                {
 643                                    //
 644                                    // Use port 5989 as the default port for SSL
 645                                    //
 646                                    _useSSL = true;
 647                                    if (!_portNumberSpecified)
 648                                    {
 649                                       _portNumber = 5989;
 650                                       _portNumberStr = "5989";
 651                                       if (!_propertyTable->insert("port", _portNumberStr))
 652                                       {
 653                                           if(verboseEnabled) 
 654                                           {
 655                                              cout<<StressTestControllerCommand::COMMAND_NAME;
 656 j.alex 1.1.2.3                               cout<<"::Property Name already saved: "<<"port"<<
 657                                                  endl;
 658 j.alex 1.1.2.1                            }
 659                                       }
 660                                    }
 661                                    if (!_propertyTable->insert("ssl", ""))
 662                                    {
 663                                        if(verboseEnabled)
 664                                        {
 665                                            cout<<StressTestControllerCommand::COMMAND_NAME;
 666 j.alex 1.1.2.3                             cout<<"::Property Name already saved: "<<"ssl"<<
 667                                                endl;
 668 j.alex 1.1.2.1                         }
 669                                    }
 670                                    break;
 671                                }
 672                                case _OPTION_USERNAME:
 673                                {
 674 j.alex 1.1.2.3                     if (getOpts.isSet(_OPTION_USERNAME) > 1)
 675 j.alex 1.1.2.1                     {
 676                                        //
 677                                        // More than one username option was found
 678                                        //
 679                                        log_file.close();
 680 j.alex 1.1.2.3                         DuplicateOptionException e(_OPTION_USERNAME);
 681 j.alex 1.1.2.1                         throw e;
 682                                    }
 683 j.alex 1.1.2.3                     _userName = getOpts[i].Value();
 684 j.alex 1.1.2.1                     _userNameSpecified = true;
 685                                    if (!_propertyTable->insert("username", _userName))
 686                                    {
 687                                        if(verboseEnabled)
 688                                        {
 689                                            cout<<StressTestControllerCommand::COMMAND_NAME;
 690 j.alex 1.1.2.3                             cout<< "::Property Name already saved: "<<
 691                                                "username"<<endl;
 692 j.alex 1.1.2.1                         }
 693                                    }
 694                                    break;
 695                                }
 696                                case _OPTION_PASSWORD:
 697                                {
 698 j.alex 1.1.2.3                     if (getOpts.isSet(_OPTION_PASSWORD) > 1)
 699 j.alex 1.1.2.1                     {
 700                                        //
 701                                        // More than one password option was found
 702                                        //
 703                                        log_file.close();
 704 j.alex 1.1.2.3                         DuplicateOptionException e(_OPTION_PASSWORD);
 705 j.alex 1.1.2.1                         throw e;
 706                                    }
 707 j.alex 1.1.2.3                     _password = getOpts[i].Value();
 708 j.alex 1.1.2.1                     _passwordSpecified = true;
 709                                    if (!_propertyTable->insert("password", _password))
 710                                    {
 711                                        if(verboseEnabled)
 712                                        {
 713                                            cout<<StressTestControllerCommand::COMMAND_NAME;
 714 j.alex 1.1.2.3                             cout<<"::Property Name already saved: "<<
 715                                                "password"<<endl;
 716 j.alex 1.1.2.1                         }
 717                                    }
 718                                    break;
 719                                }
 720                
 721                                default:
 722                                {
 723                                    //
 724                                    //  This path should not be hit
 725                                    //  PEP#167 unless an empty '-' is specified
 726                                    //
 727                                    log_file.close();
 728 j.alex 1.1.2.3                     String ErrReport = 
 729                                        String(StressTestControllerCommand::COMMAND_NAME);
 730 j.alex 1.1.2.1                     ErrReport.append("::Invalid or unknown option specified");
 731                                    throw StressTestControllerException(ErrReport);
 732                
 733                                    break;
 734                               }
 735                            }
 736                        }
 737                    }
 738                    //
 739                    //  More validation:
 740                    //    No portNumber specified
 741                    //    Default to WBEM_DEFAULT_PORT
 742                    //    Already done in constructor
 743                    //
 744 j.alex 1.1.2.3     if (getOpts.isSet(_OPTION_PORTNUMBER) == 1)
 745 j.alex 1.1.2.1     {
 746                        if (_portNumber > _MAX_PORTNUMBER)
 747                        {
 748                            //
 749                            //  Portnumber out of valid range
 750                            //
 751                            log_file.close();
 752 j.alex 1.1.2.3             InvalidOptionArgumentException e(_portNumberStr,
 753 j.alex 1.1.2.1                 _OPTION_PORTNUMBER);
 754                            throw e;
 755                        }
 756                    }
 757                    log_file.close();
 758                } /* setCommand  */
 759                
 760                /**
 761                
 762                    Generates commands and its options for each of the clients. 
 763                    The client table is traversed to generate each of the client commands.
 764                    The Commands, Duration and Delays for each client are saved in
 765                    the following array's respectively:
 766                       _clientCommands 
 767                       _clientDurations
 768                       _clientDelays 
 769                    
 770                    @param   log_file           The log file.                               
 771                
 772                    @return  0                  if the command is successfully generated
 773                             1                  if the command cannot be generated.
 774 j.alex 1.1.2.1  */
 775                Boolean StressTestControllerCommand::generateClientCommands(ostream& log_file)
 776                {
 777                
 778 j.alex 1.1.2.3     String client_command = String::EMPTY;
 779                    double duration = _duration;
 780                    double delay = 0;
 781                
 782                    // 
 783                    // Array's to store client specific information
 784                    //
 785                    _clientCommands = new String[_clientCount]; 
 786                    _clientDurations = new Uint64[_clientCount];
 787                    _clientDelays = new Uint64[_clientCount]; 
 788                
 789 j.alex 1.1.2.4     //
 790 j.alex 1.1.2.3     // Retrieve all the client options from the client table
 791                    // and build commands for respective clients. 
 792                    // Add appropriate options to command string  as required 
 793 j.alex 1.1.2.4     //
 794 j.alex 1.1.2.3     for (Uint32 j=0; j< _clientCount; j++)
 795                    {
 796                        delay = 0;
 797                        String clientName = String::EMPTY;
 798                        String clientInst = String::EMPTY;
 799                        // 
 800                        //  Stress Client Name must exist for each client/client table 
 801                        //
 802                        if (!_clientTable[j].lookup(NAME, clientName))
 803                        {
 804                            log_file<<StressTestControllerCommand::COMMAND_NAME<<
 805                                 "::Required property NAME not found."<<endl;
 806 j.alex 1.1.2.1             return false;
 807 j.alex 1.1.2.3         }
 808                        //
 809                        // Start the command string with the client name.
 810                        //
 811                        client_command = clientName;
 812 j.alex 1.1.2.1 
 813 j.alex 1.1.2.3         // 
 814                        // Generate the commands for each client from each client table.
 815                        //
 816                        for (Table::Iterator i = _clientTable[j].start(); i; i++)
 817                        {
 818                            if (String::equalNoCase(i.key(),HOSTNAME))
 819                            {
 820                                client_command.append(" -hostname ");
 821                                if (_hostNameSpecified)
 822                                {
 823                                    client_command.append(_hostName);
 824                                }
 825                                else
 826                                { 
 827                                    client_command.append(i.value());
 828                                }
 829                            } 
 830                            else if (String::equalNoCase(i.key(),NAME))
 831                            {
 832 j.alex 1.1.2.4                 //
 833 j.alex 1.1.2.3                 // should be ignored - already saved using clientName
 834 j.alex 1.1.2.4                 //
 835 j.alex 1.1.2.3             } 
 836                            else if (String::equalNoCase(i.key(),PORTNUMBER))
 837                            {
 838                                client_command.append(" -");
 839                                client_command.append(PORTNUMBER);
 840                                client_command.append(" ");
 841                                if (_portNumberSpecified)
 842                                {
 843                                    client_command.append(_portNumberStr);
 844                                } 
 845                                else
 846                                { 
 847                                    client_command.append(i.value());
 848                                }
 849                            }
 850                            else if (String::equalNoCase(i.key(),SSL))
 851                            {
 852                                client_command.append(" -");
 853                                client_command.append(SSL);
 854                            } 
 855                            else if (String::equalNoCase(i.key(),USERNAME))
 856 j.alex 1.1.2.3             {
 857                                client_command.append(" -");
 858                                client_command.append(USERNAME);
 859                                client_command.append(" ");
 860                                client_command.append(i.value());
 861                            } 
 862                            else if (String::equalNoCase(i.key(),PASSWORD))
 863                            {
 864                                client_command.append(" -");
 865                                client_command.append(PASSWORD);
 866                                client_command.append(" ");
 867                                client_command.append(i.value());
 868                            }
 869                            else if (String::equalNoCase(i.key(),CLIENTNAME))
 870                            {
 871                                client_command.append(" -");
 872                                client_command.append(CLIENTNAME);
 873                                client_command.append(" ");
 874                                client_command.append(i.value());
 875                            }
 876                            else if (String::equalNoCase(i.key(),OPTIONS))
 877 j.alex 1.1.2.3             {
 878                                client_command.append(" -");
 879                                client_command.append(OPTIONS);
 880                                client_command.append(" ");
 881                                client_command.append(i.value());
 882                            }
 883                            else if (String::equalNoCase(i.key(),NAMESPACE))
 884                            {
 885                                client_command.append(" -");
 886                                client_command.append(NAMESPACE);
 887                                client_command.append(" ");
 888                                client_command.append(i.value());
 889                            } 
 890                            else if (String::equalNoCase(i.key(),CLASSNAME))
 891                            {
 892                                client_command.append(" -");
 893                                client_command.append(CLASSNAME);
 894                                client_command.append(" ");
 895                                client_command.append(i.value());
 896                            } 
 897                            else if ((String::equalNoCase(i.key(),INSTANCE))
 898 j.alex 1.1.2.3                       ||(String::equalNoCase(i.key(),CLIENTWAIT))
 899                                      ||(String::equalNoCase(i.key(),CLIENTDURATION)))
 900                            {
 901 j.alex 1.1.2.4                 //
 902 j.alex 1.1.2.3                 // do nothing here 
 903                                //   will be utilized to run the clients later.
 904 j.alex 1.1.2.4                 //
 905 j.alex 1.1.2.3             } 
 906                            else 
 907                            { 
 908 j.alex 1.1.2.4                 //
 909 j.alex 1.1.2.3                 // Save all other options for the commands
 910 j.alex 1.1.2.4                 //
 911 j.alex 1.1.2.3                 client_command.append(" -");
 912                                client_command.append(i.key());
 913                                client_command.append(" ");
 914                                client_command.append(i.value());
 915                            }
 916 j.alex 1.1.2.1         }
 917                        //
 918                        // Include verbose if enabled to clients
 919                        //
 920 j.alex 1.1.2.3         if (verboseEnabled)
 921                        {
 922                            client_command.append(" -verbose ");
 923                        }
 924 j.alex 1.1.2.1 
 925                        //
 926 j.alex 1.1.2.3         // Acquire all the common properties listed in the property table 
 927                        // from config file and include it as part of the client command 
 928                        // as required.
 929 j.alex 1.1.2.4         //
 930 j.alex 1.1.2.1         for (Table::Iterator k = _propertyTable->start(); k; k++)
 931                        {
 932 j.alex 1.1.2.3             String propertyValue = String::EMPTY;
 933 j.alex 1.1.2.4             //
 934 j.alex 1.1.2.3             // Only include the common properties that are not already
 935                            // listed for the clients.
 936 j.alex 1.1.2.4             //
 937 j.alex 1.1.2.3             if (!_clientTable[j].lookup(k.key(), propertyValue))
 938                            {
 939 j.alex 1.1.2.4                 //
 940 j.alex 1.1.2.3                 // Include options other than ToleranceLevel
 941                                // clientDuration,clientwait and Duration
 942                                // in the command string for the clients. 
 943 j.alex 1.1.2.4                 //
 944 j.alex 1.1.2.3                 if ((!String::equalNoCase(k.key(),TOLERANCELEVEL))
 945                                     && (!String::equalNoCase(k.key(),CLIENTDURATION))
 946                                     && (!String::equalNoCase(k.key(),CLIENTWAIT))
 947                                     && (!String::equalNoCase(k.key(),DURATION)))
 948                                {
 949                                    client_command.append(" -");
 950                                    client_command.append(k.key());
 951                                    // 
 952                                    // No values required for SSL
 953                                    // 
 954                                    if (!String::equalNoCase(k.key(),SSL))
 955                                    {
 956                                        client_command.append(" ");
 957                                        client_command.append(k.value());
 958                                    }
 959                                }
 960                            }
 961                            //
 962                            // Use default duration if one was not specified in the Config file.
 963                            //
 964                            if (String::equalNoCase(k.key(),DURATION))
 965 j.alex 1.1.2.3             {
 966                                duration = atof(k.value().getCString());
 967                            } 
 968                            else 
 969                            {
 970                                duration = _duration;
 971                            }
 972 j.alex 1.1.2.1         } /* for (Table::Iterator k = _propertyTable->start(); k; k++) */
 973                
 974                        //
 975 j.alex 1.1.2.3         // Looking up table while ignoring cases for Client Duration/Wait.
 976 j.alex 1.1.2.1         //
 977                        for (Table::Iterator k = _clientTable[j].start(); k; k++)
 978                        {
 979 j.alex 1.1.2.4             //
 980 j.alex 1.1.2.1             // Overwrite duration if client duration set
 981 j.alex 1.1.2.4             //
 982 j.alex 1.1.2.1             if (String::equalNoCase(k.key(),CLIENTDURATION))
 983 j.alex 1.1.2.3             {
 984                                duration = atof(k.value().getCString());
 985                            }
 986 j.alex 1.1.2.1             if (String::equalNoCase(k.key(),CLIENTWAIT))
 987 j.alex 1.1.2.3             {
 988                                delay = atof(k.value().getCString());
 989                            }
 990 j.alex 1.1.2.1         }
 991                
 992 j.alex 1.1.2.3         //
 993                        // Save the generated command to corresponding element in the 
 994                        // clientCommand array.
 995                        //
 996                        _clientCommands[j] = client_command;
 997 j.alex 1.1.2.1 
 998 j.alex 1.1.2.3         //
 999                        // Converting minutes to milliseconds
1000                        //
1001                        _clientDurations[j] = (Uint64)convertmin2millisecs(duration);
1002                        _clientDelays[j] = (Uint64)convertmin2millisecs(delay);
1003 j.alex 1.1.2.1        
1004 j.alex 1.1.2.3         //
1005                        // Saving logs
1006                        //
1007                        log_file<<StressTestControllerCommand::COMMAND_NAME<<
1008                            "::Client Command[";
1009                        log_file<<j<<"]"<<endl;
1010                        log_file<<"  "<<_clientCommands[j]<<endl;
1011                        log_file<<"   Client Duration: "<<
1012                            convertUint64toString(_clientDurations[j])<<endl;
1013                        log_file<<
1014                            "   Client Delay: "<<convertUint64toString(_clientDelays[j])<<endl;
1015                
1016                        //
1017                        // Verbose 
1018                        //
1019                        if (verboseEnabled)
1020                        {
1021                            cout<<
1022                                StressTestControllerCommand::COMMAND_NAME<<"::Client Command[";
1023                            cout<<j<<"]"<<endl;
1024                            cout<<"  "<<_clientCommands[j]<<endl;
1025 j.alex 1.1.2.3             cout<<"   Client Duration: "<<
1026                                convertUint64toString(_clientDurations[j])<<endl;
1027                            cout<<"   Client Delay: "<<convertUint64toString(_clientDelays[j])<<
1028                                endl;
1029                        }
1030 j.alex 1.1.2.1     } /* for(Uint32 j=0; j< _clientCount; j++) */
1031                    return true;
1032                } /* generateClientCommands */
1033                
1034                /*
1035                    Executes the command and writes the results to the PrintWriters.
1036                    This method is where the clients are intiated.
1037                    The clients are kept running until its duration is met
1038                    or the controller is interrupted by a SIGINT or SIGABRT signal
1039                    or if the controller failed to acquire the clientPIDs when needed.
1040                
1041                    Clients with clientWait,  will be stopped when its duration is met and 
1042                    then restarted after its wait period is completed. This will continue 
1043                    until the end of the overall duration. 
1044                    When the overall duration has ended or the controller is interupted then
1045                    the controller will read the PID file to update its clients PID and  
1046                    request all the clients to end its processes.
1047                
1048                    @param   outPrintWriter     the ostream to which output should be
1049                                                written
1050                    @param   errPrintWriter     the ostream to which error output should be
1051 j.alex 1.1.2.1                                 written
1052                
1053                    @return  0                  if the command is successful
1054                             1                  if an error occurs in executing the command
1055                
1056                 */
1057 j.alex 1.1.2.3 Uint32 StressTestControllerCommand::execute (
1058                    ostream& outPrintWriter,
1059                    ostream& errPrintWriter)
1060 j.alex 1.1.2.1 {
1061                  
1062 j.alex 1.1.2.3     int actual_client = 0;
1063                    Uint64 startMilliseconds = 0;
1064                    Uint64 nowMilliseconds = 0;
1065                    Uint64 stopMilliseconds = 0;
1066                    Uint64 timeoutMilliseconds = 0;
1067                    Uint64 *clientStartMilliseconds = 0;
1068                    Uint64 *clientStopMilliseconds = 0;
1069                    Uint64 *clientDelayMilliseconds = 0;
1070                    Boolean *clientStopped = 0;
1071                    Boolean *clientDelayed = 0;
1072                    String act_command = String::EMPTY;
1073                    Boolean TestFailed = false;
1074                    char str[15];
1075                    char strTime[256];
1076                    struct tm tmTime;
1077 j.alex 1.1.2.1 
1078                
1079                
1080                    //
1081                    // log file
1082                    //       
1083 j.alex 1.1.2.3     ofstream log_file;
1084 j.alex 1.1.2.1 
1085                    //       
1086                    // open the file
1087                    //       
1088 j.alex 1.1.2.3     OpenAppend(log_file,_stressTestLogFile);
1089 j.alex 1.1.2.1 
1090                    // 
1091                    // Failed to read log file.
1092                    //
1093                    if (!log_file)
1094                    {
1095 j.alex 1.1.2.3         log_file.close();
1096                        if (verboseEnabled)
1097                        {
1098                            outPrintWriter<<StressTestControllerCommand::COMMAND_NAME;
1099                            outPrintWriter<<"Cannot read file "<<_stressTestLogFile<<endl;
1100                        }
1101                        return RC_ERROR;
1102 j.alex 1.1.2.1     }
1103                
1104                    // 
1105                    // Display usage message if help was specified
1106                    //
1107                    if ( _operationType == OPERATION_TYPE_HELP )
1108                    {
1109 j.alex 1.1.2.3         outPrintWriter << _usage << endl;
1110                        log_file<<StressTestControllerCommand::COMMAND_NAME<<
1111                            "::Listing usage information "<<endl;
1112 j.alex 1.1.2.1         log_file.close();
1113                        //
1114                        //  No need for the client pid and log file.
1115                        //
1116 j.alex 1.1.2.3         FileSystem::removeFile(_stressTestClientPIDFile);
1117                        FileSystem::removeFile(_stressTestClientLogFile);
1118 j.alex 1.1.2.1         return (RC_SUCCESS);
1119                    }
1120                    // 
1121                    // Display PEGASUS version if version was specified
1122                    //
1123                    else if ( _operationType == OPERATION_TYPE_VERSION )
1124                    {
1125                        outPrintWriter << "Version " << PEGASUS_PRODUCT_VERSION << endl;
1126 j.alex 1.1.2.3         log_file<<StressTestControllerCommand::COMMAND_NAME<<
1127                            "::Listing version information "<<endl;
1128 j.alex 1.1.2.1         log_file<<"Version " << PEGASUS_PRODUCT_VERSION << endl;
1129                        log_file.close();
1130                        //
1131                        //  No need for the client pid and log file.
1132                        //
1133 j.alex 1.1.2.3         FileSystem::removeFile(_stressTestClientPIDFile);
1134                        FileSystem::removeFile(_stressTestClientLogFile);
1135 j.alex 1.1.2.1         return (RC_SUCCESS);
1136                    }
1137                
1138 j.alex 1.1.2.4     //
1139                    // gracefully shutdown when interrupted
1140                    //
1141 j.alex 1.1.2.1     signal(SIGABRT, endAllTests);
1142                    signal(SIGINT, endAllTests);
1143                
1144                    // 
1145                    // Allocate variables necessary to run clients. 
1146                    //
1147                    if(_clientCount > 0)
1148                    {
1149 j.alex 1.1.2.3         clientInstance = new int[_clientCount]; 
1150 j.alex 1.1.2.1         clientStartMilliseconds = new Uint64[_clientCount];
1151                        clientStopMilliseconds  = new Uint64[_clientCount];
1152                        clientDelayMilliseconds = new Uint64[_clientCount];
1153 j.alex 1.1.2.3         clientStopped = new Boolean[_clientCount];
1154                        clientDelayed = new Boolean[_clientCount];
1155 j.alex 1.1.2.1     } 
1156                    else 
1157                    { 
1158                        errPrintWriter << "Stress Tests must have at least one Client." << endl;
1159 j.alex 1.1.2.3         log_file<<StressTestControllerCommand::COMMAND_NAME<<
1160                            "::Stress Tests must have at least one Client."<<endl;
1161 j.alex 1.1.2.1         log_file.close();
1162                        return (RC_ERROR);
1163                    }
1164                        
1165                    try
1166                    {
1167 j.alex 1.1.2.4         //
1168 j.alex 1.1.2.3         // Initializing the Boolean array's to false.
1169 j.alex 1.1.2.4         //
1170 j.alex 1.1.2.3         for (Uint32 i=0;i<_clientCount;i++)
1171                        {
1172                            clientStopped[i] = false;
1173                            clientDelayed[i] = false;
1174                        }
1175 j.alex 1.1.2.4         //
1176 j.alex 1.1.2.3         // Set up duration of the tests
1177 j.alex 1.1.2.4         //
1178 j.alex 1.1.2.3         startMilliseconds   = TimeValue::getCurrentTime().toMilliseconds();
1179                        nowMilliseconds     = startMilliseconds;
1180                        timeoutMilliseconds = (Uint64)convertmin2millisecs(_duration);
1181                        stopMilliseconds    = nowMilliseconds + timeoutMilliseconds;
1182 j.alex 1.1.2.1    
1183 j.alex 1.1.2.3         log_file<<StressTestControllerCommand::COMMAND_NAME<<
1184                            ":: Test Duration information "<<endl;
1185                        log_file<<"  Start Time in milliseconds: "<<
1186                            convertUint64toString(startMilliseconds)<<endl;
1187                        log_file<<"  Total duration in milliseconds: "<<
1188                            convertUint64toString(timeoutMilliseconds)<<endl;
1189                        log_file<<"  Actual Stop Time in milliseconds: "<<
1190                            convertUint64toString(stopMilliseconds)<<endl;
1191                        // 
1192                        //  Verbose details for Stress Test duration 
1193                        //
1194                        if (verboseEnabled)
1195                        {
1196                            outPrintWriter<<StressTestControllerCommand::COMMAND_NAME<<
1197                                ":: Test Duration information "<<endl;
1198                            outPrintWriter<<"  Start Time in milliseconds: "<<
1199                                convertUint64toString(startMilliseconds)<<endl;
1200                            outPrintWriter<<"  Total duration in milliseconds: "<<
1201                                convertUint64toString(timeoutMilliseconds)<<endl;
1202                            outPrintWriter<<
1203                                "  Actual Stop Time in milliseconds: "<<
1204 j.alex 1.1.2.3                 convertUint64toString(stopMilliseconds)<<endl;
1205                        }
1206 j.alex 1.1.2.1 
1207 j.alex 1.1.2.3         //
1208                        //  First Tolerance check up interval is set up to be twice 
1209                        //  the CHECKUP_INTERVAL. This should give the clients enough time
1210                        //  to update its PID, status  etc.
1211 j.alex 1.1.2.1         // 
1212 j.alex 1.1.2.3         Uint64 nextCheckupInMillisecs = 
1213                           (Uint64)convertmin2millisecs(2 * CHECKUP_INTERVAL) + nowMilliseconds;
1214 j.alex 1.1.2.1         //
1215 j.alex 1.1.2.3         //  Main "while" loop where the clients are initiated. 
1216                        //
1217                        while(stopMilliseconds > nowMilliseconds)
1218                        { 
1219                
1220                            // 
1221                            // Small delay in the while loop seemed to reduce the CPU usage 
1222                            // considerably  in Windows. (From 80% to 1%)
1223                            //
1224                #ifndef PEGASUS_OS_TYPE_WINDOWS
1225                            sleep(RUN_DELAY); 
1226 j.alex 1.1.2.1 #else
1227 j.alex 1.1.2.3             Sleep(RUN_DELAY * 1000);
1228 j.alex 1.1.2.1 #endif
1229                
1230 j.alex 1.1.2.4             //
1231 j.alex 1.1.2.3             // Quit if SIGINT, SIGABRT is caught
1232                            // So the clients can be gracefully shutdown.
1233 j.alex 1.1.2.4             //
1234 j.alex 1.1.2.3             if(Quit)
1235                            {
1236                                log_file<<
1237                                    "Test interrupted by either SIGINT or SIGABORT."<<endl; 
1238                                TestFailed = true;
1239                                break;
1240                            }
1241                            //
1242                            // The following block will be where clients are executed initially.
1243                            //
1244                            if(!actual_client)
1245                            {
1246                                log_file<<StressTestControllerCommand::COMMAND_NAME<<
1247                                    "::Running the following tests: "<<endl;
1248                                outPrintWriter<<StressTestControllerCommand::COMMAND_NAME<<
1249                                    "::Running the following tests: "<<endl;
1250                                for (Uint32 j=0; j< _clientCount; j++)
1251 j.alex 1.1.2.1                 {
1252 j.alex 1.1.2.3                     String clientInst = String::EMPTY;
1253 j.alex 1.1.2.1                     //
1254 j.alex 1.1.2.3                     // Acquire the client Instance for each clients
1255 j.alex 1.1.2.1                     //
1256 j.alex 1.1.2.3                     if (!_clientTable[j].lookup(INSTANCE, clientInst))
1257 j.alex 1.1.2.1                     {
1258 j.alex 1.1.2.3                         String ErrReport = String("Invalid Property Value: ");
1259                                        ErrReport.append(INSTANCE);
1260                                        ErrReport.append("=");
1261                                        ErrReport.append(clientInst);
1262                                        throw StressTestControllerException(ErrReport);
1263 j.alex 1.1.2.1                     }
1264 j.alex 1.1.2.3                     clientInstance[j] = atoi(clientInst.getCString());
1265 j.alex 1.1.2.1 
1266                                    //
1267 j.alex 1.1.2.3                     // Acquire and set client specific duration
1268 j.alex 1.1.2.1                     //
1269 j.alex 1.1.2.3                     clientStartMilliseconds[j] = 
1270                                        TimeValue::getCurrentTime().toMilliseconds();
1271                                    clientStopMilliseconds[j] = 
1272                                        clientStartMilliseconds[j] + _clientDurations[j];
1273                
1274                                    // 
1275                                    // for verbose only
1276 j.alex 1.1.2.1                     //
1277 j.alex 1.1.2.3                     if (verboseEnabled)
1278                                    {
1279                                        outPrintWriter<<"Client:"<<"["<<j<<"]"<<endl;
1280                                        log_file<<"Client:"<<"["<<j<<"]"<<endl;
1281                                        outPrintWriter<<"ClientStart:"<<
1282                                            convertUint64toString(clientStartMilliseconds[j])<<
1283                                            endl;
1284                                        outPrintWriter<<"ClientStop:"<<
1285                                            convertUint64toString(clientStopMilliseconds[j])<<
1286                                            endl;
1287                                        outPrintWriter<<"ClientDuration:"<<
1288                                            convertUint64toString(_clientDurations[j])<<endl;
1289                                        log_file<<"ClientStart:"<<
1290                                            convertUint64toString(clientStartMilliseconds[j])<<
1291                                            endl;
1292                                        log_file<<"ClientStop:"<<
1293                                            convertUint64toString(clientStopMilliseconds[j])<<
1294                                            endl;
1295                                        log_file<<
1296                                            "ClientDuration:"<<
1297                                            convertUint64toString(_clientDurations[j])<<endl;
1298 j.alex 1.1.2.3                     }
1299                                    log_file<<
1300                                        "Number of instances of this client: "<<
1301                                        clientInstance[j]<<endl;
1302                                    if(verboseEnabled)
1303                                    {
1304                                        outPrintWriter<<
1305                                            "Number of instances of this client:"<<
1306                                            clientInstance[j]<<endl;
1307                                    }
1308 j.alex 1.1.2.1                     // 
1309 j.alex 1.1.2.3                     // Execute each instance of the client.
1310                                    //   - Additional required parameters are added to the 
1311                                    //     commands.
1312                                    //     like, -clientid, -pidfile, -clientlog
1313 j.alex 1.1.2.4                     //
1314 j.alex 1.1.2.3                     for (int instanceID =0;instanceID<clientInstance[j];
1315                                         instanceID++)
1316 j.alex 1.1.2.1                     {
1317 j.alex 1.1.2.3                         outPrintWriter<<
1318                                            "Running Client("<<actual_client<<")"<<endl;
1319                                        log_file<<
1320                                            "Running Client("<<actual_client<<")"<<endl;
1321                                        act_command=String::EMPTY;
1322                #ifdef PEGASUS_OS_TYPE_WINDOWS
1323                                        act_command.append("start ");
1324                #endif
1325                                        //
1326                                        // Adding all the required parameters for the command.
1327                                        //
1328                                        act_command.append(_clientCommands[j].getCString());
1329                                        act_command.append(" -clientid ");
1330                                        sprintf(str,"%d",actual_client); 
1331                                        act_command.append(str);
1332                                        act_command.append(" -pidfile ");
1333                                        act_command.append(" \"");
1334                                        act_command.append(_stressTestClientPIDFile);
1335                                        act_command.append("\"");
1336                                        act_command.append(" -clientlog");
1337                                        act_command.append(" \"");
1338 j.alex 1.1.2.3                         act_command.append(_stressTestClientLogFile);
1339                                        act_command.append("\"");
1340                                        act_command.append("&");
1341                                        if (verboseEnabled)
1342                                        {
1343                                            outPrintWriter<<"  "<<act_command<<endl;
1344                                            tmTime = getCurrentActualTime();
1345                                            strftime(
1346                                                strTime,
1347                                                256,
1348                                                "%d/%m/%Y at %H:%M:%S\n",
1349                                                &tmTime);
1350                                            log_file<<
1351                                                StressTestControllerCommand::COMMAND_NAME<<
1352                                                "::Running following command on "<<
1353                                                strTime<<endl;
1354                                            log_file<<"     ("<<actual_client<<") \n"<<
1355                                                act_command<<endl;
1356                                        }
1357                
1358                                        //
1359 j.alex 1.1.2.3                         // Executing the Client
1360                                        //
1361                                        int rc = system(act_command.getCString());
1362                                        //
1363                                        // Continue even if the client failed to Execute
1364                                        // This failure is validated with Tolerance level later
1365                                        // 
1366                                        if (rc)
1367                                        {
1368                                            log_file<<"Command failed to Execute."<<endl;
1369                                            if (verboseEnabled)
1370                                            {
1371                                                outPrintWriter<<
1372                                                    "Command failed to Execute."<<endl;
1373                                            }
1374                                        }
1375 j.alex 1.1.2.4                         //
1376 j.alex 1.1.2.3                         // Increment the actual number of clients
1377 j.alex 1.1.2.4                         //
1378 j.alex 1.1.2.3                         ++actual_client;
1379                                    } /* for(int instanceID =0;instanceID<clientInstance[j]...*/
1380 j.alex 1.1.2.1                  
1381 j.alex 1.1.2.3                 }/* for(Uint32 j=0; j< _clientCount; j++) */
1382 j.alex 1.1.2.1 
1383 j.alex 1.1.2.3                 //
1384                                //retrieve all PIDs and status;
1385                                //
1386                                clientPIDs = new pid_t[actual_client]; 
1387                                clientStatus = new int[actual_client]; 
1388                                prev_clientStatus = new int[actual_client]; 
1389                                clientTimeStamp = new Uint64[actual_client]; 
1390                                prev_clientTimeStamp = new Uint64[actual_client]; 
1391                                clientActive = new Boolean[actual_client]; 
1392                                nowMilliseconds = TimeValue::getCurrentTime().toMilliseconds();
1393                                for (int i=0;i<actual_client;i++)
1394                                {
1395                                    clientPIDs[i] = 9999999;
1396                                    clientStatus[i] = NO_RESPONSE;
1397                                    clientActive[i] = true;
1398                                    clientTimeStamp[i] = nowMilliseconds;
1399                                    prev_clientTimeStamp[i] = nowMilliseconds;
1400                                }
1401                                log_file<<StressTestControllerCommand::COMMAND_NAME<<
1402                                    "::Getting client PID's and status. "<<endl;
1403                                if (verboseEnabled)
1404 j.alex 1.1.2.3                 {
1405                                    outPrintWriter<<StressTestControllerCommand::COMMAND_NAME<<
1406                                        "::Getting client PID's and status. "<<endl;
1407                                }
1408                                int rc = _getClientPIDs(actual_client,log_file);
1409                                if (!rc)
1410                                {
1411                                    outPrintWriter<<
1412                                        "Failed to communicate with clients."<<endl;
1413                                    log_file<<StressTestControllerCommand::COMMAND_NAME<<
1414                                        "::Failed to communicate with clients. "<<endl;
1415                                    log_file<<
1416                                    "                    ::Failed to get client PID & status. "
1417                                        <<endl;
1418 j.alex 1.1.2.1                     TestFailed = true;
1419                                    break;
1420 j.alex 1.1.2.3                 }
1421                            }/* if (!actual_client) */ 
1422                            else 
1423                            { 
1424                                /**
1425                                 Every CHECKUP_INTERVAL minutes check to see if tests are
1426                                 within tolerance. Tests will cease to run if they
1427                                 are not within tolerance. The controller will stop
1428                                 all the clients and then exit.
1429                                */
1430                 
1431 j.alex 1.1.2.4                 //
1432 j.alex 1.1.2.3                 // Retreive all the client PIDs
1433 j.alex 1.1.2.4                 //
1434 j.alex 1.1.2.3                 int rc = _getClientPIDs(actual_client,log_file);
1435                          
1436                                //
1437                                // Get Current Time
1438 j.alex 1.1.2.1                 //
1439 j.alex 1.1.2.3                 nowMilliseconds = TimeValue::getCurrentTime().toMilliseconds();
1440                
1441                                //
1442                                // Check tolerance level if its time
1443 j.alex 1.1.2.1                 //
1444 j.alex 1.1.2.3                 if (nowMilliseconds >= nextCheckupInMillisecs)
1445 j.alex 1.1.2.1                 {
1446 j.alex 1.1.2.3                     //
1447                                    //  Set up the next tolerance time
1448                                    //
1449                                    nextCheckupInMillisecs = 
1450                                           (Uint64)convertmin2millisecs(CHECKUP_INTERVAL) +
1451                                           nowMilliseconds; 
1452                                    // 
1453                                    //  End tests when failed to acquire the Client PID  or 
1454                                    //  status.
1455                                    //
1456                                    if (!rc)
1457 j.alex 1.1.2.1                     {
1458 j.alex 1.1.2.3                         outPrintWriter<<
1459                                            "Failed to communicate with clients."<<endl;
1460                                        log_file<<StressTestControllerCommand::COMMAND_NAME<<
1461                                            "::Failed to communicate with clients. "<<endl;
1462                                        log_file<<StressTestControllerCommand::COMMAND_NAME<<
1463                                            "::Get Client PID FAILED. "<<endl;
1464                                        TestFailed = true;
1465                                        break;
1466 j.alex 1.1.2.1                     }
1467 j.alex 1.1.2.3                     log_file<<StressTestControllerCommand::COMMAND_NAME<<
1468                                        "::Checking current tolerance level. "<<endl;
1469                                    //
1470                                    // Output Client info if verbose is enabled.
1471                                    //
1472                                    if (verboseEnabled)
1473                                    {
1474                                        outPrintWriter<<
1475                                            StressTestControllerCommand::COMMAND_NAME<<
1476                                            "::Checking current tolerance level. "<<endl;
1477                                        for (int i=0;i< actual_client; i++)
1478                                        {
1479                                            outPrintWriter <<" Client: "<<i;
1480                                            outPrintWriter <<" PID: "<<clientPIDs[i]<<", ";
1481                                            outPrintWriter <<" Status: "<<clientStatus[i]<<endl;
1482                                            log_file <<" Client: "<<i;
1483                                            log_file <<" PID: "<<clientPIDs[i]<<", ";
1484                                            log_file <<" Status: "<<clientStatus[i]<<", ";
1485                                            log_file<<"   TimeStamp: "<<
1486                                                convertUint64toString(clientTimeStamp[i])<<
1487                                                endl;
1488 j.alex 1.1.2.3                         }
1489                                    }
1490                                    // 
1491                                    // Check the actual tolerance level
1492                                    //
1493                                    Boolean withinTolerance = _checkToleranceLevel(
1494                                                                  actual_client,
1495                                                                  nowMilliseconds,
1496                                                                  log_file);
1497                                    // 
1498                                    //  End tests if not within tolerance
1499                                    //
1500                                    if (!withinTolerance)
1501                                    {
1502                                        log_file<<"FAILED::Tests NOT within tolerance."<<endl;
1503                                        errPrintWriter<<"FAILED::Tests NOT within tolerance."
1504                                                      <<endl;
1505                                        TestFailed = true;
1506                                        break;
1507                                    }
1508                                    // 
1509 j.alex 1.1.2.3                     //  Within Tolerance - Continue tests. 
1510                                    //
1511                                    log_file<<"********Tests are within tolerance.********* "<<
1512                                            endl;  
1513                                    if (verboseEnabled)
1514                                    {
1515                                        outPrintWriter<<
1516                                           " ********Tests are within tolerance.**********"<<
1517                                           endl;
1518                                    }
1519                                } /* if (nowMilliseconds >= nextCheckupInMillisecs)*/
1520 j.alex 1.1.2.1                 //
1521 j.alex 1.1.2.3                 // Stop clients with delay 
1522 j.alex 1.1.2.1                 //
1523 j.alex 1.1.2.3                 for (Uint32 clientID=0; clientID < _clientCount; clientID++)
1524                                {              
1525 j.alex 1.1.2.4                     //
1526 j.alex 1.1.2.3                     // Get Current time
1527 j.alex 1.1.2.4                     //
1528 j.alex 1.1.2.3                     nowMilliseconds = 
1529                                        TimeValue::getCurrentTime().toMilliseconds();
1530                
1531                                    // 
1532                                    // Stop only running clients as required.
1533 j.alex 1.1.2.1                     //
1534 j.alex 1.1.2.3                     if (!clientStopped[clientID])
1535 j.alex 1.1.2.1                     {
1536 j.alex 1.1.2.3                         // 
1537                                        // If Client's duration is up
1538                                        //
1539                                        if (clientStopMilliseconds[clientID]<= nowMilliseconds)
1540                                        {
1541                                            // 
1542                                            // Stop all the instances of this client
1543                                            //
1544                                            for (int instanceID =0;
1545                                                 instanceID<clientInstance[clientID];
1546                                                 instanceID++)
1547                                            {
1548                                                log_file<<"Stopping client:("<<
1549                                                    clientID+instanceID<<")"<<endl;
1550                                                log_file<<"  with PID = "<<
1551                                                    clientPIDs[clientID+instanceID]<<endl;
1552                                                outPrintWriter<<"Stopping client:("<<
1553                                                    clientID+instanceID<<")"<<endl;
1554                                                outPrintWriter<<"  with PID = "<<
1555                                                    clientPIDs[clientID+instanceID]<<endl;
1556                                                if (verboseEnabled)
1557 j.alex 1.1.2.3                                 {
1558                                                    tmTime = getCurrentActualTime();
1559                                                    strftime(
1560                                                        strTime,
1561                                                        256,
1562                                                        "%d/%m/%Y at %H:%M:%S\n",
1563                                                        &tmTime);
1564                                                    log_file<<"    Stopped on "<<strTime<<endl;
1565                                                }
1566                                                String stopClientFile = String::EMPTY; 
1567                                                stopClientFile.append(pegasusHome);
1568                                                stopClientFile.append(DEFAULT_TMPDIR);
1569                                                stopClientFile.append("STOP_");
1570                                                sprintf(
1571                                                    str,
1572                                                    "%d",
1573                                                    clientPIDs[clientID+instanceID]); 
1574                                                stopClientFile.append(str);
1575 j.alex 1.1.2.4                                 //
1576 j.alex 1.1.2.3                                 // Required for Windows
1577 j.alex 1.1.2.4                                 //
1578 j.alex 1.1.2.3                                 ofstream stop_file(
1579                                                    stopClientFile.getCString(),
1580                                                    ios::out);
1581                                                stop_file << "Stop Client PID : "<<
1582                                                          clientPIDs[clientID + instanceID]<<
1583                                                          endl;
1584                                                stop_file.close();
1585                #ifndef PEGASUS_OS_TYPE_WINDOWS
1586                                                // one more way to stop the clients.
1587                                                int rc = 
1588                                                  kill(clientPIDs[clientID+instanceID], SIGINT);
1589                                                if (rc)
1590                                                {
1591                                                    outPrintWriter<<"FAILED to stop client:("<<
1592                                                        clientID+instanceID<<")"<<endl;
1593                                                    log_file<<"FAILED to stop client:("<<
1594                                                        clientID + instanceID<<")"<<endl;
1595                                                }
1596 j.alex 1.1.2.1 #endif
1597 j.alex 1.1.2.4                                 //
1598 j.alex 1.1.2.3                                 // Set the client as inactive.
1599 j.alex 1.1.2.4                                 //
1600 j.alex 1.1.2.3                                 clientActive[clientID + instanceID] = false;
1601                                            }/* for (int instanceID =0;instanceID<clientInst..*/
1602 j.alex 1.1.2.4                             //
1603 j.alex 1.1.2.3                             // indicate that the client was stopped. 
1604 j.alex 1.1.2.4                             //
1605 j.alex 1.1.2.3                             clientStopped[clientID] = true;
1606                                            // 
1607                                            // If the Client has a Wait time
1608                                            //
1609                                            if (_clientDelays[clientID] !=0)
1610                                            {
1611                                                clientDelayMilliseconds[clientID] = 
1612                                                    nowMilliseconds + _clientDelays[clientID];
1613                                                clientDelayed[clientID] = true;
1614                                            }
1615                                        } /* if (clientStopMilliseconds[clientID]<= nowMilli..*/
1616                                    }  /*  if (!clientStopped[clientID]) */
1617                                    else 
1618                                    {
1619                                        //
1620                                        // Only restart clients that are waiting.
1621                                        //
1622                                        if (clientDelayed[clientID])
1623                                        {
1624 j.alex 1.1.2.4                             //
1625 j.alex 1.1.2.3                             // When waiting period is consumed.
1626 j.alex 1.1.2.4                             //
1627 j.alex 1.1.2.3                             if (clientDelayMilliseconds[clientID]<= 
1628                                                nowMilliseconds)
1629                                            {
1630                                                //
1631                                                //  Restart all the instances of the client.
1632                                                //
1633                                                for (int instanceID =0;
1634                                                    instanceID<clientInstance[clientID];
1635                                                    instanceID++)
1636                                                {
1637                                                    act_command=String::EMPTY;
1638                #ifdef PEGASUS_OS_TYPE_WINDOWS
1639                                                    act_command.append("start ");
1640                #endif
1641                                                    act_command.append(
1642                                                        _clientCommands[clientID].getCString());
1643                                                    act_command.append(" -clientid ");
1644                                                    sprintf(str,"%d",clientID+instanceID); 
1645                                                    act_command.append(str);
1646                                                    act_command.append(" -pidfile ");
1647                                                    act_command.append(" \"");
1648 j.alex 1.1.2.3                                     act_command.append(_stressTestClientPIDFile);
1649                                                    act_command.append("\"");
1650                                                    act_command.append(" -clientlog");
1651                                                    act_command.append(" \"");
1652                                                    act_command.append(_stressTestClientLogFile);
1653                                                    act_command.append("\"");
1654                                                    act_command.append("&");
1655                                                    log_file<<"Restarting client:("<<
1656                                                        clientID+instanceID<<")"<<endl;
1657                                                    outPrintWriter<<"Restarting client:("<<
1658                                                        clientID+instanceID<<")"<<endl;
1659                                                    if (verboseEnabled)
1660                                                    {
1661                                                        outPrintWriter<<"  "<<act_command<<endl;
1662                                                        log_file<<"     ("<<
1663                                                            clientID+instanceID<<
1664                                                            ") \n"<<act_command<<endl;
1665                                                        tmTime = getCurrentActualTime();
1666                                                        strftime(
1667                                                            strTime,
1668                                                            256,
1669 j.alex 1.1.2.3                                             "%d/%m/%Y at %H:%M:%S\n",
1670                                                            &tmTime);
1671                                                        log_file<<"   Restarted on "<<
1672                                                            strTime<<endl;
1673                                                    }
1674                                                    int rc = system(act_command.getCString());
1675                                                    if (rc)
1676                                                    { 
1677                                                        log_file<<"Command failed to Execute."<<
1678                                                            endl;
1679                                                        if (verboseEnabled)
1680                                                        {
1681                                                            outPrintWriter<<act_command<< 
1682                                                                "Command failed to Execute."<<
1683                                                                endl;
1684                                                        }
1685                                                    }
1686                                                    clientActive[clientID+instanceID] = true;
1687                                                } /* for (int instanceID =0;instanceID .. */
1688                                                clientStopMilliseconds[clientID] = 
1689                                                    nowMilliseconds + 
1690 j.alex 1.1.2.3                                     _clientDurations[clientID];
1691                                                clientStopped[clientID] = false;
1692                                                clientDelayed[clientID] = false;
1693                                            }/* if(clientDelayMilliseconds[clientID]<=nowMi.. */
1694                                        } /* if(clientDelayed[clientID]) */
1695                                    } /* else ..*/
1696                                } /* for(Uint32 clientID=0;clientID < _clientCount;clientID++)*/
1697                            } /* else for if(!actual_client) */
1698                            //
1699                            // Get Current time
1700                            //
1701                            nowMilliseconds = TimeValue::getCurrentTime().toMilliseconds();
1702 j.alex 1.1.2.1 
1703 j.alex 1.1.2.3         } /* while(stopMilliseconds > nowMilliseconds) */
1704 j.alex 1.1.2.1     
1705                    }//try
1706                    
1707                    catch (const StressTestControllerException& e)
1708                    {
1709 j.alex 1.1.2.3         errPrintWriter << StressTestControllerCommand::COMMAND_NAME << 
1710                            ": " << e.getMessage () << endl;
1711 j.alex 1.1.2.1         return (RC_ERROR);
1712                    }
1713                
1714                    // 
1715                    //  Stress Tests should be stopped.
1716                    //
1717                    outPrintWriter<<"Ending tests::Preparing to stop all the clients."<<endl;
1718                    log_file<<"Ending tests::Preparing to stop all the clients."<<endl;
1719                
1720                    // Waiting to allow any clients that might have been re-started 
1721                    // just before the tests were ended to add 
1722                    // its pid to the pid file.
1723                
1724 j.alex 1.1.2.3 #ifndef PEGASUS_OS_TYPE_WINDOWS
1725 j.alex 1.1.2.1     sleep(STOP_DELAY); 
1726                #else
1727                    Sleep(STOP_DELAY * 1000);
1728                #endif
1729                
1730                    //
1731                    // get all the clientPIDs before it is stopped.
1732                    //
1733 j.alex 1.1.2.3     int rc = _getClientPIDs(actual_client,log_file);
1734                    if (!rc)
1735 j.alex 1.1.2.1     {
1736 j.alex 1.1.2.3         outPrintWriter<<"Failed to communicate with clients."<<endl;
1737                        log_file<<StressTestControllerCommand::COMMAND_NAME<<
1738                            "::Failed to communicate with clients. "<<endl;
1739                        log_file<<"                    ::Failed to get client PID & status. "<<
1740                            endl;
1741                        TestFailed = true;
1742 j.alex 1.1.2.1     }
1743                    tmTime = getCurrentActualTime();
1744                    strftime(strTime,256,"%d/%m/%Y at %H:%M:%S\n",&tmTime);
1745                    log_file<<"Ending tests:: Stopping all the clients on "<<strTime <<endl;
1746 j.alex 1.1.2.3     for (int i=0;i<actual_client;i++)
1747 j.alex 1.1.2.1     {
1748 j.alex 1.1.2.3         if(verboseEnabled)
1749                        {
1750                            outPrintWriter<<"Stopping Client("<<i<<") with PID:"<<
1751                                clientPIDs[i]<<endl;
1752                        }
1753                        log_file<<"Stopping Client("<<i<<") with PID:"<<clientPIDs[i]<<endl;
1754 j.alex 1.1.2.4         //
1755 j.alex 1.1.2.3         // Required for Windows
1756 j.alex 1.1.2.4         //
1757 j.alex 1.1.2.3         String stopClientFile = String::EMPTY; 
1758                        stopClientFile.append(pegasusHome);
1759                        stopClientFile.append(DEFAULT_TMPDIR);
1760                        stopClientFile.append("STOP_");
1761                        sprintf(str,"%d",clientPIDs[i]); 
1762                        stopClientFile.append(str);
1763                        ofstream stop_file(stopClientFile.getCString(),ios::out);
1764                        stop_file << "Stop Client PID : "<<clientPIDs[i]<<endl;
1765                        stop_file.close();
1766                #ifndef PEGASUS_OS_TYPE_WINDOWS
1767                        // Another way to stop the client
1768                        int rc = 0;
1769                        rc = kill(clientPIDs[i], SIGINT);
1770                        if (rc)
1771                        {
1772                           if (verboseEnabled)
1773                           {
1774                               outPrintWriter<<"Failed to stop client:("<<i<<")"<<endl;
1775                           }
1776                           log_file<<"Failed to stop client:("<<i<<")"<<endl;
1777                        }
1778 j.alex 1.1.2.1 #endif
1779                    }
1780 j.alex 1.1.2.3     if (verboseEnabled)
1781                    {
1782 j.alex 1.1.2.1       outPrintWriter<<"Cleaning all resources"<<endl;
1783 j.alex 1.1.2.3     }
1784 j.alex 1.1.2.1     log_file<<"Cleaning all resources."<<endl;
1785                    cleanupProcess();
1786                    
1787 j.alex 1.1.2.2     //
1788                    // Waiting to allow clients to shutdown 
1789                    //
1790 j.alex 1.1.2.3 #ifndef PEGASUS_OS_TYPE_WINDOWS
1791 j.alex 1.1.2.2     sleep(SHUTDOWN_DELAY); 
1792                #else
1793                    Sleep(SHUTDOWN_DELAY * 1000);
1794                #endif
1795 j.alex 1.1.2.1     // 
1796                    // If the test did not run to completition
1797                    //
1798 j.alex 1.1.2.3     if (TestFailed)
1799                        return(RC_ERROR);
1800 j.alex 1.1.2.1 
1801                    return (RC_SUCCESS);
1802                } /* execute */
1803                
1804                
1805                /*
1806 j.alex 1.1.2.3     Retrieves the contents of the config file if specified or uses default 
1807                    values from either the default config file
1808 j.alex 1.1.2.1 
1809                    @param   fileName           The specified or default config file for the
1810                                                tests. 
1811                    @param   log_file           The log file.
1812                
1813                    @return  true               if the file was read successfully
1814                             false              if file was not read successfully.
1815                
1816                 */
1817 j.alex 1.1.2.3 Boolean StressTestControllerCommand::getFileContent(
1818                    String fileName,
1819                    ostream& log_file)
1820 j.alex 1.1.2.1 {
1821 j.alex 1.1.2.3     String configData = String::EMPTY;
1822 j.alex 1.1.2.1     String line;
1823 j.alex 1.1.2.3     int lineNumber = 0;
1824                    Boolean isSuccess = true;
1825                    String name = String::EMPTY;
1826                    String value = String::EMPTY;
1827                    String ErrReports = String::EMPTY;
1828 j.alex 1.1.2.1 
1829 j.alex 1.1.2.3     ifstream ifs;
1830 j.alex 1.1.2.1 
1831                    //
1832                    // Open the config file and read the stress test configuration data
1833                    //
1834                    Open(ifs,fileName);
1835                    if (!ifs)
1836                    {
1837 j.alex 1.1.2.3         log_file<<StressTestControllerCommand::COMMAND_NAME<<
1838                            "::Cannot read config file: "<<fileName<<endl;
1839                        throw NoSuchFile(fileName);
1840 j.alex 1.1.2.1     }
1841                
1842 j.alex 1.1.2.3     log_file<<StressTestControllerCommand::COMMAND_NAME <<
1843                        "::Storing client details. "<<endl;
1844                    if (verboseEnabled)
1845                    {
1846                        cout<<StressTestControllerCommand::COMMAND_NAME<<
1847                            "::Storing config details. "<<endl;
1848                    }
1849 j.alex 1.1.2.1     //
1850                    // Get each line of the file.
1851                    //
1852                    while (GetLine(ifs, line))
1853                    {
1854                        ++lineNumber;
1855                        IsAClient = false;
1856                        name = String::EMPTY;
1857                        value = String::EMPTY;
1858 j.alex 1.1.2.3         try 
1859                        {
1860                            //
1861                            // Parse each line of Config file
1862                            //
1863                            _parseLine(line,lineNumber,name,value,log_file);
1864 j.alex 1.1.2.1         } 
1865                        //
1866                        // catch all the exceptions if any thrown from parseLine
1867                        //   - Accumulate all the errors from the config file   
1868                        //   - Report all errors if found when complete.   
1869                        //
1870 j.alex 1.1.2.3         catch (Exception& e)
1871 j.alex 1.1.2.1         {
1872                            char line_num[10];
1873                            sprintf(line_num, "%d", lineNumber);
1874                            String msg(e.getMessage());
1875                            ErrReports.append("\n    ");
1876                            ErrReports.append("line#");
1877                            ErrReports.append(line_num);
1878                            ErrReports.append(":: ");
1879                            ErrReports.append(msg.getCString());
1880 j.alex 1.1.2.3             log_file<<StressTestControllerCommand::COMMAND_NAME<<"::"
1881                                <<msg<<endl;
1882 j.alex 1.1.2.1             isSuccess = false;
1883                        }
1884                        catch(...)
1885                        {
1886 j.alex 1.1.2.3             char line_num[10];
1887                            sprintf(line_num, "%d", lineNumber);
1888                            ErrReports.append("\n    ");
1889                            ErrReports.append("line#");
1890                            ErrReports.append(line_num);
1891                            ErrReports.append(":: ");
1892                            ErrReports.append("Unknown exception caught.");
1893                            log_file<<StressTestControllerCommand::COMMAND_NAME<<
1894                                ":Unknown exception caught when parsing line."<<endl;
1895                            cerr<<StressTestControllerCommand::COMMAND_NAME <<
1896                               ":Unknown exception caught when parsing line."<<endl;
1897                            return false; 
1898 j.alex 1.1.2.1         }
1899                
1900 j.alex 1.1.2.3         if ((IsClientOptions)||(IgnoreLine))
1901 j.alex 1.1.2.1         {
1902                            IsClientOptions = false;
1903                            IgnoreLine = false;
1904                            continue;
1905                        }
1906                        //
1907                        // If its a client Update the table
1908                        //
1909 j.alex 1.1.2.3         if (IsAClient)
1910 j.alex 1.1.2.1         {
1911 j.alex 1.1.2.3             _currClient=name;
1912                            _currClientCount=_clientCount;
1913 j.alex 1.1.2.4             //
1914 j.alex 1.1.2.3             // save the client details in a table
1915 j.alex 1.1.2.4             //
1916 j.alex 1.1.2.3             if (!_storeClientDetails(name,value))
1917                            {
1918                                log_file<<StressTestControllerCommand::COMMAND_NAME<<
1919                                    "::Syntax error found in line#"<<lineNumber<<
1920                                    " of config file: "<<fileName<<endl;
1921                                isSuccess = false;
1922                            }
1923 j.alex 1.1.2.1         } 
1924                        else 
1925                        { 
1926                            //
1927                            // Common properties are updated only if they are valid.
1928                            //
1929 j.alex 1.1.2.3             if (isSuccess)
1930 j.alex 1.1.2.1             {  
1931 j.alex 1.1.2.3                 //
1932                                // Store the property name and value in the table
1933                                //
1934                                if (verboseEnabled)
1935                                {
1936                                    cout<<"     "<<name<<"\t= "<<value<<endl;
1937                                }
1938                                if (!_propertyTable->insert(name, value))
1939                                {
1940                                    //
1941                                    // Duplicate property, ignore the new property value.
1942                                    //
1943 j.alex 1.1.2.1 #ifdef DEBUG
1944 j.alex 1.1.2.3                     cout<< "Property Name:duplicate name already saved: "<<
1945                                        name<<endl;
1946 j.alex 1.1.2.1 #endif
1947 j.alex 1.1.2.3                     log_file<<StressTestControllerCommand::COMMAND_NAME<<
1948                                        "::Duplicate property name "<<name<<" already saved."<<
1949                                        endl;
1950                                }
1951                            }
1952                        }
1953 j.alex 1.1.2.1 
1954                    }
1955                    ifs.close();
1956                    //
1957                    // If a client is not read from the config file 
1958                    //
1959 j.alex 1.1.2.3     if ((lineNumber==0)||(!_clientCount))
1960 j.alex 1.1.2.1     {
1961 j.alex 1.1.2.3         ErrReports.append("\n    ");
1962                        ErrReports.append(StressTestControllerCommand::COMMAND_NAME);
1963                        ErrReports.append("::No clients found.");
1964                        log_file<<StressTestControllerCommand::COMMAND_NAME <<
1965                            "::No clients found in"<<" config file: "<<fileName<<endl;
1966                        isSuccess = false;
1967 j.alex 1.1.2.1     }
1968                    //
1969                    // Error was found.
1970                    //
1971 j.alex 1.1.2.3     if (!isSuccess)
1972 j.alex 1.1.2.1     {
1973                       // 
1974                       // cleanup allocated memory
1975                       //
1976                       cleanupProcess();
1977                       throw StressTestControllerException(ErrReports); 
1978                    }
1979                
1980 j.alex 1.1.2.3     log_file<<StressTestControllerCommand::COMMAND_NAME<<
1981                        "::Common Properties:"<<endl;
1982                    if (verboseEnabled)
1983                    {
1984                        cout<<StressTestControllerCommand::COMMAND_NAME<<
1985                            "::Common Properties:"<<endl;
1986                    }
1987 j.alex 1.1.2.1     for (Table::Iterator i = _propertyTable->start(); i; i++)
1988                    {
1989 j.alex 1.1.2.3         log_file<<"      "<<i.key()<<"\t= "<<i.value()<<endl;
1990                        if (verboseEnabled)
1991                        {
1992                            cout<<"      "<<i.key()<<"\t= "<<i.value()<<endl;
1993                        }
1994 j.alex 1.1.2.1     }
1995 j.alex 1.1.2.3     if (verboseEnabled)
1996 j.alex 1.1.2.1     {
1997 j.alex 1.1.2.3         cout<<"Total clients found:"<<_clientCount<<endl;
1998                        cout<<"CLIENT TABLE CONTENTS:"<<endl;
1999 j.alex 1.1.2.1     }
2000 j.alex 1.1.2.3     log_file<<StressTestControllerCommand::COMMAND_NAME<<
2001                        "::Client Properties:"<<endl;
2002                    for (Uint32 j = 0; j < _clientCount; j++)
2003 j.alex 1.1.2.1     {
2004 j.alex 1.1.2.3         log_file<<"Client information #"<<j+1<<" from config file:"<<endl;
2005                        if (verboseEnabled)
2006                        {
2007                            cout<<"Client("<<j<<")"<<endl;
2008                        }
2009                        for (Table::Iterator i = _clientTable[j].start(); i; i++)
2010                        {
2011                            log_file<<"    "<<i.key()<<"    = "<<i.value()<<endl;
2012                            if (verboseEnabled)
2013                            {
2014                                cout<<"   "<< i.key() << "=" << i.value() << endl;
2015                            }
2016                        }
2017 j.alex 1.1.2.1     }
2018                   
2019                    
2020 j.alex 1.1.2.3     if (isSuccess)
2021                    {
2022                       log_file<<StressTestControllerCommand::COMMAND_NAME<<
2023                           "::Successfully retreived config values from" <<
2024                           " config file: "<<fileName<<endl;
2025                    }
2026 j.alex 1.1.2.1     return isSuccess;
2027                }/* getFileContent */
2028                
2029                  
2030                /*
2031                    Validates the configuration data found in the specified config file or 
2032                    the default config file.
2033                    Will validate known common/client specific properties in configuration.
2034                    Will validate valid client names. 
2035                      (Clients are excepted to  exist in the $PEGASUS_HOME/bin directory)
2036                
2037                    @param   vars               The property name to be validated
2038                    @param   value              The property value associated to the above name
2039                
2040                    @return  true               if the property was validated successfully
2041                             false              if the property failed validation.
2042                
2043                 */
2044                
2045                
2046 j.alex 1.1.2.3 Boolean StressTestControllerCommand::_validateConfiguration(
2047                    String & vars,
2048                    const String & value,
2049                    ostream& log_file)
2050 j.alex 1.1.2.1 {
2051                    Boolean IsValid = false;
2052                
2053                  
2054                    if (String::equalNoCase(vars,HOSTNAME))
2055                    {
2056                        vars=String::EMPTY;
2057                        vars.append(HOSTNAME);
2058                        if(!IsAClient)
2059                        {
2060 j.alex 1.1.2.3             if (!_hostNameSpecified)
2061                            {
2062                                _hostName = value;
2063                            }
2064 j.alex 1.1.2.1         } 
2065                        else
2066                        {
2067                             
2068 j.alex 1.1.2.3             if(_hostName != String::EMPTY)
2069                            {
2070                                if (!String::equalNoCase(value,_hostName))
2071                                {
2072                                    log_file<<StressTestControllerCommand::COMMAND_NAME<<
2073                                        "::Multiple hostnames were found. "<<endl;
2074                                    if (verboseEnabled)
2075                                    {
2076                                        cout<<StressTestControllerCommand::COMMAND_NAME <<
2077                                            "::Multiple hostnames were found. "<<endl;
2078                                    }
2079                                    return false;
2080                                }
2081                            }
2082                            else
2083                            { 
2084                                _hostName = value;
2085                            }
2086 j.alex 1.1.2.1         }
2087                    }
2088                    else if (String::equalNoCase(vars,PORTNUMBER))
2089                    {
2090                        vars=String::EMPTY;
2091                        vars.append(PORTNUMBER);
2092                        Uint32 vPortNumber = atoi(value.getCString());
2093                        
2094 j.alex 1.1.2.3         log_file<<StressTestControllerCommand::COMMAND_NAME <<
2095                            "::Portnumber  specified in config = "<<vPortNumber<<endl;
2096                        if (verboseEnabled)
2097                        {
2098                            cout<<StressTestControllerCommand::COMMAND_NAME <<
2099                                "::Portnumber  specified in config = "<<vPortNumber<<endl;
2100                        }
2101 j.alex 1.1.2.1         if (vPortNumber > _MAX_PORTNUMBER)
2102                        {
2103 j.alex 1.1.2.3             //
2104                            //  Portnumber out of valid range
2105                            //
2106                            if (verboseEnabled)
2107                            {
2108                                cout<<StressTestControllerCommand::COMMAND_NAME <<
2109                                    "::Invalid portnumber  was found. "<<endl;
2110                            }
2111                            log_file<<StressTestControllerCommand::COMMAND_NAME<<
2112                                "::Invalid portnumber  was found. "<<endl;
2113                            return false;
2114                        }
2115                        if (!_portNumberSpecified)
2116                        {
2117                            _portNumber = atoi(value.getCString());
2118 j.alex 1.1.2.1         }
2119                
2120 j.alex 1.1.2.3     }/* else if (String::equalNoCase ... */
2121 j.alex 1.1.2.1     else if (String::equalNoCase(vars,SSL))
2122                    {
2123 j.alex 1.1.2.3         log_file<<StressTestControllerCommand::COMMAND_NAME<<
2124                            "::SSL enabled in config. "<<endl;
2125                        if (!_useSSL)
2126 j.alex 1.1.2.1         {
2127 j.alex 1.1.2.3             _useSSL = true;
2128 j.alex 1.1.2.1         }
2129                    }
2130                    else if (String::equalNoCase(vars,USERNAME))
2131                    {
2132                        vars=String::EMPTY;
2133                        vars.append(USERNAME);
2134 j.alex 1.1.2.3         log_file<<StressTestControllerCommand::COMMAND_NAME<<
2135                            "::UserName  specified in config = "<<value<<endl;
2136                        if (!_userNameSpecified)
2137 j.alex 1.1.2.1         {
2138                           _userName = value;
2139                        }
2140                    }
2141                    else if (String::equalNoCase(vars,PASSWORD))
2142                    {
2143                        vars=String::EMPTY;
2144                        vars.append(PASSWORD);
2145                        if(!_passwordSpecified)
2146                        {
2147 j.alex 1.1.2.3             _password = value;
2148 j.alex 1.1.2.1         }
2149 j.alex 1.1.2.3         log_file<<StressTestControllerCommand::COMMAND_NAME<<
2150                            "::Password  specified in config = "<<value<<endl;
2151 j.alex 1.1.2.1     }
2152                    else if (String::equalNoCase(vars,DURATION))
2153                    {
2154                        vars=String::EMPTY;
2155                        vars.append(DURATION);
2156 j.alex 1.1.2.4         //
2157 j.alex 1.1.2.1         // converting to a double
2158 j.alex 1.1.2.4         //
2159 j.alex 1.1.2.3         if (!IsAClient)
2160 j.alex 1.1.2.1         {
2161 j.alex 1.1.2.3             _duration = atof(value.getCString());
2162                            if (_duration > _MIN_DURATION)
2163                            {
2164                                log_file<<StressTestControllerCommand::COMMAND_NAME<<
2165                                    "::Duration  specified in config = "<<value<<endl;
2166                            } 
2167                            else
2168                            {
2169                                log_file<<StressTestControllerCommand::COMMAND_NAME<<
2170                                    "::Invalid Duration  was specified. "<<endl;
2171                                return false;
2172                            }
2173 j.alex 1.1.2.1         }
2174                    }
2175                    else if (String::equalNoCase(vars,TOLERANCELEVEL))
2176                    {
2177                        _toleranceLevel =  atoi(value.getCString());
2178 j.alex 1.1.2.3         log_file<<StressTestControllerCommand::COMMAND_NAME<<
2179                            "::ToleranceLevel  specified in config = "<<value<<endl;
2180                        if (_toleranceLevel > _MAX_TOLERANCE) 
2181 j.alex 1.1.2.1         {
2182 j.alex 1.1.2.3             if(verboseEnabled)
2183                            {
2184                                cout<<StressTestControllerCommand::COMMAND_NAME <<
2185                                    "::Invalid Tolerance level  was specified. "<<endl;
2186                            }
2187                            log_file<<StressTestControllerCommand::COMMAND_NAME<<
2188                                "::Invalid Tolerance level  was specified. "<<endl;
2189 j.alex 1.1.2.1 
2190 j.alex 1.1.2.3             return false;
2191 j.alex 1.1.2.1         }
2192                    }
2193                    else if (String::equalNoCase(vars,NAMESPACE))
2194                    {
2195                        _nameSpace = value;
2196 j.alex 1.1.2.3         log_file<<StressTestControllerCommand::COMMAND_NAME <<
2197                            "::NameSpace  specified in config = "<<value<<endl;
2198 j.alex 1.1.2.1     }
2199                    else if (String::equalNoCase(vars,CLASSNAME))
2200                    {
2201                        _className = value;
2202 j.alex 1.1.2.3         log_file<<StressTestControllerCommand::COMMAND_NAME<<
2203                            "::Class name  specified in config = "<<value<<endl;
2204 j.alex 1.1.2.1     }
2205                    else
2206                    { 
2207 j.alex 1.1.2.3        if (!IsAClient)
2208 j.alex 1.1.2.1        {
2209                           IsAClient=true;
2210                           int instance = atoi(value.getCString());
2211                           //
2212                           // Check if the instances are set correctly
2213                           // Must be greater than 0 
2214                           //
2215 j.alex 1.1.2.3            if (instance <=0)
2216 j.alex 1.1.2.1            {
2217 j.alex 1.1.2.4               //
2218 j.alex 1.1.2.1               // Invalid Instance value 
2219 j.alex 1.1.2.4               //
2220 j.alex 1.1.2.1               return false;
2221                           }
2222                           //
2223                           // Check if client exists or is valid.
2224                           // Clients are expected to be in the $PEGASUS_HOME/bin directory
2225                           //
2226                           String clientName = String(DEFAULT_BINDIR);
2227                           clientName.append(vars.getCString());
2228 j.alex 1.1.2.3 #ifdef PEGASUS_OS_TYPE_WINDOWS
2229 j.alex 1.1.2.1            clientName.append(".exe");
2230                #endif
2231                           if (!FileSystem::exists(clientName))
2232                           {
2233                               String testString = String::EMPTY;
2234                               testString.append("Test");
2235                               Uint32 Index = vars.find(testString);
2236 j.alex 1.1.2.3                if (Index != 0)
2237 j.alex 1.1.2.1                {
2238                                   clientName = String(DEFAULT_BINDIR);
2239                                   testString.append(vars.getCString());
2240                                   clientName.append(testString.getCString());
2241 j.alex 1.1.2.3 #ifdef PEGASUS_OS_TYPE_WINDOWS
2242 j.alex 1.1.2.1                    clientName.append(".exe");
2243                #endif
2244                                   if (!FileSystem::exists(clientName))
2245                                   {
2246 j.alex 1.1.2.4                        //
2247 j.alex 1.1.2.3                        // Invalid client name
2248 j.alex 1.1.2.4                        //
2249 j.alex 1.1.2.3                        IsValid = false; 
2250 j.alex 1.1.2.1                    }
2251                                   else 
2252                                   {
2253 j.alex 1.1.2.3                        IsValid = true; 
2254                                       vars=String::EMPTY;
2255                                       vars.append(testString.getCString());
2256                                   }
2257                               }
2258                               else
2259                               {
2260                               
2261 j.alex 1.1.2.4                    //
2262 j.alex 1.1.2.3                    // Invalid client name
2263 j.alex 1.1.2.4                    //
2264 j.alex 1.1.2.3                    IsValid = false;
2265                               } 
2266 j.alex 1.1.2.1            } 
2267                           else 
2268                           {
2269 j.alex 1.1.2.3                IsValid = true;
2270 j.alex 1.1.2.1            }
2271 j.alex 1.1.2.3            if (!IsValid)
2272 j.alex 1.1.2.1            {
2273 j.alex 1.1.2.3               if (verboseEnabled)
2274 j.alex 1.1.2.1               {
2275 j.alex 1.1.2.3                   cout<<StressTestControllerCommand::COMMAND_NAME <<
2276                                      "::Invalid Client Name = "<<vars<<endl;
2277 j.alex 1.1.2.1               }
2278                              String ErrReport = String("Invalid Client Name:");
2279                              ErrReport.append(vars.getCString());
2280                              throw StressTestControllerException(ErrReport); 
2281                           }
2282                           return IsValid;
2283                       }
2284 j.alex 1.1.2.3         log_file<<StressTestControllerCommand::COMMAND_NAME<<"::"<<vars<<
2285                            " = "<<value<<endl;
2286                       //
2287                       // otherwise accept the properties listed with the clients.
2288                       //
2289 j.alex 1.1.2.1     }
2290                    return true;
2291                
2292 j.alex 1.1.2.3 } /* _validateConfiguration */
2293 j.alex 1.1.2.1 
2294                /*
2295                    Retrieves the client specific options from the config file.
2296                    Will check for syntax errors with the client options.
2297                    - Will retrieve all the client options in the line until ']'
2298                    - Client options/properties in Config file are 
2299                      represented as follows:
2300                         -   "[" indicates start of client options. 
2301                         -   "]" indicates end of client options. 
2302                         -   Client properties and values are seperated by commas.
2303                         Example:
2304                              [clientName=CLI,Options=niall]
2305                    - This method will throw appropriate exceptions.
2306                
2307                    @param   p               The pointer to the char in the concerned line
2308                
2309                
2310                 */
2311 j.alex 1.1.2.3 void StressTestControllerCommand::_getClientOptions(
2312                    const Char16* p,
2313                    ostream& log_file)
2314 j.alex 1.1.2.1 {
2315 j.alex 1.1.2.3     //
2316                    // Get the property name
2317                    //
2318                    String name = String::EMPTY;
2319                    String value = String::EMPTY;
2320 j.alex 1.1.2.1 
2321 j.alex 1.1.2.3     while (*p != ']')
2322                    { 
2323 j.alex 1.1.2.1         //
2324                        // Skip whitespace after property name
2325                        //
2326                        while (*p && isspace(*p))
2327                        {
2328                            p++;
2329                        }
2330                        if (!(isalpha(*p) || *p == '_'))
2331                        {
2332 j.alex 1.1.2.3             throw StressTestControllerException(StressTestControllerException::INVALID_OPTION); 
2333 j.alex 1.1.2.1         }
2334                
2335                        name.append(*p++);
2336                
2337                
2338                        while (isalnum(*p) || *p == '_')
2339                        {
2340                            name.append(*p++);
2341                        }
2342                
2343                        //
2344                        // Skip whitespace after property name
2345                        //
2346                        while (*p && isspace(*p))
2347                        {
2348                            p++;
2349                        }
2350                     
2351                        //
2352                        // Expect an equal sign
2353                        //
2354 j.alex 1.1.2.1         if (*p != '=')
2355                        {
2356 j.alex 1.1.2.3             throw StressTestControllerException(StressTestControllerException::INVALID_OPERATOR); 
2357 j.alex 1.1.2.1         }
2358                
2359                        p++;
2360                
2361                        //
2362                        // Skip whitespace after equal sign
2363                        //
2364                        while (*p && isspace(*p))
2365                        {
2366                            p++;
2367                        }
2368                
2369                        //
2370                        // Get the value
2371                        //
2372                
2373                        while (*p && *p != ']' && *p != ',')
2374 j.alex 1.1.2.3         {
2375 j.alex 1.1.2.1             value.append(*p++);
2376 j.alex 1.1.2.3         }
2377 j.alex 1.1.2.1         //
2378                        // Skip whitespace after value 
2379                        //
2380                        while (*p && isspace(*p))
2381                        {
2382                            cout << "got space after value\n";
2383                            p++;
2384                        }
2385                
2386                        if(*p !=']' && *p != ',')
2387                        {
2388 j.alex 1.1.2.3             throw StressTestControllerException(StressTestControllerException::MISSING_BRACE); 
2389 j.alex 1.1.2.1         }
2390                        if(value == String::EMPTY)
2391                        {
2392 j.alex 1.1.2.3             throw StressTestControllerException(StressTestControllerException::MISSING_VALUE); 
2393 j.alex 1.1.2.1         }
2394                           
2395                #ifdef DEBUG
2396 j.alex 1.1.2.3         cout<<"name="<<name<<endl;
2397                        cout<<"Before validate config: value="<<value<<endl;
2398 j.alex 1.1.2.1 #endif
2399                        //
2400                        // validate client property
2401                        // 
2402 j.alex 1.1.2.3         Boolean IsValid=_validateConfiguration(name,value,log_file);
2403 j.alex 1.1.2.1         if(!IsValid)
2404                        {
2405 j.alex 1.1.2.3             String ErrReport = String("Invalid Client property value: ");
2406                            ErrReport.append(name);
2407                            ErrReport.append("=");
2408                            ErrReport.append(value);
2409                            throw StressTestControllerException(ErrReport); 
2410 j.alex 1.1.2.1         }
2411                        //
2412                        // Save client property in client table if valid.
2413                        //
2414                        if (!_clientTable[_currClientCount].insert(name,value))
2415                        {
2416                            //
2417                            // Duplicate property, ignore the new property value.
2418                            // Log this message in a log file.
2419                            //
2420                           log_file<< "duplicate name already saved: "<<name<<endl;
2421 j.alex 1.1.2.3            if (verboseEnabled)
2422                           {
2423 j.alex 1.1.2.1               cout<< "duplicate name already saved: "<<name<<endl;
2424 j.alex 1.1.2.3            }
2425 j.alex 1.1.2.1         }
2426 j.alex 1.1.2.3         if (*p ==',')
2427 j.alex 1.1.2.1         {
2428                            name = String::EMPTY;
2429                            value = String::EMPTY;
2430                            p++;
2431                            continue;
2432                        }
2433 j.alex 1.1.2.3     }
2434 j.alex 1.1.2.1      
2435 j.alex 1.1.2.3     if ((name == String::EMPTY)||(value == String::EMPTY))
2436                    { 
2437 j.alex 1.1.2.1         String ErrReport = String("Missing Name & Value for client option:");
2438                        throw StressTestControllerException(ErrReport); 
2439 j.alex 1.1.2.3     }
2440                } /* _getClientOptions */
2441 j.alex 1.1.2.1 
2442                
2443                /*
2444                    Retrieves the Client PIDs and the corresponding status of the 
2445                    clients started by the Controller from the PID file.                     
2446                    Each line in the PID file if not a comment is expected to
2447                    have the following format:
2448                       <clientid>::<client_pid>::<client_status>::<timeStampInMillisec>
2449                    Example:
2450                         1::7582::0::4119329327
2451                
2452                    Client PID, status and Time Stamp from the PID file will be saved
2453                    in the following global array's for each client.  
2454                      clientPIDs
2455                      clientStatus
2456                      clientTimeStamp
2457                      
2458                 
2459                    @param   actual_clients  The actual number of clients executed by the 
2460                                             Controller.
2461                    @param   log_file        The log file.
2462 j.alex 1.1.2.1 
2463                    @return  true            if the status and PIDs were read successfully
2464                             false           Failed to read the status & PIDs of clients.
2465                
2466                 */
2467 j.alex 1.1.2.3 Boolean StressTestControllerCommand::_getClientPIDs(
2468                    int actual_clients,
2469                    ostream& log_file)
2470 j.alex 1.1.2.1 {
2471                
2472                    ifstream ifs;
2473                
2474                    //
2475                    // Make a temp copy of the file
2476                    //
2477 j.alex 1.1.2.3     Boolean cTempFile = FileSystem::copyFile(
2478                        _stressTestClientPIDFile,
2479                        _tmpStressTestClientPIDFile);
2480 j.alex 1.1.2.1 
2481                    if(!cTempFile)
2482                    {
2483 j.alex 1.1.2.3         cout<<"Cannot copy file "<<_stressTestClientPIDFile<<endl;
2484                        log_file<<StressTestControllerCommand::COMMAND_NAME<<
2485                            "::Cannot copy PID file: "<<_stressTestClientPIDFile<<endl;
2486                        return (false);
2487 j.alex 1.1.2.1     }
2488                    //
2489                    // Open the temp PID file and retreive all the client PIDs and status
2490                    //
2491 j.alex 1.1.2.3     Open(ifs,_tmpStressTestClientPIDFile);
2492 j.alex 1.1.2.1 
2493                    String line;
2494                
2495                    const Char16* p;
2496                    int lineNumber= 0;
2497                    Boolean isSuccess=false;
2498                    //
2499                    // get each line until end of file.
2500                    //
2501                    while (GetLine(ifs, line))
2502                    {
2503                        ++lineNumber;
2504                #ifdef DEBUG
2505                        log_file<<" Line number:"<<lineNumber<<endl;
2506                        log_file<<"      "<<line<<endl;
2507                #endif
2508                        p = line.getChar16Data();
2509                
2510 j.alex 1.1.2.3         while (*p && isspace(*p))
2511                        {
2512                            p++;
2513                        }
2514                
2515 j.alex 1.1.2.1         //
2516                        // Skip comment lines
2517                        //
2518 j.alex 1.1.2.3         if ((!*p)||(*p == '#'))
2519                        {
2520                            continue;
2521                        }
2522 j.alex 1.1.2.1 
2523 j.alex 1.1.2.4         //
2524 j.alex 1.1.2.1         // Get the client ID
2525 j.alex 1.1.2.4         //
2526 j.alex 1.1.2.1         String client = String::EMPTY;
2527 j.alex 1.1.2.3         while (isalnum(*p) || *p == '_')
2528                        {
2529                            client.append(*p++);
2530                        }
2531 j.alex 1.1.2.1 
2532 j.alex 1.1.2.4         //
2533 j.alex 1.1.2.1         // Skip whitespace after property name
2534 j.alex 1.1.2.4         //
2535 j.alex 1.1.2.3         while (*p && isspace(*p))
2536                        {
2537                            p++;
2538                        }
2539 j.alex 1.1.2.1 
2540 j.alex 1.1.2.4         //
2541 j.alex 1.1.2.1         // Expecting a colon 
2542 j.alex 1.1.2.4         //
2543 j.alex 1.1.2.1         if (*p != ':')
2544                        {
2545                            ifs.close();
2546 j.alex 1.1.2.3             log_file<<StressTestControllerCommand::COMMAND_NAME<<
2547                                "::Syntax Error in PID file line number:"<<lineNumber<<endl;
2548                            FileSystem::removeFile(_tmpStressTestClientPIDFile);
2549 j.alex 1.1.2.1             return(isSuccess = false);
2550                        }
2551                
2552                        //
2553                        // point to next character in line.
2554                        //
2555                        p++;
2556                
2557 j.alex 1.1.2.4         //
2558 j.alex 1.1.2.1         // Expecting a colon 
2559 j.alex 1.1.2.4         //
2560 j.alex 1.1.2.1         if (*p != ':')
2561                        {
2562                            ifs.close();
2563 j.alex 1.1.2.3             log_file<<StressTestControllerCommand::COMMAND_NAME<<
2564                                "::Syntax Error in PID file line number:"<<lineNumber<<endl;
2565                            FileSystem::removeFile(_tmpStressTestClientPIDFile);
2566 j.alex 1.1.2.1             return(isSuccess = false);
2567                        }
2568                        
2569                        //
2570                        // point to next character in line.
2571                        //
2572                        p++;
2573                
2574                        //
2575                        // Skip whitespace after colon 
2576                        //
2577 j.alex 1.1.2.3         while (*p && isspace(*p))
2578                        {
2579                            p++;
2580                        }
2581 j.alex 1.1.2.1 
2582 j.alex 1.1.2.4         //
2583 j.alex 1.1.2.1         // Get the client PID 
2584 j.alex 1.1.2.4         //
2585 j.alex 1.1.2.1         String clntPID = String::EMPTY;
2586 j.alex 1.1.2.3         while (isalnum(*p) || *p == '_')
2587                        {
2588                            clntPID.append(*p++);
2589                        }
2590                        
2591 j.alex 1.1.2.4         //
2592 j.alex 1.1.2.1         // Skip whitespace after property name
2593 j.alex 1.1.2.4         //
2594 j.alex 1.1.2.3         while (*p && isspace(*p))
2595                        {
2596                            p++;
2597                        }
2598 j.alex 1.1.2.1 
2599                        //
2600                        // Expecting a colon 
2601                        //
2602                        if (*p != ':')
2603                        {
2604                            ifs.close();
2605 j.alex 1.1.2.3             log_file<<StressTestControllerCommand::COMMAND_NAME <<
2606                                "::Syntax Error in PID file line number:"<<lineNumber<<endl;
2607                            FileSystem::removeFile(_tmpStressTestClientPIDFile);
2608 j.alex 1.1.2.1             return(isSuccess = false);
2609                        }
2610                
2611                        //
2612                        // point to next character in line.
2613                        //
2614                        p++;
2615                
2616                        //
2617                        // Expecting a colon 
2618                        //
2619                        if (*p != ':')
2620                        {
2621                            ifs.close();
2622 j.alex 1.1.2.3             log_file<<StressTestControllerCommand::COMMAND_NAME <<
2623                                "::Syntax Error in PID file line number:"<<lineNumber<<endl;
2624                            FileSystem::removeFile(_tmpStressTestClientPIDFile);
2625 j.alex 1.1.2.1             return(isSuccess = false);
2626                        }
2627                        p++;
2628 j.alex 1.1.2.3 
2629 j.alex 1.1.2.4         //
2630 j.alex 1.1.2.1         // Skip whitespace after the colon if any 
2631 j.alex 1.1.2.4         //
2632 j.alex 1.1.2.3         while (*p && isspace(*p))
2633                        { 
2634                            p++;
2635                        }
2636 j.alex 1.1.2.1 
2637                        String clntStatus = String::EMPTY;
2638 j.alex 1.1.2.3         while (isalnum(*p) || *p == '_')
2639                        {
2640                            clntStatus.append(*p++);
2641                        }
2642 j.alex 1.1.2.1 
2643 j.alex 1.1.2.4         //
2644 j.alex 1.1.2.1         // Skip whitespace after property name
2645 j.alex 1.1.2.4         //
2646 j.alex 1.1.2.3         while (*p && isspace(*p))
2647                        {
2648                            p++;
2649                        }
2650 j.alex 1.1.2.1 
2651                        //
2652                        // Expecting a colon 
2653                        //
2654                        if (*p != ':')
2655                        {
2656                            ifs.close();
2657 j.alex 1.1.2.3             log_file<<StressTestControllerCommand::COMMAND_NAME <<
2658                                "::Syntax Error in PID file line number:"<<lineNumber<<endl;
2659                            FileSystem::removeFile(_tmpStressTestClientPIDFile);
2660 j.alex 1.1.2.1             return(isSuccess = false);
2661                        }
2662                
2663                        //
2664                        // next character in line.
2665                        //
2666                        p++;
2667                
2668                        if (*p != ':')
2669                        {
2670                            ifs.close();
2671 j.alex 1.1.2.3             log_file<<StressTestControllerCommand::COMMAND_NAME<<
2672                                "::Syntax Error in PID file line number:"<<lineNumber<<endl;
2673                            FileSystem::removeFile(_tmpStressTestClientPIDFile);
2674 j.alex 1.1.2.1             return(isSuccess = false);
2675                        }
2676                        //
2677                        // next character in line.
2678                        //
2679                        p++;
2680 j.alex 1.1.2.4         //
2681 j.alex 1.1.2.1         // Skip whitespace after the colon if any 
2682 j.alex 1.1.2.4         //
2683 j.alex 1.1.2.3         while (*p && isspace(*p))
2684                        {
2685                            p++;
2686                        }
2687 j.alex 1.1.2.1 
2688 j.alex 1.1.2.4         //
2689 j.alex 1.1.2.1         // Get the client timestamp 
2690 j.alex 1.1.2.4         //
2691 j.alex 1.1.2.1         String clntTmStmp = String::EMPTY;
2692 j.alex 1.1.2.3         while (isalnum(*p))
2693                        {
2694                            clntTmStmp.append(*p++);
2695                        }
2696 j.alex 1.1.2.1 
2697                        //
2698                        // Store the PID, Status and TimeStamp for each client 
2699                        //
2700                        if(atoi(client.getCString()) <= actual_clients)
2701                        {
2702 j.alex 1.1.2.3             clientPIDs[atoi(client.getCString())] = 
2703                                (pid_t)atoi(clntPID.getCString());
2704                            clientStatus[atoi(client.getCString())] = 
2705                                (pid_t)atoi(clntStatus.getCString());
2706                            sscanf(
2707                                (const char*)clntTmStmp.getCString(),
2708                                "%" PEGASUS_64BIT_CONVERSION_WIDTH "u",
2709                                &clientTimeStamp[atoi(client.getCString())]);
2710                        }
2711                        else
2712                        {
2713                            if (verboseEnabled)
2714 j.alex 1.1.2.1             {
2715 j.alex 1.1.2.3                 log_file<<StressTestControllerCommand::COMMAND_NAME<<
2716                                    "::Unknown client PID for client#"<<
2717                                    atoi(client.getCString())<<
2718                                    " read at line number:"<<lineNumber<<endl;
2719                                cout<<"Unknown Client PID recieved"<<endl;
2720                            }
2721 j.alex 1.1.2.1         }  
2722                    }
2723 j.alex 1.1.2.3     //
2724                    // remove the temporary file.
2725                    //
2726                    FileSystem::removeFile(_tmpStressTestClientPIDFile);
2727                    return(isSuccess = true);
2728                }/* _getClientPIDs */
2729 j.alex 1.1.2.1 
2730                /*
2731                   Parses specified line to retrieve valid config data for the stress tests. 
2732                   - Identifies client specific properties from common properties in config file
2733                   - Saves all the client specific data from the config file into appropriate
2734                     client tables.
2735                   - Saves all the common properties in the property table
2736                   - This method will throw appropriate exceptions.
2737                   Config File Format:
2738                     - All comments begin with "#"
2739                     - Properties in Config file are represented as follows:
2740                          <property> = <property value>
2741                     - Client options/properties in Config file are 
2742                       represented as follows:
2743                         -   "[" indicates start of client options. 
2744                         -   Client properties and values are seperated by commas.
2745                         Example:
2746                              [clientName=CLI,Options=niall]
2747                
2748                    @param   line            The line that will be parsed.
2749                    @parm    lineNumber      The line number of the line.
2750 j.alex 1.1.2.1     @parm    name            The property name that will be retrieved.
2751                    @parm    value           The property value of the name.
2752                    @parm    log_file        The log file.                    
2753                
2754                    @return  true            Succesfully parsed the line.
2755                             false           Failed to parse the lines successfully.     
2756                 */
2757 j.alex 1.1.2.3 Boolean StressTestControllerCommand::_parseLine(
2758                    const String & line,
2759                    int lineNumber,
2760                    String &name,
2761                    String &value,
2762                    ostream& log_file)
2763 j.alex 1.1.2.1 {
2764                
2765                    const Char16* p;
2766                    p = line.getChar16Data();
2767 j.alex 1.1.2.3 
2768 j.alex 1.1.2.1     //
2769                    // Skip whitespace
2770                    //
2771                    while (*p && isspace(*p))
2772                    {
2773                       p++;
2774                    }
2775 j.alex 1.1.2.3 
2776 j.alex 1.1.2.1     // 
2777                    //  Ignore empty lines
2778                    //
2779                    if (!*p)
2780                    {
2781                       IgnoreLine = true;
2782                       return IgnoreLine;
2783                    }
2784 j.alex 1.1.2.3 
2785 j.alex 1.1.2.1     //
2786                    // Skip comment lines
2787                    //
2788                    if (*p == '#')
2789                    {
2790                       IgnoreLine = true;
2791                       return IgnoreLine;
2792                    }
2793 j.alex 1.1.2.3 
2794 j.alex 1.1.2.1     //
2795                    // Retreive all the Client Options 
2796                    //   "[" indicates start of client options.
2797                    //
2798                    if (*p == '[')
2799                    {
2800                       IsAClient = true;
2801                       IsClientOptions = true;
2802                       p++;
2803                       // 
2804                       // Ignore spaces before client property
2805                       //
2806                       while (*p && isspace(*p))
2807                       {
2808                         p++;
2809                       }
2810                       //
2811                       // Invalid Client property name
2812                       //
2813                       if (!(isalpha(*p) || *p == '_'))
2814                       {
2815 j.alex 1.1.2.1             String ErrReport = String("Syntax Error with client options:");
2816                            ErrReport.append(line.getCString());
2817                            throw StressTestControllerException(ErrReport); 
2818                       }
2819                       // 
2820                       // Retrieve client options
2821                       //
2822                       try
2823                       {
2824 j.alex 1.1.2.3            //
2825                           //  get and validate client options 
2826                           //
2827                           _getClientOptions(p,log_file);
2828 j.alex 1.1.2.1        }
2829 j.alex 1.1.2.3        catch (Exception& e)
2830 j.alex 1.1.2.1        {
2831                           String msg(e.getMessage());
2832 j.alex 1.1.2.3            if ((name == String::EMPTY)
2833                              ||(value == String::EMPTY))
2834 j.alex 1.1.2.1            {
2835                               msg.append(" in ");
2836                               msg.append(line.getCString());
2837                           }
2838                           throw StressTestControllerException(msg); 
2839                       }
2840 j.alex 1.1.2.3        catch (...)
2841                       {
2842                           String msg = String(
2843                               "Unknown exception caught when geting client options.");
2844                           log_file<<StressTestControllerCommand::COMMAND_NAME <<
2845                               ":Unknown exception caught when geting client options."<<endl;
2846                           cerr<<StressTestControllerCommand::COMMAND_NAME <<
2847                               ":Unknown exception caught when geting client options."<<endl;
2848 j.alex 1.1.2.1            throw StressTestControllerException(msg); 
2849                        }
2850                
2851 j.alex 1.1.2.3         //
2852                        // Successfully retrieved all the client options.
2853                        //
2854                        return true;
2855 j.alex 1.1.2.1     }
2856 j.alex 1.1.2.3 
2857 j.alex 1.1.2.1     //
2858                    // Get Common Properties 
2859                    //
2860                    name = String::EMPTY;
2861 j.alex 1.1.2.3 
2862 j.alex 1.1.2.1     //
2863                    // Invalid Common Property name
2864                    //
2865                    if (!(isalpha(*p) || *p == '_'))
2866                    {
2867 j.alex 1.1.2.3        String ErrReport = String("Invalid Property Value: ");
2868                       ErrReport.append(name);
2869                       ErrReport.append("=");
2870                       ErrReport.append(value);
2871                       throw StressTestControllerException(ErrReport);
2872 j.alex 1.1.2.1     }
2873 j.alex 1.1.2.3 
2874 j.alex 1.1.2.1     //
2875                    // Save the property Name
2876                    //
2877                    name.append(*p++);
2878                    while (isalnum(*p) || *p == '_')
2879                    {
2880                        name.append(*p++);
2881                    }
2882 j.alex 1.1.2.3 
2883 j.alex 1.1.2.1     //
2884                    // Skip whitespace after property name
2885                    //
2886                    while (*p && isspace(*p))
2887                    {
2888                        p++;
2889                    }
2890 j.alex 1.1.2.3 
2891 j.alex 1.1.2.1     //
2892                    // Expect an equal sign
2893                    //
2894                    if (*p != '=')
2895                    {
2896 j.alex 1.1.2.3        String ErrReport = String("Invalid Property Value: ");
2897                       ErrReport.append(name);
2898                       ErrReport.append("=");
2899                       ErrReport.append(value);
2900                       throw StressTestControllerException(ErrReport);
2901 j.alex 1.1.2.1     }
2902 j.alex 1.1.2.3 
2903 j.alex 1.1.2.1     //
2904                    // go to next
2905                    // 
2906                    p++;
2907                
2908                    //
2909                    // Retrive the property value 
2910                    //   Skip whitespace after equal sign
2911                    //
2912                    while (*p && isspace(*p))
2913                    {
2914                        p++;
2915                    }
2916                
2917                    //
2918                    // Get the value
2919                    //
2920                    value = String::EMPTY;
2921                    while (*p)
2922                    {
2923                        value.append(*p++);
2924 j.alex 1.1.2.1     }
2925                #ifdef DEBUG
2926 j.alex 1.1.2.3     cout<<"name="<<name<<endl;
2927                    cout<<"value="<<value<<endl;
2928 j.alex 1.1.2.1 #endif
2929                    IsAClient = false;
2930                    Boolean IsValid = false;
2931                    // 
2932                    // Validate property and its value
2933                    //
2934                    try
2935                    {
2936 j.alex 1.1.2.3         IsValid=_validateConfiguration(name,value,log_file);
2937 j.alex 1.1.2.1     }
2938 j.alex 1.1.2.3     catch (Exception& e)
2939 j.alex 1.1.2.1     {
2940                        String msg(e.getMessage());
2941                        throw StressTestControllerException(msg); 
2942                    }
2943 j.alex 1.1.2.3     if (!IsValid)
2944 j.alex 1.1.2.1     {
2945 j.alex 1.1.2.3        String ErrReport = String("Invalid Property Value: ");
2946                       ErrReport.append(name);
2947                       ErrReport.append("=");
2948                       ErrReport.append(value);
2949                       throw StressTestControllerException(ErrReport);
2950 j.alex 1.1.2.1     }
2951                    return true;
2952 j.alex 1.1.2.3 } /* _parseLine */
2953 j.alex 1.1.2.1 
2954                /*
2955                    Storing client details in a table.
2956                    - Stores the Client name  and instance for specific clients in their 
2957                      respective client table for later use.
2958                
2959                    @parm    name            The client name that will be stored.
2960                    @parm    value           The number of instances of the client.
2961                
2962                    @return  true            Succesfully stored the name or instance.
2963                             false           Failed to store the name or instance.
2964                 */
2965 j.alex 1.1.2.3 Boolean StressTestControllerCommand::_storeClientDetails(
2966                    String name,
2967                    String value)
2968 j.alex 1.1.2.1 {
2969                     
2970                    // 
2971                    // Expand the client table as required.
2972                    //
2973                    if (_clientCount >= Total_Clients)
2974                    {
2975                        Total_Clients += NEW_CLIENTS;
2976                        Table* tempClientTable = new Table[Total_Clients]; 
2977 j.alex 1.1.2.3         for (Uint32 i =0;i<_clientCount;i++)
2978 j.alex 1.1.2.1         {
2979                            tempClientTable[i] = _clientTable[i];
2980                        }
2981                        delete [] _clientTable;
2982                        _clientTable = tempClientTable;
2983                    }         
2984                
2985                    // 
2986                    // Store the client Name in the table
2987                    // 
2988                    if (!_clientTable[_clientCount].insert(NAME, name))
2989                    {
2990                        //
2991                        // Duplicate property, ignore the new property value.
2992                        //
2993 j.alex 1.1.2.3         if (verboseEnabled)
2994                        {
2995 j.alex 1.1.2.1             cout<< "Duplicate Client already saved: "<<endl;
2996 j.alex 1.1.2.3         }
2997 j.alex 1.1.2.1         return false;
2998                    }
2999 j.alex 1.1.2.3 
3000 j.alex 1.1.2.1     // 
3001                    // Store the number of instances for the client in the table
3002                    // 
3003                    if (!_clientTable[_clientCount].insert(INSTANCE, value))
3004                    {
3005 j.alex 1.1.2.3 
3006 j.alex 1.1.2.1        //
3007                       // Duplicate property, ignore the new property value.
3008                       //
3009                       if(verboseEnabled)
3010 j.alex 1.1.2.3        {
3011 j.alex 1.1.2.1           cout<< "Duplicate Instance already saved: "<<endl;
3012 j.alex 1.1.2.3        }
3013 j.alex 1.1.2.1        return false;
3014                    }
3015                    ++_clientCount;
3016                    return true;
3017 j.alex 1.1.2.3 } /* _storeClientDetails */
3018 j.alex 1.1.2.1 
3019                /*
3020                    Will check the current tolerance level of the running clients with
3021                    respect to the expected tolerance level.
3022                    @parm    actual_client     The total number of executed clients. 
3023                    @parm    nowMilliseconds   The current time in milliseconds.
3024                    @parm    log_file          The log_file.
3025                
3026                    @return  true            Clients with tolerance.
3027                             false           Clients failed tolerance.
3028                 */
3029 j.alex 1.1.2.3 Boolean StressTestControllerCommand::_checkToleranceLevel(
3030                    int actual_client,
3031                    Uint64 nowMilliseconds,
3032                    ostream& log_file) 
3033 j.alex 1.1.2.1 {
3034 j.alex 1.1.2.3     int count = 0;
3035                    int failed_count = 0;
3036                    Uint64 lastUpdateinMilliSec =0; 
3037                    Boolean withinTolerance = false;
3038 j.alex 1.1.2.1 
3039 j.alex 1.1.2.3     for (int i=0;i<actual_client;i++)
3040                    {
3041                        // 
3042                        //Observe only the status of running clients
3043                        //
3044                        if (clientActive[i])
3045                        {
3046                            ++count;
3047                            //
3048                            //  Validate the timestamps:
3049                            //  The timestamps on the status is compared to the previous 
3050                            //  timestamp to ensure that the status has been updated within 
3051                            //  the previous 2 updates.
3052                            //
3053                            if(clientStatus[i]== VALID_RESPONSE)
3054                            {
3055 j.alex 1.1.2.4                 //
3056 j.alex 1.1.2.3                 //check with the last timestamp
3057 j.alex 1.1.2.4                 //
3058 j.alex 1.1.2.3                 lastUpdateinMilliSec = nowMilliseconds - clientTimeStamp[i];
3059                                //
3060                                // Assume failure if status update is
3061                                // longer than 2 * checkup interval 
3062                                //
3063                                if ((clientTimeStamp[i] == prev_clientTimeStamp[i])
3064                                   && (lastUpdateinMilliSec >=
3065                                   (2 * (Uint64)convertmin2millisecs(CHECKUP_INTERVAL))))
3066                                {  
3067                                    if (verboseEnabled)
3068                                    {
3069                                        log_file <<" Status not updated for client (" <<i<<
3070                                            ")pid :"<<clientPIDs[i]<<endl;
3071                                        log_file << "        for the past " << 
3072                                            2*(CHECKUP_INTERVAL) << " minutes." << endl;
3073                                        cout<<" Status not updated for client ("<<i<<")pid :"<<
3074                                            clientPIDs[i]<<endl;
3075                                        cout<<"        for the past " << 2*(CHECKUP_INTERVAL)<<
3076                                            " minutes." << endl;
3077                                    }
3078                                    ++failed_count; 
3079 j.alex 1.1.2.3                 }
3080                            }
3081                            //
3082                            // If unknown status - server or client may be hung.
3083                            // Two consective failures on the same client will be counted
3084                            // as a failed client. 
3085                            //
3086                            if (((clientStatus[i]== NO_RESPONSE)
3087                               ||(clientStatus[i]== INVALID_RESPONSE))
3088                               &&((prev_clientStatus[i]== NO_RESPONSE)
3089                                 ||(prev_clientStatus[i]== INVALID_RESPONSE)))
3090                            {
3091                                if (verboseEnabled)
3092                                {
3093                                    if (clientStatus[i]== INVALID_RESPONSE)
3094                                    {
3095                                        log_file<<
3096                                            "Recieved an Invalid response Status from client("<<
3097                                            i <<") pid :"<<clientPIDs[i]<<endl;
3098                                    }
3099                                    else
3100 j.alex 1.1.2.3                     { 
3101                                        log_file<<"Recieved a no response Status from client("<<
3102                                            i <<") pid :"<<clientPIDs[i]<<endl;
3103                                    }
3104                                }
3105                                ++failed_count; 
3106                            } /* if (((clientStatus[i]== NO_RESPONSE) ... */
3107 j.alex 1.1.2.4             //
3108 j.alex 1.1.2.3             // Save previous time stamp of client
3109 j.alex 1.1.2.4             //
3110 j.alex 1.1.2.3             prev_clientTimeStamp[i] = clientTimeStamp[i];
3111                            prev_clientStatus[i] = clientStatus[i];
3112                        } /* if (clientActive[i]) */
3113                    }
3114 j.alex 1.1.2.4     //
3115 j.alex 1.1.2.3     // check actual tolerance
3116 j.alex 1.1.2.4     //
3117 j.alex 1.1.2.3     if(count > 0)
3118                    {
3119                        double curr_tolerancePercent = getToleranceInPercent(
3120                                                           failed_count,
3121                                                           (double)count);
3122                        if (verboseEnabled)
3123                        {
3124                            cout<<" total running clients ="<<count<<endl;
3125                            cout<<" failed clients ="<<failed_count<<endl;
3126                            cout<<"Actual Tolerance % ="<<curr_tolerancePercent<<endl;
3127                            cout<<"Expected Tolerance % ="<<_toleranceLevel<<endl;
3128                            log_file<<"Total Running clients:"<<count<<endl;
3129                            log_file<<"Actual Failed clients:"<<failed_count<<endl;
3130                            log_file<<"::Expected Tolerance:"<<_toleranceLevel<<endl;
3131                            log_file<<"::Actual Tolerance:"<<curr_tolerancePercent<<endl;
3132                        }
3133                        if ((double)_toleranceLevel >= curr_tolerancePercent)
3134                        {
3135                            withinTolerance = true;
3136                        }
3137                        return(withinTolerance);
3138 j.alex 1.1.2.3     }
3139 j.alex 1.1.2.4     //
3140 j.alex 1.1.2.3     // All process are stopped.
3141 j.alex 1.1.2.4     //
3142 j.alex 1.1.2.3     return(withinTolerance = true);
3143                } /* _checkToleranceLevel */
3144 j.alex 1.1.2.1 
3145                
3146                /*
3147                    This will populate the client table with the hard coded
3148                    values for the stress tests.
3149                    This method is only used if the default configuration 
3150                    file does not exist.
3151                    Default clients are 5 instances of 
3152                    "TestWrapperStressClient" and "TestModelWalkStressClient".
3153                
3154                    @parm    log_file      The log_file. 
3155                    
3156                 */
3157                void StressTestControllerCommand::getDefaultClients(ostream& log_file)
3158                {
3159 j.alex 1.1.2.3     //
3160                    // Setting the client count to default client value
3161                    //
3162                    _clientCount = DEFAULT_CLIENTS; 
3163                
3164                    log_file << "Populating default configuration for stress Tests." << endl; 
3165                    if (verboseEnabled)
3166                    {
3167                        cout << "Populating default configuration for stress Tests." << endl; 
3168                    }
3169 j.alex 1.1.2.4     //
3170 j.alex 1.1.2.3     // Populating default client attributes
3171 j.alex 1.1.2.4     //
3172 j.alex 1.1.2.3     for (Uint32 i=0;i<_clientCount; i++)
3173                    {
3174                        //
3175                        // Adding the default instance value to each client table
3176 j.alex 1.1.2.4         //
3177 j.alex 1.1.2.3         if (!_clientTable[i].insert(INSTANCE, DEFAULT_INSTANCE))
3178                        {
3179                            log_file <<  "Duplicate name already saved: "<<INSTANCE<<endl;
3180                            if (verboseEnabled)
3181                            {
3182                                cout<< "duplicate name already saved: "<<INSTANCE<<endl;
3183                            }
3184                        }
3185                        switch(i)
3186                        { 
3187                            case 0:
3188                            {
3189                                if (!_clientTable[i].insert(NAME, MODELWALK_CLIENT))
3190                                {
3191                                    log_file <<  "Duplicate name already saved: "<<NAME<<endl;
3192                                    if (verboseEnabled)
3193                                    {
3194                                        cout<< "Duplicate name already saved: "<<NAME<<endl;
3195                                    }
3196                                }
3197                                log_file << "Stress Test Client Name:"<<MODELWALK_CLIENT<< endl; 
3198 j.alex 1.1.2.3                 if (verboseEnabled)
3199                                {
3200                                    cout<< "Stress Test Client Name:"<<MODELWALK_CLIENT<< endl; 
3201                                }
3202                
3203                                break;
3204                            }
3205                            case 1:
3206                            {
3207                                if (!_clientTable[i].insert(NAME, WRAPPER_CLIENT))
3208                                {
3209                                    log_file <<  "Duplicate name already saved: "<<NAME<<endl;
3210                                    if (verboseEnabled)
3211                                    {
3212                                        cout<< "Duplicate name already saved: "<<NAME<<endl;
3213                                    }
3214                                }
3215                                log_file << "Stress Test Client Name:" <<WRAPPER_CLIENT<< endl; 
3216                                if (verboseEnabled)
3217                                {
3218                                    cout << "Stress Test Client Name:" <<WRAPPER_CLIENT<< endl; 
3219 j.alex 1.1.2.3                 }
3220                                if (!_clientTable[i].insert(CLIENTNAME, "CLI"))
3221                                {
3222                                    log_file<< "Duplicate name already saved: "<<
3223                                        CLIENTNAME<<endl;
3224                                    if (verboseEnabled) 
3225                                    { 
3226                                        cout<< "Duplicate name already saved: "<<
3227                                            CLIENTNAME<<endl;
3228                                    }
3229                                }
3230                                if (!_clientTable[i].insert(OPTIONS, "niall"))
3231                                {
3232                                    log_file<< "Duplicate name already saved: "<<OPTIONS<<endl;
3233                                    if (verboseEnabled)
3234                                    {
3235                                        cout<< "Duplicate name already saved: "<<OPTIONS<<endl;
3236                                    } 
3237                                }
3238                                log_file<< "            Client Command &  options: CLI niall"<<
3239                                    endl; 
3240 j.alex 1.1.2.3                 if (verboseEnabled)
3241                                {
3242                                   cout<< "            Client Command &  options: CLI niall"<<
3243                                       endl; 
3244                                }
3245                                break;
3246                            } /* case 1: */
3247                        } /* switch(i) */
3248                    } /* for(Uint32 i=0;i<_clientCount; i++) */
3249 j.alex 1.1.2.1 
3250                } /* getDefaultClients */
3251                
3252                
3253                
3254                
3255                /**
3256                    Will generate or create all the required files for the tests.
3257                    - Required log files, pid files, client log file are created here. 
3258                
3259                    @parm    strTime         The time stamp for the tests. 
3260                                             This is used in the naming of the log file.
3261                
3262                    @return  true            The files were successfully created.
3263                             false           Failed to create one or more of the required
3264                                             files.
3265                
3266                 */
3267                Boolean StressTestControllerCommand::generateRequiredFileNames(char *strTime)
3268                {
3269 j.alex 1.1.2.3     char pid_str[15];
3270                    ofstream log_file;
3271                    ofstream pid_file;
3272                    ofstream clntlog_file;
3273 j.alex 1.1.2.1 
3274 j.alex 1.1.2.3     sprintf(pid_str, "%d", getpid());
3275 j.alex 1.1.2.1    
3276 j.alex 1.1.2.4     //
3277 j.alex 1.1.2.3     // Stress Controller Log file
3278 j.alex 1.1.2.4     //
3279 j.alex 1.1.2.3     _stressTestLogFile.append(pegasusHome);
3280                    _stressTestLogFile.append(TESTDIR);
3281                    FileSystem::makeDirectory(_stressTestLogFile);
3282                    _stressTestLogFile.append(STRESSTESTDIR);
3283                    FileSystem::makeDirectory(_stressTestLogFile);
3284                    _stressTestLogFile.append(LOGDIR);
3285                    FileSystem::makeDirectory(_stressTestLogFile);
3286                    _stressTestLogFile.append(pid_str);
3287                    _stressTestLogFile.append("_stressTest_");
3288                    _stressTestLogFile.append(strTime);
3289                    _stressTestLogFile.append("log");
3290                
3291 j.alex 1.1.2.4     //
3292 j.alex 1.1.2.3     // StressClient PID  file
3293 j.alex 1.1.2.4     //
3294 j.alex 1.1.2.3     _stressTestClientPIDFile.append(pegasusHome);
3295                    _stressTestClientPIDFile.append(DEFAULT_TMPDIR);
3296                    FileSystem::makeDirectory(_stressTestClientPIDFile);
3297                    _stressTestClientPIDFile.append(pid_str);
3298                    _stressTestClientPIDFile.append("_StressTestClients");
3299                    _stressTestClientPIDFile.append(strTime);
3300                    _stressTestClientPIDFile.append("pid");
3301                
3302 j.alex 1.1.2.4     //
3303 j.alex 1.1.2.3     // StressClient Log  file
3304 j.alex 1.1.2.4     //
3305 j.alex 1.1.2.3     _stressTestClientLogFile.append(pegasusHome);
3306                    _stressTestClientLogFile.append(DEFAULT_LOGDIR);
3307                    _stressTestClientLogFile.append(pid_str);
3308                    _stressTestClientLogFile.append("_StressTestClients");
3309                    _stressTestClientLogFile.append(".log");
3310                 
3311 j.alex 1.1.2.4     //
3312 j.alex 1.1.2.3     // Temporary StressClient PID/status  file
3313 j.alex 1.1.2.4     //
3314 j.alex 1.1.2.3     _tmpStressTestClientPIDFile.append(pegasusHome);
3315                    _tmpStressTestClientPIDFile.append(DEFAULT_TMPDIR);
3316                    _tmpStressTestClientPIDFile.append(pid_str);
3317                    _tmpStressTestClientPIDFile.append("TEMP");
3318                    _tmpStressTestClientPIDFile.append("_Clients");
3319                    _tmpStressTestClientPIDFile.append(".pid");
3320                
3321 j.alex 1.1.2.4     //
3322 j.alex 1.1.2.3     // Translate slashed for appropriate OS
3323 j.alex 1.1.2.4     //
3324 j.alex 1.1.2.3     FileSystem::translateSlashes(_stressTestClientPIDFile);
3325                    FileSystem::translateSlashes(_stressTestClientLogFile);
3326                    FileSystem::translateSlashes(_stressTestLogFile);
3327                    FileSystem::translateSlashes(_tmpStressTestClientPIDFile);
3328 j.alex 1.1.2.1 
3329 j.alex 1.1.2.4     //
3330 j.alex 1.1.2.1     // open the file
3331 j.alex 1.1.2.4     //
3332 j.alex 1.1.2.3     OpenAppend(log_file,_stressTestLogFile);
3333                    Open(pid_file,_stressTestClientPIDFile);
3334                    Open(clntlog_file,_stressTestClientLogFile);
3335 j.alex 1.1.2.1 
3336                    //
3337                    //  Failed to open the log file
3338                    //
3339                    if (!log_file)
3340                    {
3341                       log_file.close();
3342                       pid_file.close();
3343                       clntlog_file.close();
3344 j.alex 1.1.2.3        cout<<"Cannot get file "<<_stressTestLogFile<<endl;
3345 j.alex 1.1.2.1        return false;
3346                
3347                    }
3348                    //
3349                    //  Failed to open the pid file
3350                    //
3351                    if (!pid_file)
3352                    {
3353 j.alex 1.1.2.3        cout<<"Cannot get file "<<_stressTestClientPIDFile<<endl;
3354                       log_file<<StressTestControllerCommand::COMMAND_NAME<<
3355                           "Cannot read file "<<_stressTestClientPIDFile<<endl;
3356 j.alex 1.1.2.1        log_file.close();
3357                       clntlog_file.close();
3358                       return false;
3359                    }
3360                    //
3361                    //  Failed to open the clntlog file
3362                    //
3363                    if (!clntlog_file)
3364                    {
3365 j.alex 1.1.2.3        log_file<<StressTestControllerCommand::COMMAND_NAME<<
3366                           "Cannot read file "<<_stressTestClientLogFile<<endl;
3367 j.alex 1.1.2.1        log_file.close();
3368                       pid_file.close();
3369                       return false;
3370                    }
3371 j.alex 1.1.2.3 
3372 j.alex 1.1.2.1     //
3373                    // Successfully opened all the files.
3374                    //
3375 j.alex 1.1.2.3     pid_file<<"#"<<StressTestControllerCommand::COMMAND_NAME<<
3376                        " has the following clients:: \n";
3377                    clntlog_file<<"#"<<StressTestControllerCommand::COMMAND_NAME<<
3378                        "::Process ID:"<<getpid()<<endl;
3379 j.alex 1.1.2.1     clntlog_file.close();
3380                    pid_file.close();
3381                    return true;
3382                
3383                } /* generateRequiredFileNames */
3384                
3385                /**
3386                    Will remove all the unused files for the tests.
3387                    - Unused log files & pid files are removed here. 
3388                
3389                 */
3390 j.alex 1.1.2.3 void StressTestControllerCommand::removeUnusedFiles()
3391 j.alex 1.1.2.1 {
3392 j.alex 1.1.2.3     FileSystem::removeFile(_stressTestClientPIDFile);
3393                    FileSystem::removeFile(_stressTestClientLogFile);
3394 j.alex 1.1.2.1 }
3395                
3396                PEGASUS_NAMESPACE_END
3397                
3398                /**
3399                    Cleanup function for stressTestController to free allocated
3400                    memory used to execute clients.
3401                 */
3402 j.alex 1.1.2.3 void cleanupProcess()
3403 j.alex 1.1.2.1 {
3404                
3405                    delete [] clientPIDs;
3406                    delete [] clientStatus;
3407                    delete [] clientInstance;
3408                    delete [] clientActive;
3409                    delete [] clientTimeStamp;
3410                    delete [] prev_clientTimeStamp;
3411                    delete [] prev_clientStatus;
3412                }
3413                
3414                /*
3415                    This will generate the current time.
3416                 */
3417 j.alex 1.1.2.3 struct tm getCurrentActualTime()
3418 j.alex 1.1.2.1 {
3419 j.alex 1.1.2.3     struct tm tmTime;
3420                    time_t inTime=time(NULL);
3421                #ifdef PEGASUS_OS_TYPE_WINDOWS
3422                    tmTime=*localtime(&inTime);
3423 j.alex 1.1.2.1 #else
3424 j.alex 1.1.2.3     localtime_r(&inTime,&tmTime);
3425 j.alex 1.1.2.1 #endif
3426 j.alex 1.1.2.3     return tmTime;
3427 j.alex 1.1.2.1 }
3428                
3429                /**
3430                    Signal handler for SIGINT, SIGABRT.
3431                
3432                    @param   signum  the signal identifier
3433                */
3434                void endAllTests(int signum)
3435                {
3436 j.alex 1.1.2.3     if (verboseEnabled)
3437                    {
3438                        switch(signum)
3439                        {
3440                            case SIGINT:
3441                            {
3442                                cout<<StressTestControllerCommand::COMMAND_NAME<<
3443                                    "::Recieved interupt signal SIGINT!"<<endl;
3444                                break;
3445                            }
3446                            case SIGABRT:
3447                            {
3448                                cout<<StressTestControllerCommand::COMMAND_NAME<<
3449                                    "::Recieved signal SIGABRT!"<<endl;
3450                                break;
3451                            }
3452                            default:
3453                            {
3454                                cout<<StressTestControllerCommand::COMMAND_NAME<<
3455                                    "::Recieved Signal ( "<<signum<<"!" <<endl;
3456                                break;
3457 j.alex 1.1.2.3             }
3458                        }
3459                    }
3460                    //
3461                    // Sets the variable that will interupt stress tests
3462                    //
3463                    Quit = true;
3464 j.alex 1.1.2.1 } /* endAllTests */
3465                
3466                /**
3467                    This function will convert a Uint64
3468                    to a string.
3469                
3470                    @param   x       The Uint64 integer
3471                
3472                    @return  String  Returns the converted string.
3473                */
3474                String convertUint64toString(Uint64 x)
3475                {
3476                    char buffer[32];
3477                    sprintf(buffer, "%" PEGASUS_64BIT_CONVERSION_WIDTH "u", x);
3478                    return(String(buffer));
3479 j.alex 1.1.2.3 }/* convertUint64toString(..) */

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2