1 j.alex 1.2 //%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.2 // 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.2 #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 #ifdef PEGASUS_OS_TYPE_WINDOWS
57 // for DWORD etc.
58 #include <windows.h>
59 // getpid() and others
60 typedef DWORD pid_t;
61 #include <process.h>
62 #elif !defined(PEGASUS_OS_OS400)
63 #include <unistd.h>
64 j.alex 1.2 #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 #define SHUTDOWN_DELAY 5
73 #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 static void cleanupProcess();
84
85 j.alex 1.2 static String convertUint64toString(Uint64 x);
86
87
88 PEGASUS_NAMESPACE_BEGIN
89 PEGASUS_USING_PEGASUS;
90 PEGASUS_USING_STD;
91
92
93
94 /**
95 Log file descripter
96 */
97
98 /**
99 variable for Signal handler
100 */
101 static Boolean Quit = false;
102
103 /**
104 The command name.
105 */
106 j.alex 1.2 const char StressTestControllerCommand::COMMAND_NAME [] =
107 "TestStressTestController";
108
109
110 /**
111 StressTest Configuration file details
112 */
113 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 j.alex 1.2 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
132 static char MODELWALK_CLIENT[] = "TestModelWalkStressClient";
133 static char WRAPPER_CLIENT[] = "TestWrapperStressClient";
134
135 /**
136 StressTest Client Status types
137 */
138 enum CStatus{
139 VALID_RESPONSE,
140 INVALID_RESPONSE,
141 NO_RESPONSE};
142
143
144 /**
145 Temporary arrays to store client information
146 */
147
148 j.alex 1.2 /**
149 Client PID's
150 */
151 static pid_t *clientPIDs;
152
153 /**
154 Client Status
155 */
156 static int *clientStatus;
157
158
159 /**
160 Client Status
161 */
162 static int *prev_clientStatus;
163
164 /**
165 Client Instance
166 */
167 static int *clientInstance;
168
169 j.alex 1.2 /**
170 Indicates if client is Active
171 */
172 static Boolean *clientActive;
173
174 /**
175 Client status time stamp
176 */
177 static Uint64 *clientTimeStamp;
178
179 /**
180 Previous client status time stamp
181 */
182 static Uint64 *prev_clientTimeStamp;
183
184 /**
185 DEFAULT VALUES:
186 */
187
188 /**
189 Default duration for the stress tests
190 j.alex 1.2 */
191 double StressTestControllerCommand::_duration = 180;
192
193 /**
194 Label for the usage string for this command.
195 */
196 const char StressTestControllerCommand::_USAGE [] = "Usage: ";
197
198 /**
199 The option character used to specify the hostname.
200 */
201 const char StressTestControllerCommand::_OPTION_HOSTNAME = 'h';
202
203 /**
204 The option character used to specify the port number.
205 */
206 const char StressTestControllerCommand::_OPTION_PORTNUMBER = 'p';
207
208 /**
209 The option character used to specify SSL usage.
210 */
211 j.alex 1.2 const char StressTestControllerCommand::_OPTION_SSL = 's';
212
213 /**
214 The option character used to specify the username.
215 */
216 const char StressTestControllerCommand::_OPTION_USERNAME = 'u';
217
218 /**
219 The option character used to specify the password.
220 */
221 const char StressTestControllerCommand::_OPTION_PASSWORD = 'w';
222
223 /**
224 The minimum valid portnumber.
225 */
226 const Uint32 StressTestControllerCommand::_MIN_PORTNUMBER = 0;
227
228 /**
229 The maximum valid portnumber.
230 */
231 const Uint32 StressTestControllerCommand::_MAX_PORTNUMBER = 65535;
232 j.alex 1.2
233 /**
234 The minimum Duration.
235 */
236 const Uint32 StressTestControllerCommand::_MIN_DURATION = 0;
237
238 /**
239 The minimum valid Tolerance Level.
240 */
241 const Uint32 StressTestControllerCommand::_MIN_TOLERANCE = 0;
242
243 /**
244 The maximum valid Tolerance Level.
245 */
246 const Uint32 StressTestControllerCommand::_MAX_TOLERANCE = 100;
247
248 /**
249 The variable used to specify the hostname.
250 */
251 static const char HOSTNAME[] = "hostname";
252
253 j.alex 1.2 /**
254 The variable used to specify the port number.
255 */
256 static const char PORTNUMBER[] = "port";
257
258 /**
259 The variable used to specify SSL usage.
260 */
261 static const char SSL [] = "ssl";
262
263 /**
264 The variable used to specify the username.
265 */
266 static const char USERNAME[] = "username";
267
268 /**
269 The variable used to specify the password.
270 */
271 static const char PASSWORD[] = "password";
272
273 /**
274 j.alex 1.2 The variable used to specify the duration of the tests.
275 */
276 static const char DURATION[] = "duration";
277
278 /**
279 The variable used to specify the duration of the Client tests.
280 */
281 static const char CLIENTDURATION[] = "ClientDuration";
282
283 /**
284 The variable used to specify the ToleranceLevel for the tests.
285 */
286 static const char TOLERANCELEVEL[] = "TOLERANCELEVEL";
287
288 /**
289 The variable used to specify the NameSpace for the tests.
290 */
291 static const char NAMESPACE[] = "namespace";
292
293 /**
294 The variable used to specify the ClassName for the tests.
295 j.alex 1.2 */
296 static const char CLASSNAME[] = "classname";
297
298 /**
299 The variable used to specify the Name for the tests.
300 */
301 static const char NAME[] = "NAME";
302
303 /**
304 The variable used to specify the Clientname for the tests.
305 */
306 static const char CLIENTNAME[] = "clientname";
307
308 /**
309 The variable used to specify the Clientname for the tests.
310 */
311 static const char OPTIONS[] = "options";
312
313 /**
314 The variable used to specify the Clientname for the tests.
315 */
316 j.alex 1.2 static const char INSTANCE[] = "INSTANCE";
317
318 /**
319 The variable used to specify the Clientname for the tests.
320 */
321 static const char CLIENTWAIT[] = "CLIENTWAIT";
322
323
324
325 /**
326 * Message resource name
327 */
328 static const char PASSWORD_PROMPT [] =
329 "Please enter your password: ";
330 static const char PASSWORD_BLANK [] =
331 "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
336 static Boolean IsAClient = false;
337 j.alex 1.2
338 static Boolean IsClientOptions = false;
339
340 static Boolean IgnoreLine = false;
341
342 /**
343
344 Constructs a StressTestControllerCommand and initializes instance variables.
345
346 */
347 StressTestControllerCommand::StressTestControllerCommand ()
348 {
349
350 _hostName = String ();
351 _hostNameSpecified = false;
352 _portNumber = WBEM_DEFAULT_HTTP_PORT;
353 _portNumberSpecified = false;
354
355 char buffer[32];
356 sprintf(buffer, "%lu", (unsigned long) _portNumber);
357
358 j.alex 1.2 _portNumberStr = buffer;
359
360 _timeout = DEFAULT_TIMEOUT_MILLISECONDS;
361 _userName = String ();
362 _userNameSpecified = false;
363 _password = String ();
364 _passwordSpecified = false;
365 _useSSL = false;
366
367 //
368 // initialize
369 //
370 _clientCount = 0;
371 _currClientCount = 0;
372
373 //
374 // Set up tables for client properties.
375 //
376 _clientTable = new Table[Total_Clients];
377
378 //
379 j.alex 1.2 // Allocate one table to collect all the common properties Thy use AutoPtr
380 //
381 _propertyTable = new Table;
382
383 //
384 // Client Information
385 //
386 _clientCommands = 0;
387 _clientDurations = 0;
388 _clientDelays = 0;
389
390 //
391 // Get environment variables:
392 //
393 pegasusHome = getenv("PEGASUS_HOME");
394
395 DEFAULT_BINDIR = String(pegasusHome);
396 DEFAULT_BINDIR.append(BINDIR);
397
398 _stressTestLogFile = String::EMPTY;
399
400 j.alex 1.2 _stressTestClientPIDFile = String::EMPTY;
401
402 _stressTestClientLogFile = String::EMPTY;
403
404 _tmpStressTestClientPIDFile = String::EMPTY;
405
406
407
408 _usage = String (_USAGE);
409
410 _usage.append (COMMAND_NAME);
411 #ifndef DISABLE_SUPPORT_FOR_REMOTE_CONNECTIONS
412 _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 j.alex 1.2 _usage.append (_OPTION_PASSWORD);
422 _usage.append (" password ]");
423 #endif
424 _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 j.alex 1.2 _usage.append(" username\n");
443 _usage.append(" --version - Display CIM Server version number\n");
444 _usage.append(" --verbose - Display verbose information\n");
445 _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
453 setUsage(_usage);
454
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 j.alex 1.2 @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 Uint32 i = 0;
472 Uint32 c = 0;
473 String GetOptString = String ();
474 getoopt getOpts;
475 _toleranceLevel = 0;
476 _configFilePath = String ();
477 _configFilePathSpecified = false;
478
479 _operationType = OPERATION_TYPE_UNINITIALIZED;
480
481
482 ofstream log_file;
483
484 j.alex 1.2 //
485 // opens the log file
486 //
487 OpenAppend(log_file,_stressTestLogFile);
488
489 if (!log_file)
490 {
491 if(verboseEnabled)
492 {
493 cout<<StressTestControllerCommand::COMMAND_NAME<<
494 "::Cannot get file "<<_stressTestLogFile<<endl;
495 }
496
497 }
498 log_file<<StressTestControllerCommand::COMMAND_NAME<<
499 ":: Preparing to set up parameters: "<<endl;
500
501 //
502 // Construct GetOptString
503 //
504 GetOptString.append (_OPTION_HOSTNAME);
505 j.alex 1.2 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 //
521 // per PEP#167
522 //
523 getOpts.addLongFlagspec(LONG_HELP,getoopt::NOARG);
524 getOpts.addLongFlagspec(LONG_VERSION,getoopt::NOARG);
525 getOpts.addLongFlagspec(LONG_VERBOSE,getoopt::NOARG);
526 j.alex 1.2
527 getOpts.parse (argc, argv);
528
529 if (getOpts.hasErrors ())
530 {
531 log_file.close();
532 CommandFormatException e(getOpts.getErrorStrings () [0]);
533 throw e;
534 }
535
536 //
537 // Get options and arguments from the command line
538 //
539 for (i = getOpts.first(); i < getOpts.last (); i++)
540 {
541 if (getOpts[i].getType() == Optarg::LONGFLAG)
542 {
543 if (getOpts[i].getopt() == LONG_HELP)
544 {
545 _operationType = OPERATION_TYPE_HELP;
546 }
547 j.alex 1.2 else if (getOpts[i].getopt() == LONG_VERSION)
548 {
549 _operationType = OPERATION_TYPE_VERSION;
550 }
551 if (getOpts[i].getopt() == LONG_VERBOSE)
552 {
553 verboseEnabled = true;
554 }
555 }
556 else if (getOpts [i].getType() == Optarg::REGULAR)
557 {
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 log_file<<StressTestControllerCommand::COMMAND_NAME<<
567 "::More than one arguement was found "<<endl;
568 j.alex 1.2 log_file.close();
569 UnexpectedArgumentException e(getOpts[i].Value());
570 throw e;
571 }
572 _configFilePath = getOpts[i].Value();
573 _configFilePathSpecified = true;
574 }
575 else /* getOpts[i].getType() == FLAG */
576 {
577 c = getOpts[i].getopt()[0];
578 switch(c)
579 {
580 case _OPTION_HOSTNAME:
581 {
582 if (getOpts.isSet(_OPTION_HOSTNAME) > 1)
583 {
584 //
585 // More than one hostname option was found
586 //
587 log_file.close();
588 DuplicateOptionException e(_OPTION_HOSTNAME);
589 j.alex 1.2 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 cout<<"::Property Name name already saved: "<<
600 "hostname"<<endl;
601 }
602 }
603 break;
604 }
605 case _OPTION_PORTNUMBER:
606 {
607 if (getOpts.isSet(_OPTION_PORTNUMBER) > 1)
608 {
609 //
610 j.alex 1.2 // More than one portNumber option was found
611 //
612 log_file.close();
613 DuplicateOptionException e(_OPTION_PORTNUMBER);
614 throw e;
615 }
616 _portNumberStr = getOpts [i].Value ();
617 try
618 {
619 getOpts[i].Value(_portNumber);
620 }
621 catch (const TypeMismatchException&)
622 {
623 log_file.close();
624 InvalidOptionArgumentException e(
625 _portNumberStr,
626 _OPTION_PORTNUMBER);
627 throw e;
628 }
629 _portNumberSpecified = true;
630 if (!_propertyTable->insert("port", _portNumberStr))
631 j.alex 1.2 {
632 if(verboseEnabled)
633 {
634 cout<<StressTestControllerCommand::COMMAND_NAME;
635 cout<<"::Property Name:duplicate name already saved:"
636 <<"port"<<endl;
637 }
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 j.alex 1.2 {
653 if(verboseEnabled)
654 {
655 cout<<StressTestControllerCommand::COMMAND_NAME;
656 cout<<"::Property Name already saved: "<<"port"<<
657 endl;
658 }
659 }
660 }
661 if (!_propertyTable->insert("ssl", ""))
662 {
663 if(verboseEnabled)
664 {
665 cout<<StressTestControllerCommand::COMMAND_NAME;
666 cout<<"::Property Name already saved: "<<"ssl"<<
667 endl;
668 }
669 }
670 break;
671 }
672 case _OPTION_USERNAME:
673 j.alex 1.2 {
674 if (getOpts.isSet(_OPTION_USERNAME) > 1)
675 {
676 //
677 // More than one username option was found
678 //
679 log_file.close();
680 DuplicateOptionException e(_OPTION_USERNAME);
681 throw e;
682 }
683 _userName = getOpts[i].Value();
684 _userNameSpecified = true;
685 if (!_propertyTable->insert("username", _userName))
686 {
687 if(verboseEnabled)
688 {
689 cout<<StressTestControllerCommand::COMMAND_NAME;
690 cout<< "::Property Name already saved: "<<
691 "username"<<endl;
692 }
693 }
694 j.alex 1.2 break;
695 }
696 case _OPTION_PASSWORD:
697 {
698 if (getOpts.isSet(_OPTION_PASSWORD) > 1)
699 {
700 //
701 // More than one password option was found
702 //
703 log_file.close();
704 DuplicateOptionException e(_OPTION_PASSWORD);
705 throw e;
706 }
707 _password = getOpts[i].Value();
708 _passwordSpecified = true;
709 if (!_propertyTable->insert("password", _password))
710 {
711 if(verboseEnabled)
712 {
713 cout<<StressTestControllerCommand::COMMAND_NAME;
714 cout<<"::Property Name already saved: "<<
715 j.alex 1.2 "password"<<endl;
716 }
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 String ErrReport =
729 String(StressTestControllerCommand::COMMAND_NAME);
730 ErrReport.append("::Invalid or unknown option specified");
731 throw StressTestControllerException(ErrReport);
732
733 break;
734 }
735 }
736 j.alex 1.2 }
737 }
738 //
739 // More validation:
740 // No portNumber specified
741 // Default to WBEM_DEFAULT_PORT
742 // Already done in constructor
743 //
744 if (getOpts.isSet(_OPTION_PORTNUMBER) == 1)
745 {
746 if (_portNumber > _MAX_PORTNUMBER)
747 {
748 //
749 // Portnumber out of valid range
750 //
751 log_file.close();
752 InvalidOptionArgumentException e(_portNumberStr,
753 _OPTION_PORTNUMBER);
754 throw e;
755 }
756 }
757 j.alex 1.2 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 */
775 Boolean StressTestControllerCommand::generateClientCommands(ostream& log_file)
776 {
777
778 j.alex 1.2 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 //
790 // 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 //
794 for (Uint32 j=0; j< _clientCount; j++)
795 {
796 delay = 0;
797 String clientName = String::EMPTY;
798 String clientInst = String::EMPTY;
799 j.alex 1.2 //
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 return false;
807 }
808 //
809 // Start the command string with the client name.
810 //
811 client_command = clientName;
812
813 //
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 j.alex 1.2 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 //
833 // should be ignored - already saved using clientName
834 //
835 }
836 else if (String::equalNoCase(i.key(),PORTNUMBER))
837 {
838 client_command.append(" -");
839 client_command.append(PORTNUMBER);
840 client_command.append(" ");
841 j.alex 1.2 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 {
857 client_command.append(" -");
858 client_command.append(USERNAME);
859 client_command.append(" ");
860 client_command.append(i.value());
861 }
862 j.alex 1.2 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 {
878 client_command.append(" -");
879 client_command.append(OPTIONS);
880 client_command.append(" ");
881 client_command.append(i.value());
882 }
883 j.alex 1.2 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 ||(String::equalNoCase(i.key(),CLIENTWAIT))
899 ||(String::equalNoCase(i.key(),CLIENTDURATION)))
900 {
901 //
902 // do nothing here
903 // will be utilized to run the clients later.
904 j.alex 1.2 //
905 }
906 else
907 {
908 //
909 // Save all other options for the commands
910 //
911 client_command.append(" -");
912 client_command.append(i.key());
913 client_command.append(" ");
914 client_command.append(i.value());
915 }
916 }
917 //
918 // Include verbose if enabled to clients
919 //
920 if (verboseEnabled)
921 {
922 client_command.append(" -verbose ");
923 }
924
925 j.alex 1.2 //
926 // 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 //
930 for (Table::Iterator k = _propertyTable->start(); k; k++)
931 {
932 String propertyValue = String::EMPTY;
933 //
934 // Only include the common properties that are not already
935 // listed for the clients.
936 //
937 if (!_clientTable[j].lookup(k.key(), propertyValue))
938 {
939 //
940 // Include options other than ToleranceLevel
941 // clientDuration,clientwait and Duration
942 // in the command string for the clients.
943 //
944 if ((!String::equalNoCase(k.key(),TOLERANCELEVEL))
945 && (!String::equalNoCase(k.key(),CLIENTDURATION))
946 j.alex 1.2 && (!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 {
966 duration = atof(k.value().getCString());
967 j.alex 1.2 }
968 else
969 {
970 duration = _duration;
971 }
972 } /* for (Table::Iterator k = _propertyTable->start(); k; k++) */
973
974 //
975 // Looking up table while ignoring cases for Client Duration/Wait.
976 //
977 for (Table::Iterator k = _clientTable[j].start(); k; k++)
978 {
979 //
980 // Overwrite duration if client duration set
981 //
982 if (String::equalNoCase(k.key(),CLIENTDURATION))
983 {
984 duration = atof(k.value().getCString());
985 }
986 if (String::equalNoCase(k.key(),CLIENTWAIT))
987 {
988 j.alex 1.2 delay = atof(k.value().getCString());
989 }
990 }
991
992 //
993 // Save the generated command to corresponding element in the
994 // clientCommand array.
995 //
996 _clientCommands[j] = client_command;
997
998 //
999 // Converting minutes to milliseconds
1000 //
1001 _clientDurations[j] = (Uint64)convertmin2millisecs(duration);
1002 _clientDelays[j] = (Uint64)convertmin2millisecs(delay);
1003
1004 //
1005 // Saving logs
1006 //
1007 log_file<<StressTestControllerCommand::COMMAND_NAME<<
1008 "::Client Command[";
1009 j.alex 1.2 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 cout<<" Client Duration: "<<
1026 convertUint64toString(_clientDurations[j])<<endl;
1027 cout<<" Client Delay: "<<convertUint64toString(_clientDelays[j])<<
1028 endl;
1029 }
1030 j.alex 1.2 } /* 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.2 written
1052
1053 @return 0 if the command is successful
1054 1 if an error occurs in executing the command
1055
1056 */
1057 Uint32 StressTestControllerCommand::execute (
1058 ostream& outPrintWriter,
1059 ostream& errPrintWriter)
1060 {
1061
1062 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 j.alex 1.2 String act_command = String::EMPTY;
1073 Boolean TestFailed = false;
1074 char str[15];
1075 char strTime[256];
1076 struct tm tmTime;
1077
1078
1079
1080 //
1081 // log file
1082 //
1083 ofstream log_file;
1084
1085 //
1086 // open the file
1087 //
1088 OpenAppend(log_file,_stressTestLogFile);
1089
1090 //
1091 // Failed to read log file.
1092 //
1093 j.alex 1.2 if (!log_file)
1094 {
1095 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 }
1103
1104 //
1105 // Display usage message if help was specified
1106 //
1107 if ( _operationType == OPERATION_TYPE_HELP )
1108 {
1109 outPrintWriter << _usage << endl;
1110 log_file<<StressTestControllerCommand::COMMAND_NAME<<
1111 "::Listing usage information "<<endl;
1112 log_file.close();
1113 //
1114 j.alex 1.2 // No need for the client pid and log file.
1115 //
1116 FileSystem::removeFile(_stressTestClientPIDFile);
1117 FileSystem::removeFile(_stressTestClientLogFile);
1118 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 log_file<<StressTestControllerCommand::COMMAND_NAME<<
1127 "::Listing version information "<<endl;
1128 log_file<<"Version " << PEGASUS_PRODUCT_VERSION << endl;
1129 log_file.close();
1130 //
1131 // No need for the client pid and log file.
1132 //
1133 FileSystem::removeFile(_stressTestClientPIDFile);
1134 FileSystem::removeFile(_stressTestClientLogFile);
1135 j.alex 1.2 return (RC_SUCCESS);
1136 }
1137
1138 //
1139 // gracefully shutdown when interrupted
1140 //
1141 signal(SIGABRT, endAllTests);
1142 signal(SIGINT, endAllTests);
1143
1144 //
1145 // Allocate variables necessary to run clients.
1146 //
1147 if(_clientCount > 0)
1148 {
1149 clientInstance = new int[_clientCount];
1150 clientStartMilliseconds = new Uint64[_clientCount];
1151 clientStopMilliseconds = new Uint64[_clientCount];
1152 clientDelayMilliseconds = new Uint64[_clientCount];
1153 clientStopped = new Boolean[_clientCount];
1154 clientDelayed = new Boolean[_clientCount];
1155 }
1156 j.alex 1.2 else
1157 {
1158 errPrintWriter << "Stress Tests must have at least one Client." << endl;
1159 log_file<<StressTestControllerCommand::COMMAND_NAME<<
1160 "::Stress Tests must have at least one Client."<<endl;
1161 log_file.close();
1162 return (RC_ERROR);
1163 }
1164
1165 try
1166 {
1167 //
1168 // Initializing the Boolean array's to false.
1169 //
1170 for (Uint32 i=0;i<_clientCount;i++)
1171 {
1172 clientStopped[i] = false;
1173 clientDelayed[i] = false;
1174 }
1175 //
1176 // Set up duration of the tests
1177 j.alex 1.2 //
1178 startMilliseconds = TimeValue::getCurrentTime().toMilliseconds();
1179 nowMilliseconds = startMilliseconds;
1180 timeoutMilliseconds = (Uint64)convertmin2millisecs(_duration);
1181 stopMilliseconds = nowMilliseconds + timeoutMilliseconds;
1182
1183 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 j.alex 1.2 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 convertUint64toString(stopMilliseconds)<<endl;
1205 }
1206
1207 //
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 //
1212 Uint64 nextCheckupInMillisecs =
1213 (Uint64)convertmin2millisecs(2 * CHECKUP_INTERVAL) + nowMilliseconds;
1214 //
1215 // Main "while" loop where the clients are initiated.
1216 //
1217 while(stopMilliseconds > nowMilliseconds)
1218 {
1219 j.alex 1.2
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 #else
1227 Sleep(RUN_DELAY * 1000);
1228 #endif
1229
1230 //
1231 // Quit if SIGINT, SIGABRT is caught
1232 // So the clients can be gracefully shutdown.
1233 //
1234 if(Quit)
1235 {
1236 log_file<<
1237 "Test interrupted by either SIGINT or SIGABORT."<<endl;
1238 TestFailed = true;
1239 break;
1240 j.alex 1.2 }
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 {
1252 String clientInst = String::EMPTY;
1253 //
1254 // Acquire the client Instance for each clients
1255 //
1256 if (!_clientTable[j].lookup(INSTANCE, clientInst))
1257 {
1258 String ErrReport = String("Invalid Property Value: ");
1259 ErrReport.append(INSTANCE);
1260 ErrReport.append("=");
1261 j.alex 1.2 ErrReport.append(clientInst);
1262 throw StressTestControllerException(ErrReport);
1263 }
1264 clientInstance[j] = atoi(clientInst.getCString());
1265
1266 //
1267 // Acquire and set client specific duration
1268 //
1269 clientStartMilliseconds[j] =
1270 TimeValue::getCurrentTime().toMilliseconds();
1271 clientStopMilliseconds[j] =
1272 clientStartMilliseconds[j] + _clientDurations[j];
1273
1274 //
1275 // for verbose only
1276 //
1277 if (verboseEnabled)
1278 {
1279 outPrintWriter<<"Client:"<<"["<<j<<"]"<<endl;
1280 log_file<<"Client:"<<"["<<j<<"]"<<endl;
1281 outPrintWriter<<"ClientStart:"<<
1282 j.alex 1.2 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 }
1299 log_file<<
1300 "Number of instances of this client: "<<
1301 clientInstance[j]<<endl;
1302 if(verboseEnabled)
1303 j.alex 1.2 {
1304 outPrintWriter<<
1305 "Number of instances of this client:"<<
1306 clientInstance[j]<<endl;
1307 }
1308 //
1309 // Execute each instance of the client.
1310 // - Additional required parameters are added to the
1311 // commands.
1312 // like, -clientid, -pidfile, -clientlog
1313 //
1314 for (int instanceID =0;instanceID<clientInstance[j];
1315 instanceID++)
1316 {
1317 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 j.alex 1.2 #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 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 j.alex 1.2 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 // 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 j.alex 1.2 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 //
1376 // Increment the actual number of clients
1377 //
1378 ++actual_client;
1379 } /* for(int instanceID =0;instanceID<clientInstance[j]...*/
1380
1381 }/* for(Uint32 j=0; j< _clientCount; j++) */
1382
1383 //
1384 //retrieve all PIDs and status;
1385 //
1386 clientPIDs = new pid_t[actual_client];
1387 j.alex 1.2 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 {
1405 outPrintWriter<<StressTestControllerCommand::COMMAND_NAME<<
1406 "::Getting client PID's and status. "<<endl;
1407 }
1408 j.alex 1.2 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 TestFailed = true;
1419 break;
1420 }
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 j.alex 1.2 */
1430
1431 //
1432 // Retreive all the client PIDs
1433 //
1434 int rc = _getClientPIDs(actual_client,log_file);
1435
1436 //
1437 // Get Current Time
1438 //
1439 nowMilliseconds = TimeValue::getCurrentTime().toMilliseconds();
1440
1441 //
1442 // Check tolerance level if its time
1443 //
1444 if (nowMilliseconds >= nextCheckupInMillisecs)
1445 {
1446 //
1447 // Set up the next tolerance time
1448 //
1449 nextCheckupInMillisecs =
1450 j.alex 1.2 (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 {
1458 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 }
1467 log_file<<StressTestControllerCommand::COMMAND_NAME<<
1468 "::Checking current tolerance level. "<<endl;
1469 //
1470 // Output Client info if verbose is enabled.
1471 j.alex 1.2 //
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 }
1489 }
1490 //
1491 // Check the actual tolerance level
1492 j.alex 1.2 //
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 // Within Tolerance - Continue tests.
1510 //
1511 log_file<<"********Tests are within tolerance.********* "<<
1512 endl;
1513 j.alex 1.2 if (verboseEnabled)
1514 {
1515 outPrintWriter<<
1516 " ********Tests are within tolerance.**********"<<
1517 endl;
1518 }
1519 } /* if (nowMilliseconds >= nextCheckupInMillisecs)*/
1520 //
1521 // Stop clients with delay
1522 //
1523 for (Uint32 clientID=0; clientID < _clientCount; clientID++)
1524 {
1525 //
1526 // Get Current time
1527 //
1528 nowMilliseconds =
1529 TimeValue::getCurrentTime().toMilliseconds();
1530
1531 //
1532 // Stop only running clients as required.
1533 //
1534 j.alex 1.2 if (!clientStopped[clientID])
1535 {
1536 //
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 j.alex 1.2 clientPIDs[clientID+instanceID]<<endl;
1556 if (verboseEnabled)
1557 {
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 //
1576 j.alex 1.2 // Required for Windows
1577 //
1578 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 #endif
1597 j.alex 1.2 //
1598 // Set the client as inactive.
1599 //
1600 clientActive[clientID + instanceID] = false;
1601 }/* for (int instanceID =0;instanceID<clientInst..*/
1602 //
1603 // indicate that the client was stopped.
1604 //
1605 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 j.alex 1.2 {
1619 //
1620 // Only restart clients that are waiting.
1621 //
1622 if (clientDelayed[clientID])
1623 {
1624 //
1625 // When waiting period is consumed.
1626 //
1627 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 j.alex 1.2 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 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 j.alex 1.2 {
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 "%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 j.alex 1.2 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 _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.2
1703 } /* while(stopMilliseconds > nowMilliseconds) */
1704
1705 }//try
1706
1707 catch (const StressTestControllerException& e)
1708 {
1709 errPrintWriter << StressTestControllerCommand::COMMAND_NAME <<
1710 ": " << e.getMessage () << endl;
1711 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 j.alex 1.2
1724 #ifndef PEGASUS_OS_TYPE_WINDOWS
1725 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 int rc = _getClientPIDs(actual_client,log_file);
1734 if (!rc)
1735 {
1736 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 }
1743 tmTime = getCurrentActualTime();
1744 j.alex 1.2 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 for (int i=0;i<actual_client;i++)
1747 {
1748 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 //
1755 // Required for Windows
1756 //
1757 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 j.alex 1.2 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 #endif
1779 }
1780 if (verboseEnabled)
1781 {
1782 outPrintWriter<<"Cleaning all resources"<<endl;
1783 }
1784 log_file<<"Cleaning all resources."<<endl;
1785 cleanupProcess();
1786 j.alex 1.2
1787 //
1788 // Waiting to allow clients to shutdown
1789 //
1790 #ifndef PEGASUS_OS_TYPE_WINDOWS
1791 sleep(SHUTDOWN_DELAY);
1792 #else
1793 Sleep(SHUTDOWN_DELAY * 1000);
1794 #endif
1795 //
1796 // If the test did not run to completition
1797 //
1798 if (TestFailed)
1799 return(RC_ERROR);
1800
1801 return (RC_SUCCESS);
1802 } /* execute */
1803
1804
1805 /*
1806 Retrieves the contents of the config file if specified or uses default
1807 j.alex 1.2 values from either the default config file
1808
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 Boolean StressTestControllerCommand::getFileContent(
1818 String fileName,
1819 ostream& log_file)
1820 {
1821 String configData = String::EMPTY;
1822 String line;
1823 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.2
1829 ifstream ifs;
1830
1831 //
1832 // Open the config file and read the stress test configuration data
1833 //
1834 Open(ifs,fileName);
1835 if (!ifs)
1836 {
1837 log_file<<StressTestControllerCommand::COMMAND_NAME<<
1838 "::Cannot read config file: "<<fileName<<endl;
1839 throw NoSuchFile(fileName);
1840 }
1841
1842 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.2 //
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 try
1859 {
1860 //
1861 // Parse each line of Config file
1862 //
1863 _parseLine(line,lineNumber,name,value,log_file);
1864 }
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.2 catch (Exception& e)
1871 {
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 log_file<<StressTestControllerCommand::COMMAND_NAME<<"::"
1881 <<msg<<endl;
1882 isSuccess = false;
1883 }
1884 catch(...)
1885 {
1886 char line_num[10];
1887 sprintf(line_num, "%d", lineNumber);
1888 ErrReports.append("\n ");
1889 ErrReports.append("line#");
1890 ErrReports.append(line_num);
1891 j.alex 1.2 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 }
1899
1900 if ((IsClientOptions)||(IgnoreLine))
1901 {
1902 IsClientOptions = false;
1903 IgnoreLine = false;
1904 continue;
1905 }
1906 //
1907 // If its a client Update the table
1908 //
1909 if (IsAClient)
1910 {
1911 _currClient=name;
1912 j.alex 1.2 _currClientCount=_clientCount;
1913 //
1914 // save the client details in a table
1915 //
1916 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 }
1924 else
1925 {
1926 //
1927 // Common properties are updated only if they are valid.
1928 //
1929 if (isSuccess)
1930 {
1931 //
1932 // Store the property name and value in the table
1933 j.alex 1.2 //
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 #ifdef DEBUG
1944 cout<< "Property Name:duplicate name already saved: "<<
1945 name<<endl;
1946 #endif
1947 log_file<<StressTestControllerCommand::COMMAND_NAME<<
1948 "::Duplicate property name "<<name<<" already saved."<<
1949 endl;
1950 }
1951 }
1952 }
1953
1954 j.alex 1.2 }
1955 ifs.close();
1956 //
1957 // If a client is not read from the config file
1958 //
1959 if ((lineNumber==0)||(!_clientCount))
1960 {
1961 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 }
1968 //
1969 // Error was found.
1970 //
1971 if (!isSuccess)
1972 {
1973 //
1974 // cleanup allocated memory
1975 j.alex 1.2 //
1976 cleanupProcess();
1977 throw StressTestControllerException(ErrReports);
1978 }
1979
1980 log_file<<StressTestControllerCommand::COMMAND_NAME<<
1981 "::Common Properties:"<<endl;
1982 if (verboseEnabled)
1983 {
1984 cout<<StressTestControllerCommand::COMMAND_NAME<<
1985 "::Common Properties:"<<endl;
1986 }
1987 for (Table::Iterator i = _propertyTable->start(); i; i++)
1988 {
1989 log_file<<" "<<i.key()<<"\t= "<<i.value()<<endl;
1990 if (verboseEnabled)
1991 {
1992 cout<<" "<<i.key()<<"\t= "<<i.value()<<endl;
1993 }
1994 }
1995 if (verboseEnabled)
1996 j.alex 1.2 {
1997 cout<<"Total clients found:"<<_clientCount<<endl;
1998 cout<<"CLIENT TABLE CONTENTS:"<<endl;
1999 }
2000 log_file<<StressTestControllerCommand::COMMAND_NAME<<
2001 "::Client Properties:"<<endl;
2002 for (Uint32 j = 0; j < _clientCount; j++)
2003 {
2004 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.2 }
2018
2019
2020 if (isSuccess)
2021 {
2022 log_file<<StressTestControllerCommand::COMMAND_NAME<<
2023 "::Successfully retreived config values from" <<
2024 " config file: "<<fileName<<endl;
2025 }
2026 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 j.alex 1.2 @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 Boolean StressTestControllerCommand::_validateConfiguration(
2047 String & vars,
2048 const String & value,
2049 ostream& log_file)
2050 {
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 j.alex 1.2 {
2060 if (!_hostNameSpecified)
2061 {
2062 _hostName = value;
2063 }
2064 }
2065 else
2066 {
2067
2068 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 j.alex 1.2 }
2081 }
2082 else
2083 {
2084 _hostName = value;
2085 }
2086 }
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 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.2 if (vPortNumber > _MAX_PORTNUMBER)
2102 {
2103 //
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 }
2119
2120 }/* else if (String::equalNoCase ... */
2121 else if (String::equalNoCase(vars,SSL))
2122 j.alex 1.2 {
2123 log_file<<StressTestControllerCommand::COMMAND_NAME<<
2124 "::SSL enabled in config. "<<endl;
2125 if (!_useSSL)
2126 {
2127 _useSSL = true;
2128 }
2129 }
2130 else if (String::equalNoCase(vars,USERNAME))
2131 {
2132 vars=String::EMPTY;
2133 vars.append(USERNAME);
2134 log_file<<StressTestControllerCommand::COMMAND_NAME<<
2135 "::UserName specified in config = "<<value<<endl;
2136 if (!_userNameSpecified)
2137 {
2138 _userName = value;
2139 }
2140 }
2141 else if (String::equalNoCase(vars,PASSWORD))
2142 {
2143 j.alex 1.2 vars=String::EMPTY;
2144 vars.append(PASSWORD);
2145 if(!_passwordSpecified)
2146 {
2147 _password = value;
2148 }
2149 log_file<<StressTestControllerCommand::COMMAND_NAME<<
2150 "::Password specified in config = "<<value<<endl;
2151 }
2152 else if (String::equalNoCase(vars,DURATION))
2153 {
2154 vars=String::EMPTY;
2155 vars.append(DURATION);
2156 //
2157 // converting to a double
2158 //
2159 if (!IsAClient)
2160 {
2161 _duration = atof(value.getCString());
2162 if (_duration > _MIN_DURATION)
2163 {
2164 j.alex 1.2 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 }
2174 }
2175 else if (String::equalNoCase(vars,TOLERANCELEVEL))
2176 {
2177 _toleranceLevel = atoi(value.getCString());
2178 log_file<<StressTestControllerCommand::COMMAND_NAME<<
2179 "::ToleranceLevel specified in config = "<<value<<endl;
2180 if (_toleranceLevel > _MAX_TOLERANCE)
2181 {
2182 if(verboseEnabled)
2183 {
2184 cout<<StressTestControllerCommand::COMMAND_NAME <<
2185 j.alex 1.2 "::Invalid Tolerance level was specified. "<<endl;
2186 }
2187 log_file<<StressTestControllerCommand::COMMAND_NAME<<
2188 "::Invalid Tolerance level was specified. "<<endl;
2189
2190 return false;
2191 }
2192 }
2193 else if (String::equalNoCase(vars,NAMESPACE))
2194 {
2195 _nameSpace = value;
2196 log_file<<StressTestControllerCommand::COMMAND_NAME <<
2197 "::NameSpace specified in config = "<<value<<endl;
2198 }
2199 else if (String::equalNoCase(vars,CLASSNAME))
2200 {
2201 _className = value;
2202 log_file<<StressTestControllerCommand::COMMAND_NAME<<
2203 "::Class name specified in config = "<<value<<endl;
2204 }
2205 else
2206 j.alex 1.2 {
2207 if (!IsAClient)
2208 {
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 if (instance <=0)
2216 {
2217 //
2218 // Invalid Instance value
2219 //
2220 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 j.alex 1.2 clientName.append(vars.getCString());
2228 #ifdef PEGASUS_OS_TYPE_WINDOWS
2229 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 if (Index != 0)
2237 {
2238 clientName = String(DEFAULT_BINDIR);
2239 testString.append(vars.getCString());
2240 clientName.append(testString.getCString());
2241 #ifdef PEGASUS_OS_TYPE_WINDOWS
2242 clientName.append(".exe");
2243 #endif
2244 if (!FileSystem::exists(clientName))
2245 {
2246 //
2247 // Invalid client name
2248 j.alex 1.2 //
2249 IsValid = false;
2250 }
2251 else
2252 {
2253 IsValid = true;
2254 vars=String::EMPTY;
2255 vars.append(testString.getCString());
2256 }
2257 }
2258 else
2259 {
2260
2261 //
2262 // Invalid client name
2263 //
2264 IsValid = false;
2265 }
2266 }
2267 else
2268 {
2269 j.alex 1.2 IsValid = true;
2270 }
2271 if (!IsValid)
2272 {
2273 if (verboseEnabled)
2274 {
2275 cout<<StressTestControllerCommand::COMMAND_NAME <<
2276 "::Invalid Client Name = "<<vars<<endl;
2277 }
2278 String ErrReport = String("Invalid Client Name:");
2279 ErrReport.append(vars.getCString());
2280 throw StressTestControllerException(ErrReport);
2281 }
2282 return IsValid;
2283 }
2284 log_file<<StressTestControllerCommand::COMMAND_NAME<<"::"<<vars<<
2285 " = "<<value<<endl;
2286 //
2287 // otherwise accept the properties listed with the clients.
2288 //
2289 }
2290 j.alex 1.2 return true;
2291
2292 } /* _validateConfiguration */
2293
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.2 void StressTestControllerCommand::_getClientOptions(
2312 const Char16* p,
2313 ostream& log_file)
2314 {
2315 //
2316 // Get the property name
2317 //
2318 String name = String::EMPTY;
2319 String value = String::EMPTY;
2320
2321 while (*p != ']')
2322 {
2323 //
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.2 throw StressTestControllerException(StressTestControllerException::INVALID_OPTION);
2333 }
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 j.alex 1.2 //
2354 if (*p != '=')
2355 {
2356 throw StressTestControllerException(StressTestControllerException::INVALID_OPERATOR);
2357 }
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.2 {
2375 value.append(*p++);
2376 }
2377 //
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 throw StressTestControllerException(StressTestControllerException::MISSING_BRACE);
2389 }
2390 if(value == String::EMPTY)
2391 {
2392 throw StressTestControllerException(StressTestControllerException::MISSING_VALUE);
2393 }
2394
2395 j.alex 1.2 #ifdef DEBUG
2396 cout<<"name="<<name<<endl;
2397 cout<<"Before validate config: value="<<value<<endl;
2398 #endif
2399 //
2400 // validate client property
2401 //
2402 Boolean IsValid=_validateConfiguration(name,value,log_file);
2403 if(!IsValid)
2404 {
2405 String ErrReport = String("Invalid Client property value: ");
2406 ErrReport.append(name);
2407 ErrReport.append("=");
2408 ErrReport.append(value);
2409 throw StressTestControllerException(ErrReport);
2410 }
2411 //
2412 // Save client property in client table if valid.
2413 //
2414 if (!_clientTable[_currClientCount].insert(name,value))
2415 {
2416 j.alex 1.2 //
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 if (verboseEnabled)
2422 {
2423 cout<< "duplicate name already saved: "<<name<<endl;
2424 }
2425 }
2426 if (*p ==',')
2427 {
2428 name = String::EMPTY;
2429 value = String::EMPTY;
2430 p++;
2431 continue;
2432 }
2433 }
2434
2435 if ((name == String::EMPTY)||(value == String::EMPTY))
2436 {
2437 j.alex 1.2 String ErrReport = String("Missing Name & Value for client option:");
2438 throw StressTestControllerException(ErrReport);
2439 }
2440 } /* _getClientOptions */
2441
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 j.alex 1.2
2459 @param actual_clients The actual number of clients executed by the
2460 Controller.
2461 @param log_file The log file.
2462
2463 @return true if the status and PIDs were read successfully
2464 false Failed to read the status & PIDs of clients.
2465
2466 */
2467 Boolean StressTestControllerCommand::_getClientPIDs(
2468 int actual_clients,
2469 ostream& log_file)
2470 {
2471
2472 ifstream ifs;
2473
2474 //
2475 // Make a temp copy of the file
2476 //
2477 Boolean cTempFile = FileSystem::copyFile(
2478 _stressTestClientPIDFile,
2479 j.alex 1.2 _tmpStressTestClientPIDFile);
2480
2481 if(!cTempFile)
2482 {
2483 cout<<"Cannot copy file "<<_stressTestClientPIDFile<<endl;
2484 log_file<<StressTestControllerCommand::COMMAND_NAME<<
2485 "::Cannot copy PID file: "<<_stressTestClientPIDFile<<endl;
2486 return (false);
2487 }
2488 //
2489 // Open the temp PID file and retreive all the client PIDs and status
2490 //
2491 Open(ifs,_tmpStressTestClientPIDFile);
2492
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 j.alex 1.2 //
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 while (*p && isspace(*p))
2511 {
2512 p++;
2513 }
2514
2515 //
2516 // Skip comment lines
2517 //
2518 if ((!*p)||(*p == '#'))
2519 {
2520 continue;
2521 j.alex 1.2 }
2522
2523 //
2524 // Get the client ID
2525 //
2526 String client = String::EMPTY;
2527 while (isalnum(*p) || *p == '_')
2528 {
2529 client.append(*p++);
2530 }
2531
2532 //
2533 // Skip whitespace after property name
2534 //
2535 while (*p && isspace(*p))
2536 {
2537 p++;
2538 }
2539
2540 //
2541 // Expecting a colon
2542 j.alex 1.2 //
2543 if (*p != ':')
2544 {
2545 ifs.close();
2546 log_file<<StressTestControllerCommand::COMMAND_NAME<<
2547 "::Syntax Error in PID file line number:"<<lineNumber<<endl;
2548 FileSystem::removeFile(_tmpStressTestClientPIDFile);
2549 return(isSuccess = false);
2550 }
2551
2552 //
2553 // point to next character in line.
2554 //
2555 p++;
2556
2557 //
2558 // Expecting a colon
2559 //
2560 if (*p != ':')
2561 {
2562 ifs.close();
2563 j.alex 1.2 log_file<<StressTestControllerCommand::COMMAND_NAME<<
2564 "::Syntax Error in PID file line number:"<<lineNumber<<endl;
2565 FileSystem::removeFile(_tmpStressTestClientPIDFile);
2566 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 while (*p && isspace(*p))
2578 {
2579 p++;
2580 }
2581
2582 //
2583 // Get the client PID
2584 j.alex 1.2 //
2585 String clntPID = String::EMPTY;
2586 while (isalnum(*p) || *p == '_')
2587 {
2588 clntPID.append(*p++);
2589 }
2590
2591 //
2592 // Skip whitespace after property name
2593 //
2594 while (*p && isspace(*p))
2595 {
2596 p++;
2597 }
2598
2599 //
2600 // Expecting a colon
2601 //
2602 if (*p != ':')
2603 {
2604 ifs.close();
2605 j.alex 1.2 log_file<<StressTestControllerCommand::COMMAND_NAME <<
2606 "::Syntax Error in PID file line number:"<<lineNumber<<endl;
2607 FileSystem::removeFile(_tmpStressTestClientPIDFile);
2608 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 log_file<<StressTestControllerCommand::COMMAND_NAME <<
2623 "::Syntax Error in PID file line number:"<<lineNumber<<endl;
2624 FileSystem::removeFile(_tmpStressTestClientPIDFile);
2625 return(isSuccess = false);
2626 j.alex 1.2 }
2627 p++;
2628
2629 //
2630 // Skip whitespace after the colon if any
2631 //
2632 while (*p && isspace(*p))
2633 {
2634 p++;
2635 }
2636
2637 String clntStatus = String::EMPTY;
2638 while (isalnum(*p) || *p == '_')
2639 {
2640 clntStatus.append(*p++);
2641 }
2642
2643 //
2644 // Skip whitespace after property name
2645 //
2646 while (*p && isspace(*p))
2647 j.alex 1.2 {
2648 p++;
2649 }
2650
2651 //
2652 // Expecting a colon
2653 //
2654 if (*p != ':')
2655 {
2656 ifs.close();
2657 log_file<<StressTestControllerCommand::COMMAND_NAME <<
2658 "::Syntax Error in PID file line number:"<<lineNumber<<endl;
2659 FileSystem::removeFile(_tmpStressTestClientPIDFile);
2660 return(isSuccess = false);
2661 }
2662
2663 //
2664 // next character in line.
2665 //
2666 p++;
2667
2668 j.alex 1.2 if (*p != ':')
2669 {
2670 ifs.close();
2671 log_file<<StressTestControllerCommand::COMMAND_NAME<<
2672 "::Syntax Error in PID file line number:"<<lineNumber<<endl;
2673 FileSystem::removeFile(_tmpStressTestClientPIDFile);
2674 return(isSuccess = false);
2675 }
2676 //
2677 // next character in line.
2678 //
2679 p++;
2680 //
2681 // Skip whitespace after the colon if any
2682 //
2683 while (*p && isspace(*p))
2684 {
2685 p++;
2686 }
2687
2688 //
2689 j.alex 1.2 // Get the client timestamp
2690 //
2691 String clntTmStmp = String::EMPTY;
2692 while (isalnum(*p))
2693 {
2694 clntTmStmp.append(*p++);
2695 }
2696
2697 //
2698 // Store the PID, Status and TimeStamp for each client
2699 //
2700 if(atoi(client.getCString()) <= actual_clients)
2701 {
2702 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 j.alex 1.2 }
2711 else
2712 {
2713 if (verboseEnabled)
2714 {
2715 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 }
2722 }
2723 //
2724 // remove the temporary file.
2725 //
2726 FileSystem::removeFile(_tmpStressTestClientPIDFile);
2727 return(isSuccess = true);
2728 }/* _getClientPIDs */
2729
2730 /*
2731 j.alex 1.2 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 @parm name The property name that will be retrieved.
2751 @parm value The property value of the name.
2752 j.alex 1.2 @parm log_file The log file.
2753
2754 @return true Succesfully parsed the line.
2755 false Failed to parse the lines successfully.
2756 */
2757 Boolean StressTestControllerCommand::_parseLine(
2758 const String & line,
2759 int lineNumber,
2760 String &name,
2761 String &value,
2762 ostream& log_file)
2763 {
2764
2765 const Char16* p;
2766 p = line.getChar16Data();
2767
2768 //
2769 // Skip whitespace
2770 //
2771 while (*p && isspace(*p))
2772 {
2773 j.alex 1.2 p++;
2774 }
2775
2776 //
2777 // Ignore empty lines
2778 //
2779 if (!*p)
2780 {
2781 IgnoreLine = true;
2782 return IgnoreLine;
2783 }
2784
2785 //
2786 // Skip comment lines
2787 //
2788 if (*p == '#')
2789 {
2790 IgnoreLine = true;
2791 return IgnoreLine;
2792 }
2793
2794 j.alex 1.2 //
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.2 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 //
2825 // get and validate client options
2826 //
2827 _getClientOptions(p,log_file);
2828 }
2829 catch (Exception& e)
2830 {
2831 String msg(e.getMessage());
2832 if ((name == String::EMPTY)
2833 ||(value == String::EMPTY))
2834 {
2835 msg.append(" in ");
2836 j.alex 1.2 msg.append(line.getCString());
2837 }
2838 throw StressTestControllerException(msg);
2839 }
2840 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 throw StressTestControllerException(msg);
2849 }
2850
2851 //
2852 // Successfully retrieved all the client options.
2853 //
2854 return true;
2855 }
2856
2857 j.alex 1.2 //
2858 // Get Common Properties
2859 //
2860 name = String::EMPTY;
2861
2862 //
2863 // Invalid Common Property name
2864 //
2865 if (!(isalpha(*p) || *p == '_'))
2866 {
2867 String ErrReport = String("Invalid Property Value: ");
2868 ErrReport.append(name);
2869 ErrReport.append("=");
2870 ErrReport.append(value);
2871 throw StressTestControllerException(ErrReport);
2872 }
2873
2874 //
2875 // Save the property Name
2876 //
2877 name.append(*p++);
2878 j.alex 1.2 while (isalnum(*p) || *p == '_')
2879 {
2880 name.append(*p++);
2881 }
2882
2883 //
2884 // Skip whitespace after property name
2885 //
2886 while (*p && isspace(*p))
2887 {
2888 p++;
2889 }
2890
2891 //
2892 // Expect an equal sign
2893 //
2894 if (*p != '=')
2895 {
2896 String ErrReport = String("Invalid Property Value: ");
2897 ErrReport.append(name);
2898 ErrReport.append("=");
2899 j.alex 1.2 ErrReport.append(value);
2900 throw StressTestControllerException(ErrReport);
2901 }
2902
2903 //
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 j.alex 1.2 value = String::EMPTY;
2921 while (*p)
2922 {
2923 value.append(*p++);
2924 }
2925 #ifdef DEBUG
2926 cout<<"name="<<name<<endl;
2927 cout<<"value="<<value<<endl;
2928 #endif
2929 IsAClient = false;
2930 Boolean IsValid = false;
2931 //
2932 // Validate property and its value
2933 //
2934 try
2935 {
2936 IsValid=_validateConfiguration(name,value,log_file);
2937 }
2938 catch (Exception& e)
2939 {
2940 String msg(e.getMessage());
2941 j.alex 1.2 throw StressTestControllerException(msg);
2942 }
2943 if (!IsValid)
2944 {
2945 String ErrReport = String("Invalid Property Value: ");
2946 ErrReport.append(name);
2947 ErrReport.append("=");
2948 ErrReport.append(value);
2949 throw StressTestControllerException(ErrReport);
2950 }
2951 return true;
2952 } /* _parseLine */
2953
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 j.alex 1.2 @return true Succesfully stored the name or instance.
2963 false Failed to store the name or instance.
2964 */
2965 Boolean StressTestControllerCommand::_storeClientDetails(
2966 String name,
2967 String value)
2968 {
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 for (Uint32 i =0;i<_clientCount;i++)
2978 {
2979 tempClientTable[i] = _clientTable[i];
2980 }
2981 delete [] _clientTable;
2982 _clientTable = tempClientTable;
2983 j.alex 1.2 }
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 if (verboseEnabled)
2994 {
2995 cout<< "Duplicate Client already saved: "<<endl;
2996 }
2997 return false;
2998 }
2999
3000 //
3001 // Store the number of instances for the client in the table
3002 //
3003 if (!_clientTable[_clientCount].insert(INSTANCE, value))
3004 j.alex 1.2 {
3005
3006 //
3007 // Duplicate property, ignore the new property value.
3008 //
3009 if(verboseEnabled)
3010 {
3011 cout<< "Duplicate Instance already saved: "<<endl;
3012 }
3013 return false;
3014 }
3015 ++_clientCount;
3016 return true;
3017 } /* _storeClientDetails */
3018
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 j.alex 1.2
3026 @return true Clients with tolerance.
3027 false Clients failed tolerance.
3028 */
3029 Boolean StressTestControllerCommand::_checkToleranceLevel(
3030 int actual_client,
3031 Uint64 nowMilliseconds,
3032 ostream& log_file)
3033 {
3034 int count = 0;
3035 int failed_count = 0;
3036 Uint64 lastUpdateinMilliSec =0;
3037 Boolean withinTolerance = false;
3038
3039 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 j.alex 1.2 ++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 //
3056 //check with the last timestamp
3057 //
3058 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 j.alex 1.2 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 }
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 j.alex 1.2 &&((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 {
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 //
3108 // Save previous time stamp of client
3109 j.alex 1.2 //
3110 prev_clientTimeStamp[i] = clientTimeStamp[i];
3111 prev_clientStatus[i] = clientStatus[i];
3112 } /* if (clientActive[i]) */
3113 }
3114 //
3115 // check actual tolerance
3116 //
3117 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 j.alex 1.2 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 }
3139 //
3140 // All process are stopped.
3141 //
3142 return(withinTolerance = true);
3143 } /* _checkToleranceLevel */
3144
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 j.alex 1.2 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 //
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 //
3170 // Populating default client attributes
3171 //
3172 j.alex 1.2 for (Uint32 i=0;i<_clientCount; i++)
3173 {
3174 //
3175 // Adding the default instance value to each client table
3176 //
3177 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 j.alex 1.2 {
3194 cout<< "Duplicate name already saved: "<<NAME<<endl;
3195 }
3196 }
3197 log_file << "Stress Test Client Name:"<<MODELWALK_CLIENT<< endl;
3198 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 j.alex 1.2 }
3215 log_file << "Stress Test Client Name:" <<WRAPPER_CLIENT<< endl;
3216 if (verboseEnabled)
3217 {
3218 cout << "Stress Test Client Name:" <<WRAPPER_CLIENT<< endl;
3219 }
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 j.alex 1.2 cout<< "Duplicate name already saved: "<<OPTIONS<<endl;
3236 }
3237 }
3238 log_file<< " Client Command & options: CLI niall"<<
3239 endl;
3240 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
3250 } /* getDefaultClients */
3251
3252
3253
3254
3255 /**
3256 j.alex 1.2 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 char pid_str[15];
3270 ofstream log_file;
3271 ofstream pid_file;
3272 ofstream clntlog_file;
3273
3274 sprintf(pid_str, "%d", getpid());
3275
3276 //
3277 j.alex 1.2 // Stress Controller Log file
3278 //
3279 _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 //
3292 // StressClient PID file
3293 //
3294 _stressTestClientPIDFile.append(pegasusHome);
3295 _stressTestClientPIDFile.append(DEFAULT_TMPDIR);
3296 FileSystem::makeDirectory(_stressTestClientPIDFile);
3297 _stressTestClientPIDFile.append(pid_str);
3298 j.alex 1.2 _stressTestClientPIDFile.append("_StressTestClients");
3299 _stressTestClientPIDFile.append(strTime);
3300 _stressTestClientPIDFile.append("pid");
3301
3302 //
3303 // StressClient Log file
3304 //
3305 _stressTestClientLogFile.append(pegasusHome);
3306 _stressTestClientLogFile.append(DEFAULT_LOGDIR);
3307 _stressTestClientLogFile.append(pid_str);
3308 _stressTestClientLogFile.append("_StressTestClients");
3309 _stressTestClientLogFile.append(".log");
3310
3311 //
3312 // Temporary StressClient PID/status file
3313 //
3314 _tmpStressTestClientPIDFile.append(pegasusHome);
3315 _tmpStressTestClientPIDFile.append(DEFAULT_TMPDIR);
3316 _tmpStressTestClientPIDFile.append(pid_str);
3317 _tmpStressTestClientPIDFile.append("TEMP");
3318 _tmpStressTestClientPIDFile.append("_Clients");
3319 j.alex 1.2 _tmpStressTestClientPIDFile.append(".pid");
3320
3321 //
3322 // Translate slashed for appropriate OS
3323 //
3324 FileSystem::translateSlashes(_stressTestClientPIDFile);
3325 FileSystem::translateSlashes(_stressTestClientLogFile);
3326 FileSystem::translateSlashes(_stressTestLogFile);
3327 FileSystem::translateSlashes(_tmpStressTestClientPIDFile);
3328
3329 //
3330 // open the file
3331 //
3332 OpenAppend(log_file,_stressTestLogFile);
3333 Open(pid_file,_stressTestClientPIDFile);
3334 Open(clntlog_file,_stressTestClientLogFile);
3335
3336 //
3337 // Failed to open the log file
3338 //
3339 if (!log_file)
3340 j.alex 1.2 {
3341 log_file.close();
3342 pid_file.close();
3343 clntlog_file.close();
3344 cout<<"Cannot get file "<<_stressTestLogFile<<endl;
3345 return false;
3346
3347 }
3348 //
3349 // Failed to open the pid file
3350 //
3351 if (!pid_file)
3352 {
3353 cout<<"Cannot get file "<<_stressTestClientPIDFile<<endl;
3354 log_file<<StressTestControllerCommand::COMMAND_NAME<<
3355 "Cannot read file "<<_stressTestClientPIDFile<<endl;
3356 log_file.close();
3357 clntlog_file.close();
3358 return false;
3359 }
3360 //
3361 j.alex 1.2 // Failed to open the clntlog file
3362 //
3363 if (!clntlog_file)
3364 {
3365 log_file<<StressTestControllerCommand::COMMAND_NAME<<
3366 "Cannot read file "<<_stressTestClientLogFile<<endl;
3367 log_file.close();
3368 pid_file.close();
3369 return false;
3370 }
3371
3372 //
3373 // Successfully opened all the files.
3374 //
3375 pid_file<<"#"<<StressTestControllerCommand::COMMAND_NAME<<
3376 " has the following clients:: \n";
3377 clntlog_file<<"#"<<StressTestControllerCommand::COMMAND_NAME<<
3378 "::Process ID:"<<getpid()<<endl;
3379 clntlog_file.close();
3380 pid_file.close();
3381 return true;
3382 j.alex 1.2
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 void StressTestControllerCommand::removeUnusedFiles()
3391 {
3392 FileSystem::removeFile(_stressTestClientPIDFile);
3393 FileSystem::removeFile(_stressTestClientLogFile);
3394 }
3395
3396 PEGASUS_NAMESPACE_END
3397
3398 /**
3399 Cleanup function for stressTestController to free allocated
3400 memory used to execute clients.
3401 */
3402 void cleanupProcess()
3403 j.alex 1.2 {
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 struct tm getCurrentActualTime()
3418 {
3419 struct tm tmTime;
3420 time_t inTime=time(NULL);
3421 #ifdef PEGASUS_OS_TYPE_WINDOWS
3422 tmTime=*localtime(&inTime);
3423 #else
3424 j.alex 1.2 localtime_r(&inTime,&tmTime);
3425 #endif
3426 return tmTime;
3427 }
3428
3429 /**
3430 Signal handler for SIGINT, SIGABRT.
3431
3432 @param signum the signal identifier
3433 */
3434 void endAllTests(int signum)
3435 {
3436 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 j.alex 1.2 }
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 }
3458 }
3459 }
3460 //
3461 // Sets the variable that will interupt stress tests
3462 //
3463 Quit = true;
3464 } /* endAllTests */
3465
3466 j.alex 1.2 /**
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 }/* convertUint64toString(..) */
|