1 const char stats_rcs[] = "$Id: stats.c,v 2.3 2002/12/30 19:56:16 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.
37 *********************************************************************/
42 #include <sys/signal.h>
50 #include "jbsockets.h"
52 const char stats_h_rcs[] = STATS_H_VERSION;
53 const char ipc_h_rcs[] = IPC_H_VERSION;
54 static IPC_MUTEX_LOCK stats_lock;
56 stats_struct *main_stats;
58 /*********************************************************************
60 * Function : init_stats_config
62 * Description : Initializes the statistics array and spawns a thread
63 * to transmit statistics to the listening party.
66 * 1 : config = Privoxy configuration.
70 *********************************************************************/
71 void init_stats_config(struct configuration_spec * config)
79 main_stats = zalloc(sizeof(stats_struct));
80 IPC_CREATE_MUTEX(stats_lock);
81 for (i=0; i < STATS_MAX_KEYS; i++)
83 main_stats->stats_array[i] = 0;
85 main_stats->config = config;
87 accumulate_stats(STATS_PRIVOXY_PORT, config->hport);
90 * Start the timing/sending thread - I stole this from jcc.c.
91 * The idea is to get a mutiplatform thread started.
92 * YMMV - please tweak for your platform!
95 /* this is a switch () statment in the C preprocessor - ugh */
96 #undef SELECTED_ONE_OPTION
98 /* Use pthreads in preference to any native code */
99 #if defined(FEATURE_PTHREAD) && !defined(SELECTED_ONE_OPTION)
100 #define SELECTED_ONE_OPTION
101 signal(SIGALRM, null_routine); /* Ignore the SIGALRM signal */
102 pthread_attr_init(&attr);
103 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
104 child_id = (pthread_create(&thread, &attr,
105 (void*)forward_stats, main_stats) ? -1 : 0);
106 pthread_attr_destroy(&attr);
109 #if defined(_WIN32) && !defined(_CYGWIN) && !defined(SELECTED_ONE_OPTION)
110 #define SELECTED_ONE_OPTION
111 child_id = _beginthread(
112 (void (*)(void *))forward_stats,
117 #if defined(__OS2__) && !defined(SELECTED_ONE_OPTION)
118 #define SELECTED_ONE_OPTION
119 child_id = _beginthread(
120 (void(* _Optlink)(void*))forward_stats,
126 #if defined(__BEOS__) && !defined(SELECTED_ONE_OPTION)
127 #define SELECTED_ONE_OPTION
128 thread_id tid = spawn_thread
129 (server_thread, "forward_stats", B_NORMAL_PRIORITY, NULL);
130 if ((tid >= 0) && (resume_thread(tid) == B_OK))
132 child_id = (int) tid;
140 #if defined(AMIGA) && !defined(SELECTED_ONE_OPTION)
141 #define SELECTED_ONE_OPTION
142 if((child_id = (int)CreateNewProcTags(
143 NP_Entry, (ULONG)server_thread,
145 NP_CloseOutput, FALSE,
146 NP_Name, (ULONG)"privoxy child",
147 NP_StackSize, 200*1024,
151 Signal((struct Task *)child_id, SIGF_SINGLE);
156 #if !defined(SELECTED_ONE_OPTION)
157 /* I don't think the IPC will really work in a fork()'d environment,
158 * so proceed with caution. FIXME.
160 #error FIXME - stats won't work without pthreads!
163 if (child_id == 0) /* child */
165 forward_stats(main_stats);
168 else if (child_id > 0) /* parent */
173 #undef SELECTED_ONE_OPTION
174 /* end of c preprocessor switch () */
178 /*********************************************************************
180 * Function : update_stats_config
182 * Description : Updates the pointer to the most recent Privoxy
183 * configuration changes.
186 * 1 : config = Privoxy configuration.
190 *********************************************************************/
191 void update_stats_config(struct configuration_spec * config)
193 main_stats->config = config;
196 /*********************************************************************
198 * Function : accumulate_stats
200 * Description : Updates one element of the statistics array with a
201 * single integer value.
204 * 1 : key = the key into the stats array
205 * 2 : value = the value to add to the current stats key
209 *********************************************************************/
210 void accumulate_stats(int key, int value)
212 if (key < STATS_MAX_KEYS)
214 IPC_LOCK_MUTEX(stats_lock);
215 main_stats->stats_array[key] += value;
216 main_stats->changed = 1;
217 IPC_UNLOCK_MUTEX(stats_lock);
221 /*********************************************************************
223 * Function : forward_stats
225 * Description : Main routine for the statistics thread; loops and
226 * periodically checks if there's anything to send. If
227 * so, call send_stats() to do the work.
233 *********************************************************************/
234 void *forward_stats(stats_struct *pstats)
236 int local_stats_array[STATS_MAX_KEYS];
240 IPC_SLEEP_SECONDS(pstats->config->activity_freq);
241 if (pstats->changed == 1)
243 IPC_LOCK_MUTEX(stats_lock);
244 memcpy(local_stats_array,pstats->stats_array,sizeof(pstats->stats_array));
246 IPC_UNLOCK_MUTEX(stats_lock);
247 send_stats(local_stats_array);
252 /*********************************************************************
254 * Function : send_stats
256 * Description : Attempt to send statistics to the listening console.
257 * Stats are formatted as a clear-text string for now -
258 * no need for any encoding fanciness just yet.
261 * 1 : local_stats_array, a pointer to a local copy of the
266 *********************************************************************/
267 void send_stats(int local_stats_array[])
270 char *msg = NULL, tmp_msg[64];
273 /* Here, we initiate the socket send to the console */
274 sk = connect_to(main_stats->config->activity_address,main_stats->config->activity_port,NULL);
277 /* max size of a key looks like this: xxxxx:xxxxxb */
279 STATS_MAX_KEYS * 64 /* Space for keys - much bigger than necessary for safety */
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 */