1 martin 1.7 //%LICENSE////////////////////////////////////////////////////////////////
|
2 martin 1.8 //
|
3 martin 1.7 // Licensed to The Open Group (TOG) under one or more contributor license
4 // agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
5 // this work for additional information regarding copyright ownership.
6 // Each contributor licenses this file to you under the OpenPegasus Open
7 // Source License; you may not use this file except in compliance with the
8 // License.
|
9 martin 1.8 //
|
10 martin 1.7 // Permission is hereby granted, free of charge, to any person obtaining a
11 // copy of this software and associated documentation files (the "Software"),
12 // to deal in the Software without restriction, including without limitation
13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 // and/or sell copies of the Software, and to permit persons to whom the
15 // Software is furnished to do so, subject to the following conditions:
|
16 martin 1.8 //
|
17 martin 1.7 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
|
19 martin 1.8 //
|
20 martin 1.7 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
21 martin 1.8 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
22 martin 1.7 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
27 martin 1.8 //
|
28 martin 1.7 //////////////////////////////////////////////////////////////////////////
|
29 j.alex 1.2 //
30 //%/////////////////////////////////////////////////////////////////////////////
31
32 #include "TestStressTestClient.h"
33
34 PEGASUS_USING_PEGASUS;
35 PEGASUS_USING_STD;
36
37 /** Constructor - Initializes the time variables and defines the Options
38 Table.
39 */
40 TestStressTestClient::TestStressTestClient()
41 {
42 startMilliseconds = 0;
43 nowMilliseconds = 0;
44 nextCheckupInMillisecs = 0;
45 static struct OptionRow testOptionsTable[] = {
46 {"namespace", "", false, Option::STRING, 0, 0, "namespace",
47 "specifies namespace to be used for the test"},
48
49 {"classname", "", false, Option::STRING, 0, 0, "classname",
50 j.alex 1.2 "specifies classname to be used for the test"},
51
52 {"verbose", "false", false, Option::BOOLEAN, 0, 0, "verbose",
53 "If set, outputs extra information "},
54
55 {"help", "false", false, Option::BOOLEAN, 0, 0, "help",
56 "Prints help message with command line options "},
57
|
58 thilo.boehm 1.5 #ifdef PEGASUS_HAS_SSL
|
59 j.alex 1.2 {"ssl", "false", false, Option::BOOLEAN, 0, 0, "ssl", "use SSL"},
|
60 thilo.boehm 1.5 #endif
|
61 j.alex 1.2
62 {"username", "", false, Option::STRING, 0, 0, "username",
63 "Specifies user name"},
64
65 {"password", "", false, Option::STRING, 0, 0, "password",
66 "Specifies password"},
67
68 {"port", "", false, Option::STRING, 0, 0, "port",
69 "Port number on host"},
70
71 {"clientid", "", true, Option::STRING, 0, 0, "clientid",
72 "Client identification by controller"},
73
74 {"pidfile", "", true, Option::STRING, 0, 0, "pidfile",
75 "Client process log file"},
76
77 {"clientlog", "", true, Option::STRING, 0, 0, "clientlog",
78 "Client error log file"},
79
80 {"hostname", "", false, Option::STRING, 0, 0, "hostname",
81 "Host name"}
82 j.alex 1.2 };
83 optionCount = sizeof(testOptionsTable) / sizeof(testOptionsTable[0]);
84 optionsTable = testOptionsTable;
85 }
86 /**
87 OPTION MANAGEMENT
88 */
89
90 /** GetOptions function - This function sets up the options from
91 testOptionsTable which is initialized through constructor
92 using the option manager.
93 const char* optionName;
94 const char* defaultValue;
95 int required;
96 Option::Type type;
97 char** domain;
98 Uint32 domainSize;
99 const char* commandLineOptionName;
100 const char* optionHelpMessage;
101 */
102 int TestStressTestClient::GetOptions(
103 j.alex 1.2 OptionManager& om,
104 int& argc,
105 char** argv,
106 OptionRow* newOptionsTable, Uint32 cOptionCount)
107 {
108 char **argvv;
109 int counter = 0;
110 String argument = String::EMPTY;
111
112
113 //
114 // om.registerOptions(newOptionsTable, (const)cOptionCount);
115 //
116 om.registerOptions(newOptionsTable, cOptionCount);
117 argvv = argv;
118
119 //
120 // Following section is introduced to ignore options not
121 // required by a client.
122 //
123 for (int i = 1; i < argc; i++)
124 j.alex 1.2 {
125 argument = String::EMPTY;
126 const char* arg = argv[i];
127
128 //
129 // Check for - option.
130 //
131 if (*arg == '-')
132 {
133 //
134 // Look for the option.
135 //
136 argument.append(arg + 1);
137 const Option* option = om.lookupOption(argument);
138
139 //
140 // Get the option argument if any.
141 //
142 if (option)
143 {
144 argvv[++counter]=argv[i];
145 j.alex 1.2 if (option->getType() != Option::BOOLEAN)
146 {
147 if (i + 1 != argc)
148 {
149 argvv[++counter] = argv[++i];
150 }
151 }
152 }
153 }
154 }
155 ++counter;
156 om.mergeCommandLine(counter, argvv);
157 om.checkRequiredOptions();
158 return counter;
159 }
160
161 /** This method is used by clients to register client specific required
162 options to the option table. All these options are taken as mandatory one.
163 */
164 OptionRow *TestStressTestClient::generateClientOptions(
165 OptionRow* clientOptionsTable,
166 j.alex 1.2 Uint32 clientOptionCount,
167 Uint32& totalOptions)
168 {
169
170 Uint32 currOptionCount = 0;
171 static struct OptionRow *newOptionsTable = 0;
172
173 totalOptions = optionCount + clientOptionCount;
174
175 newOptionsTable = new struct OptionRow[totalOptions];
176
177 for (; currOptionCount < optionCount; currOptionCount++)
178 {
179 newOptionsTable[currOptionCount] = optionsTable[currOptionCount];
180 }
181 for (Uint32 i =0; i < clientOptionCount; i++)
182 {
183 newOptionsTable[currOptionCount] = clientOptionsTable[i];
184 currOptionCount++;
185 }
186 return newOptionsTable;
187 j.alex 1.2 }
188
189 /** This method is used by the clients to log information which are required
190 for controller reference. It logs the information with Client ID and
191 status of the client in the PID File log file.
192 */
193 void TestStressTestClient::logInfo(
194 String clientId,
195 pid_t clientPid,
196 int clientStatus,
197 String &pidFile)
198 {
199 char pid_str[15];
200 char status_str[15];
201 char time_str[32];
202
203 #ifdef PEGASUS_OS_TYPE_WINDOWS
204 int offset = 2;
205 #else
206 int offset = 1;
207 #endif
208 j.alex 1.2
209 //
210 // Get current time for time stamp
211 //
212 nowMilliseconds = TimeValue::getCurrentTime().toMilliseconds();
213
214 sprintf(pid_str, "%d", clientPid);
215 sprintf(status_str, "%d", clientStatus);
216 sprintf(time_str, "%" PEGASUS_64BIT_CONVERSION_WIDTH "u",
217 nowMilliseconds);
218
219 fstream pFile(pidFile.getCString(),ios::in|ios::out);
220
221 Boolean addClient= false;
222
|
223 kumpf 1.4 if (!!pFile)
|
224 j.alex 1.2 {
|
225 kumpf 1.4 String line;
226 while(!pFile.eof() && GetLine(pFile, line))
|
227 j.alex 1.2 {
|
228 kumpf 1.4 String subLine;
229
230 Uint32 indx=line.find(':');
231 if (indx != PEG_NOT_FOUND)
|
232 j.alex 1.2 {
|
233 kumpf 1.4 subLine = line.subString(0, indx);
|
234 j.alex 1.2 }
|
235 kumpf 1.4
236 if (String::compare(subLine, clientId) == 0)
|
237 j.alex 1.2 {
238 long pos;
239 addClient = true;
|
240 a.dunfey 1.3 pos = (long)pFile.tellp();
|
241 j.alex 1.2 pFile.seekp(pos - line.size()-offset);
|
242 kumpf 1.4 String newLine = clientId;
|
243 j.alex 1.2 newLine.append("::");
244 newLine.append(pid_str);
245 newLine.append("::");
246 newLine.append(status_str);
247 newLine.append("::");
248 newLine.append(time_str);
|
249 kumpf 1.4
250 Sint32 jSize = line.size() - newLine.size();
251 CString newLineCString = newLine.getCString();
252 pFile.write(newLineCString, strlen(newLineCString));
253 for (Sint32 i = 0; i < jSize; i++)
|
254 j.alex 1.2 {
|
255 kumpf 1.4 pFile.write(" ",1);
|
256 j.alex 1.2 }
257 break;
258 }
259 }
260 if(!addClient)
261 {
262 pFile.close();
|
263 kumpf 1.6 fstream newPidFile(pidFile.getCString(),ios::out|ios::app);
264 newPidFile<<clientId<<"::"<<clientPid<<"::"<<clientStatus<<"::"
|
265 j.alex 1.2 <<time_str<<"\n";
266 }
267 }
268 pFile.close();
269 }
270
271 /** This method is used to take the client process start time.*/
272 void TestStressTestClient::startTime()
273 {
274 startMilliseconds = TimeValue::getCurrentTime().toMilliseconds();
275 nowMilliseconds = startMilliseconds;
276 }
277
278 /** This method is used to check the time stamp for logging information about
279 the success or failure.
280 */
281 Boolean TestStressTestClient::checkTime()
282 {
283 nowMilliseconds = TimeValue::getCurrentTime().toMilliseconds();
284
285 if (nowMilliseconds >= nextCheckupInMillisecs)
286 j.alex 1.2 {
287 nextCheckupInMillisecs = (Uint64)convertmin2millisecs(CHECKUP_INTERVAL)
288 + nowMilliseconds;
289 return true;
290 }
291 return false;
292 }
293
294 /** This method is used to log the information about the client's success or
295 failure percentage at a specific interval of time.
296 */
297 void TestStressTestClient::logErrorPercentage(
298 Uint32 successCount,
299 Uint32 totalCount,
300 pid_t clientPid,
301 String &clientLog,
302 char client[])
303 {
304 Uint32 successPercentage, errorPercentage;
305 successPercentage = (successCount/totalCount)*100;
306 errorPercentage = 100 - successPercentage;
307 j.alex 1.2
308 //
309 // loging details here
310 //
311 ofstream errorLog_File(clientLog.getCString(), ios::app);
312 errorLog_File<<client<<" PID#"<<clientPid<<" ran "<<totalCount
313 <<" times with a "<<errorPercentage<<"% failure"<<"\n";
314 errorLog_File.close();
315 }
316
317 /** This method is used to log the informations of client logs to the client
318 log file.
319 */
320 void TestStressTestClient::errorLog(
321 pid_t clientPid,
322 String &clientLog,
323 String &message)
324 {
325 //
326 // loging details here .
327 //
328 j.alex 1.2 ofstream errorLog_File(clientLog.getCString(), ios::app);
329 errorLog_File<<" PID#"<<clientPid<<"::"<<message<<"\n";
330 errorLog_File.close();
331 }
332
333 /** This method handles the SSLCertificate verification part. */
334 static Boolean verifyCertificate(SSLCertificateInfo &certInfo)
335 {
336 //
337 // Add code to handle server certificate verification.
338 //
339 return true;
340 }
341
342 /** This method is used by the clients to connect to the server. If useSSL is
343 true then an SSL connection will be atemped with the userName and passWord
344 that is passed in. Otherwise connection will be established using
345 localhost. All parameters are required.
346 */
347 void TestStressTestClient::connectClient(
348 CIMClient *client,
349 j.alex 1.2 String host,
350 Uint32 portNumber,
351 String userName,
352 String password,
353 Boolean useSSL,
354 Uint32 timeout,
355 Boolean verboseTest)
356 {
357 if (useSSL)
358 {
|
359 thilo.boehm 1.5 #ifdef PEGASUS_HAS_SSL
|
360 j.alex 1.2 //
361 // Get environment variables.
362 //
363 const char* pegasusHome = getenv("PEGASUS_HOME");
364
365 String trustpath = FileSystem::getAbsolutePath(
366 pegasusHome, PEGASUS_SSLCLIENT_CERTIFICATEFILE);
367
368 String randFile = String::EMPTY;
369
370 #ifdef PEGASUS_SSL_RANDOMFILE
371 randFile = FileSystem::getAbsolutePath(
372 pegasusHome,
373 PEGASUS_SSLCLIENT_RANDOMFILE);
374 #endif
375
376 SSLContext sslContext(
377 trustpath, verifyCertificate, randFile);
378 if (verboseTest)
379 {
380 cout << "connecting to " << host << ":"
381 j.alex 1.2 << portNumber << " using SSL"
382 << endl;
383 }
384 client->connect (host, portNumber, sslContext, userName, password);
|
385 thilo.boehm 1.5 #else
386 PEGASUS_ASSERT(false);
387 #endif
|
388 j.alex 1.2 } /* useSSL. */
389 else
390 {
391 if (verboseTest)
392 {
393 cout << "Connecting to " << host << ":" << portNumber
394 << endl;
395 }
396 client->connect (host, portNumber, userName, password);
397 }
398 if (verboseTest)
399 {
400 cout << "Client Connected" << endl;
401 }
402 }
|