1 const char stats_rcs[] = "$Id: stats.c,v 2.2 2002/12/28 04:17:58 david__schmidt Exp $";
2 /*********************************************************************
4 * File : $Source: /cvsroot/ijbswa/current/src/stats.c,v $
6 * Purpose : Functions and definitions for accumulating and
7 * sending statistics to an "external" stats console
9 * Copyright : Written by and Copyright (C) 2002, 2003 the SourceForge
10 * Privoxy team. http://www.privoxy.org/
12 * Based on the Internet Junkbuster originally written
13 * by and Copyright (C) 1997 Anonymous Coders and
14 * Junkbusters Corporation. http://www.junkbusters.com
16 * This program is free software; you can redistribute it
17 * and/or modify it under the terms of the GNU General
18 * Public License as published by the Free Software
19 * Foundation; either version 2 of the License, or (at
20 * your option) any later version.
22 * This program is distributed in the hope that it will
23 * be useful, but WITHOUT ANY WARRANTY; without even the
24 * implied warranty of MERCHANTABILITY or FITNESS FOR A
25 * PARTICULAR PURPOSE. See the GNU General Public
26 * License for more details.
28 * The GNU General Public License should be included with
29 * this file. If not, you can view it at
30 * http://www.gnu.org/copyleft/gpl.html
31 * or write to the Free Software Foundation, Inc., 59
32 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34 *********************************************************************/
39 #include <sys/signal.h>
46 #include "jbsockets.h"
48 const char stats_h_rcs[] = STATS_H_VERSION;
49 const char ipc_h_rcs[] = IPC_H_VERSION;
50 static IPC_MUTEX_LOCK stats_lock;
52 struct configuration_spec *latest_config;
54 stats_array[STATS_MAX_KEYS];
56 /*********************************************************************
58 * Function : init_stats_config
60 * Description : Initializes the statistics array and spawns a thread
61 * to transmit statistics to the listening party.
64 * 1 : config = Privoxy configuration.
68 *********************************************************************/
69 void init_stats_config(struct configuration_spec * config)
72 #if defined(FEATURE_PTHREAD)
75 #endif /* def FEATURE_PTHREAD */
77 IPC_CREATE_MUTEX(stats_lock);
78 for (i=0; i < STATS_MAX_KEYS; i++)
82 latest_config = config;
85 * Start the timing/sending thread - I stole this from jcc.c.
86 * The idea is to get a mutiplatform thread started.
87 * YMMV - please tweak for your platform!
90 /* this is a switch () statment in the C preprocessor - ugh */
91 #undef SELECTED_ONE_OPTION
93 /* Use pthreads in preference to any native code */
94 #if defined(FEATURE_PTHREAD) && !defined(SELECTED_ONE_OPTION)
95 #define SELECTED_ONE_OPTION
99 signal(SIGALRM, null_routine); /* Ignore the SIGALRM signal */
100 pthread_attr_init(&attrs);
101 pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);
102 child_id = (pthread_create(&the_thread, &attrs,
103 (void*)forward_stats, NULL) ? -1 : 0);
104 pthread_attr_destroy(&attrs);
107 #if defined(_WIN32) && !defined(_CYGWIN) && !defined(SELECTED_ONE_OPTION)
108 #define SELECTED_ONE_OPTION
109 child_id = _beginthread(
110 (void (*)(void *))forward_stats,
115 #if defined(__OS2__) && !defined(SELECTED_ONE_OPTION)
116 #define SELECTED_ONE_OPTION
117 child_id = _beginthread(
118 (void(* _Optlink)(void*))forward_stats,
124 #if defined(__BEOS__) && !defined(SELECTED_ONE_OPTION)
125 #define SELECTED_ONE_OPTION
126 thread_id tid = spawn_thread
127 (server_thread, "forward_stats", B_NORMAL_PRIORITY, NULL);
129 if ((tid >= 0) && (resume_thread(tid) == B_OK))
131 child_id = (int) tid;
139 #if defined(AMIGA) && !defined(SELECTED_ONE_OPTION)
140 #define SELECTED_ONE_OPTION
141 if((child_id = (int)CreateNewProcTags(
142 NP_Entry, (ULONG)server_thread,
144 NP_CloseOutput, FALSE,
145 NP_Name, (ULONG)"privoxy child",
146 NP_StackSize, 200*1024,
150 Signal((struct Task *)child_id, SIGF_SINGLE);
155 #if !defined(SELECTED_ONE_OPTION)
156 /* I don't think the IPC will really work in a fork()'d environment,
157 * so proceed with caution. FIXME.
161 if (child_id == 0) /* child */
166 else if (child_id > 0) /* parent */
171 #undef SELECTED_ONE_OPTION
172 /* end of c preprocessor switch () */
176 /*********************************************************************
178 * Function : update_stats_config
180 * Description : Updates the pointer to the most recent Privoxy
181 * configuration changes.
184 * 1 : config = Privoxy configuration.
188 *********************************************************************/
189 void update_stats_config(struct configuration_spec * config)
191 latest_config = config;
194 /*********************************************************************
196 * Function : accumulate_stats
198 * Description : Updates one element of the statistics array with a
199 * single integer value.
202 * 1 : key = the key into the stats array
203 * 2 : value = the value to add to the current stats key
207 *********************************************************************/
208 void accumulate_stats(int key, int value)
210 if (key < STATS_MAX_KEYS)
212 IPC_LOCK_MUTEX(stats_lock);
213 stats_array[key] += value;
215 IPC_UNLOCK_MUTEX(stats_lock);
219 /*********************************************************************
221 * Function : forward_stats
223 * Description : Main routine for the statistics thread; loops and
224 * periodically checks if there's anything to send. If
225 * so, call send_stats() to do the work.
231 *********************************************************************/
232 void *forward_stats()
234 int local_stats_array[STATS_MAX_KEYS];
238 IPC_SLEEP_SECONDS(latest_config->activity_freq);
241 IPC_LOCK_MUTEX(stats_lock);
242 memcpy(local_stats_array,stats_array,sizeof(stats_array));
244 IPC_UNLOCK_MUTEX(stats_lock);
245 send_stats(local_stats_array);
250 /*********************************************************************
252 * Function : send_stats
254 * Description : Attempt to send statistics to the listening console.
255 * Stats are formatted as a clear-text string for now -
256 * no need for any encoding fanciness just yet.
259 * 1 : local_stats_array, a pointer to a local copy of the
264 *********************************************************************/
265 void send_stats(int local_stats_array[])
268 char *msg = NULL, tmp_msg[64];
271 /* Here, we initiate the socket send to the console */
272 sk = connect_to(latest_config->activity_address,latest_config->activity_port,NULL);
275 /* max size of a key looks like this: xxxxx:xxxxxb */
277 64 + /* space for socket key ("serving:") and value and stuff */
278 STATS_MAX_KEYS * 64 /* Space for keys - much bigger than necessary for safety */
282 sprintf(msg,"serving:%d ",latest_config->hport);
283 for (i = 0; i < STATS_MAX_KEYS; i++)
285 sprintf(tmp_msg,"%d:%d ",i,local_stats_array[i]);
288 write_socket(sk,msg,strlen(msg));
295 /*********************************************************************
297 * Function : null_routine
299 * Description : Called when hit by a signal in unix; do nothing.
302 * 1 : sig - the integer signal
306 *********************************************************************/
308 void null_routine(int sig)
310 /* sigignore(sig); */
312 #endif /* def unix */