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