]>
Commit | Line | Data |
---|---|---|
e5f6c5c2 | 1 | |
30a4f2a8 | 2 | /* |
f6c78bd2 | 3 | * $Id: stat.cc,v 1.88 1996/10/15 18:06:25 wessels Exp $ |
30a4f2a8 | 4 | * |
5 | * DEBUG: section 18 Cache Manager Statistics | |
6 | * AUTHOR: Harvest Derived | |
7 | * | |
8 | * SQUID Internet Object Cache http://www.nlanr.net/Squid/ | |
9 | * -------------------------------------------------------- | |
10 | * | |
11 | * Squid is the result of efforts by numerous individuals from the | |
12 | * Internet community. Development is led by Duane Wessels of the | |
13 | * National Laboratory for Applied Network Research and funded by | |
14 | * the National Science Foundation. | |
15 | * | |
16 | * This program is free software; you can redistribute it and/or modify | |
17 | * it under the terms of the GNU General Public License as published by | |
18 | * the Free Software Foundation; either version 2 of the License, or | |
19 | * (at your option) any later version. | |
20 | * | |
21 | * This program is distributed in the hope that it will be useful, | |
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
24 | * GNU General Public License for more details. | |
25 | * | |
26 | * You should have received a copy of the GNU General Public License | |
27 | * along with this program; if not, write to the Free Software | |
28 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
29 | * | |
30 | */ | |
019dd986 | 31 | |
32 | /* | |
30a4f2a8 | 33 | * Copyright (c) 1994, 1995. All rights reserved. |
34 | * | |
35 | * The Harvest software was developed by the Internet Research Task | |
36 | * Force Research Group on Resource Discovery (IRTF-RD): | |
37 | * | |
38 | * Mic Bowman of Transarc Corporation. | |
39 | * Peter Danzig of the University of Southern California. | |
40 | * Darren R. Hardy of the University of Colorado at Boulder. | |
41 | * Udi Manber of the University of Arizona. | |
42 | * Michael F. Schwartz of the University of Colorado at Boulder. | |
43 | * Duane Wessels of the University of Colorado at Boulder. | |
44 | * | |
45 | * This copyright notice applies to software in the Harvest | |
46 | * ``src/'' directory only. Users should consult the individual | |
47 | * copyright notices in the ``components/'' subdirectories for | |
48 | * copyright information about other software bundled with the | |
49 | * Harvest source code distribution. | |
50 | * | |
51 | * TERMS OF USE | |
52 | * | |
53 | * The Harvest software may be used and re-distributed without | |
54 | * charge, provided that the software origin and research team are | |
55 | * cited in any use of the system. Most commonly this is | |
56 | * accomplished by including a link to the Harvest Home Page | |
57 | * (http://harvest.cs.colorado.edu/) from the query page of any | |
58 | * Broker you deploy, as well as in the query result pages. These | |
59 | * links are generated automatically by the standard Broker | |
60 | * software distribution. | |
61 | * | |
62 | * The Harvest software is provided ``as is'', without express or | |
63 | * implied warranty, and with no support nor obligation to assist | |
64 | * in its use, correction, modification or enhancement. We assume | |
65 | * no liability with respect to the infringement of copyrights, | |
66 | * trade secrets, or any patents, and are not responsible for | |
67 | * consequential damages. Proper use of the Harvest software is | |
68 | * entirely the responsibility of the user. | |
69 | * | |
70 | * DERIVATIVE WORKS | |
71 | * | |
72 | * Users may make derivative works from the Harvest software, subject | |
73 | * to the following constraints: | |
74 | * | |
75 | * - You must include the above copyright notice and these | |
76 | * accompanying paragraphs in all forms of derivative works, | |
77 | * and any documentation and other materials related to such | |
78 | * distribution and use acknowledge that the software was | |
79 | * developed at the above institutions. | |
80 | * | |
81 | * - You must notify IRTF-RD regarding your distribution of | |
82 | * the derivative work. | |
83 | * | |
84 | * - You must clearly notify users that your are distributing | |
85 | * a modified version and not the original Harvest software. | |
86 | * | |
87 | * - Any derivative product is also subject to these copyright | |
88 | * and use restrictions. | |
89 | * | |
90 | * Note that the Harvest software is NOT in the public domain. We | |
91 | * retain copyright, as specified above. | |
92 | * | |
93 | * HISTORY OF FREE SOFTWARE STATUS | |
94 | * | |
95 | * Originally we required sites to license the software in cases | |
96 | * where they were going to build commercial products/services | |
97 | * around Harvest. In June 1995 we changed this policy. We now | |
98 | * allow people to use the core Harvest software (the code found in | |
99 | * the Harvest ``src/'' directory) for free. We made this change | |
100 | * in the interest of encouraging the widest possible deployment of | |
101 | * the technology. The Harvest software is really a reference | |
102 | * implementation of a set of protocols and formats, some of which | |
103 | * we intend to standardize. We encourage commercial | |
104 | * re-implementations of code complying to this set of standards. | |
019dd986 | 105 | */ |
ed43818f | 106 | |
234967c9 | 107 | |
44a47c6e | 108 | #include "squid.h" |
090089c4 | 109 | |
090089c4 | 110 | #define MAX_LINELEN (4096) |
111 | #define max(a,b) ((a)>(b)? (a): (b)) | |
112 | ||
113 | typedef struct _log_read_data_t { | |
114 | StoreEntry *sentry; | |
115 | } log_read_data_t; | |
116 | ||
b8de7ebe | 117 | typedef struct _squid_read_data_t { |
090089c4 | 118 | StoreEntry *sentry; |
119 | int fd; | |
b8de7ebe | 120 | } squid_read_data_t; |
090089c4 | 121 | |
122 | /* GLOBALS */ | |
123 | Meta_data meta_data; | |
86ee2017 | 124 | volatile unsigned long ntcpconn = 0; |
125 | volatile unsigned long nudpconn = 0; | |
30a4f2a8 | 126 | struct _iostats IOStats; |
30a4f2a8 | 127 | char *open_bracket = "{\n"; |
128 | char *close_bracket = "}\n"; | |
a528eb87 | 129 | |
67508012 | 130 | extern char *diskFileName _PARAMS((int)); |
131 | ||
132 | /* LOCALS */ | |
133 | static char *stat_describe _PARAMS((StoreEntry * entry)); | |
134 | static char *mem_describe _PARAMS((StoreEntry * entry)); | |
135 | static char *ttl_describe _PARAMS((StoreEntry * entry)); | |
136 | static char *flags_describe _PARAMS((StoreEntry * entry)); | |
137 | static char *elapsed_time _PARAMS((StoreEntry * entry, int since, char *TTL)); | |
138 | static void dummyhandler _PARAMS((cacheinfo *, StoreEntry *)); | |
139 | static void info_get _PARAMS((cacheinfo *, StoreEntry *)); | |
140 | static void logReadEndHandler _PARAMS((int, int, log_read_data_t *)); | |
141 | static void log_clear _PARAMS((cacheinfo *, StoreEntry *)); | |
142 | static void log_disable _PARAMS((cacheinfo *, StoreEntry *)); | |
143 | static void log_enable _PARAMS((cacheinfo *, StoreEntry *)); | |
144 | static void log_get_start _PARAMS((cacheinfo *, StoreEntry *)); | |
145 | static void log_status_get _PARAMS((cacheinfo *, StoreEntry *)); | |
146 | static void parameter_get _PARAMS((cacheinfo *, StoreEntry *)); | |
147 | static void proto_count _PARAMS((cacheinfo *, protocol_t, log_type)); | |
148 | static void proto_newobject _PARAMS((cacheinfo *, protocol_t, int, int)); | |
149 | static void proto_purgeobject _PARAMS((cacheinfo *, protocol_t, int)); | |
150 | static void proto_touchobject _PARAMS((cacheinfo *, protocol_t, int)); | |
151 | static void server_list _PARAMS((cacheinfo *, StoreEntry *)); | |
152 | static void squidReadEndHandler _PARAMS((int, int, squid_read_data_t *)); | |
153 | static void squid_get_start _PARAMS((cacheinfo *, StoreEntry *)); | |
154 | static void statFiledescriptors _PARAMS((StoreEntry *)); | |
155 | static void stat_get _PARAMS((cacheinfo *, char *req, StoreEntry *)); | |
156 | static void stat_io_get _PARAMS((StoreEntry *)); | |
157 | static void stat_objects_get _PARAMS((cacheinfo *, StoreEntry *, int vm_or_not)); | |
158 | static void stat_utilization_get _PARAMS((cacheinfo *, StoreEntry *, char *desc)); | |
159 | static int cache_size_get _PARAMS((cacheinfo *)); | |
160 | static int logReadHandler _PARAMS((int, char *, int, log_read_data_t *)); | |
161 | static int squidReadHandler _PARAMS((int, char *, int, squid_read_data_t *)); | |
162 | static int memoryAccounted _PARAMS((void)); | |
20882fb1 | 163 | |
164 | #ifdef UNUSED_CODE | |
67508012 | 165 | static int mallinfoTotal _PARAMS((void)); |
20882fb1 | 166 | #endif |
167 | ||
168 | #ifdef XMALLOC_STATISTICS | |
67508012 | 169 | static void info_get_mallstat _PARAMS((int, int, StoreEntry *)); |
20882fb1 | 170 | #endif |
30a4f2a8 | 171 | |
090089c4 | 172 | /* process utilization information */ |
b8d8561b | 173 | static void |
174 | stat_utilization_get(cacheinfo * obj, StoreEntry * sentry, char *desc) | |
090089c4 | 175 | { |
8213067d | 176 | protocol_t proto_id; |
177 | proto_stat *p = &obj->proto_stat_data[PROTO_MAX]; | |
090089c4 | 178 | proto_stat *q = NULL; |
179 | int secs = 0; | |
180 | ||
b8de7ebe | 181 | secs = (int) (squid_curtime - squid_starttime); |
a528eb87 | 182 | storeAppendPrintf(sentry, "{ %s\n", desc); /* } */ |
234967c9 | 183 | strcpy(p->protoname, "TOTAL"); |
090089c4 | 184 | p->object_count = 0; |
185 | p->kb.max = 0; | |
186 | p->kb.min = 0; | |
187 | p->kb.avg = 0; | |
188 | p->kb.now = 0; | |
189 | p->hit = 0; | |
190 | p->miss = 0; | |
191 | p->refcount = 0; | |
192 | p->transferbyte = 0; | |
090089c4 | 193 | /* find the total */ |
30a4f2a8 | 194 | for (proto_id = PROTO_NONE; proto_id < PROTO_MAX; ++proto_id) { |
090089c4 | 195 | q = &obj->proto_stat_data[proto_id]; |
090089c4 | 196 | p->object_count += q->object_count; |
197 | p->kb.max += q->kb.max; | |
198 | p->kb.min += q->kb.min; | |
199 | p->kb.avg += q->kb.avg; | |
200 | p->kb.now += q->kb.now; | |
201 | p->hit += q->hit; | |
202 | p->miss += q->miss; | |
203 | p->refcount += q->refcount; | |
204 | p->transferbyte += q->transferbyte; | |
205 | } | |
090089c4 | 206 | /* dump it */ |
30a4f2a8 | 207 | for (proto_id = PROTO_NONE; proto_id <= PROTO_MAX; ++proto_id) { |
090089c4 | 208 | p = &obj->proto_stat_data[proto_id]; |
209 | if (p->hit != 0) { | |
210 | p->hitratio = | |
211 | (float) p->hit / | |
212 | ((float) p->hit + | |
213 | (float) p->miss); | |
214 | } | |
30a4f2a8 | 215 | storeAppendPrintf(sentry, "{%8.8s %d %d %d %d %4.2f %d %d %d}\n", |
090089c4 | 216 | p->protoname, |
217 | p->object_count, | |
218 | p->kb.max, | |
219 | p->kb.now, | |
220 | p->kb.min, | |
221 | p->hitratio, | |
222 | (secs ? p->transferbyte / secs : 0), | |
223 | p->refcount, | |
224 | p->transferbyte); | |
090089c4 | 225 | } |
30a4f2a8 | 226 | storeAppendPrintf(sentry, close_bracket); |
227 | } | |
228 | ||
b8d8561b | 229 | static void |
230 | stat_io_get(StoreEntry * sentry) | |
30a4f2a8 | 231 | { |
232 | int i; | |
233 | ||
234 | storeAppendPrintf(sentry, open_bracket); | |
235 | storeAppendPrintf(sentry, "{HTTP I/O}\n"); | |
236 | storeAppendPrintf(sentry, "{number of reads: %d}\n", IOStats.Http.reads); | |
237 | storeAppendPrintf(sentry, "{deferred reads: %d (%d%%)}\n", | |
238 | IOStats.Http.reads_deferred, | |
239 | percent(IOStats.Http.reads_deferred, IOStats.Http.reads)); | |
240 | storeAppendPrintf(sentry, "{Read Histogram:}\n"); | |
241 | for (i = 0; i < 16; i++) { | |
242 | storeAppendPrintf(sentry, "{%5d-%5d: %9d %2d%%}\n", | |
243 | i ? (1 << (i - 1)) + 1 : 1, | |
244 | 1 << i, | |
245 | IOStats.Http.read_hist[i], | |
246 | percent(IOStats.Http.read_hist[i], IOStats.Http.reads)); | |
247 | } | |
248 | ||
249 | storeAppendPrintf(sentry, "{}\n"); | |
250 | storeAppendPrintf(sentry, "{FTP I/O}\n"); | |
251 | storeAppendPrintf(sentry, "{number of reads: %d}\n", IOStats.Ftp.reads); | |
252 | storeAppendPrintf(sentry, "{deferred reads: %d (%d%%)}\n", | |
253 | IOStats.Ftp.reads_deferred, | |
254 | percent(IOStats.Ftp.reads_deferred, IOStats.Ftp.reads)); | |
255 | storeAppendPrintf(sentry, "{Read Histogram:}\n"); | |
256 | for (i = 0; i < 16; i++) { | |
257 | storeAppendPrintf(sentry, "{%5d-%5d: %9d %2d%%}\n", | |
258 | i ? (1 << (i - 1)) + 1 : 1, | |
259 | 1 << i, | |
260 | IOStats.Ftp.read_hist[i], | |
261 | percent(IOStats.Ftp.read_hist[i], IOStats.Ftp.reads)); | |
262 | } | |
263 | ||
56fa4cad | 264 | storeAppendPrintf(sentry, "{}\n"); |
265 | storeAppendPrintf(sentry, "{Gopher I/O}\n"); | |
266 | storeAppendPrintf(sentry, "{number of reads: %d}\n", IOStats.Gopher.reads); | |
267 | storeAppendPrintf(sentry, "{deferred reads: %d (%d%%)}\n", | |
268 | IOStats.Gopher.reads_deferred, | |
269 | percent(IOStats.Gopher.reads_deferred, IOStats.Gopher.reads)); | |
270 | storeAppendPrintf(sentry, "{Read Histogram:}\n"); | |
271 | for (i = 0; i < 16; i++) { | |
272 | storeAppendPrintf(sentry, "{%5d-%5d: %9d %2d%%}\n", | |
273 | i ? (1 << (i - 1)) + 1 : 1, | |
274 | 1 << i, | |
275 | IOStats.Gopher.read_hist[i], | |
276 | percent(IOStats.Gopher.read_hist[i], IOStats.Gopher.reads)); | |
277 | } | |
278 | ||
279 | storeAppendPrintf(sentry, "{}\n"); | |
280 | storeAppendPrintf(sentry, "{WAIS I/O}\n"); | |
281 | storeAppendPrintf(sentry, "{number of reads: %d}\n", IOStats.Wais.reads); | |
282 | storeAppendPrintf(sentry, "{deferred reads: %d (%d%%)}\n", | |
283 | IOStats.Wais.reads_deferred, | |
284 | percent(IOStats.Wais.reads_deferred, IOStats.Wais.reads)); | |
285 | storeAppendPrintf(sentry, "{Read Histogram:}\n"); | |
286 | for (i = 0; i < 16; i++) { | |
287 | storeAppendPrintf(sentry, "{%5d-%5d: %9d %2d%%}\n", | |
288 | i ? (1 << (i - 1)) + 1 : 1, | |
289 | 1 << i, | |
290 | IOStats.Wais.read_hist[i], | |
291 | percent(IOStats.Wais.read_hist[i], IOStats.Wais.reads)); | |
292 | } | |
293 | ||
30a4f2a8 | 294 | storeAppendPrintf(sentry, close_bracket); |
090089c4 | 295 | } |
296 | ||
297 | ||
298 | /* return total bytes of all registered and known objects. | |
299 | * may not reflect the retrieving object.... | |
300 | * something need to be done here to get more accurate cache size */ | |
b8d8561b | 301 | static int |
302 | cache_size_get(cacheinfo * obj) | |
090089c4 | 303 | { |
304 | int size = 0; | |
8213067d | 305 | protocol_t proto_id; |
090089c4 | 306 | /* sum all size, exclude total */ |
30a4f2a8 | 307 | for (proto_id = PROTO_NONE; proto_id < PROTO_MAX; proto_id++) |
090089c4 | 308 | size += obj->proto_stat_data[proto_id].kb.now; |
8213067d | 309 | return size; |
090089c4 | 310 | } |
311 | ||
090089c4 | 312 | /* process objects list */ |
b8d8561b | 313 | static void |
314 | stat_objects_get(cacheinfo * obj, StoreEntry * sentry, int vm_or_not) | |
090089c4 | 315 | { |
95d659f0 | 316 | LOCAL_ARRAY(char, space, 40); |
317 | LOCAL_ARRAY(char, space2, 40); | |
090089c4 | 318 | int npend = 0; |
09610784 | 319 | StoreEntry *entry = NULL; |
090089c4 | 320 | int N = 0; |
321 | int obj_size; | |
322 | ||
30a4f2a8 | 323 | storeAppendPrintf(sentry, open_bracket); |
090089c4 | 324 | |
325 | for (entry = storeGetFirst(); | |
326 | entry != NULL; | |
327 | entry = storeGetNext()) { | |
328 | if (vm_or_not && (entry->mem_status == NOT_IN_MEMORY) && | |
329 | (entry->swap_status == SWAP_OK)) | |
330 | continue; | |
331 | if ((++N & 0xFF) == 0) { | |
316a3472 | 332 | getCurrentTime(); |
019dd986 | 333 | debug(18, 3, "stat_objects_get: Processed %d objects...\n", N); |
090089c4 | 334 | } |
335 | obj_size = entry->object_len; | |
336 | npend = storePendingNClients(entry); | |
337 | if (entry->mem_obj) | |
22e4fa85 | 338 | obj_size = entry->mem_obj->e_current_len; |
c30c5a73 | 339 | storeAppendPrintf(sentry, "{ %s %d %s %s %s %s %d %d %s %s }\n", |
090089c4 | 340 | entry->url, |
341 | obj_size, | |
342 | elapsed_time(entry, (int) entry->timestamp, space), | |
343 | flags_describe(entry), | |
344 | elapsed_time(entry, (int) entry->lastref, space2), | |
ed82beba | 345 | ttl_describe(entry), |
090089c4 | 346 | npend, |
644642ab | 347 | (int) entry->refcount, |
090089c4 | 348 | mem_describe(entry), |
349 | stat_describe(entry)); | |
090089c4 | 350 | } |
30a4f2a8 | 351 | storeAppendPrintf(sentry, close_bracket); |
090089c4 | 352 | } |
353 | ||
354 | ||
355 | /* process a requested object into a manager format */ | |
b8d8561b | 356 | static void |
357 | stat_get(cacheinfo * obj, char *req, StoreEntry * sentry) | |
090089c4 | 358 | { |
359 | ||
30a4f2a8 | 360 | if (strcmp(req, "objects") == 0) { |
090089c4 | 361 | stat_objects_get(obj, sentry, 0); |
30a4f2a8 | 362 | } else if (strcmp(req, "vm_objects") == 0) { |
090089c4 | 363 | stat_objects_get(obj, sentry, 1); |
f88bb09c | 364 | } else if (strcmp(req, "ipcache") == 0) { |
30a4f2a8 | 365 | stat_ipcache_get(sentry); |
f88bb09c | 366 | } else if (strcmp(req, "fqdncache") == 0) { |
367 | fqdnStats(sentry); | |
f83b7b2c | 368 | } else if (strcmp(req, "dns") == 0) { |
369 | dnsStats(sentry); | |
d2af9477 | 370 | } else if (strcmp(req, "redirector") == 0) { |
371 | redirectStats(sentry); | |
30a4f2a8 | 372 | } else if (strcmp(req, "utilization") == 0) { |
a528eb87 | 373 | stat_utilization_get(HTTPCacheInfo, sentry, "HTTP"); |
374 | stat_utilization_get(ICPCacheInfo, sentry, "ICP"); | |
30a4f2a8 | 375 | } else if (strcmp(req, "io") == 0) { |
376 | stat_io_get(sentry); | |
377 | } else if (strcmp(req, "reply_headers") == 0) { | |
378 | httpReplyHeaderStats(sentry); | |
d51e52f5 | 379 | } else if (strcmp(req, "filedescriptors") == 0) { |
380 | statFiledescriptors(sentry); | |
67508012 | 381 | } else if (strcmp(req, "netdb") == 0) { |
382 | netdbDump(sentry); | |
090089c4 | 383 | } |
384 | } | |
385 | ||
386 | ||
387 | /* generate logfile status information */ | |
b8d8561b | 388 | static void |
389 | log_status_get(cacheinfo * obj, StoreEntry * sentry) | |
090089c4 | 390 | { |
090089c4 | 391 | if (obj->logfile_status == LOG_ENABLE) { |
c30c5a73 | 392 | storeAppendPrintf(sentry, "{\"Logfile is Enabled. Filename: %s\"}\n", |
090089c4 | 393 | obj->logfilename); |
394 | } else { | |
c30c5a73 | 395 | storeAppendPrintf(sentry, "{\"Logfile is Disabled.\"}\n"); |
090089c4 | 396 | } |
090089c4 | 397 | } |
398 | ||
399 | ||
400 | ||
401 | /* log convert handler */ | |
402 | /* call for each line in file, use fileWalk routine */ | |
b8d8561b | 403 | static int |
404 | logReadHandler(int fd_unused, char *buf, int size_unused, log_read_data_t * data) | |
090089c4 | 405 | { |
c30c5a73 | 406 | storeAppendPrintf(data->sentry, "{%s}\n", buf); |
a2cc6ac9 | 407 | return 0; |
090089c4 | 408 | } |
409 | ||
410 | /* log convert end handler */ | |
411 | /* call when a walk is completed or error. */ | |
b8d8561b | 412 | static void |
413 | logReadEndHandler(int fd, int errflag_unused, log_read_data_t * data) | |
090089c4 | 414 | { |
30a4f2a8 | 415 | storeAppendPrintf(data->sentry, close_bracket); |
090089c4 | 416 | storeComplete(data->sentry); |
417 | safe_free(data); | |
557a6b70 | 418 | file_close(fd); |
090089c4 | 419 | } |
420 | ||
421 | ||
422 | ||
423 | /* start converting logfile to processed format */ | |
b8d8561b | 424 | static void |
425 | log_get_start(cacheinfo * obj, StoreEntry * sentry) | |
090089c4 | 426 | { |
090089c4 | 427 | log_read_data_t *data = NULL; |
557a6b70 | 428 | int fd; |
090089c4 | 429 | |
430 | if (obj->logfile_status == LOG_DISABLE) { | |
431 | /* Manufacture status when logging is disabled */ | |
432 | log_status_get(obj, sentry); | |
433 | storeComplete(sentry); | |
434 | return; | |
435 | } | |
557a6b70 | 436 | fd = file_open(obj->logfilename, NULL, O_RDONLY); |
437 | if (fd < 0) { | |
438 | debug(18, 0, "Cannot open logfile: %s: %s\n", | |
439 | obj->logfilename, xstrerror()); | |
440 | return; | |
441 | } | |
30a4f2a8 | 442 | data = xcalloc(1, sizeof(log_read_data_t)); |
090089c4 | 443 | data->sentry = sentry; |
c30c5a73 | 444 | storeAppendPrintf(sentry, "{\n"); |
557a6b70 | 445 | file_walk(fd, |
446 | (FILE_WALK_HD) logReadEndHandler, | |
447 | (void *) data, | |
448 | (FILE_WALK_LHD) logReadHandler, | |
449 | (void *) data); | |
090089c4 | 450 | return; |
451 | } | |
452 | ||
453 | ||
b8de7ebe | 454 | /* squid convert handler */ |
090089c4 | 455 | /* call for each line in file, use fileWalk routine */ |
b8d8561b | 456 | static int |
457 | squidReadHandler(int fd_unused, char *buf, int size_unused, squid_read_data_t * data) | |
090089c4 | 458 | { |
c30c5a73 | 459 | storeAppendPrintf(data->sentry, "{\"%s\"}\n", buf); |
a2cc6ac9 | 460 | return 0; |
090089c4 | 461 | } |
462 | ||
b8de7ebe | 463 | /* squid convert end handler */ |
090089c4 | 464 | /* call when a walk is completed or error. */ |
b8d8561b | 465 | static void |
466 | squidReadEndHandler(int fd_unused, int errflag_unused, squid_read_data_t * data) | |
090089c4 | 467 | { |
30a4f2a8 | 468 | storeAppendPrintf(data->sentry, close_bracket); |
090089c4 | 469 | storeComplete(data->sentry); |
470 | file_close(data->fd); | |
471 | safe_free(data); | |
472 | } | |
473 | ||
474 | ||
b8de7ebe | 475 | /* start convert squid.conf file to processed format */ |
b8d8561b | 476 | static void |
477 | squid_get_start(cacheinfo * obj, StoreEntry * sentry) | |
090089c4 | 478 | { |
b8de7ebe | 479 | squid_read_data_t *data; |
090089c4 | 480 | |
30a4f2a8 | 481 | data = xcalloc(1, sizeof(squid_read_data_t)); |
090089c4 | 482 | data->sentry = sentry; |
00fac1f8 | 483 | data->fd = file_open((char *) ConfigFile, NULL, O_RDONLY); |
30a4f2a8 | 484 | storeAppendPrintf(sentry, open_bracket); |
b8de7ebe | 485 | file_walk(data->fd, (FILE_WALK_HD) squidReadEndHandler, (void *) data, |
486 | (FILE_WALK_LHD) squidReadHandler, (void *) data); | |
090089c4 | 487 | } |
488 | ||
489 | ||
b8d8561b | 490 | static void |
491 | dummyhandler(cacheinfo * obj, StoreEntry * sentry) | |
090089c4 | 492 | { |
c30c5a73 | 493 | storeAppendPrintf(sentry, "{ \"Not_Implemented_yet.\"}\n"); |
090089c4 | 494 | } |
495 | ||
b8d8561b | 496 | static void |
497 | server_list(cacheinfo * obj, StoreEntry * sentry) | |
090089c4 | 498 | { |
090089c4 | 499 | edge *e = NULL; |
500 | dom_list *d = NULL; | |
30a4f2a8 | 501 | icp_opcode op; |
090089c4 | 502 | |
30a4f2a8 | 503 | storeAppendPrintf(sentry, open_bracket); |
090089c4 | 504 | |
30a4f2a8 | 505 | if (getFirstEdge() == NULL) |
c30c5a73 | 506 | storeAppendPrintf(sentry, "{There are no neighbors installed.}\n"); |
090089c4 | 507 | for (e = getFirstEdge(); e; e = getNextEdge(e)) { |
508 | if (e->host == NULL) | |
6eb42cae | 509 | fatal_dump("Found an edge without a hostname!"); |
30a4f2a8 | 510 | storeAppendPrintf(sentry, "\n{%-11.11s: %s/%d/%d}\n", |
511 | e->type == EDGE_PARENT ? "Parent" : "Sibling", | |
512 | e->host, | |
513 | e->http_port, | |
514 | e->icp_port); | |
515 | storeAppendPrintf(sentry, "{Status : %s}\n", | |
090089c4 | 516 | e->neighbor_up ? "Up" : "Down"); |
30a4f2a8 | 517 | storeAppendPrintf(sentry, "{AVG RTT : %d msec}\n", e->stats.rtt); |
518 | storeAppendPrintf(sentry, "{ACK DEFICIT: %8d}\n", e->stats.ack_deficit); | |
519 | storeAppendPrintf(sentry, "{PINGS SENT : %8d}\n", e->stats.pings_sent); | |
520 | storeAppendPrintf(sentry, "{PINGS ACKED: %8d %3d%%}\n", | |
521 | e->stats.pings_acked, | |
522 | percent(e->stats.pings_acked, e->stats.pings_sent)); | |
523 | storeAppendPrintf(sentry, "{Histogram of PINGS ACKED:}\n"); | |
524 | for (op = ICP_OP_INVALID; op < ICP_OP_END; op++) { | |
525 | if (e->stats.counts[op] == 0) | |
526 | continue; | |
527 | storeAppendPrintf(sentry, "{%-10.10s : %8d %3d%%}\n", | |
528 | IcpOpcodeStr[op], | |
529 | e->stats.counts[op], | |
530 | percent(e->stats.counts[op], e->stats.pings_acked)); | |
531 | } | |
532 | storeAppendPrintf(sentry, "{FETCHES : %8d %3d%%}\n", | |
533 | e->stats.fetches, | |
534 | percent(e->stats.fetches, e->stats.pings_acked)); | |
535 | ||
090089c4 | 536 | if (e->last_fail_time) { |
c30c5a73 | 537 | storeAppendPrintf(sentry, "{Last failed connect() at: %s}\n", |
090089c4 | 538 | mkhttpdlogtime(&(e->last_fail_time))); |
090089c4 | 539 | } |
c30c5a73 | 540 | storeAppendPrintf(sentry, "{DOMAIN LIST: "); |
090089c4 | 541 | for (d = e->domains; d; d = d->next) { |
542 | if (d->do_ping) | |
c30c5a73 | 543 | storeAppendPrintf(sentry, "%s ", d->domain); |
090089c4 | 544 | else |
c30c5a73 | 545 | storeAppendPrintf(sentry, "!%s ", d->domain); |
090089c4 | 546 | } |
30a4f2a8 | 547 | storeAppendPrintf(sentry, close_bracket); /* } */ |
090089c4 | 548 | } |
30a4f2a8 | 549 | storeAppendPrintf(sentry, close_bracket); |
090089c4 | 550 | } |
551 | ||
30a4f2a8 | 552 | #if XMALLOC_STATISTICS |
b8d8561b | 553 | static void |
554 | info_get_mallstat(int size, number, StoreEntry * sentry) | |
30a4f2a8 | 555 | { |
30a4f2a8 | 556 | if (number > 0) |
557 | storeAppendPrintf(sentry, "{\t%d = %d}\n", size, number); | |
558 | } | |
559 | #endif | |
090089c4 | 560 | |
b8d8561b | 561 | static char * |
562 | host_port_fmt(char *host, u_short port) | |
d51e52f5 | 563 | { |
95d659f0 | 564 | LOCAL_ARRAY(char, buf, 32); |
d2af9477 | 565 | sprintf(buf, "%s.%d", host, (int) port); |
566 | return buf; | |
d51e52f5 | 567 | } |
568 | ||
b8d8561b | 569 | static void |
570 | statFiledescriptors(StoreEntry * sentry) | |
d51e52f5 | 571 | { |
572 | int i; | |
573 | int j; | |
574 | char *s = NULL; | |
575 | int lft; | |
576 | int to; | |
577 | ||
578 | storeAppendPrintf(sentry, open_bracket); | |
579 | storeAppendPrintf(sentry, "{Active file descriptors:}\n"); | |
580 | storeAppendPrintf(sentry, "{%-4s %-6s %-4s %-4s %-21s %s}\n", | |
581 | "File", | |
582 | "Type", | |
583 | "Lftm", | |
584 | "Tout", | |
585 | "Remote Address", | |
586 | "Description"); | |
587 | storeAppendPrintf(sentry, "{---- ------ ---- ---- --------------------- ------------------------------}\n"); | |
d51e52f5 | 588 | for (i = 0; i < FD_SETSIZE; i++) { |
589 | if (!fdstat_isopen(i)) | |
590 | continue; | |
591 | j = fdstatGetType(i); | |
592 | storeAppendPrintf(sentry, "{%4d %-6s ", | |
d2af9477 | 593 | i, |
594 | fdstatTypeStr[j]); | |
d51e52f5 | 595 | switch (j) { |
596 | case FD_SOCKET: | |
597 | if ((lft = comm_get_fd_lifetime(i)) < 0) | |
598 | lft = 0; | |
599 | to = comm_get_fd_timeout(i); | |
600 | if (lft > 0) | |
601 | lft = (lft - squid_curtime) / 60; | |
602 | if (to > 0) | |
603 | to = (to - squid_curtime) / 60; | |
3f155cbf | 604 | if (fd_table[i].timeout_handler == NULL) |
605 | to = 0; | |
d51e52f5 | 606 | storeAppendPrintf(sentry, "%4d %4d %-21s %s}\n", |
607 | lft, | |
608 | to, | |
609 | host_port_fmt(fd_table[i].ipaddr, fd_table[i].remote_port), | |
610 | fd_note(i, NULL)); | |
611 | break; | |
612 | case FD_FILE: | |
613 | storeAppendPrintf(sentry, "%31s %s}\n", | |
614 | "", | |
615 | (s = diskFileName(i)) ? s : "-"); | |
616 | break; | |
617 | case FD_PIPE: | |
618 | storeAppendPrintf(sentry, "%31s %s}\n", "", fd_note(i, NULL)); | |
619 | break; | |
620 | case FD_LOG: | |
621 | storeAppendPrintf(sentry, "%31s %s}\n", "", fd_note(i, NULL)); | |
622 | break; | |
623 | case FD_UNKNOWN: | |
624 | default: | |
625 | storeAppendPrintf(sentry, "%31s %s}\n", "", fd_note(i, NULL)); | |
626 | break; | |
627 | } | |
628 | } | |
629 | storeAppendPrintf(sentry, close_bracket); | |
630 | } | |
631 | ||
b8d8561b | 632 | static int |
0673c0ba | 633 | memoryAccounted(void) |
1a082686 | 634 | { |
92a8c005 | 635 | return (int) |
636 | meta_data.store_entries * sizeof(StoreEntry) + | |
637 | meta_data.ipcache_count * sizeof(ipcache_entry) + | |
f88bb09c | 638 | meta_data.fqdncache_count * sizeof(fqdncache_entry) + |
b15fe823 | 639 | hash_links_allocated * sizeof(hash_link) + |
92a8c005 | 640 | sm_stats.total_pages_allocated * sm_stats.page_size + |
641 | disk_stats.total_pages_allocated * disk_stats.page_size + | |
642 | request_pool.total_pages_allocated * request_pool.page_size + | |
643 | mem_obj_pool.total_pages_allocated * mem_obj_pool.page_size + | |
644 | meta_data.url_strings + | |
3e12e062 | 645 | meta_data.netdb_addrs * sizeof(netdbEntry) + |
646 | meta_data.netdb_hosts * sizeof(struct _net_db_name) + | |
f6c78bd2 | 647 | meta_data.client_info * client_info_sz + |
f6610c4e | 648 | meta_data.misc; |
1a082686 | 649 | } |
650 | ||
20882fb1 | 651 | #ifdef UNUSED_CODE |
b8d8561b | 652 | static int |
0673c0ba | 653 | mallinfoTotal(void) |
1a082686 | 654 | { |
655 | int total = 0; | |
656 | #if HAVE_MALLINFO | |
657 | struct mallinfo mp; | |
658 | mp = mallinfo(); | |
659 | total = mp.arena; | |
660 | #endif | |
661 | return total; | |
662 | } | |
20882fb1 | 663 | #endif |
090089c4 | 664 | |
b8d8561b | 665 | static void |
666 | info_get(cacheinfo * obj, StoreEntry * sentry) | |
090089c4 | 667 | { |
668 | char *tod = NULL; | |
e5f6c5c2 | 669 | float f; |
4c05a8b1 | 670 | #if HAVE_MALLINFO |
30a4f2a8 | 671 | int t; |
672 | #endif | |
090089c4 | 673 | |
674 | #if defined(HAVE_GETRUSAGE) && defined(RUSAGE_SELF) | |
675 | struct rusage rusage; | |
676 | #endif | |
677 | ||
50bc2565 | 678 | #if HAVE_MALLINFO |
090089c4 | 679 | struct mallinfo mp; |
680 | #endif | |
681 | ||
30a4f2a8 | 682 | storeAppendPrintf(sentry, open_bracket); |
d51e52f5 | 683 | storeAppendPrintf(sentry, "{Squid Object Cache: Version %s}\n", |
684 | version_string); | |
620da955 | 685 | tod = mkrfc850(squid_starttime); |
c30c5a73 | 686 | storeAppendPrintf(sentry, "{Start Time:\t%s}\n", tod); |
620da955 | 687 | tod = mkrfc850(squid_curtime); |
c30c5a73 | 688 | storeAppendPrintf(sentry, "{Current Time:\t%s}\n", tod); |
d51e52f5 | 689 | storeAppendPrintf(sentry, "{Connection information for %s:}\n", |
690 | appname); | |
691 | storeAppendPrintf(sentry, "{\tNumber of TCP connections:\t%lu}\n", | |
692 | ntcpconn); | |
693 | storeAppendPrintf(sentry, "{\tNumber of UDP connections:\t%lu}\n", | |
694 | nudpconn); | |
090089c4 | 695 | |
e5f6c5c2 | 696 | f = (float) (squid_curtime - squid_starttime); |
d2af9477 | 697 | storeAppendPrintf(sentry, "{\tConnections per hour:\t%.1f}\n", |
d51e52f5 | 698 | f == 0.0 ? 0.0 : ((ntcpconn + nudpconn) / (f / 3600))); |
090089c4 | 699 | |
30a4f2a8 | 700 | storeAppendPrintf(sentry, "{Cache information for %s:}\n", |
701 | appname); | |
702 | storeAppendPrintf(sentry, "{\tStorage Swap size:\t%d MB}\n", | |
703 | storeGetSwapSize() >> 10); | |
704 | storeAppendPrintf(sentry, "{\tStorage Mem size:\t%d KB}\n", | |
e954773d | 705 | store_mem_size >> 10); |
090089c4 | 706 | |
30a4f2a8 | 707 | #if HAVE_GETRUSAGE && defined(RUSAGE_SELF) |
c30c5a73 | 708 | storeAppendPrintf(sentry, "{Resource usage for %s:}\n", appname); |
090089c4 | 709 | getrusage(RUSAGE_SELF, &rusage); |
d51e52f5 | 710 | storeAppendPrintf(sentry, "{\tCPU Time: %d seconds (%d user %d sys)}\n", |
711 | (int) rusage.ru_utime.tv_sec + (int) rusage.ru_stime.tv_sec, | |
712 | (int) rusage.ru_utime.tv_sec, | |
713 | (int) rusage.ru_stime.tv_sec); | |
714 | storeAppendPrintf(sentry, "{\tCPU Usage: %d%%}\n", | |
715 | percent(rusage.ru_utime.tv_sec + rusage.ru_stime.tv_sec, | |
716 | squid_curtime - squid_starttime)); | |
30a4f2a8 | 717 | storeAppendPrintf(sentry, "{\tProcess Size: rss %ld KB}\n", |
090089c4 | 718 | rusage.ru_maxrss * getpagesize() >> 10); |
30a4f2a8 | 719 | storeAppendPrintf(sentry, "{\tPage faults with physical i/o: %ld}\n", |
090089c4 | 720 | rusage.ru_majflt); |
090089c4 | 721 | #endif |
722 | ||
50bc2565 | 723 | #if HAVE_MALLINFO |
090089c4 | 724 | mp = mallinfo(); |
d51e52f5 | 725 | storeAppendPrintf(sentry, "{Memory usage for %s via mallinfo():}\n", |
726 | appname); | |
30a4f2a8 | 727 | storeAppendPrintf(sentry, "{\tTotal space in arena: %6d KB}\n", |
b560dd20 | 728 | mp.arena >> 10); |
30a4f2a8 | 729 | storeAppendPrintf(sentry, "{\tOrdinary blocks: %6d KB %6d blks}\n", |
730 | mp.uordblks >> 10, mp.ordblks); | |
731 | storeAppendPrintf(sentry, "{\tSmall blocks: %6d KB %6d blks}\n", | |
732 | mp.usmblks >> 10, mp.smblks); | |
733 | storeAppendPrintf(sentry, "{\tHolding blocks: %6d KB %6d blks}\n", | |
734 | mp.hblkhd >> 10, mp.hblks); | |
735 | storeAppendPrintf(sentry, "{\tFree Small blocks: %6d KB}\n", | |
736 | mp.fsmblks >> 10); | |
737 | storeAppendPrintf(sentry, "{\tFree Ordinary blocks: %6d KB}\n", | |
738 | mp.fordblks >> 10); | |
739 | t = mp.uordblks + mp.usmblks + mp.hblkhd; | |
740 | storeAppendPrintf(sentry, "{\tTotal in use: %6d KB %d%%}\n", | |
741 | t >> 10, percent(t, mp.arena)); | |
742 | t = mp.fsmblks + mp.fordblks; | |
743 | storeAppendPrintf(sentry, "{\tTotal free: %6d KB %d%%}\n", | |
744 | t >> 10, percent(t, mp.arena)); | |
745 | #ifdef WE_DONT_USE_KEEP | |
746 | storeAppendPrintf(sentry, "{\tKeep option: %6d KB}\n", | |
747 | mp.keepcost >> 10); | |
748 | #endif | |
46c883ed | 749 | #if HAVE_EXT_MALLINFO |
c30c5a73 | 750 | storeAppendPrintf(sentry, "{\tmax size of small blocks:\t%d}\n", mp.mxfast); |
751 | storeAppendPrintf(sentry, "{\tnumber of small blocks in a holding block:\t%d}\n", | |
090089c4 | 752 | mp.nlblks); |
c30c5a73 | 753 | storeAppendPrintf(sentry, "{\tsmall block rounding factor:\t%d}\n", mp.grain); |
754 | storeAppendPrintf(sentry, "{\tspace (including overhead) allocated in ord. blks:\t%d}\n" | |
090089c4 | 755 | ,mp.uordbytes); |
c30c5a73 | 756 | storeAppendPrintf(sentry, "{\tnumber of ordinary blocks allocated:\t%d}\n", |
090089c4 | 757 | mp.allocated); |
c30c5a73 | 758 | storeAppendPrintf(sentry, "{\tbytes used in maintaining the free tree:\t%d}\n", |
090089c4 | 759 | mp.treeoverhead); |
46c883ed | 760 | #endif /* HAVE_EXT_MALLINFO */ |
50bc2565 | 761 | #endif /* HAVE_MALLINFO */ |
090089c4 | 762 | |
c30c5a73 | 763 | storeAppendPrintf(sentry, "{File descriptor usage for %s:}\n", appname); |
30a4f2a8 | 764 | storeAppendPrintf(sentry, "{\tMax number of file desc available: %4d}\n", |
765 | FD_SETSIZE); | |
766 | storeAppendPrintf(sentry, "{\tLargest file desc currently in use: %4d}\n", | |
090089c4 | 767 | fdstat_biggest_fd()); |
30a4f2a8 | 768 | storeAppendPrintf(sentry, "{\tAvailable number of file descriptors: %4d}\n", |
090089c4 | 769 | fdstat_are_n_free_fd(0)); |
30a4f2a8 | 770 | storeAppendPrintf(sentry, "{\tReserved number of file descriptors: %4d}\n", |
090089c4 | 771 | RESERVED_FD); |
090089c4 | 772 | |
c30c5a73 | 773 | storeAppendPrintf(sentry, "{Internal Data Structures:}\n"); |
c31201c6 | 774 | storeAppendPrintf(sentry, "{\t%6d StoreEntries}\n", |
775 | meta_data.store_entries); | |
776 | storeAppendPrintf(sentry, "{\t%6d StoreEntries with MemObjects}\n", | |
777 | meta_data.mem_obj_count); | |
778 | storeAppendPrintf(sentry, "{\t%6d StoreEntries with MemObject Data}\n", | |
779 | meta_data.mem_data_count); | |
780 | storeAppendPrintf(sentry, "{\t%6d Hot Object Cache Items}\n", | |
30a4f2a8 | 781 | meta_data.hot_vm); |
30a4f2a8 | 782 | |
c31201c6 | 783 | storeAppendPrintf(sentry, "{Accounted Memory Usage:}\n"); |
30a4f2a8 | 784 | storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB}\n", |
785 | "StoreEntry", | |
cff333e8 | 786 | meta_data.store_entries, |
787 | (int) sizeof(StoreEntry), | |
0d5fc38a | 788 | (int) (meta_data.store_entries * sizeof(StoreEntry) >> 10)); |
cff333e8 | 789 | |
a6f3a003 | 790 | storeAppendPrintf(sentry, "{\t%-25.25s = %6d KB}\n", |
791 | "URL strings", | |
792 | meta_data.url_strings >> 10); | |
793 | ||
30a4f2a8 | 794 | storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB}\n", |
795 | "IPCacheEntry", | |
cff333e8 | 796 | meta_data.ipcache_count, |
797 | (int) sizeof(ipcache_entry), | |
0d5fc38a | 798 | (int) (meta_data.ipcache_count * sizeof(ipcache_entry) >> 10)); |
cff333e8 | 799 | |
f88bb09c | 800 | storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB}\n", |
801 | "FQDNCacheEntry", | |
802 | meta_data.fqdncache_count, | |
803 | (int) sizeof(fqdncache_entry), | |
804 | (int) (meta_data.fqdncache_count * sizeof(fqdncache_entry) >> 10)); | |
805 | ||
30a4f2a8 | 806 | storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB}\n", |
807 | "Hash link", | |
b15fe823 | 808 | hash_links_allocated, |
cff333e8 | 809 | (int) sizeof(hash_link), |
b15fe823 | 810 | (int) (hash_links_allocated * sizeof(hash_link) >> 10)); |
cff333e8 | 811 | |
30a4f2a8 | 812 | storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB (%6d free)}\n", |
813 | "Pool MemObject structures", | |
814 | mem_obj_pool.total_pages_allocated, | |
815 | mem_obj_pool.page_size, | |
816 | mem_obj_pool.total_pages_allocated * mem_obj_pool.page_size >> 10, | |
817 | (mem_obj_pool.total_pages_allocated - mem_obj_pool.n_pages_in_use) * mem_obj_pool.page_size >> 10); | |
818 | ||
819 | storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB (%6d free)}\n", | |
820 | "Pool for Request structures", | |
821 | request_pool.total_pages_allocated, | |
822 | request_pool.page_size, | |
823 | request_pool.total_pages_allocated * request_pool.page_size >> 10, | |
824 | (request_pool.total_pages_allocated - request_pool.n_pages_in_use) * request_pool.page_size >> 10); | |
825 | ||
826 | storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB (%6d free)}\n", | |
827 | "Pool for in-memory object data", | |
828 | sm_stats.total_pages_allocated, | |
829 | sm_stats.page_size, | |
830 | sm_stats.total_pages_allocated * sm_stats.page_size >> 10, | |
831 | (sm_stats.total_pages_allocated - sm_stats.n_pages_in_use) * sm_stats.page_size >> 10); | |
cff333e8 | 832 | |
30a4f2a8 | 833 | storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB (%6d free)}\n", |
834 | "Pool for disk I/O", | |
835 | disk_stats.total_pages_allocated, | |
836 | disk_stats.page_size, | |
cff333e8 | 837 | disk_stats.total_pages_allocated * disk_stats.page_size >> 10, |
838 | (disk_stats.total_pages_allocated - disk_stats.n_pages_in_use) * disk_stats.page_size >> 10); | |
cff333e8 | 839 | |
82696127 | 840 | storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB}\n", |
3e12e062 | 841 | "NetDB Address Entries", |
842 | meta_data.netdb_addrs, | |
82696127 | 843 | (int) sizeof(netdbEntry), |
3e12e062 | 844 | (int) (meta_data.netdb_addrs * sizeof(netdbEntry) >> 10)); |
845 | ||
846 | storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB}\n", | |
847 | "NetDB Host Entries", | |
848 | meta_data.netdb_hosts, | |
849 | (int) sizeof(struct _net_db_name), | |
f6610c4e | 850 | (int) (meta_data.netdb_hosts * sizeof(struct _net_db_name) >> 10)); |
e97f40f4 | 851 | |
5ecceaa4 | 852 | storeAppendPrintf(sentry, "{\t%-25.25s %7d x %4d bytes = %6d KB}\n", |
853 | "ClientDB Entries", | |
854 | meta_data.client_info, | |
855 | client_info_sz, | |
856 | (int) (meta_data.client_info * client_info_sz >> 10)); | |
82696127 | 857 | |
30a4f2a8 | 858 | storeAppendPrintf(sentry, "{\t%-25.25s = %6d KB}\n", |
859 | "Miscellaneous", | |
860 | meta_data.misc >> 10); | |
cff333e8 | 861 | |
30a4f2a8 | 862 | storeAppendPrintf(sentry, "{\t%-25.25s = %6d KB}\n", |
863 | "Total Accounted", | |
1a082686 | 864 | memoryAccounted() >> 10); |
30a4f2a8 | 865 | |
866 | #if XMALLOC_STATISTICS | |
867 | storeAppendPrintf(sentry, "{Memory allocation statistics}\n"); | |
868 | malloc_statistics(info_get_mallstat, sentry); | |
869 | #endif | |
090089c4 | 870 | |
30a4f2a8 | 871 | storeAppendPrintf(sentry, close_bracket); |
090089c4 | 872 | } |
873 | ||
b8d8561b | 874 | static void |
875 | parameter_get(cacheinfo * obj, StoreEntry * sentry) | |
090089c4 | 876 | { |
30a4f2a8 | 877 | storeAppendPrintf(sentry, open_bracket); |
d51e52f5 | 878 | storeAppendPrintf(sentry, |
879 | "{VM-Max %d \"# Maximum hot-vm cache (MB)\"}\n", | |
b6f794d6 | 880 | Config.Mem.maxSize / (1 << 20)); |
d51e52f5 | 881 | storeAppendPrintf(sentry, |
882 | "{VM-High %d \"# High water mark hot-vm cache (%%)\"}\n", | |
b6f794d6 | 883 | Config.Mem.highWaterMark); |
d51e52f5 | 884 | storeAppendPrintf(sentry, |
885 | "{VM-Low %d \"# Low water-mark hot-vm cache (%%)\"}\n", | |
b6f794d6 | 886 | Config.Mem.lowWaterMark); |
d51e52f5 | 887 | storeAppendPrintf(sentry, |
888 | "{Swap-Max %d \"# Maximum disk cache (MB)\"}\n", | |
b6f794d6 | 889 | Config.Swap.maxSize / (1 << 10)); |
d51e52f5 | 890 | storeAppendPrintf(sentry, |
891 | "{Swap-High %d \"# High Water mark disk cache (%%)\"}\n", | |
b6f794d6 | 892 | Config.Swap.highWaterMark); |
d51e52f5 | 893 | storeAppendPrintf(sentry, |
894 | "{Swap-Low %d \"# Low water mark disk cache (%%)\"}\n", | |
b6f794d6 | 895 | Config.Swap.lowWaterMark); |
d51e52f5 | 896 | storeAppendPrintf(sentry, |
897 | "{HTTP-Max %d\"# Maximum size HTTP objects (KB)\"}\n", | |
b6f794d6 | 898 | Config.Http.maxObjSize / (1 << 10)); |
d51e52f5 | 899 | storeAppendPrintf(sentry, |
900 | "{HTTP-TTL %d \"# Http object default TTL (hrs)\"}\n", | |
b6f794d6 | 901 | Config.Http.defaultTtl / 3600); |
d51e52f5 | 902 | storeAppendPrintf(sentry, |
903 | "{Gopher-Max %d \"# Maximum size gopher objects (KB)\"}\n", | |
b6f794d6 | 904 | Config.Gopher.maxObjSize / (1 << 10)); |
d51e52f5 | 905 | storeAppendPrintf(sentry, |
906 | "{Gopher-TTL %d \"# TTL for gopher objects (hrs)\"}\n", | |
b6f794d6 | 907 | Config.Gopher.defaultTtl / 3600); |
d51e52f5 | 908 | storeAppendPrintf(sentry, |
909 | "{FTP-Max %d \"# Maximum size FTP objects (KB)\"}\n", | |
b6f794d6 | 910 | Config.Ftp.maxObjSize / (1 << 10)); |
d51e52f5 | 911 | storeAppendPrintf(sentry, |
912 | "{FTP-TTL %d \"# TTL for FTP objects (hrs)\"}\n", | |
b6f794d6 | 913 | Config.Ftp.defaultTtl / 3600); |
d51e52f5 | 914 | storeAppendPrintf(sentry, |
915 | "{Neg-TTL %d \"# TTL for negative cache (s)\"}\n", | |
b6f794d6 | 916 | Config.negativeTtl); |
d51e52f5 | 917 | storeAppendPrintf(sentry, |
918 | "{ReadTimeout %d \"# Maximum idle connection (s)\"}\n", | |
b6f794d6 | 919 | Config.readTimeout); |
d51e52f5 | 920 | storeAppendPrintf(sentry, |
921 | "{ClientLifetime %d \"# Lifetime for incoming HTTP requests\"}\n", | |
b6f794d6 | 922 | Config.lifetimeDefault); |
d51e52f5 | 923 | storeAppendPrintf(sentry, |
924 | "{CleanRate %d \"# Rate for periodic object expiring\"}\n", | |
b6f794d6 | 925 | Config.cleanRate); |
090089c4 | 926 | /* Cachemgr.cgi expects an integer in the second field of the string */ |
d51e52f5 | 927 | storeAppendPrintf(sentry, |
928 | "{HttpAccelMode %d \"# Is operating as an HTTP accelerator\"}\n", | |
090089c4 | 929 | httpd_accel_mode); |
30a4f2a8 | 930 | storeAppendPrintf(sentry, close_bracket); |
090089c4 | 931 | } |
932 | ||
2ba42578 | 933 | #if LOG_FULL_HEADERS |
e43efe50 | 934 | static char c2x[] = |
f6c78bd2 | 935 | "000102030405060708090a0b0c0d0e0f" |
936 | "101112131415161718191a1b1c1d1e1f" | |
937 | "202122232425262728292a2b2c2d2e2f" | |
938 | "303132333435363738393a3b3c3d3e3f" | |
939 | "404142434445464748494a4b4c4d4e4f" | |
940 | "505152535455565758595a5b5c5d5e5f" | |
941 | "606162636465666768696a6b6c6d6e6f" | |
942 | "707172737475767778797a7b7c7d7e7f" | |
943 | "808182838485868788898a8b8c8d8e8f" | |
944 | "909192939495969798999a9b9c9d9e9f" | |
945 | "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" | |
946 | "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" | |
947 | "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" | |
948 | "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" | |
949 | "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" | |
950 | "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"; | |
e43efe50 | 951 | |
952 | /* log_quote -- URL-style encoding on MIME headers. */ | |
953 | ||
b8d8561b | 954 | char * |
955 | log_quote(char *header) | |
e43efe50 | 956 | { |
957 | int c, i; | |
958 | char *buf, *buf_cursor; | |
e43efe50 | 959 | if (header == NULL) { |
960 | buf = xcalloc(1, 1); | |
961 | *buf = '\0'; | |
962 | return buf; | |
963 | } | |
e43efe50 | 964 | buf = xcalloc((strlen(header) * 3) + 1, 1); |
965 | buf_cursor = buf; | |
e43efe50 | 966 | /* |
967 | * We escape: \x00-\x1F"#%;<>?{}|\\\\^~`\[\]\x7F-\xFF | |
968 | * which is the default escape list for the CPAN Perl5 URI module | |
969 | * modulo the inclusion of space (x40) to make the raw logs a bit | |
970 | * more readable. | |
971 | */ | |
972 | while ((c = *header++)) { | |
973 | if (c <= 0x1F | |
e8a6899c | 974 | || c >= 0x7F |
975 | || c == '"' | |
976 | || c == '#' | |
977 | || c == '%' | |
978 | || c == ';' | |
979 | || c == '<' | |
980 | || c == '>' | |
981 | || c == '?' | |
982 | || c == '{' | |
983 | || c == '}' | |
984 | || c == '|' | |
985 | || c == '\\' | |
986 | || c == '^' | |
987 | || c == '~' | |
988 | || c == '`' | |
989 | || c == '[' | |
990 | || c == ']') { | |
e43efe50 | 991 | *buf_cursor++ = '%'; |
e8a6899c | 992 | i = c * 2; |
e43efe50 | 993 | *buf_cursor++ = c2x[i]; |
e8a6899c | 994 | *buf_cursor++ = c2x[i + 1]; |
e43efe50 | 995 | } else { |
996 | *buf_cursor++ = c; | |
997 | } | |
998 | } | |
e43efe50 | 999 | *buf_cursor = '\0'; |
1000 | return buf; | |
1001 | } | |
2ba42578 | 1002 | #endif /* LOG_FULL_HEADERS */ |
e43efe50 | 1003 | |
1004 | ||
b8d8561b | 1005 | static void |
1006 | log_append(cacheinfo * obj, | |
1007 | char *url, | |
1008 | struct in_addr caddr, | |
1009 | int size, | |
1010 | char *action, | |
1011 | char *method, | |
1012 | int http_code, | |
1013 | int msec, | |
1014 | char *ident, | |
1015 | #if !LOG_FULL_HEADERS | |
1016 | struct _hierarchyLogData *hierData | |
2ba42578 | 1017 | #else |
b8d8561b | 1018 | struct _hierarchyLogData *hierData, |
1019 | char *request_hdr, | |
1020 | char *reply_hdr | |
e8a6899c | 1021 | #endif /* LOG_FULL_HEADERS */ |
b8d8561b | 1022 | ) |
090089c4 | 1023 | { |
2ba42578 | 1024 | #if LOG_FULL_HEADERS |
e43efe50 | 1025 | LOCAL_ARRAY(char, tmp, 10000); /* MAX_URL is 4096 */ |
2ba42578 | 1026 | #else |
1027 | LOCAL_ARRAY(char, tmp, 6000); /* MAX_URL is 4096 */ | |
e43efe50 | 1028 | #endif /* LOG_FULL_HEADERS */ |
557a6b70 | 1029 | int x; |
00859e30 | 1030 | char *client = NULL; |
eaa77841 | 1031 | hier_code hier_code = HIER_NONE; |
e81957b7 | 1032 | char *hier_host = dash_str; |
eaa77841 | 1033 | int hier_timeout = 0; |
090089c4 | 1034 | |
b6f794d6 | 1035 | if (Config.Log.log_fqdn) |
00859e30 | 1036 | client = fqdncache_gethostbyaddr(caddr, 0); |
b7f3c263 | 1037 | if (client == NULL) |
1038 | client = inet_ntoa(caddr); | |
090089c4 | 1039 | |
b7f3c263 | 1040 | getCurrentTime(); |
090089c4 | 1041 | |
316a3472 | 1042 | if (!method) |
e81957b7 | 1043 | method = dash_str; |
6eb42cae | 1044 | if (!url) |
e81957b7 | 1045 | url = dash_str; |
a0c09e11 | 1046 | if (!ident || ident[0] == '\0') |
e81957b7 | 1047 | ident = dash_str; |
eaa77841 | 1048 | if (hierData) { |
1049 | hier_code = hierData->code; | |
e81957b7 | 1050 | hier_host = hierData->host ? hierData->host : dash_str; |
eaa77841 | 1051 | hier_timeout = hierData->timeout; |
1052 | } | |
090089c4 | 1053 | if (obj->logfile_status == LOG_ENABLE) { |
b6f794d6 | 1054 | if (Config.commonLogFormat) |
92f80c9c | 1055 | sprintf(tmp, "%s %s - [%s] \"%s %s\" %s %d\n", |
b7f3c263 | 1056 | client, |
92f80c9c | 1057 | ident, |
1058 | mkhttpdlogtime(&squid_curtime), | |
1059 | method, | |
1060 | url, | |
1061 | action, | |
1062 | size); | |
090089c4 | 1063 | else |
eaa77841 | 1064 | sprintf(tmp, "%9d.%03d %6d %s %s/%03d %d %s %s %s %s%s/%s\n", |
316a3472 | 1065 | (int) current_time.tv_sec, |
fc07a0e4 | 1066 | (int) current_time.tv_usec / 1000, |
1067 | msec, | |
b7f3c263 | 1068 | client, |
316a3472 | 1069 | action, |
fc07a0e4 | 1070 | http_code, |
316a3472 | 1071 | size, |
1072 | method, | |
a0c09e11 | 1073 | url, |
9864ee44 | 1074 | ident, |
eaa77841 | 1075 | hier_timeout ? "TIMEOUT_" : "", |
1076 | hier_strings[hier_code], | |
1077 | hier_host); | |
2ba42578 | 1078 | #if LOG_FULL_HEADERS |
e43efe50 | 1079 | if (Config.logMimeHdrs) { |
1080 | int msize = strlen(tmp); | |
1081 | char *ereq = log_quote(request_hdr); | |
1082 | char *erep = log_quote(reply_hdr); | |
1083 | ||
1084 | if (msize + strlen(ereq) + strlen(erep) + 7 <= sizeof(tmp)) | |
e8a6899c | 1085 | sprintf(tmp + msize - 1, " [%s] [%s]\n", ereq, erep); |
e43efe50 | 1086 | else |
1087 | debug(18, 1, "log_append: Long headers not logged.\n"); | |
1088 | safe_free(ereq); | |
1089 | safe_free(erep); | |
1090 | } | |
e43efe50 | 1091 | #endif /* LOG_FULL_HEADERS */ |
557a6b70 | 1092 | x = file_write(obj->logfile_fd, |
9864ee44 | 1093 | xstrdup(tmp), |
557a6b70 | 1094 | strlen(tmp), |
1095 | obj->logfile_access, | |
1096 | NULL, | |
1097 | NULL, | |
1098 | xfree); | |
9864ee44 | 1099 | if (x != DISK_OK) |
019dd986 | 1100 | debug(18, 1, "log_append: File write failed.\n"); |
090089c4 | 1101 | } |
1102 | } | |
1103 | ||
b8d8561b | 1104 | static void |
1105 | log_enable(cacheinfo * obj, StoreEntry * sentry) | |
090089c4 | 1106 | { |
090089c4 | 1107 | if (obj->logfile_status == LOG_DISABLE) { |
1108 | obj->logfile_status = LOG_ENABLE; | |
1109 | ||
1110 | /* open the logfile */ | |
557a6b70 | 1111 | obj->logfile_fd = file_open(obj->logfilename, NULL, O_WRONLY | O_CREAT); |
090089c4 | 1112 | if (obj->logfile_fd == DISK_ERROR) { |
019dd986 | 1113 | debug(18, 0, "Cannot open logfile: %s\n", obj->logfilename); |
090089c4 | 1114 | obj->logfile_status = LOG_DISABLE; |
1115 | } | |
1116 | obj->logfile_access = file_write_lock(obj->logfile_fd); | |
1117 | ||
1118 | } | |
1119 | /* at the moment, store one char to make a storage manager happy */ | |
c30c5a73 | 1120 | storeAppendPrintf(sentry, " "); |
090089c4 | 1121 | } |
1122 | ||
b8d8561b | 1123 | static void |
1124 | log_disable(cacheinfo * obj, StoreEntry * sentry) | |
090089c4 | 1125 | { |
090089c4 | 1126 | if (obj->logfile_status == LOG_ENABLE) |
1127 | file_close(obj->logfile_fd); | |
1128 | ||
1129 | obj->logfile_status = LOG_DISABLE; | |
1130 | /* at the moment, store one char to make a storage manager happy */ | |
c30c5a73 | 1131 | storeAppendPrintf(sentry, " "); |
090089c4 | 1132 | } |
1133 | ||
1134 | ||
1135 | ||
b8d8561b | 1136 | static void |
1137 | log_clear(cacheinfo * obj, StoreEntry * sentry) | |
090089c4 | 1138 | { |
30a4f2a8 | 1139 | /* what should be done here. Erase file ??? or move it to another name? At the moment, just erase it. bug here need to be fixed. what if there are still data in memory. Need flush here */ |
090089c4 | 1140 | if (obj->logfile_status == LOG_ENABLE) |
1141 | file_close(obj->logfile_fd); | |
1142 | ||
1143 | unlink(obj->logfilename); | |
1144 | ||
1145 | /* reopen it anyway */ | |
557a6b70 | 1146 | obj->logfile_fd = file_open(obj->logfilename, NULL, O_WRONLY | O_CREAT); |
090089c4 | 1147 | if (obj->logfile_fd == DISK_ERROR) { |
019dd986 | 1148 | debug(18, 0, "Cannot open logfile: %s\n", obj->logfilename); |
090089c4 | 1149 | obj->logfile_status = LOG_DISABLE; |
1150 | } | |
1151 | /* at the moment, store one char to make a storage manager happy */ | |
c30c5a73 | 1152 | storeAppendPrintf(sentry, " "); |
090089c4 | 1153 | } |
1154 | ||
1155 | ||
1156 | ||
b8d8561b | 1157 | static void |
1158 | proto_newobject(cacheinfo * obj, protocol_t proto_id, int size, int restart) | |
090089c4 | 1159 | { |
1160 | proto_stat *p = &obj->proto_stat_data[proto_id]; | |
1161 | ||
1162 | p->object_count++; | |
1163 | ||
1164 | /* Account for 1KB granularity */ | |
1165 | p->kb.now += ((size + 1023) >> 10); | |
1166 | ||
1167 | if (p->kb.now > p->kb.max) | |
1168 | p->kb.max = p->kb.now; | |
1169 | if (restart) | |
1170 | p->kb.min = p->kb.now; | |
1171 | } | |
1172 | ||
1173 | ||
b8d8561b | 1174 | static void |
1175 | proto_purgeobject(cacheinfo * obj, protocol_t proto_id, int size) | |
090089c4 | 1176 | { |
1177 | proto_stat *p = &obj->proto_stat_data[proto_id]; | |
1178 | ||
1179 | p->object_count--; | |
1180 | ||
1181 | /* Scale down to KB */ | |
1182 | p->kb.now -= ((size + 1023) >> 10); | |
1183 | ||
1184 | if (p->kb.now < p->kb.min) | |
1185 | p->kb.min = p->kb.now; | |
1186 | } | |
1187 | ||
1188 | /* update stat for each particular protocol when an object is fetched */ | |
b8d8561b | 1189 | static void |
1190 | proto_touchobject(cacheinfo * obj, protocol_t proto_id, int size) | |
090089c4 | 1191 | { |
1192 | obj->proto_stat_data[proto_id].refcount++; | |
1193 | obj->proto_stat_data[proto_id].transferbyte += (1023 + size) >> 10; | |
1194 | } | |
1195 | ||
b8d8561b | 1196 | static void |
1197 | proto_count(cacheinfo * obj, protocol_t proto_id, log_type type) | |
090089c4 | 1198 | { |
a528eb87 | 1199 | switch (type) { |
1200 | case LOG_TCP_HIT: | |
1201 | case LOG_TCP_IMS_HIT: | |
1202 | case LOG_TCP_EXPIRED_HIT: | |
1203 | case LOG_UDP_HIT: | |
1204 | case LOG_UDP_HIT_OBJ: | |
1205 | obj->proto_stat_data[proto_id].hit++; | |
1206 | break; | |
1207 | default: | |
1208 | obj->proto_stat_data[proto_id].miss++; | |
1209 | break; | |
1210 | } | |
090089c4 | 1211 | } |
1212 | ||
090089c4 | 1213 | |
b8d8561b | 1214 | void |
1215 | stat_init(cacheinfo ** object, char *logfilename) | |
090089c4 | 1216 | { |
1217 | cacheinfo *obj = NULL; | |
1218 | int i; | |
1219 | ||
92a8c005 | 1220 | debug(18, 5, "stat_init: Initializing...\n"); |
30a4f2a8 | 1221 | obj = xcalloc(1, sizeof(cacheinfo)); |
090089c4 | 1222 | obj->stat_get = stat_get; |
1223 | obj->info_get = info_get; | |
1224 | obj->cache_size_get = cache_size_get; | |
090089c4 | 1225 | obj->log_get_start = log_get_start; |
1226 | obj->log_status_get = log_status_get; | |
1227 | obj->log_append = log_append; | |
1228 | obj->log_clear = log_clear; | |
1229 | obj->log_enable = log_enable; | |
1230 | obj->log_disable = log_disable; | |
1231 | obj->logfile_status = LOG_ENABLE; | |
b8de7ebe | 1232 | obj->squid_get_start = squid_get_start; |
090089c4 | 1233 | obj->parameter_get = parameter_get; |
1234 | obj->server_list = server_list; | |
a528eb87 | 1235 | if (logfilename) { |
1236 | memset(obj->logfilename, '0', MAX_FILE_NAME_LEN); | |
1237 | strncpy(obj->logfilename, logfilename, MAX_FILE_NAME_LEN - 1); | |
1238 | obj->logfile_fd = file_open(obj->logfilename, NULL, O_WRONLY | O_CREAT); | |
1239 | if (obj->logfile_fd == DISK_ERROR) { | |
1240 | debug(18, 0, "%s: %s\n", obj->logfilename, xstrerror()); | |
1241 | fatal("Cannot open logfile."); | |
1242 | } | |
1243 | obj->logfile_access = file_write_lock(obj->logfile_fd); | |
090089c4 | 1244 | } |
92a6f4b1 | 1245 | obj->proto_id = urlParseProtocol; |
090089c4 | 1246 | obj->proto_newobject = proto_newobject; |
1247 | obj->proto_purgeobject = proto_purgeobject; | |
1248 | obj->proto_touchobject = proto_touchobject; | |
a528eb87 | 1249 | obj->proto_count = proto_count; |
090089c4 | 1250 | obj->NotImplement = dummyhandler; |
30a4f2a8 | 1251 | for (i = PROTO_NONE; i <= PROTO_MAX; i++) { |
090089c4 | 1252 | switch (i) { |
8213067d | 1253 | case PROTO_HTTP: |
090089c4 | 1254 | strcpy(obj->proto_stat_data[i].protoname, "HTTP"); |
1255 | break; | |
8213067d | 1256 | case PROTO_GOPHER: |
090089c4 | 1257 | strcpy(obj->proto_stat_data[i].protoname, "GOPHER"); |
1258 | break; | |
8213067d | 1259 | case PROTO_FTP: |
090089c4 | 1260 | strcpy(obj->proto_stat_data[i].protoname, "FTP"); |
1261 | break; | |
234967c9 | 1262 | case PROTO_WAIS: |
1263 | strcpy(obj->proto_stat_data[i].protoname, "WAIS"); | |
1264 | break; | |
8213067d | 1265 | case PROTO_CACHEOBJ: |
1266 | strcpy(obj->proto_stat_data[i].protoname, "CACHE_OBJ"); | |
090089c4 | 1267 | break; |
8213067d | 1268 | case PROTO_MAX: |
1269 | strcpy(obj->proto_stat_data[i].protoname, "TOTAL"); | |
090089c4 | 1270 | break; |
8213067d | 1271 | case PROTO_NONE: |
090089c4 | 1272 | default: |
8213067d | 1273 | strcpy(obj->proto_stat_data[i].protoname, "OTHER"); |
090089c4 | 1274 | break; |
1275 | } | |
090089c4 | 1276 | obj->proto_stat_data[i].object_count = 0; |
1277 | obj->proto_stat_data[i].hit = 0; | |
1278 | obj->proto_stat_data[i].miss = 0; | |
1279 | obj->proto_stat_data[i].hitratio = 0.0; | |
1280 | obj->proto_stat_data[i].transferrate = 0; | |
1281 | obj->proto_stat_data[i].refcount = 0; | |
1282 | obj->proto_stat_data[i].transferbyte = 0; | |
090089c4 | 1283 | obj->proto_stat_data[i].kb.max = 0; |
1284 | obj->proto_stat_data[i].kb.min = 0; | |
1285 | obj->proto_stat_data[i].kb.avg = 0; | |
1286 | obj->proto_stat_data[i].kb.now = 0; | |
090089c4 | 1287 | } |
090089c4 | 1288 | *object = obj; |
1289 | } | |
1290 | ||
67508012 | 1291 | static char * |
b8d8561b | 1292 | stat_describe(StoreEntry * entry) |
090089c4 | 1293 | { |
95d659f0 | 1294 | LOCAL_ARRAY(char, state, 256); |
090089c4 | 1295 | |
1296 | state[0] = '\0'; | |
e62d2dea | 1297 | sprintf(state, "%s/%s", |
9dfb6c1c | 1298 | storeStatusStr[entry->store_status], |
1299 | pingStatusStr[entry->ping_status]); | |
090089c4 | 1300 | return (state); |
1301 | } | |
1302 | ||
67508012 | 1303 | static char * |
b8d8561b | 1304 | mem_describe(StoreEntry * entry) |
090089c4 | 1305 | { |
95d659f0 | 1306 | LOCAL_ARRAY(char, where, 100); |
090089c4 | 1307 | |
1308 | where[0] = '\0'; | |
e62d2dea | 1309 | sprintf(where, "D%d/%s/%s", |
9dfb6c1c | 1310 | entry->swap_file_number, |
1311 | swapStatusStr[entry->swap_status], | |
1312 | memStatusStr[entry->mem_status]); | |
090089c4 | 1313 | return (where); |
1314 | } | |
1315 | ||
1316 | ||
67508012 | 1317 | static char * |
b8d8561b | 1318 | ttl_describe(StoreEntry * entry) |
090089c4 | 1319 | { |
1320 | int hh, mm, ss; | |
95d659f0 | 1321 | LOCAL_ARRAY(char, TTL, 60); |
090089c4 | 1322 | int ttl; |
1323 | ||
1324 | TTL[0] = '\0'; | |
1325 | strcpy(TTL, "UNKNOWN"); /* sometimes the TTL isn't set below */ | |
b8de7ebe | 1326 | ttl = entry->expires - squid_curtime; |
090089c4 | 1327 | if (ttl < 0) |
1328 | strcpy(TTL, "EXPIRED"); | |
1329 | else { | |
1330 | ||
1331 | hh = ttl / 3600; | |
1332 | ttl -= hh * 3600; | |
1333 | mm = ttl / 60; | |
1334 | ttl -= mm * 60; | |
1335 | ss = ttl; | |
1336 | ||
1337 | sprintf(TTL, "% 6d:%02d:%02d", hh, mm, ss); | |
1338 | } | |
1339 | return (TTL); | |
1340 | } | |
1341 | ||
67508012 | 1342 | static char * |
b8d8561b | 1343 | elapsed_time(StoreEntry * entry, int since, char *TTL) |
090089c4 | 1344 | { |
1345 | int hh, mm, ss, ttl; | |
1346 | ||
1347 | TTL[0] = '\0'; | |
1348 | strcpy(TTL, "UNKNOWN"); /* sometimes TTL doesn't get set */ | |
b8de7ebe | 1349 | ttl = squid_curtime - since; |
090089c4 | 1350 | if (since == 0) { |
1351 | strcpy(TTL, "NEVER"); | |
1352 | } else if (ttl < 0) { | |
1353 | strcpy(TTL, "EXPIRED"); | |
1354 | } else { | |
1355 | hh = ttl / 3600; | |
1356 | ttl -= hh * 3600; | |
1357 | mm = ttl / 60; | |
1358 | ttl -= mm * 60; | |
1359 | ss = ttl; | |
1360 | sprintf(TTL, "% 6d:%02d:%02d", hh, mm, ss); | |
1361 | } | |
1362 | return (TTL); | |
1363 | } | |
1364 | ||
1365 | ||
67508012 | 1366 | static char * |
b8d8561b | 1367 | flags_describe(StoreEntry * entry) |
090089c4 | 1368 | { |
95d659f0 | 1369 | LOCAL_ARRAY(char, FLAGS, 32); |
090089c4 | 1370 | char LOCK_CNT[32]; |
1371 | ||
1372 | strcpy(FLAGS, "F:"); | |
1373 | if (BIT_TEST(entry->flag, KEY_CHANGE)) | |
1374 | strncat(FLAGS, "K", sizeof(FLAGS) - 1); | |
1c481e00 | 1375 | if (BIT_TEST(entry->flag, ENTRY_CACHABLE)) |
090089c4 | 1376 | strncat(FLAGS, "C", sizeof(FLAGS) - 1); |
1377 | if (BIT_TEST(entry->flag, REFRESH_REQUEST)) | |
1378 | strncat(FLAGS, "R", sizeof(FLAGS) - 1); | |
1379 | if (BIT_TEST(entry->flag, RELEASE_REQUEST)) | |
1380 | strncat(FLAGS, "Z", sizeof(FLAGS) - 1); | |
1381 | if (BIT_TEST(entry->flag, ABORT_MSG_PENDING)) | |
1382 | strncat(FLAGS, "A", sizeof(FLAGS) - 1); | |
1383 | if (BIT_TEST(entry->flag, DELAY_SENDING)) | |
1384 | strncat(FLAGS, "D", sizeof(FLAGS) - 1); | |
1385 | if (BIT_TEST(entry->flag, IP_LOOKUP_PENDING)) | |
1386 | strncat(FLAGS, "P", sizeof(FLAGS) - 1); | |
1387 | if (entry->lock_count) | |
1388 | strncat(FLAGS, "L", sizeof(FLAGS) - 1); | |
1389 | if (entry->lock_count) { | |
1390 | sprintf(LOCK_CNT, "%d", entry->lock_count); | |
1391 | strncat(FLAGS, LOCK_CNT, sizeof(FLAGS) - 1); | |
1392 | } | |
1393 | return (FLAGS); | |
1394 | } | |
1395 | ||
b8d8561b | 1396 | void |
0673c0ba | 1397 | stat_rotate_log(void) |
090089c4 | 1398 | { |
1399 | int i; | |
95d659f0 | 1400 | LOCAL_ARRAY(char, from, MAXPATHLEN); |
1401 | LOCAL_ARRAY(char, to, MAXPATHLEN); | |
090089c4 | 1402 | char *fname = NULL; |
1403 | ||
a528eb87 | 1404 | if ((fname = HTTPCacheInfo->logfilename) == NULL) |
090089c4 | 1405 | return; |
1406 | ||
019dd986 | 1407 | debug(18, 1, "stat_rotate_log: Rotating\n"); |
090089c4 | 1408 | |
1409 | /* Rotate numbers 0 through N up one */ | |
b6f794d6 | 1410 | for (i = Config.Log.rotateNumber; i > 1;) { |
090089c4 | 1411 | i--; |
1412 | sprintf(from, "%s.%d", fname, i - 1); | |
1413 | sprintf(to, "%s.%d", fname, i); | |
1414 | rename(from, to); | |
1415 | } | |
1416 | /* Rotate the current log to .0 */ | |
b6f794d6 | 1417 | if (Config.Log.rotateNumber > 0) { |
090089c4 | 1418 | sprintf(to, "%s.%d", fname, 0); |
1419 | rename(fname, to); | |
1420 | } | |
1421 | /* Close and reopen the log. It may have been renamed "manually" | |
1422 | * before HUP'ing us. */ | |
a528eb87 | 1423 | file_close(HTTPCacheInfo->logfile_fd); |
1424 | HTTPCacheInfo->logfile_fd = file_open(fname, NULL, O_WRONLY | O_CREAT); | |
1425 | if (HTTPCacheInfo->logfile_fd == DISK_ERROR) { | |
30a4f2a8 | 1426 | debug(18, 0, "stat_rotate_log: Cannot open logfile: %s\n", fname); |
a528eb87 | 1427 | HTTPCacheInfo->logfile_status = LOG_DISABLE; |
6eb42cae | 1428 | fatal("Cannot open logfile."); |
090089c4 | 1429 | } |
a528eb87 | 1430 | HTTPCacheInfo->logfile_access = file_write_lock(HTTPCacheInfo->logfile_fd); |
090089c4 | 1431 | } |
457bedbd | 1432 | |
b8d8561b | 1433 | void |
0673c0ba | 1434 | statCloseLog(void) |
457bedbd | 1435 | { |
a528eb87 | 1436 | file_close(HTTPCacheInfo->logfile_fd); |
457bedbd | 1437 | } |