1 const char stats_rcs[] = "$Id: stats.c,v 2.4 2003/01/06 02:03:13 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.
36 * Revision 2.4 2003/01/06 02:03:13 david__schmidt
37 * Update stats protocol now that the console is actually running
40 *********************************************************************/
45 #include <sys/signal.h>
54 #include "jbsockets.h"
56 const char stats_h_rcs[] = STATS_H_VERSION;
57 const char ipc_h_rcs[] = IPC_H_VERSION;
58 static IPC_MUTEX_LOCK stats_lock;
60 stats_struct *main_stats;
62 /*********************************************************************
64 * Function : init_stats_config
66 * Description : Initializes the statistics array and spawns a thread
67 * to transmit statistics to the listening party.
70 * 1 : config = Privoxy configuration.
74 *********************************************************************/
75 void init_stats_config(struct configuration_spec * config)
83 main_stats = zalloc(sizeof(stats_struct));
84 IPC_CREATE_MUTEX(stats_lock);
85 for (i=0; i < STATS_MAX_KEYS; i++)
87 main_stats->stats_array[i] = 0;
89 main_stats->config = config;
91 accumulate_stats(STATS_PRIVOXY_PORT, config->hport);
94 * Start the timing/sending thread - I stole this from jcc.c.
95 * The idea is to get a mutiplatform thread started.
96 * YMMV - please tweak for your platform!
99 /* this is a switch () statment in the C preprocessor - ugh */
100 #undef SELECTED_ONE_OPTION
102 /* Use pthreads in preference to any native code */
103 #if defined(FEATURE_PTHREAD) && !defined(SELECTED_ONE_OPTION)
104 #define SELECTED_ONE_OPTION
105 signal(SIGALRM, null_routine); /* Ignore the SIGALRM signal */
106 pthread_attr_init(&attr);
107 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
108 child_id = (pthread_create(&thread, &attr,
109 (void*)forward_stats, main_stats) ? -1 : 0);
110 pthread_attr_destroy(&attr);
113 #if defined(_WIN32) && !defined(_CYGWIN) && !defined(SELECTED_ONE_OPTION)
114 #define SELECTED_ONE_OPTION
115 child_id = _beginthread(
116 (void (*)(void *))forward_stats,
121 #if defined(__OS2__) && !defined(SELECTED_ONE_OPTION)
122 #define SELECTED_ONE_OPTION
123 child_id = _beginthread(
124 (void(* _Optlink)(void*))forward_stats,
130 #if defined(__BEOS__) && !defined(SELECTED_ONE_OPTION)
131 #define SELECTED_ONE_OPTION
132 thread_id tid = spawn_thread
133 (server_thread, "forward_stats", B_NORMAL_PRIORITY, NULL);
134 if ((tid >= 0) && (resume_thread(tid) == B_OK))
136 child_id = (int) tid;
144 #if defined(AMIGA) && !defined(SELECTED_ONE_OPTION)
145 #define SELECTED_ONE_OPTION
146 if((child_id = (int)CreateNewProcTags(
147 NP_Entry, (ULONG)server_thread,
149 NP_CloseOutput, FALSE,
150 NP_Name, (ULONG)"privoxy child",
151 NP_StackSize, 200*1024,
155 Signal((struct Task *)child_id, SIGF_SINGLE);
160 #if !defined(SELECTED_ONE_OPTION)
161 /* I don't think the IPC will really work in a fork()'d environment,
162 * so proceed with caution. FIXME.
164 #error FIXME - stats will not work without pthreads!
167 if (child_id == 0) /* child */
169 forward_stats(main_stats);
172 else if (child_id > 0) /* parent */
177 #undef SELECTED_ONE_OPTION
178 /* end of c preprocessor switch () */
182 /*********************************************************************
184 * Function : update_stats_config
186 * Description : Updates the pointer to the most recent Privoxy
187 * configuration changes.
190 * 1 : config = Privoxy configuration.
194 *********************************************************************/
195 void update_stats_config(struct configuration_spec * config)
197 main_stats->config = config;
200 /*********************************************************************
202 * Function : accumulate_stats
204 * Description : Updates one element of the statistics array with a
205 * single integer value.
208 * 1 : key = the key into the stats array
209 * 2 : value = the value to add to the current stats key
213 *********************************************************************/
214 void accumulate_stats(int key, int value)
216 if (key < STATS_MAX_KEYS)
218 IPC_LOCK_MUTEX(stats_lock);
219 main_stats->stats_array[key] += value;
220 main_stats->changed = 1;
221 IPC_UNLOCK_MUTEX(stats_lock);
225 /*********************************************************************
227 * Function : forward_stats
229 * Description : Main routine for the statistics thread; loops and
230 * periodically checks if there's anything to send. If
231 * so, call send_stats() to do the work.
237 *********************************************************************/
238 void *forward_stats(stats_struct *pstats)
240 int local_stats_array[STATS_MAX_KEYS];
244 IPC_SLEEP_SECONDS(pstats->config->activity_freq);
245 if (pstats->changed == 1)
247 IPC_LOCK_MUTEX(stats_lock);
248 memcpy(local_stats_array,pstats->stats_array,sizeof(pstats->stats_array));
250 IPC_UNLOCK_MUTEX(stats_lock);
251 send_stats(local_stats_array);
256 /*********************************************************************
258 * Function : send_stats
260 * Description : Attempt to send statistics to the listening console.
261 * Stats are formatted as a clear-text string for now -
262 * no need for any encoding fanciness just yet.
265 * 1 : local_stats_array, a pointer to a local copy of the
270 *********************************************************************/
271 void send_stats(int local_stats_array[])
274 char *msg = NULL, tmp_msg[64];
277 /* Here, we initiate the socket send to the console */
278 sk = connect_to(main_stats->config->activity_address,main_stats->config->activity_port,NULL);
281 /* max size of a key looks like this: xxxxx:xxxxxb */
283 STATS_MAX_KEYS * 64 /* Space for keys - much bigger than necessary for safety */
287 for (i = 0; i < STATS_MAX_KEYS; i++)
289 sprintf(tmp_msg,"%d:%d ",i,local_stats_array[i]);
292 write_socket(sk,msg,strlen(msg));
299 /*********************************************************************
301 * Function : null_routine
303 * Description : Called when hit by a signal in unix; do nothing.
306 * 1 : sig - the integer signal
310 *********************************************************************/
312 void null_routine(int sig)
314 /* sigignore(sig); */
316 #endif /* def unix */