~ubuntu-branches/ubuntu/gutsy/poco/gutsy

« back to all changes in this revision

Viewing changes to Net/samples/HTTPLoadTest/src/HTTPLoadTest.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Krzysztof Burghardt
  • Date: 2007-04-27 18:33:48 UTC
  • Revision ID: james.westby@ubuntu.com-20070427183348-xgnpct0qd6a2ip34
Tags: upstream-1.2.9
ImportĀ upstreamĀ versionĀ 1.2.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// HTTPLoadTest.cpp
 
3
//
 
4
// $Id: //poco/1.2/Net/samples/HTTPLoadTest/src/HTTPLoadTest.cpp#1 $
 
5
//
 
6
// This sample demonstrates the HTTPClientSession class.
 
7
//
 
8
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
 
9
// and Contributors.
 
10
//
 
11
// Permission is hereby granted, free of charge, to any person or organization
 
12
// obtaining a copy of the software and accompanying documentation covered by
 
13
// this license (the "Software") to use, reproduce, display, distribute,
 
14
// execute, and transmit the Software, and to prepare derivative works of the
 
15
// Software, and to permit third-parties to whom the Software is furnished to
 
16
// do so, all subject to the following:
 
17
// 
 
18
// The copyright notices in the Software and this entire statement, including
 
19
// the above license grant, this restriction and the following disclaimer,
 
20
// must be included in all copies of the Software, in whole or in part, and
 
21
// all derivative works of the Software, unless such copies or derivative
 
22
// works are solely in the form of machine-executable object code generated by
 
23
// a source language processor.
 
24
// 
 
25
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
26
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
27
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 
28
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 
29
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 
30
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 
31
// DEALINGS IN THE SOFTWARE.
 
32
//
 
33
 
 
34
 
 
35
#include "Poco/Net/HTTPClientSession.h"
 
36
#include "Poco/Net/HTTPRequest.h"
 
37
#include "Poco/Net/HTTPResponse.h"
 
38
#include "Poco/Net/HTTPCookie.h"
 
39
#include "Poco/Net/NameValueCollection.h"
 
40
#include "Poco/Path.h"
 
41
#include "Poco/URI.h"
 
42
#include "Poco/AutoPtr.h"
 
43
#include "Poco/Thread.h"
 
44
#include "Poco/Mutex.h"
 
45
#include "Poco/Runnable.h"
 
46
#include "Poco/Stopwatch.h"
 
47
#include "Poco/NumberParser.h"
 
48
#include "Poco/Exception.h"
 
49
#include "Poco/Util/Application.h"
 
50
#include "Poco/Util/Option.h"
 
51
#include "Poco/Util/OptionSet.h"
 
52
#include "Poco/Util/HelpFormatter.h"
 
53
#include "Poco/Util/AbstractConfiguration.h"
 
54
#include <iostream>
 
55
 
 
56
 
 
57
using Poco::Net::HTTPClientSession;
 
58
using Poco::Net::HTTPRequest;
 
59
using Poco::Net::HTTPResponse;
 
60
using Poco::Net::HTTPMessage;
 
61
using Poco::Net::HTTPCookie;
 
62
using Poco::Net::NameValueCollection;
 
63
using Poco::Util::Application;
 
64
using Poco::Util::Option;
 
65
using Poco::Util::OptionSet;
 
66
using Poco::Util::HelpFormatter;
 
67
using Poco::Util::AbstractConfiguration;
 
68
using Poco::AutoPtr;
 
69
using Poco::Thread;
 
70
using Poco::FastMutex;
 
71
using Poco::Runnable;
 
72
using Poco::Stopwatch;
 
73
using Poco::NumberParser;
 
74
using Poco::Path;
 
75
using Poco::URI;
 
76
using Poco::Exception;
 
77
 
 
78
class HTTPClient : public Runnable
 
79
{
 
80
public:
 
81
        HTTPClient(const URI& uri, int repetitions, bool cookies=false, bool verbose=false):
 
82
          _uri(uri), 
 
83
          _cookies(cookies), 
 
84
          _verbose(verbose), 
 
85
          _repetitions(repetitions), 
 
86
          _usec(0), 
 
87
          _success(0)
 
88
        {
 
89
                _gRepetitions += _repetitions;
 
90
        }
 
91
 
 
92
        ~HTTPClient()
 
93
        {
 
94
        }
 
95
 
 
96
        void run()
 
97
        {
 
98
                Stopwatch sw;
 
99
                std::vector<HTTPCookie> cookies;
 
100
 
 
101
                for (int i = 0; i < _repetitions; ++i)
 
102
                {
 
103
                        try
 
104
                        {
 
105
                                int usec = 0;
 
106
                                std::string path(_uri.getPathAndQuery());
 
107
                                if (path.empty()) path = "/";
 
108
 
 
109
                                HTTPClientSession session(_uri.getHost(), _uri.getPort());
 
110
                                HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1);
 
111
                                
 
112
                                if (_cookies)
 
113
                                {
 
114
                                        NameValueCollection nvc;
 
115
                                        std::vector<HTTPCookie>::iterator it = cookies.begin();
 
116
                                        for(; it != cookies.end(); ++it)
 
117
                                                nvc.add((*it).getName(), (*it).getValue());
 
118
 
 
119
                                        req.setCookies(nvc);
 
120
                                }
 
121
 
 
122
                                HTTPResponse res;
 
123
                                sw.restart();
 
124
                                session.sendRequest(req);
 
125
                                std::istream& rs = session.receiveResponse(res);
 
126
                                sw.stop();
 
127
                                _success += HTTPResponse::HTTP_OK == res.getStatus() ? 1 : 0;
 
128
                                if (_cookies) res.getCookies(cookies);
 
129
                                usec = sw.elapsed();
 
130
 
 
131
                                if (_verbose)
 
132
                                {
 
133
                                        FastMutex::ScopedLock lock(_mutex);
 
134
                                        std::cout 
 
135
                                        << _uri.toString() << ' ' << res.getStatus() << ' ' << res.getReason() 
 
136
                                        << ' ' << usec/1000.0 << "ms" << std::endl;
 
137
                                }
 
138
 
 
139
                                _usec += usec;
 
140
                        }
 
141
                        catch (Exception& exc)
 
142
                        {
 
143
                                FastMutex::ScopedLock lock(_mutex);
 
144
                                std::cerr << exc.displayText() << std::endl;
 
145
                        }
 
146
                }
 
147
                
 
148
                {
 
149
                        FastMutex::ScopedLock lock(_mutex);
 
150
                        _gSuccess += _success;
 
151
                        _gUsec += _usec;
 
152
                }
 
153
                if (_verbose)
 
154
                        printStats(_uri.toString(), _repetitions, _success, _usec);
 
155
        }
 
156
 
 
157
        static void printStats(std::string uri, int repetitions, int success, Poco::UInt64 usec);
 
158
        static int totalAttempts();
 
159
        static Poco::UInt64 totalMicroseconds();
 
160
        static int totalSuccessCount();
 
161
 
 
162
private:
 
163
        HTTPClient();
 
164
 
 
165
        URI _uri;
 
166
        bool _verbose;
 
167
        bool _cookies;
 
168
        int _repetitions;
 
169
        Poco::UInt64 _usec;
 
170
        int _success;
 
171
        static int _gRepetitions;
 
172
        static Poco::UInt64 _gUsec;
 
173
        static int _gSuccess;
 
174
        static FastMutex _mutex;
 
175
};
 
176
 
 
177
FastMutex HTTPClient::_mutex;
 
178
int HTTPClient::_gRepetitions;
 
179
Poco::UInt64 HTTPClient::_gUsec;
 
