📄 wsesslog.c
字号:
/* httperf -- a tool for measuring web server performance Copyright (C) 2000 Hewlett-Packard Company Contributed by Richard Carter <carter@hpl.hp.com> This file is part of httperf, a web server performance measurment tool. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*//* Creates sessions at the fixed rate PARAM.RATE. The session descriptions are read in from a configuration file. There is currently no tool that translates from standard log formats to the format accepted by this module. An example input file follows: # # This file specifies the potentially-bursty uri sequence for a number of # user sessions. The format rules of this file are as follows: # # Comment lines start with a '#' as the first character. # anywhere else # is considered part of the uri. # # Lines with only whitespace delimit session definitions (multiple blank # lines do not generate "null" sessions). # # Lines otherwise specify a uri-sequence (1 uri per line). If the # first character of the line is whitespace (e.g. space or tab), the # uri is considered to be part of a burst that is sent out after the # previous non-burst uri. # # session 1 definition (this is a comment) /foo.html /pict1.gif /pict2.gif /foo2.html /pict3.gif /pict4.gif #session 2 definition /foo3.html /foo4.html /pict5.gif Any comment on this module contact carter@hpl.hp.com. */#include <assert.h>#include <ctype.h>#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <httperf.h>#include <conn.h>#include <core.h>#include <event.h>#include <rate.h>#include <session.h>#include <timer.h>/* Maximum number of sessions that can be defined in the configuration file. */#define MAX_SESSION_TEMPLATES 1000#define TRUE (1)#define FALSE (0)#define SESS_PRIVATE_DATA(c) \ ((Sess_Private_Data *) ((char *)(c) + sess_private_data_offset))typedef struct req REQ;struct req { REQ *next; int method; char *uri; int uri_len; char *contents; int contents_len; char extra_hdrs[50]; /* plenty for "Content-length: 1234567890" */ int extra_hdrs_len; };typedef struct burst BURST;struct burst { BURST *next; int num_reqs; Time user_think_time; REQ *req_list; };typedef struct Sess_Private_Data Sess_Private_Data;struct Sess_Private_Data { u_int num_calls_in_this_burst; /* # of calls created for this burst */ u_int num_calls_target; /* total # of calls desired */ u_int num_calls_destroyed; /* # of calls destroyed so far */ Timer *timer; /* timer for session think time */ int total_num_reqs; /* total number of requests in this session */ BURST *current_burst; /* the current burst we're working on */ REQ *current_req; /* the current request we're working on */ };/* Methods allowed for a request: */enum { HM_DELETE, HM_GET, HM_HEAD, HM_OPTIONS, HM_POST, HM_PUT, HM_TRACE, HM_LEN };static const char *call_method_name[] = { "DELETE", "GET", "HEAD", "OPTIONS", "POST", "PUT", "TRACE" };static size_t sess_private_data_offset;static int num_sessions_generated;static int num_sessions_destroyed;static Rate_Generator rg_sess;/* This is an array rather than a list because we may want different httperf clients to start at different places in the sequence of sessions. */static int num_templates;static int next_session_template;static Sess_Private_Data session_templates[MAX_SESSION_TEMPLATES] = { { 0, } };static voidsess_destroyed (Event_Type et, Object *obj, Any_Type regarg, Any_Type callarg){ Sess_Private_Data *priv; Sess *sess; assert (et == EV_SESS_DESTROYED && object_is_sess (obj)); sess = (Sess *) obj; priv = SESS_PRIVATE_DATA (sess); if (priv->timer) { timer_cancel (priv->timer); priv->timer = 0; } if (++num_sessions_destroyed >= param.wsesslog.num_sessions) core_exit ();}static voidissue_calls (Sess *sess, Sess_Private_Data *priv){ int i, to_create, retval, n; const char *method_str; Call *call; REQ *req; /* Mimic browser behavior of fetching html object, then a couple of embedded objects: */ to_create = 1; if (priv->num_calls_in_this_burst > 0) to_create = priv->current_burst->num_reqs - priv->num_calls_in_this_burst; n = session_max_qlen (sess) - session_current_qlen (sess); if (n < to_create) to_create = n; priv->num_calls_in_this_burst += to_create; for (i = 0; i < to_create; ++i) { call = call_new (); if (!call) { sess_failure (sess); return; } /* fill in the new call: */ req = priv->current_req; if (req == NULL) panic ("%s: internal error, requests ran past end of burst\n", prog_name); method_str = call_method_name[req->method]; call_set_method (call, method_str, strlen (method_str)); call_set_uri (call, req->uri, req->uri_len); if (req->contents_len > 0) { /* add "Content-length:" header and contents, if necessary: */ call_append_request_header (call, req->extra_hdrs, req->extra_hdrs_len); call_set_contents (call, req->contents, req->contents_len); } priv->current_req = req->next; if (DBG > 0) fprintf (stderr, "%s: accessing URI `%s'\n", prog_name, req->uri); retval = session_issue_call (sess, call); call_dec_ref (call); if (retval < 0) return; }}static voiduser_think_time_expired (Timer *t, Any_Type arg){ Sess *sess = arg.vp; Sess_Private_Data *priv; assert (object_is_sess (sess)); priv = SESS_PRIVATE_DATA (sess); priv->timer = 0; issue_calls (sess, priv);}/* Create a new session and fill in our private information. */static intsess_create (Any_Type arg){ Sess_Private_Data *priv, *template; Sess *sess; if (num_sessions_generated++ >= param.wsesslog.num_sessions) return -1; sess = sess_new (); template = &session_templates[next_session_template]; if (++next_session_template >= num_templates) next_session_template = 0; priv = SESS_PRIVATE_DATA (sess); priv->current_burst = template->current_burst; priv->current_req = priv->current_burst->req_list; priv->total_num_reqs = template->total_num_reqs; priv->num_calls_target = priv->current_burst->num_reqs; if (DBG > 0) fprintf (stderr, "Starting session, first burst_len = %d\n", priv->num_calls_target); issue_calls (sess, SESS_PRIVATE_DATA (sess)); return 0;}static voidprepare_for_next_burst (Sess *sess, Sess_Private_Data *priv){ Time think_time; Any_Type arg; if (priv->current_burst != NULL) { think_time = priv->current_burst->user_think_time; /* advance to next burst: */ priv->current_burst = priv->current_burst->next; if (priv->current_burst != NULL) { priv->current_req = priv->current_burst->req_list; priv->num_calls_in_this_burst = 0; priv->num_calls_target += priv->current_burst->num_reqs; assert (!priv->timer); arg.vp = sess; priv->timer = timer_schedule (user_think_time_expired, arg, think_time); } }}static voidcall_destroyed (Event_Type et, Object *obj, Any_Type regarg, Any_Type callarg){ Sess_Private_Data *priv; Sess *sess; Call *call; assert (et == EV_CALL_DESTROYED && object_is_call (obj)); call = (Call *) obj; sess = session_get_sess_from_call (call); priv = SESS_PRIVATE_DATA (sess); ++priv->num_calls_destroyed;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -