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