1 /*
2 httperf -- a tool for measuring web server performance
3 Copyright 2000-2007 Hewlett-Packard Company
4
5 This file is part of httperf, a web server performance measurment
6 tool.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version.
12
13 In addition, as a special exception, the copyright holders give
14 permission to link the code of this work with the OpenSSL project's
15 "OpenSSL" library (or with modified versions of it that use the same
16 license as the "OpenSSL" library), and distribute linked combinations
17 including the two. You must obey the GNU General Public License in
18 all respects for all of the code used other than "OpenSSL". If you
19 modify this file, you may extend this exception to your version of the
20 file, but you are not obligated to do so. If you do not wish to do
21 so, delete this exception statement from your version.
22
23 This program is distributed in the hope that it will be useful,
24 but WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 General Public License for more details.
27
28 You should have received a copy of the GNU General Public License
29 along with this program; if not, write to the Free Software
30 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
31 02110-1301, USA
32 */
33
34 /* Issue a sequence of calls on a connection. */
35
36 #include "config.h"
37
38 #include <assert.h>
39 #include <sys/types.h>
40
41 #include <generic_types.h>
42
43 #include <object.h>
44 #include <timer.h>
45 #include <httperf.h>
46 #include <call.h>
47 #include <conn.h>
48 #include <core.h>
49 #include <localevent.h>
50
51 #define CONN_PRIVATE_DATA(c) \
52 ((Conn_Private_Data *) ((char *)(c) + conn_private_data_offset))
53
54 #define MIN(a,b) ((a) < (b) ? (a) : (b))
55
56 typedef struct Conn_Private_Data
57 {
58 int num_calls;
59 int num_completed;
60 int num_destroyed;
61 }
62 Conn_Private_Data;
63
64 static size_t conn_private_data_offset;
65
66 static void
issue_calls(Conn * conn)67 issue_calls (Conn *conn)
68 {
69 Conn_Private_Data *priv;
70 Call *call;
71 int i;
72
73 priv = CONN_PRIVATE_DATA (conn);
74 priv->num_completed = 0;
75 priv->num_destroyed = 0;
76
77 for (i = 0; i < param.burst_len; ++i)
78 if (priv->num_calls++ < param.num_calls)
79 {
80 call = call_new ();
81 if (call)
82 {
83 core_send (conn, call);
84 call_dec_ref (call);
85 }
86 }
87 }
88
89 static void
conn_connected(Event_Type et,Conn * conn)90 conn_connected (Event_Type et, Conn *conn)
91 {
92 assert (et == EV_CONN_CONNECTED && object_is_conn (conn));
93
94 issue_calls (conn);
95 }
96
97 static void
call_done(Event_Type et,Call * call)98 call_done (Event_Type et, Call *call)
99 {
100 Conn *conn = call->conn;
101 Conn_Private_Data *priv;
102
103 assert (et == EV_CALL_RECV_STOP && conn && object_is_conn (conn));
104
105 priv = CONN_PRIVATE_DATA (conn);
106 ++priv->num_completed;
107 }
108
109 static void
call_destroyed(Event_Type et,Call * call)110 call_destroyed (Event_Type et, Call *call)
111 {
112 Conn_Private_Data *priv;
113 Conn *conn;
114
115 assert (et == EV_CALL_DESTROYED && object_is_call (call));
116
117 conn = call->conn;
118 priv = CONN_PRIVATE_DATA (conn);
119
120 if (++priv->num_destroyed >= MIN (param.burst_len, param.num_calls))
121 {
122 if (priv->num_completed == priv->num_destroyed
123 && priv->num_calls < param.num_calls)
124 issue_calls (conn);
125 else
126 core_close (conn);
127 }
128 }
129
130 static void
init(void)131 init (void)
132 {
133 Any_Type arg;
134
135 conn_private_data_offset = object_expand (OBJ_CONN,
136 sizeof (Conn_Private_Data));
137
138 arg.l = 0;
139 event_register_handler (EV_CONN_CONNECTED, (Event_Handler) conn_connected,
140 arg);
141 event_register_handler (EV_CALL_RECV_STOP, (Event_Handler) call_done, arg);
142 event_register_handler (EV_CALL_DESTROYED, (Event_Handler) call_destroyed,
143 arg);
144 }
145
146 Load_Generator call_seq =
147 {
148 "performs a sequence of calls on a connection",
149 init,
150 no_op,
151 no_op
152 };
153