180
int HTTPClient::_gSuccess;
 
181
 
 
182
int HTTPClient::totalAttempts()
 
183
{
 
184
        return _gRepetitions;
 
185
}
 
186
 
 
187
Poco::UInt64 HTTPClient::totalMicroseconds()
 
188
{
 
189
        return _gUsec;
 
190
}
 
191
 
 
192
int HTTPClient::totalSuccessCount()
 
193
{
 
194
        return _gSuccess;
 
195
}
 
196
 
 
197
void HTTPClient::printStats(std::string uri, int repetitions, int success, Poco::UInt64 usec)
 
198
{
 
199
        FastMutex::ScopedLock lock(_mutex);
 
200
 
 
201
        std::cout << std::endl << "--------------" << std::endl 
 
202
                << "Statistics for " << uri << std::endl << "--------------" 
 
203
                << std::endl
 
204
                << repetitions << " attempts, " << success << " succesful (" 
 
205
                <<  ((float) success / (float) repetitions) * 100.0 << "%)" << std::endl
 
206
                << "Avg response time: " << ((float) usec / (float) repetitions) / 1000.0 << "ms, " << std::endl
 
207
                << "Avg requests/second handled: " << ((float) success  /((float) usec / 1000000.0)) << std::endl
 
208
                << "Total time: " << (float) usec / 1000000.0 << std::endl;
 
209
}
 
210
 
 
211
class HTTPLoadTest: public Application
 
212
        /// This sample demonstrates some of the features of the Poco::Util::Application class,
 
213
        /// such as configuration file handling and command line arguments processing.
 
214
        ///
 
215
        /// Try HTTPLoadTest --help (on Unix platforms) or HTTPLoadTest /help (elsewhere) for
 
216
        /// more information.
 
