]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/stat.cc
1 /* $Id: stat.cc,v 1.15 1996/04/04 01:30:51 wessels Exp $ */
4 * DEBUG: Section 18 stat
10 #include <sys/syscall.h>
11 #define getrusage(a, b) syscall(SYS_GETRUSAGE, a, b)
12 #define getpagesize( ) sysconf(_SC_PAGE_SIZE)
13 #endif /* _SQUID_HPUX_ */
15 extern int emulate_httpd_log
;
17 #define MIN_BUFSIZE (4096)
18 #define MAX_LINELEN (4096)
19 #define max(a,b) ((a)>(b)? (a): (b))
21 typedef struct _log_read_data_t
{
25 typedef struct _cached_read_data_t
{
32 unsigned long nconn
= 0;
34 char *stat_describe();
37 char *flags_describe();
42 static char *open_bracket
= "{\n";
43 static char *close_bracket
= "}\n";
45 /* process utilization information */
46 void stat_utilization_get(obj
, sentry
)
50 static char tempbuf
[MAX_LINELEN
];
52 proto_stat
*p
= &obj
->proto_stat_data
[0];
56 secs
= (int) (cached_curtime
- cached_starttime
);
58 storeAppend(sentry
, open_bracket
, (int) strlen(open_bracket
));
72 for (proto_id
= 1; proto_id
<= PROTOCOL_SUPPORTED
; ++proto_id
) {
73 q
= &obj
->proto_stat_data
[proto_id
];
75 p
->object_count
+= q
->object_count
;
76 p
->kb
.max
+= q
->kb
.max
;
77 p
->kb
.min
+= q
->kb
.min
;
78 p
->kb
.avg
+= q
->kb
.avg
;
79 p
->kb
.now
+= q
->kb
.now
;
82 p
->refcount
+= q
->refcount
;
83 p
->transferbyte
+= q
->transferbyte
;
87 for (proto_id
= 0; proto_id
< PROTOCOL_SUPPORTED
+ PROTOCOL_EXTRA
; ++proto_id
) {
88 p
= &obj
->proto_stat_data
[proto_id
];
95 sprintf(tempbuf
, "{%s %d %d %d %d %4.2f %d %d %d}\n",
102 (secs
? p
->transferbyte
/ secs
: 0),
105 storeAppend(sentry
, tempbuf
, strlen(tempbuf
));
108 storeAppend(sentry
, close_bracket
, strlen(close_bracket
));
112 /* return total bytes of all registered and known objects.
113 * may not reflect the retrieving object....
114 * something need to be done here to get more accurate cache size */
115 int cache_size_get(obj
)
120 /* sum all size, exclude total */
121 for (proto_id
= 1; proto_id
<= PROTOCOL_SUPPORTED
+ PROTOCOL_EXTRA
- 1;
123 size
+= obj
->proto_stat_data
[proto_id
].kb
.now
;
128 /* process general IP cache information */
129 void stat_general_get(obj
, sentry
)
133 /* have to use old method for this guy,
134 * otherwise we have to make ipcache know about StoreEntry */
135 stat_ipcache_get(sentry
, obj
);
139 /* process objects list */
140 void stat_objects_get(obj
, sentry
, vm_or_not
)
145 static char tempbuf
[MAX_LINELEN
];
146 static char space
[40];
147 static char space2
[40];
149 StoreEntry
*entry
= NULL
;
153 storeAppend(sentry
, open_bracket
, (int) strlen(open_bracket
));
155 for (entry
= storeGetFirst();
157 entry
= storeGetNext()) {
158 if (vm_or_not
&& (entry
->mem_status
== NOT_IN_MEMORY
) &&
159 (entry
->swap_status
== SWAP_OK
))
161 if ((++N
& 0xFF) == 0) {
163 debug(18, 3, "stat_objects_get: Processed %d objects...\n", N
);
165 obj_size
= entry
->object_len
;
166 npend
= storePendingNClients(entry
);
168 obj_size
= entry
->mem_obj
->e_current_len
;
170 sprintf(tempbuf
, "{ %s %d %s %s %s %s %d %d %s %s }\n",
173 elapsed_time(entry
, (int) entry
->timestamp
, space
),
174 flags_describe(entry
),
175 elapsed_time(entry
, (int) entry
->lastref
, space2
),
178 (int) entry
->refcount
,
180 stat_describe(entry
));
181 storeAppend(sentry
, tempbuf
, strlen(tempbuf
));
183 storeAppend(sentry
, close_bracket
, strlen(close_bracket
));
187 /* process a requested object into a manager format */
188 void stat_get(obj
, req
, sentry
)
194 if (strncmp(req
, "objects", strlen("objects")) == 0) {
195 stat_objects_get(obj
, sentry
, 0);
196 } else if (strncmp(req
, "vm_objects", strlen("vm_objects")) == 0) {
197 stat_objects_get(obj
, sentry
, 1);
198 } else if (strncmp(req
, "general", strlen("general")) == 0) {
199 stat_general_get(obj
, sentry
);
200 } else if (strncmp(req
, "utilization", strlen("utilization")) == 0) {
201 stat_utilization_get(obj
, sentry
);
206 /* generate logfile status information */
207 void log_status_get(obj
, sentry
)
211 static char tempbuf
[MAX_LINELEN
];
213 if (obj
->logfile_status
== LOG_ENABLE
) {
214 sprintf(tempbuf
, "{\"Logfile is Enabled. Filename: %s\"}\n",
217 sprintf(tempbuf
, "{\"Logfile is Disabled.\"}\n");
219 storeAppend(sentry
, tempbuf
, strlen(tempbuf
));
224 /* log convert handler */
225 /* call for each line in file, use fileWalk routine */
226 int logReadHandler(fd_unused
, buf
, size_unused
, data
)
230 log_read_data_t
*data
;
232 static char tempbuf
[MAX_LINELEN
];
234 sprintf(tempbuf
, "{%s}\n", buf
);
235 return storeAppend(data
->sentry
,
237 (int) strlen(tempbuf
) % MAX_LINELEN
);
240 /* log convert end handler */
241 /* call when a walk is completed or error. */
242 void logReadEndHandler(fd_unused
, errflag_unused
, data
)
245 log_read_data_t
*data
;
247 storeAppend(data
->sentry
, close_bracket
, strlen(close_bracket
));
248 storeComplete(data
->sentry
);
254 /* start converting logfile to processed format */
255 void log_get_start(obj
, sentry
)
260 log_read_data_t
*data
= NULL
;
262 if (obj
->logfile_status
== LOG_DISABLE
) {
263 /* Manufacture status when logging is disabled */
264 log_status_get(obj
, sentry
);
265 storeComplete(sentry
);
268 data
= (log_read_data_t
*) xmalloc(sizeof(log_read_data_t
));
269 memset(data
, '\0', sizeof(log_read_data_t
));
270 data
->sentry
= sentry
;
271 strcpy(tmp
, open_bracket
);
272 storeAppend(sentry
, tmp
, 2);
273 file_walk(obj
->logfile_fd
, (FILE_WALK_HD
) logReadEndHandler
,
274 (caddr_t
) data
, (FILE_WALK_LHD
) logReadHandler
, (caddr_t
) data
);
279 /* cached convert handler */
280 /* call for each line in file, use fileWalk routine */
281 int cachedReadHandler(fd_unused
, buf
, size_unused
, data
)
285 cached_read_data_t
*data
;
287 static char tempbuf
[MAX_LINELEN
];
289 sprintf(tempbuf
, "{\"%s\"}\n", buf
);
290 return storeAppend(data
->sentry
,
292 (int) strlen(tempbuf
) % MAX_LINELEN
);
295 /* cached convert end handler */
296 /* call when a walk is completed or error. */
297 void cachedReadEndHandler(fd_unused
, errflag_unused
, data
)
300 cached_read_data_t
*data
;
302 storeAppend(data
->sentry
, close_bracket
, strlen(close_bracket
));
303 storeComplete(data
->sentry
);
304 file_close(data
->fd
);
309 /* start convert cached.conf file to processed format */
310 void cached_get_start(obj
, sentry
)
314 cached_read_data_t
*data
;
315 extern char *config_file
;
317 data
= (cached_read_data_t
*) xmalloc(sizeof(cached_read_data_t
));
318 memset(data
, '\0', sizeof(cached_read_data_t
));
319 data
->sentry
= sentry
;
320 data
->fd
= file_open((char *) config_file
, NULL
, O_RDONLY
);
321 storeAppend(sentry
, open_bracket
, (int) strlen(open_bracket
));
322 file_walk(data
->fd
, (FILE_WALK_HD
) cachedReadEndHandler
, (caddr_t
) data
,
323 (FILE_WALK_LHD
) cachedReadHandler
, (caddr_t
) data
);
327 void dummyhandler(obj
, sentry
)
331 static char *msg
= "{ \"Not_Implemented_yet.\"}\n";
332 storeAppend(sentry
, msg
, strlen(msg
));
335 void server_list(obj
, sentry
)
339 static char tempbuf
[MAX_LINELEN
];
343 storeAppend(sentry
, open_bracket
, (int) strlen(open_bracket
));
345 if (getFirstEdge() == (edge
*) NULL
) {
346 sprintf(tempbuf
, "{There are no neighbors installed.}\n");
347 storeAppend(sentry
, tempbuf
, strlen(tempbuf
));
349 for (e
= getFirstEdge(); e
; e
= getNextEdge(e
)) {
351 fatal_dump("Found an edge without a hostname!");
352 sprintf(tempbuf
, "\n{Hostname: %s}\n", e
->host
);
353 storeAppend(sentry
, tempbuf
, strlen(tempbuf
));
354 sprintf(tempbuf
, "{Edge type: %s}\n",
355 e
->type
== is_a_parent
? "parent" : "neighbor");
356 storeAppend(sentry
, tempbuf
, strlen(tempbuf
));
357 sprintf(tempbuf
, "{Status: %s}\n",
358 e
->neighbor_up
? "Up" : "Down");
359 storeAppend(sentry
, tempbuf
, strlen(tempbuf
));
360 sprintf(tempbuf
, "{UDP PORT: %d}\n", e
->udp_port
);
361 storeAppend(sentry
, tempbuf
, strlen(tempbuf
));
362 sprintf(tempbuf
, "{ASCII PORT: %d}\n", e
->ascii_port
);
363 storeAppend(sentry
, tempbuf
, strlen(tempbuf
));
364 sprintf(tempbuf
, "{ACK DEFICIT: %d}\n", e
->ack_deficit
);
365 storeAppend(sentry
, tempbuf
, strlen(tempbuf
));
366 sprintf(tempbuf
, "{PINGS SENT: %d}\n", e
->num_pings
);
367 storeAppend(sentry
, tempbuf
, strlen(tempbuf
));
368 sprintf(tempbuf
, "{PINGS ACKED: %d}\n", e
->pings_acked
);
369 storeAppend(sentry
, tempbuf
, strlen(tempbuf
));
370 if (e
->last_fail_time
) {
371 sprintf(tempbuf
, "{Last failed connect() at: %s}\n",
372 mkhttpdlogtime(&(e
->last_fail_time
)));
373 storeAppend(sentry
, tempbuf
, strlen(tempbuf
));
375 sprintf(tempbuf
, "{DOMAIN LIST: ");
376 storeAppend(sentry
, tempbuf
, strlen(tempbuf
));
377 for (d
= e
->domains
; d
; d
= d
->next
) {
379 sprintf(tempbuf
, "%s ", d
->domain
);
381 sprintf(tempbuf
, "!%s ", d
->domain
);
382 storeAppend(sentry
, tempbuf
, strlen(tempbuf
));
384 storeAppend(sentry
, close_bracket
, strlen(close_bracket
)); /* } */
386 storeAppend(sentry
, close_bracket
, strlen(close_bracket
));
391 void info_get(obj
, sentry
)
396 static char line
[MAX_LINELEN
];
398 #if defined(HAVE_GETRUSAGE) && defined(RUSAGE_SELF)
399 struct rusage rusage
;
406 memset(line
, '\0', SM_PAGE_SIZE
);
408 storeAppend(sentry
, open_bracket
, (int) strlen(open_bracket
));
410 sprintf(line
, "{Harvest Object Cache: Version %s}\n", SQUID_VERSION
);
411 storeAppend(sentry
, line
, strlen(line
));
413 tod
= mkrfc850(&cached_starttime
);
415 sprintf(line
, "{Start Time:\t%s}\n", tod
);
416 storeAppend(sentry
, line
, strlen(line
));
418 tod
= mkrfc850(&cached_curtime
);
419 sprintf(line
, "{Current Time:\t%s}\n", tod
);
420 storeAppend(sentry
, line
, strlen(line
));
422 /* -------------------------------------------------- */
424 sprintf(line
, "{Connection information for cached:}\n");
425 storeAppend(sentry
, line
, strlen(line
));
427 sprintf(line
, "{\tNumber of connections:\t%lu}\n", nconn
);
428 storeAppend(sentry
, line
, strlen(line
));
432 f
= cached_curtime
- cached_starttime
;
433 sprintf(line
, "{\tConnections per hour:\t%.1f}\n", f
== 0.0 ? 0.0 :
434 (nconn
/ (f
/ 3600)));
435 storeAppend(sentry
, line
, strlen(line
));
438 /* -------------------------------------------------- */
442 sprintf(line
, "{Cache information for cached:}\n");
443 storeAppend(sentry
, line
, strlen(line
));
445 sprintf(line
, "{\tStorage Swap size:\t%d MB}\n", storeGetSwapSize() >> 10);
446 storeAppend(sentry
, line
, strlen(line
));
448 sprintf(line
, "{\tStorage Mem size:\t%d KB}\n", storeGetMemSize() >> 10);
449 storeAppend(sentry
, line
, strlen(line
));
451 tod
= mkrfc850(&next_cleaning
);
452 sprintf(line
, "{\tStorage Expiration at:\t%s}\n", tod
);
453 storeAppend(sentry
, line
, strlen(line
));
455 #if defined(HAVE_GETRUSAGE) && defined(RUSAGE_SELF)
456 sprintf(line
, "{Resource usage for cached:}\n");
457 storeAppend(sentry
, line
, strlen(line
));
459 getrusage(RUSAGE_SELF
, &rusage
);
460 sprintf(line
, "{\tCPU Usage: user %d sys %d}\n{\tProcess Size: rss %d KB}\n",
461 rusage
.ru_utime
.tv_sec
, rusage
.ru_stime
.tv_sec
,
462 rusage
.ru_maxrss
* getpagesize() >> 10);
463 storeAppend(sentry
, line
, strlen(line
));
465 sprintf(line
, "{\tPage faults with physical i/o:\t%d}\n",
467 storeAppend(sentry
, line
, strlen(line
));
474 sprintf(line
, "{Memory usage for cached via mallinfo():}\n");
475 storeAppend(sentry
, line
, strlen(line
));
477 sprintf(line
, "{\ttotal space in arena:\t%d KB}\n", mp
.arena
>> 10);
478 storeAppend(sentry
, line
, strlen(line
));
479 sprintf(line
, "{\tnumber of ordinary blocks:\t%d}\n", mp
.ordblks
);
480 storeAppend(sentry
, line
, strlen(line
));
481 sprintf(line
, "{\tnumber of small blocks:\t%d}\n", mp
.smblks
);
482 storeAppend(sentry
, line
, strlen(line
));
484 sprintf(line
, "{\tnumber of holding blocks:\t%d}\n", mp
.hblks
);
485 storeAppend(sentry
, line
, strlen(line
));
488 sprintf(line
, "{\tspace in holding block headers:\t%d}\n", mp
.hblkhd
);
489 storeAppend(sentry
, line
, strlen(line
));
492 sprintf(line
, "{\tspace in small blocks in use:\t%d}\n", mp
.usmblks
);
493 storeAppend(sentry
, line
, strlen(line
));
496 sprintf(line
, "{\tspace in free blocks:\t%d}\n", mp
.fsmblks
);
497 storeAppend(sentry
, line
, strlen(line
));
499 sprintf(line
, "{\tspace in ordinary blocks in use:\t%d KB}\n",
501 storeAppend(sentry
, line
, strlen(line
));
502 sprintf(line
, "{\tspace in free ordinary blocks:\t%d KB}\n", mp
.fordblks
>> 10);
503 storeAppend(sentry
, line
, strlen(line
));
505 sprintf(line
, "{\tcost of enabling keep option:\t%d}\n", mp
.keepcost
);
506 storeAppend(sentry
, line
, strlen(line
));
509 sprintf(line
, "{\tmax size of small blocks:\t%d}\n", mp
.mxfast
);
510 storeAppend(sentry
, line
, strlen(line
));
511 sprintf(line
, "{\tnumber of small blocks in a holding block:\t%d}\n",
513 storeAppend(sentry
, line
, strlen(line
));
514 sprintf(line
, "{\tsmall block rounding factor:\t%d}\n", mp
.grain
);
515 storeAppend(sentry
, line
, strlen(line
));
516 sprintf(line
, "{\tspace (including overhead) allocated in ord. blks:\t%d}\n"
518 sprintf(line
, "{\tnumber of ordinary blocks allocated:\t%d}\n",
520 storeAppend(sentry
, line
, strlen(line
));
521 sprintf(line
, "{\tbytes used in maintaining the free tree:\t%d}\n",
523 storeAppend(sentry
, line
, strlen(line
));
525 #endif /* LNG_MALLINFO */
527 #endif /* HAVE_MALLINFO */
529 sprintf(line
, "{File descriptor usage for cached:}\n");
530 storeAppend(sentry
, line
, strlen(line
));
532 sprintf(line
, "{\tMax number of file desc available:\t%d}\n", getMaxFD());
533 storeAppend(sentry
, line
, strlen(line
));
535 sprintf(line
, "{\tLargest file desc currently in use:\t%d}\n",
536 fdstat_biggest_fd());
537 storeAppend(sentry
, line
, strlen(line
));
539 sprintf(line
, "{\tAvailable number of file descriptors :\t%d}\n",
540 fdstat_are_n_free_fd(0));
541 storeAppend(sentry
, line
, strlen(line
));
543 sprintf(line
, "{\tReserved number of file descriptors :\t%d}\n",
545 storeAppend(sentry
, line
, strlen(line
));
548 int i
, max_fd
= getMaxFD();
551 sprintf(line
, "{\tActive file descriptors:}\n");
552 storeAppend(sentry
, line
, strlen(line
));
554 for (i
= 0; i
< max_fd
; i
++) {
556 if (!fdstat_isopen(i
))
559 switch (fdstat_type(i
)) {
561 /* the lifetime should be greater than curtime */
562 lft
= comm_get_fd_lifetime(i
);
563 to
= comm_get_fd_timeout(i
);
564 sprintf(line
, "{\t\t(%3d = %3d, %3d) NET %s}\n",
566 (int) (lft
> 0 ? lft
- cached_curtime
: -1),
567 (int) max((to
- cached_curtime
), 0),
571 sprintf(line
, "{\t\t(%3d = FILE) %s}\n", i
,
572 (s
= diskFileName(i
)) ? s
: "Unknown");
575 sprintf(line
, "{\t\t(%3d = PIPE) %s}\n", i
, fd_note(i
, NULL
));
578 sprintf(line
, "{\t\t(%3d = LOG) %s}\n", i
, fd_note(i
, NULL
));
582 sprintf(line
, "{\t\t(%3d = UNKNOWN) %s}\n", i
, fd_note(i
, NULL
));
585 storeAppend(sentry
, line
, strlen(line
));
590 sprintf(line
, "{Stop List:}\n");
591 storeAppend(sentry
, line
, strlen(line
));
595 sprintf(line
, "{\tHTTP:}\n");
596 storeAppend(sentry
, line
, strlen(line
));
598 sprintf(line
, "{\t\t%s}\n", p
->key
);
599 storeAppend(sentry
, line
, strlen(line
));
603 if (gopher_stoplist
) {
606 sprintf(line
, "{\tGOPHER:}\n");
607 storeAppend(sentry
, line
, strlen(line
));
609 sprintf(line
, "{\t\t%s}\n", p
->key
);
610 storeAppend(sentry
, line
, strlen(line
));
617 sprintf(line
, "{\tFTP:}\n");
618 storeAppend(sentry
, line
, strlen(line
));
620 sprintf(line
, "{\t\t%s}\n", p
->key
);
621 storeAppend(sentry
, line
, strlen(line
));
625 sprintf(line
, "{Internal Data Structures:}\n");
626 storeAppend(sentry
, line
, strlen(line
));
627 sprintf(line
, "{Meta Data:}\n");
628 storeAppend(sentry
, line
, strlen(line
));
629 sprintf(line
, "{\t\tStoreEntry %d x %d}\n", (int) sizeof(StoreEntry
),
630 meta_data
.store_entries
);
631 storeAppend(sentry
, line
, strlen(line
));
632 sprintf(line
, "{\t\tStoreMemObject %d x %d}\n", (int) sizeof(MemObject
),
633 meta_data
.store_in_mem_objects
);
634 storeAppend(sentry
, line
, strlen(line
));
635 sprintf(line
, "{\t\tIPCacheEntry %d x %d}\n", (int) sizeof(ipcache_entry
),
636 meta_data
.ipcache_count
);
637 storeAppend(sentry
, line
, strlen(line
));
638 sprintf(line
, "{\t\tHash link %d x %d}\n", (int) sizeof(hash_link
),
639 meta_data
.hash_links
= hash_links_allocated
);
640 storeAppend(sentry
, line
, strlen(line
));
641 sprintf(line
, "{\t\tURL strings %d}\n", meta_data
.url_strings
);
642 storeAppend(sentry
, line
, strlen(line
));
643 sprintf(line
, "{\t\tHot Object Cache Items %d}\n", meta_data
.hot_vm
);
644 storeAppend(sentry
, line
, strlen(line
));
645 sprintf(line
, "{\t\tPool for disk I/O %d KB (Free %d KB)}\n",
646 (disk_stats
.total_pages_allocated
* disk_stats
.page_size
) / (1 << 10),
647 ((disk_stats
.total_pages_allocated
- disk_stats
.n_pages_in_use
) * disk_stats
.page_size
) /
650 storeAppend(sentry
, line
, strlen(line
));
651 sprintf(line
, "{\t\tPool for in-memory objects %d KB (Free %d KB)}\n",
652 (sm_stats
.total_pages_allocated
* sm_stats
.page_size
) / (1 << 10),
653 ((sm_stats
.total_pages_allocated
- sm_stats
.n_pages_in_use
) * sm_stats
.page_size
) / (1 << 10));
654 storeAppend(sentry
, line
, strlen(line
));
655 sprintf(line
, "{\tTotal Accounted %d KB}\n",
656 (int) (meta_data
.store_entries
* sizeof(StoreEntry
) +
657 meta_data
.store_in_mem_objects
* sizeof(MemObject
) +
658 meta_data
.ipcache_count
* sizeof(ipcache_entry
) +
659 meta_data
.hash_links
* sizeof(hash_link
) +
660 sm_stats
.total_pages_allocated
* sm_stats
.page_size
+
661 disk_stats
.total_pages_allocated
* disk_stats
.page_size
+
662 meta_data
.url_strings
) >> 10);
663 storeAppend(sentry
, line
, strlen(line
));
665 storeAppend(sentry
, close_bracket
, strlen(close_bracket
));
669 void parameter_get(obj
, sentry
)
674 /* be careful if an object is bigger than 4096,
675 * need more malloc here */
676 static char line
[MAX_LINELEN
];
678 memset(line
, '\0', MAX_LINELEN
);
680 storeAppend(sentry
, open_bracket
, (int) strlen(open_bracket
));
682 sprintf(line
, "{VM-Max %d \"# Maximum hot-vm cache (MB)\"}\n",
683 getCacheMemMax() / (1 << 20));
684 storeAppend(sentry
, line
, strlen(line
));
686 sprintf(line
, "{VM-High %d \"# High water mark hot-vm cache (%%)\"}\n",
687 getCacheMemHighWaterMark());
688 storeAppend(sentry
, line
, strlen(line
));
690 sprintf(line
, "{VM-Low %d \"# Low water-mark hot-vm cache (%%)\"}\n",
691 getCacheMemLowWaterMark());
692 storeAppend(sentry
, line
, strlen(line
));
694 sprintf(line
, "{Swap-Max %d \"# Maximum disk cache (MB)\"}\n",
695 getCacheSwapMax() / (1 << 10));
696 storeAppend(sentry
, line
, strlen(line
));
698 sprintf(line
, "{Swap-High %d \"# High Water mark disk cache (%%)\"}\n",
699 getCacheSwapHighWaterMark());
700 storeAppend(sentry
, line
, strlen(line
));
702 sprintf(line
, "{Swap-Low %d \"# Low water mark disk cache (%%)\"}\n",
703 getCacheSwapLowWaterMark());
704 storeAppend(sentry
, line
, strlen(line
));
706 sprintf(line
, "{HTTP-Max %d\"# Maximum size HTTP objects (KB)\"}\n",
707 getHttpMax() / (1 << 10));
708 storeAppend(sentry
, line
, strlen(line
));
710 sprintf(line
, "{HTTP-TTL %d \"# Http object default TTL (hrs)\"}\n", getHttpTTL() / 3600);
711 storeAppend(sentry
, line
, strlen(line
));
713 sprintf(line
, "{Gopher-Max %d \"# Maximum size gopher objects (KB)\"}\n",
714 getGopherMax() / (1 << 10));
715 storeAppend(sentry
, line
, strlen(line
));
717 sprintf(line
, "{Gopher-TTL %d \"# TTL for gopher objects (hrs)\"}\n", getGopherTTL() / 3600);
718 storeAppend(sentry
, line
, strlen(line
));
720 sprintf(line
, "{FTP-Max %d \"# Maximum size FTP objects (KB)\"}\n",
721 getFtpMax() / (1 << 10));
722 storeAppend(sentry
, line
, strlen(line
));
724 sprintf(line
, "{FTP-TTL %d \"# TTL for FTP objects (hrs)\"}\n", getFtpTTL() / 3600);
725 storeAppend(sentry
, line
, strlen(line
));
727 sprintf(line
, "{Neg-TTL %d \"# TTL for negative cache (s)\"}\n",
729 storeAppend(sentry
, line
, strlen(line
));
731 sprintf(line
, "{ReadTimeout %d \"# Maximum idle connection (s)\"}\n", getReadTimeout());
732 storeAppend(sentry
, line
, strlen(line
));
734 sprintf(line
, "{ClientLifetime %d \"# Lifetime for incoming ascii port requests or outgoing clients (s)\"}\n", getClientLifetime());
735 storeAppend(sentry
, line
, strlen(line
));
737 sprintf(line
, "{CleanRate %d \"# Rate for periodic object expiring\"}\n",
739 storeAppend(sentry
, line
, strlen(line
));
741 /* Cachemgr.cgi expects an integer in the second field of the string */
742 sprintf(line
, "{HttpAccelMode %d \"# Is operating as an HTTP accelerator\"}\n",
744 storeAppend(sentry
, line
, strlen(line
));
747 storeAppend(sentry
, close_bracket
, strlen(close_bracket
));
751 void log_append(obj
, url
, id
, size
, action
, method
, http_code
, msec
)
761 static char tmp
[6000]; /* MAX_URL is 4096 */
767 /* ENABLE THIS IF YOU WANT A *SLOW* CACHE, OR
768 * JUST WRITE A PERL SCRIPT TO MUCK YOUR LOGS */
772 struct hostent
*h
= NULL
;
773 if (sscanf(id
, "%d.%d.%d.%d", &ipx
[0], &ipx
[1], &ipx
[2], &ipx
[3]) == 4) {
775 if (h
= gethostbyaddr((char *) &ipy
, 4, AF_INET
)) {
776 id
= xstrdup(h
->h_name
);
787 if (obj
->logfile_status
== LOG_ENABLE
) {
788 if (emulate_httpd_log
)
789 sprintf(tmp
, "%s - - [%s] \"%s %s\" %s %d\n",
790 id
, mkhttpdlogtime(&cached_curtime
), method
, url
, action
, size
);
792 sprintf(tmp
, "%9d.%03d %6d %s %s/%03d %d %s %s\n",
793 (int) current_time
.tv_sec
,
794 (int) current_time
.tv_usec
/ 1000,
804 if (file_write(obj
->logfile_fd
, buf
= xstrdup(tmp
), strlen(tmp
),
805 obj
->logfile_access
, NULL
, NULL
) != DISK_OK
) {
806 debug(18, 1, "log_append: File write failed.\n");
812 void log_enable(obj
, sentry
)
816 static char tempbuf
[MAX_LINELEN
];
818 if (obj
->logfile_status
== LOG_DISABLE
) {
819 obj
->logfile_status
= LOG_ENABLE
;
821 /* open the logfile */
822 obj
->logfile_fd
= file_open(obj
->logfilename
, NULL
, O_RDWR
| O_CREAT
);
823 if (obj
->logfile_fd
== DISK_ERROR
) {
824 debug(18, 0, "Cannot open logfile: %s\n", obj
->logfilename
);
825 obj
->logfile_status
= LOG_DISABLE
;
827 obj
->logfile_access
= file_write_lock(obj
->logfile_fd
);
830 /* at the moment, store one char to make a storage manager happy */
831 sprintf(tempbuf
, " ");
832 storeAppend(sentry
, tempbuf
, strlen(tempbuf
));
835 void log_disable(obj
, sentry
)
839 static char tempbuf
[MAX_LINELEN
];
841 if (obj
->logfile_status
== LOG_ENABLE
)
842 file_close(obj
->logfile_fd
);
844 obj
->logfile_status
= LOG_DISABLE
;
845 /* at the moment, store one char to make a storage manager happy */
846 sprintf(tempbuf
, " ");
847 storeAppend(sentry
, tempbuf
, strlen(tempbuf
));
852 void log_clear(obj
, sentry
)
856 static char tempbuf
[MAX_LINELEN
];
859 /* what should be done here. Erase file ??? or move it to another name */
860 /* At the moment, just erase it. */
861 /* bug here need to be fixed. what if there are still data in memory. Need flush here */
862 if (obj
->logfile_status
== LOG_ENABLE
)
863 file_close(obj
->logfile_fd
);
865 unlink(obj
->logfilename
);
867 /* reopen it anyway */
868 obj
->logfile_fd
= file_open(obj
->logfilename
, NULL
, O_RDWR
| O_CREAT
);
869 if (obj
->logfile_fd
== DISK_ERROR
) {
870 debug(18, 0, "Cannot open logfile: %s\n", obj
->logfilename
);
871 obj
->logfile_status
= LOG_DISABLE
;
873 /* at the moment, store one char to make a storage manager happy */
874 sprintf(tempbuf
, " ");
875 storeAppend(sentry
, tempbuf
, strlen(tempbuf
));
880 void proto_newobject(obj
, proto_id
, size
, restart
)
886 proto_stat
*p
= &obj
->proto_stat_data
[proto_id
];
890 /* Account for 1KB granularity */
891 p
->kb
.now
+= ((size
+ 1023) >> 10);
893 if (p
->kb
.now
> p
->kb
.max
)
894 p
->kb
.max
= p
->kb
.now
;
896 p
->kb
.min
= p
->kb
.now
;
900 void proto_purgeobject(obj
, proto_id
, size
)
905 proto_stat
*p
= &obj
->proto_stat_data
[proto_id
];
909 /* Scale down to KB */
910 p
->kb
.now
-= ((size
+ 1023) >> 10);
912 if (p
->kb
.now
< p
->kb
.min
)
913 p
->kb
.min
= p
->kb
.now
;
916 /* update stat for each particular protocol when an object is fetched */
917 void proto_touchobject(obj
, proto_id
, size
)
922 obj
->proto_stat_data
[proto_id
].refcount
++;
923 obj
->proto_stat_data
[proto_id
].transferbyte
+= (1023 + size
) >> 10;
926 void proto_hit(obj
, proto_id
)
930 obj
->proto_stat_data
[proto_id
].hit
++;
933 void proto_miss(obj
, proto_id
)
937 obj
->proto_stat_data
[proto_id
].miss
++;
940 int proto_url_to_id(url
)
943 if (strncmp(url
, "http:", 5) == 0)
945 if (strncmp(url
, "ftp:", 4) == 0)
947 if (strncmp(url
, "gopher:", 7) == 0)
949 if (strncmp(url
, "cache_object:", 13) == 0)
951 if (strncmp(url
, "abort:", 6) == 0)
953 if (strncmp(url
, "news:", 5) == 0)
955 if (strncmp(url
, "file:", 5) == 0)
962 void stat_init(object
, logfilename
)
966 cacheinfo
*obj
= NULL
;
969 obj
= (cacheinfo
*) xmalloc(sizeof(cacheinfo
));
970 memset(obj
, '\0', sizeof(cacheinfo
));
972 obj
->stat_get
= stat_get
;
973 obj
->info_get
= info_get
;
974 obj
->cache_size_get
= cache_size_get
;
976 obj
->log_get_start
= log_get_start
;
977 obj
->log_status_get
= log_status_get
;
978 obj
->log_append
= log_append
;
979 obj
->log_clear
= log_clear
;
980 obj
->log_enable
= log_enable
;
981 obj
->log_disable
= log_disable
;
982 obj
->logfile_status
= LOG_ENABLE
;
984 obj
->cached_get_start
= cached_get_start
;
986 obj
->parameter_get
= parameter_get
;
987 obj
->server_list
= server_list
;
989 memcpy(obj
->logfilename
, logfilename
, (int) (strlen(logfilename
) + 1) % 256);
990 obj
->logfile_fd
= file_open(obj
->logfilename
, NULL
, O_RDWR
| O_CREAT
);
991 if (obj
->logfile_fd
== DISK_ERROR
) {
992 debug(18, 0, "Cannot open logfile: %s\n", obj
->logfilename
);
993 obj
->logfile_status
= LOG_DISABLE
;
994 fatal("Cannot open logfile.");
996 obj
->logfile_access
= file_write_lock(obj
->logfile_fd
);
998 obj
->proto_id
= proto_url_to_id
;
999 obj
->proto_newobject
= proto_newobject
;
1000 obj
->proto_purgeobject
= proto_purgeobject
;
1001 obj
->proto_touchobject
= proto_touchobject
;
1002 obj
->proto_hit
= proto_hit
;
1003 obj
->proto_miss
= proto_miss
;
1004 obj
->NotImplement
= dummyhandler
;
1006 for (i
= 0; i
< PROTOCOL_SUPPORTED
+ PROTOCOL_EXTRA
; ++i
) {
1011 strcpy(obj
->proto_stat_data
[i
].protoname
, "TOTAL");
1015 strcpy(obj
->proto_stat_data
[i
].protoname
, "HTTP");
1019 strcpy(obj
->proto_stat_data
[i
].protoname
, "GOPHER");
1023 strcpy(obj
->proto_stat_data
[i
].protoname
, "FTP");
1027 strcpy(obj
->proto_stat_data
[i
].protoname
, "CACHEMGR");
1031 strcpy(obj
->proto_stat_data
[i
].protoname
, "ABORTED");
1036 strcpy(obj
->proto_stat_data
[i
].protoname
, "UNKNOWN");
1040 obj
->proto_stat_data
[i
].object_count
= 0;
1041 obj
->proto_stat_data
[i
].hit
= 0;
1042 obj
->proto_stat_data
[i
].miss
= 0;
1043 obj
->proto_stat_data
[i
].hitratio
= 0.0;
1044 obj
->proto_stat_data
[i
].transferrate
= 0;
1045 obj
->proto_stat_data
[i
].refcount
= 0;
1046 obj
->proto_stat_data
[i
].transferbyte
= 0;
1048 obj
->proto_stat_data
[i
].kb
.max
= 0;
1049 obj
->proto_stat_data
[i
].kb
.min
= 0;
1050 obj
->proto_stat_data
[i
].kb
.avg
= 0;
1051 obj
->proto_stat_data
[i
].kb
.now
= 0;
1058 char *stat_describe(entry
)
1061 static char state
[256];
1064 switch (entry
->status
) {
1066 strncat(state
, "STORE-OK", sizeof(state
));
1069 strncat(state
, "ST-PEND", sizeof(state
));
1072 strncat(state
, "ABORTED", sizeof(state
));
1075 strncat(state
, "YEEHAH", sizeof(state
));
1078 strncat(state
, "/", sizeof(state
));
1080 switch (entry
->ping_status
) {
1082 strncat(state
, "PING-WAIT", sizeof(state
));
1085 strncat(state
, "PING-TIMEOUT", sizeof(state
));
1088 strncat(state
, "PING-DONE", sizeof(state
));
1091 strncat(state
, "NO-PING", sizeof(state
));
1094 strncat(state
, "YEEHAH", sizeof(state
));
1100 char *mem_describe(entry
)
1103 static char where
[100];
1106 if (entry
->swap_file_number
>= 0)
1107 sprintf(where
, "D%d", entry
->swap_file_number
);
1108 if (entry
->swap_status
== SWAPPING_OUT
)
1109 strncat(where
, "/SWAP-OUT", sizeof(where
));
1110 if (entry
->swap_status
== SWAP_OK
)
1111 strncat(where
, "/SWAP-OK", sizeof(where
));
1113 strncat(where
, "/NO-SWAP", sizeof(where
));
1115 if (entry
->mem_status
== SWAPPING_IN
)
1116 strncat(where
, "/SWAP-IN", sizeof(where
));
1117 else if (entry
->mem_status
== IN_MEMORY
)
1118 strncat(where
, "/IN-MEM", sizeof(where
));
1119 else /* STORE_PENDING */
1120 strncat(where
, "/OUT-MEM", sizeof(where
));
1125 char *ttl_describe(entry
)
1129 static char TTL
[60];
1133 strcpy(TTL
, "UNKNOWN"); /* sometimes the TTL isn't set below */
1134 ttl
= entry
->expires
- cached_curtime
;
1136 strcpy(TTL
, "EXPIRED");
1145 sprintf(TTL
, "% 6d:%02d:%02d", hh
, mm
, ss
);
1150 char *elapsed_time(entry
, since
, TTL
)
1155 int hh
, mm
, ss
, ttl
;
1158 strcpy(TTL
, "UNKNOWN"); /* sometimes TTL doesn't get set */
1159 ttl
= cached_curtime
- since
;
1161 strcpy(TTL
, "NEVER");
1162 } else if (ttl
< 0) {
1163 strcpy(TTL
, "EXPIRED");
1170 sprintf(TTL
, "% 6d:%02d:%02d", hh
, mm
, ss
);
1176 char *flags_describe(entry
)
1179 static char FLAGS
[32];
1182 strcpy(FLAGS
, "F:");
1183 if (BIT_TEST(entry
->flag
, KEY_CHANGE
))
1184 strncat(FLAGS
, "K", sizeof(FLAGS
) - 1);
1185 if (BIT_TEST(~entry
->flag
, CACHABLE
))
1186 strncat(FLAGS
, "C", sizeof(FLAGS
) - 1);
1187 if (BIT_TEST(entry
->flag
, REFRESH_REQUEST
))
1188 strncat(FLAGS
, "R", sizeof(FLAGS
) - 1);
1189 if (BIT_TEST(entry
->flag
, RELEASE_REQUEST
))
1190 strncat(FLAGS
, "Z", sizeof(FLAGS
) - 1);
1191 if (BIT_TEST(entry
->flag
, ABORT_MSG_PENDING
))
1192 strncat(FLAGS
, "A", sizeof(FLAGS
) - 1);
1193 if (BIT_TEST(entry
->flag
, DELAY_SENDING
))
1194 strncat(FLAGS
, "D", sizeof(FLAGS
) - 1);
1195 if (BIT_TEST(entry
->flag
, IP_LOOKUP_PENDING
))
1196 strncat(FLAGS
, "P", sizeof(FLAGS
) - 1);
1197 if (entry
->lock_count
)
1198 strncat(FLAGS
, "L", sizeof(FLAGS
) - 1);
1199 if (entry
->lock_count
) {
1200 sprintf(LOCK_CNT
, "%d", entry
->lock_count
);
1201 strncat(FLAGS
, LOCK_CNT
, sizeof(FLAGS
) - 1);
1206 void stat_rotate_log()
1209 static char from
[MAXPATHLEN
];
1210 static char to
[MAXPATHLEN
];
1213 if ((fname
= CacheInfo
->logfilename
) == NULL
)
1216 debug(18, 1, "stat_rotate_log: Rotating\n");
1218 /* Rotate numbers 0 through N up one */
1219 for (i
= getLogfileRotateNumber(); i
> 1;) {
1221 sprintf(from
, "%s.%d", fname
, i
- 1);
1222 sprintf(to
, "%s.%d", fname
, i
);
1225 /* Rotate the current log to .0 */
1226 if (getLogfileRotateNumber() > 0) {
1227 sprintf(to
, "%s.%d", fname
, 0);
1230 /* Close and reopen the log. It may have been renamed "manually"
1231 * before HUP'ing us. */
1232 file_close(CacheInfo
->logfile_fd
);
1233 CacheInfo
->logfile_fd
= file_open(fname
, NULL
, O_RDWR
| O_CREAT
| O_APPEND
);
1234 if (CacheInfo
->logfile_fd
== DISK_ERROR
) {
1235 debug(18, 0, "rotate_logs: Cannot open logfile: %s\n", fname
);
1236 CacheInfo
->logfile_status
= LOG_DISABLE
;
1237 fatal("Cannot open logfile.");
1239 CacheInfo
->logfile_access
= file_write_lock(CacheInfo
->logfile_fd
);