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