217
{
 
218
public:
 
219
        HTTPLoadTest(): 
 
220
                _helpRequested(false), 
 
221
                _repetitions(1), 
 
222
                _threads(1), 
 
223
                _verbose(false), 
 
224
                _cookies(false)
 
225
        {
 
226
        }
 
227
 
 
228
protected:      
 
229
        void initialize(Application& self)
 
230
        {
 
231
                loadConfiguration(); // load default configuration files, if present
 
232
                Application::initialize(self);
 
233
                // add your own initialization code here
 
234
        }
 
235
        
 
236
        void uninitialize()
 
237
        {
 
238
                // add your own uninitialization code here
 
239
                Application::uninitialize();
 
240
        }
 
241
        
 
242
        void reinitialize(Application& self)
 
243
        {
 
244
                Application::reinitialize(self);
 
245
                // add your own reinitialization code here
 
246
        }
 
247
        
 
248
        void defineOptions(OptionSet& options)
 
249
        {
 
250
                Application::defineOptions(options);
 
251
 
 
252
                options.addOption(
 
253
                        Option("help", "h", "display help information on command line arguments")
 
254
                                .required(false)
 
255
                                .repeatable(false));
 
256
 
 
257
                options.addOption(
 
258
                        Option("verbose", "v", "display messages on stdout")
 
259
                                .required(false)
 
260
                                .repeatable(false));
 
261
 
 
262
                options.addOption(
 
263
                        Option("cookies", "c", "resend cookies")
 
264
                                .required(false)
 
265
                                .repeatable(false));
 
266
 
 
267
                options.addOption(
 
268
                        Option("uri", "u", "HTTP URI")
 
269
                                .required(true)
 
270
                                .repeatable(false)
 
271
                                .argument("uri"));
 
272
                                
 
273
                options.addOption(
 
274
                        Option("repetitions", "r", "fetch repetitions")
 
275
                                .required(false)
 
276
                                .repeatable(false)
 
277
                                .argument("repetitions"));
 
278
 
 
279
                options.addOption(
 
280
                        Option("threads", "t", "thread count")
 
281
                                .required(false)
 
282
                                .repeatable(false)
 
283
                                .argument("threads"));
 
284
        }
 
285
        
 
286
        void handleOption(const std::string& name, const std::string& value)
 
287
        {
 
288
                Application::handleOption(name, value);
 
289
 
 
290
                if (name == "help")
 
291
                        _helpRequested = true;
 
292
                else if (name == "verbose")
 
293
                        _verbose = true;
 
294
                else if (name == "cookies")
 
295
                        _cookies = true;
 
296
                else if (name == "uri")
 
297
                        _uri = value;
 
298
                else if (name == "repetitions")
 
299
                        _repetitions = NumberParser::parse(value);
 
300
                else if (name == "threads")
 
301
                        _threads = NumberParser::parse(value);
 
302
        }
 
303
        
 
304
        void displayHelp()
 
305
        {
 
306
                HelpFormatter helpFormatter(options());
 
307
                helpFormatter.setCommand(commandName());
 
308
                helpFormatter.setUsage("OPTIONS");
 
309
                helpFormatter.setHeader("A sample application that demonstrates some of the features of the Poco::Util::Application class.");
 
310
                helpFormatter.format(std::cout);
 
311
        }
 
312
        
 
313
        void defineProperty(const std::string& def)
 
314
        {
 
315
                std::string name;
 
316
                std::string value;
 
317
                std::string::size_type pos = def.find('=');
 
318
                if (pos != std::string::npos)
 
319
                {
 
320
                        name.assign(def, 0, pos);
 
321
                        value.assign(def, pos + 1, def.length() - pos);
 
322
                }
 
323
                else name = def;
 
324
                config().setString(name, value);
 
325
        }
 
326
 
 
327
        int main(const std::vector<std::string>& args)
 
328
        {
 
329
                if (_helpRequested)
 
330
                {
 
331
                        displayHelp();
 
332
                }
 
333
                else
 
334
                {
 
335
                        URI uri(_uri);
 
336
                        std::vector<Thread*> threads;
 
337
 
 
338
                        Stopwatch sw;
 
339
                        sw.start();
 
340
                        for (int i = 0; i < _threads; ++i)
 
341
                        {
 
342
                                Thread* pt = new Thread(_uri);
 
343
                                poco_check_ptr(pt);
 
344
                                threads.push_back(pt);
 
345
                                HTTPClient* pHTTPClient = new HTTPClient(uri, _repetitions, _cookies, _verbose);
 
346
                                poco_check_ptr(pHTTPClient);
 
347
                                threads.back()->start(*pHTTPClient);
 
348
                        }
 
349
 
 
350
                        std::vector<Thread*>::iterator it = threads.begin();
 
351
                        for(; it != threads.end(); ++it)
 
352
                        {
 
353
                                (*it)->join();
 
354
                                delete *it;
 
355
                        }
 
356
                        sw.stop();
 
357
 
 
358
                        HTTPClient::printStats(_uri, HTTPClient::totalAttempts(), HTTPClient::totalSuccessCount(), sw.elapsed());
 
359
                }
 
360
                
 
361
                return Application::EXIT_OK;
 
362
        }
 
363
        
 
364
private:
 
365
        bool _helpRequested;
 
366
        bool _verbose;
 
367
        bool _cookies;
 
368
        std::string _uri;
 
369
        int _repetitions;
 
370
        int _threads;
 
371
};
 
372
 
 
373
 
 
374
int main(int argc, char** argv)
 
375
{
 
376
        AutoPtr<HTTPLoadTest> pApp = new HTTPLoadTest;
 
377
        try
 
378
        {
 
379
                pApp->init(argc, argv);
 
380
        }
 
381
        catch (Poco::Exception& exc)
 
382
        {
 
383
                pApp->logger().log(exc);
 
384
                return Application::EXIT_CONFIG;
 
385
        }
 
386
        return pApp->run();
 
387
}
 
388