/[hyperestraier]/upstream/0.5.0/estload.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/0.5.0/estload.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show annotations)
Fri Jul 29 21:52:03 2005 UTC (18 years, 10 months ago) by dpavlin
File MIME type: text/plain
File size: 9711 byte(s)
import of HyperEstraier 0.5.0

1 /*************************************************************************************************
2 * The load tester for web applications
3 * Copyright (C) 2004-2005 Mikio Hirabayashi
4 * This file is part of Hyper Estraier.
5 * Hyper Estraier is free software; you can redistribute it and/or modify it under the terms of
6 * the GNU Lesser General Public License as published by the Free Software Foundation; either
7 * version 2.1 of the License or any later version. Hyper Estraier is distributed in the hope
8 * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
10 * License for more details.
11 * You should have received a copy of the GNU Lesser General Public License along with Hyper
12 * Estraier; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
13 * Boston, MA 02111-1307 USA.
14 *************************************************************************************************/
15
16
17 #include "estraier.h"
18 #include "estmtdb.h"
19 #include "estnode.h"
20 #include "myconf.h"
21
22 #define AGENTNAME "estload" /* name of the user agent */
23 #define IOBUFSIZ 8192 /* size of a buffer for I/O */
24
25 typedef struct { /* type of structure for a target URL */
26 char *host; /* hostname */
27 char *addr; /* IP address */
28 int port; /* port number */
29 char *auth; /* authority */
30 char *path; /* path */
31 char *query; /* query string */
32 } TARGET;
33
34 typedef struct { /* type of structure for a worker thread */
35 int id; /* ID number */
36 int ims; /* interval time in milliseconds */
37 int pb; /* to print received data */
38 int qb; /* to be quiet */
39 CBLIST *targets; /* list of targets */
40 int alive; /* to be alive */
41 } MISSION;
42
43
44 /* global variables */
45 const char *g_progname; /* program name */
46
47
48 /* function prototypes */
49 int main(int argc, char **argv);
50 static void usage(void);
51 static void printferror(const char *format, ...);
52 static void printfinfo(const char *format, ...);
53 static int procmain(const char *file, int tnum, int lnum, int ims, int pb, int qb);
54 static void *procthread(void *arg);
55
56
57 /* main routine */
58 int main(int argc, char **argv){
59 char *file;
60 int i, tnum, lnum, ims, pb, qb, rv;
61 cbstdiobin();
62 g_progname = argv[0];
63 if(!est_init_net_env()){
64 printferror("could not initialize network environment");
65 exit(1);
66 }
67 file = NULL;
68 tnum = 1;
69 lnum = 1;
70 ims = 0;
71 pb = FALSE;
72 qb = FALSE;
73 for(i = 1; i < argc; i++){
74 if(!file && argv[i][0] == '-'){
75 if(!strcmp(argv[i], "-t")){
76 if(++i >= argc) usage();
77 tnum = atoi(argv[i]);
78 } else if(!strcmp(argv[i], "-l")){
79 if(++i >= argc) usage();
80 lnum = atoi(argv[i]);
81 } else if(!strcmp(argv[i], "-i")){
82 if(++i >= argc) usage();
83 ims = atoi(argv[i]);
84 } else if(!strcmp(argv[i], "-p")){
85 pb = TRUE;
86 } else if(!strcmp(argv[i], "-q")){
87 qb = TRUE;
88 } else {
89 usage();
90 }
91 } else if(!file){
92 file = argv[i];
93 } else {
94 usage();
95 }
96 }
97 if(!file || tnum < 1 || lnum < 1) usage();
98 rv = procmain(file, tnum, lnum, ims, pb, qb);
99 return rv;
100 }
101
102
103 /* print the usage and exit */
104 static void usage(void){
105 fprintf(stderr, "%s: stresser for web applications\n", g_progname);
106 fprintf(stderr, "\n");
107 fprintf(stderr, "usage:\n");
108 fprintf(stderr, " %s [-t num] [-l num] [-i num] [-p] [-q] [file|url]\n", g_progname);
109 fprintf(stderr, "\n");
110 exit(1);
111 }
112
113
114 /* print formatted error string and flush the buffer */
115 static void printferror(const char *format, ...){
116 va_list ap;
117 va_start(ap, format);
118 fprintf(stderr, "%s: ERROR: ", g_progname);
119 vfprintf(stderr, format, ap);
120 fputc('\n', stderr);
121 fflush(stderr);
122 va_end(ap);
123 }
124
125
126 /* print formatted information string and flush the buffer */
127 static void printfinfo(const char *format, ...){
128 va_list ap;
129 va_start(ap, format);
130 printf("%s: INFO: ", g_progname);
131 vprintf(format, ap);
132 putchar('\n');
133 fflush(stdout);
134 va_end(ap);
135 }
136
137
138 /* proc the main command */
139 static int procmain(const char *file, int tnum, int lnum, int ims, int pb, int qb){
140 pthread_t *threads;
141 MISSION *missions;
142 TARGET target;
143 CBLIST *list;
144 CBMAP *elems;
145 const char *line, *host, *pstr, *auth, *path, *query;
146 int i, j, cnt, pnum, err;
147 double etime;
148 if(cbstrfwimatch(file, "http://")){
149 list = cblistopen();
150 cblistpush(list, file, -1);
151 } else if(!(list = cbreadlines(file))){
152 printferror("%s: could not open", file);
153 return 1;
154 }
155 threads = cbmalloc(tnum * sizeof(pthread_t));
156 missions = cbmalloc(tnum * sizeof(MISSION));
157 for(i = 0; i < tnum; i++){
158 missions[i].id = i + 1;
159 missions[i].ims = ims;
160 missions[i].pb = pb;
161 missions[i].qb = qb;
162 missions[i].targets = cblistopen();
163 }
164 cnt = 0;
165 for(i = 0; i < lnum; i++){
166 for(j = 0; j < cblistnum(list); j++){
167 line = cblistval(list, j, NULL);
168 if((line[0] == '\0')) continue;
169 elems = cburlbreak(line);
170 host = cbmapget(elems, "host", -1, NULL);
171 pnum = (pstr = cbmapget(elems, "port", -1, NULL)) ? atoi(pstr) : 80;
172 auth = cbmapget(elems, "authority", -1, NULL);
173 path = cbmapget(elems, "path", -1, NULL);
174 query = cbmapget(elems, "query", -1, NULL);
175 if(!host || pnum < 1){
176 printferror("%s: invalid URL", line);
177 cbmapclose(elems);
178 continue;
179 }
180 if(!auth) auth = "";
181 if(!path) path = "/";
182 if(!query) query = "";
183 if(!(target.addr = est_get_host_addr(host))){
184 printferror("%s: unknown host", host);
185 cbmapclose(elems);
186 continue;
187 }
188 target.host = cbmemdup(host, -1);
189 target.port = pnum;
190 target.auth = cbmemdup(auth, -1);
191 target.path = cbmemdup(path, -1);
192 target.query = cbmemdup(query, -1);
193 cblistpush(missions[cnt++%tnum].targets, (char *)&target, sizeof(TARGET));
194 cbmapclose(elems);
195 }
196 }
197 cblistclose(list);
198 err = FALSE;
199 etime = est_gettimeofday();
200 if(tnum > 1){
201 for(i = 0; i < tnum; i++){
202 missions[i].alive = FALSE;
203 if(pthread_create(threads + i, NULL, procthread, missions + i) == 0){
204 missions[i].alive = TRUE;
205 } else {
206 printferror("thread creation failed");
207 err = TRUE;
208 }
209 }
210 for(i = 0; i < tnum; i++){
211 if(!missions[i].alive) continue;
212 if(pthread_join(threads[i], NULL) != 0){
213 printferror("thread join failed");
214 err = TRUE;
215 }
216 }
217 } else {
218 procthread(missions);
219 }
220 etime = est_gettimeofday() - etime;
221 if(cnt > 0 && !err)
222 printfinfo("finished: elepsed time: %.3f sec. (average: %.3f)",
223 etime / 1000, etime / cnt / 1000);
224 for(i = 0; i < tnum; i++){
225 for(j = 0; j < cblistnum(missions[i].targets); j++){
226 target = *(TARGET *)cblistval(missions[i].targets, j, NULL);
227 free(target.query);
228 free(target.path);
229 free(target.auth);
230 free(target.addr);
231 free(target.host);
232 }
233 cblistclose(missions[i].targets);
234 }
235 free(missions);
236 free(threads);
237 return err ? 1 : 0;
238 }
239
240
241 /* process as a child thread */
242 static void *procthread(void *arg){
243 CBLIST *targets;
244 TARGET target;
245 char iobuf[IOBUFSIZ], *wp, *tmp;
246 int i, id, ims, pb, qb, clsock, size;
247 double etime;
248 targets = ((MISSION *)arg)->targets;
249 id = ((MISSION *)arg)->id;
250 ims = ((MISSION *)arg)->ims;
251 pb = ((MISSION *)arg)->pb;
252 qb = ((MISSION *)arg)->qb;
253 if(cblistnum(targets) < 1) return NULL;
254 printfinfo("%d: started", id);
255 etime = est_gettimeofday();
256 for(i = 0; i < cblistnum(targets); i++){
257 target = *(TARGET *)cblistval(targets, i, NULL);
258 if(!qb) printfinfo("%d(%d/%d): http://%s:%d%s%s%s",
259 id, i + 1, cblistnum(targets), target.host, target.port,
260 target.path, target.query[0] != '\0' ? "?" : "", target.query);
261 if((clsock = est_get_client_sock(target.addr, target.port)) != -1){
262 wp = iobuf;
263 wp += sprintf(wp, "GET %s%s%s HTTP/1.0\r\n",
264 target.path, target.query[0] != '\0' ? "?" : "", target.query);
265 wp += sprintf(wp, "Host: %s:%d\r\n", target.host, target.port);
266 wp += sprintf(wp, "Connection: close\r\n");
267 if(target.auth[0] != '\0'){
268 tmp = cbbaseencode(target.auth, -1);
269 wp += sprintf(wp, "Authorization: Basic %s\r\n", tmp);
270 free(tmp);
271 }
272 wp += sprintf(wp, "Referer: http://%s:%d%s%s%s\r\n", target.host, target.port,
273 target.path, target.query[0] != '\0' ? "?" : "", target.query);
274 wp += sprintf(wp, "User-Agent: %s/%s\r\n", AGENTNAME, est_version);
275 wp += sprintf(wp, "\r\n");
276 est_sock_send_all(clsock, iobuf, wp - iobuf);
277 while((size = recv(clsock, iobuf, IOBUFSIZ, 0)) > 0){
278 if(pb) fwrite(iobuf, 1, size, stdout);
279 }
280 est_sock_down(clsock);
281 } else {
282 printferror("%d(%d/%d): connection failed", id, i + 1, cblistnum(targets));
283 }
284 if(ims > 0) est_usleep(ims * 1000);
285 }
286 etime = est_gettimeofday() - etime;
287 printfinfo("%d: finished: elapsed time: %.3f sec. (average: %.3f)",
288 id, etime / 1000, etime / cblistnum(targets) / 1000);
289 return NULL;
290 }
291
292
293
294 /* END OF FILE */

  ViewVC Help
Powered by ViewVC 1.1.26