=== modified file 'src/CacheDigest.cc' --- src/CacheDigest.cc 2010-12-13 11:31:14 +0000 +++ src/CacheDigest.cc 2011-12-15 21:17:34 +0000 @@ -17,40 +17,41 @@ * incorporates software developed and/or copyrighted by other * sources; see the CREDITS file for full details. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #include "squid.h" +#include "StatCounters.h" #include "Store.h" #if USE_CACHE_DIGESTS /* local types */ typedef struct { int bit_count; /* total number of bits */ int bit_on_count; /* #bits turned on */ int bseq_len_sum; /* sum of all bit seq length */ int bseq_count; /* number of bit seqs */ } CacheDigestStats; /* local functions */ static void cacheDigestHashKey(const CacheDigest * cd, const cache_key * key); /* static array used by cacheDigestHashKey for optimization purposes */ static uint32_t hashed_keys[4]; static void @@ -159,41 +160,41 @@ if (!CBIT_TEST(cd->mask, hashed_keys[0])) { CBIT_SET(cd->mask, hashed_keys[0]); on_xition_cnt++; } if (!CBIT_TEST(cd->mask, hashed_keys[1])) { CBIT_SET(cd->mask, hashed_keys[1]); on_xition_cnt++; } if (!CBIT_TEST(cd->mask, hashed_keys[2])) { CBIT_SET(cd->mask, hashed_keys[2]); on_xition_cnt++; } if (!CBIT_TEST(cd->mask, hashed_keys[3])) { CBIT_SET(cd->mask, hashed_keys[3]); on_xition_cnt++; } - statHistCount(&statCounter.cd.on_xition_count, on_xition_cnt); + statCounter.cd.on_xition_count.count(on_xition_cnt); } #endif cd->count++; } void cacheDigestDel(CacheDigest * cd, const cache_key * key) { assert(cd && key); cd->del_count++; /* we do not support deletions from the digest */ } /* returns mask utilization parameters */ static void cacheDigestStats(const CacheDigest * cd, CacheDigestStats * stats) { int on_count = 0; int pos = cd->mask_size * 8; int seq_len_sum = 0; @@ -218,91 +219,91 @@ cur_seq_len++; } stats->bit_count = cd->mask_size * 8; stats->bit_on_count = on_count; stats->bseq_len_sum = seq_len_sum; stats->bseq_count = seq_count; } int cacheDigestBitUtil(const CacheDigest * cd) { CacheDigestStats stats; assert(cd); cacheDigestStats(cd, &stats); return xpercentInt(stats.bit_on_count, stats.bit_count); } void -cacheDigestGuessStatsUpdate(cd_guess_stats * stats, int real_hit, int guess_hit) +cacheDigestGuessStatsUpdate(CacheDigestGuessStats * stats, int real_hit, int guess_hit) { assert(stats); if (real_hit) { if (guess_hit) - stats->true_hits++; + ++stats->trueHits; else - stats->false_misses++; + ++stats->falseMisses; } else { if (guess_hit) - stats->false_hits++; + ++stats->falseHits; else - stats->true_misses++; + ++stats->trueMisses; } } void -cacheDigestGuessStatsReport(const cd_guess_stats * stats, StoreEntry * sentry, const char *label) +cacheDigestGuessStatsReport(const CacheDigestGuessStats * stats, StoreEntry * sentry, const char *label) { - const int true_count = stats->true_hits + stats->true_misses; - const int false_count = stats->false_hits + stats->false_misses; - const int hit_count = stats->true_hits + stats->false_hits; - const int miss_count = stats->true_misses + stats->false_misses; + const int true_count = stats->trueHits + stats->trueMisses; + const int false_count = stats->falseHits + stats->falseMisses; + const int hit_count = stats->trueHits + stats->falseHits; + const int miss_count = stats->trueMisses + stats->falseMisses; const int tot_count = true_count + false_count; assert(label); assert(tot_count == hit_count + miss_count); /* paranoid */ if (!tot_count) { storeAppendPrintf(sentry, "no guess stats for %s available\n", label); return; } storeAppendPrintf(sentry, "Digest guesses stats for %s:\n", label); storeAppendPrintf(sentry, "guess\t hit\t\t miss\t\t total\t\t\n"); storeAppendPrintf(sentry, " \t #\t %%\t #\t %%\t #\t %%\t\n"); storeAppendPrintf(sentry, "true\t %d\t %.2f\t %d\t %.2f\t %d\t %.2f\n", - stats->true_hits, xpercent(stats->true_hits, tot_count), - stats->true_misses, xpercent(stats->true_misses, tot_count), + stats->trueHits, xpercent(stats->trueHits, tot_count), + stats->trueMisses, xpercent(stats->trueMisses, tot_count), true_count, xpercent(true_count, tot_count)); storeAppendPrintf(sentry, "false\t %d\t %.2f\t %d\t %.2f\t %d\t %.2f\n", - stats->false_hits, xpercent(stats->false_hits, tot_count), - stats->false_misses, xpercent(stats->false_misses, tot_count), + stats->falseHits, xpercent(stats->falseHits, tot_count), + stats->falseMisses, xpercent(stats->falseMisses, tot_count), false_count, xpercent(false_count, tot_count)); storeAppendPrintf(sentry, "all\t %d\t %.2f\t %d\t %.2f\t %d\t %.2f\n", hit_count, xpercent(hit_count, tot_count), miss_count, xpercent(miss_count, tot_count), tot_count, xpercent(tot_count, tot_count)); storeAppendPrintf(sentry, "\tclose_hits: %d ( %d%%) /* cd said hit, doc was in the peer cache, but we got a miss */\n", - stats->close_hits, xpercentInt(stats->close_hits, stats->false_hits)); + stats->closeHits, xpercentInt(stats->closeHits, stats->falseHits)); } void cacheDigestReport(CacheDigest * cd, const char *label, StoreEntry * e) { CacheDigestStats stats; assert(cd && e); cacheDigestStats(cd, &stats); storeAppendPrintf(e, "%s digest: size: %d bytes\n", label ? label : "", stats.bit_count / 8 ); storeAppendPrintf(e, "\t entries: count: %d capacity: %d util: %d%%\n", cd->count, cd->capacity, xpercentInt(cd->count, cd->capacity) ); storeAppendPrintf(e, "\t deletion attempts: %d\n", cd->del_count ); storeAppendPrintf(e, "\t bits: per entry: %d on: %d capacity: %d util: %d%%\n", === modified file 'src/DiskIO/DiskDaemon/DiskdFile.cc' --- src/DiskIO/DiskDaemon/DiskdFile.cc 2010-12-13 11:31:14 +0000 +++ src/DiskIO/DiskDaemon/DiskdFile.cc 2011-12-10 15:21:36 +0000 @@ -30,40 +30,41 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * * CopyRight (c) 2003, Robert Collins */ #include "squid.h" #include #include #include #include "DiskdFile.h" #include "ConfigOption.h" #include "diomsg.h" #include "DiskdIOStrategy.h" #include "DiskIO/IORequestor.h" #include "DiskIO/ReadRequest.h" #include "DiskIO/WriteRequest.h" +#include "StatCounters.h" CBDATA_CLASS_INIT(DiskdFile); void * DiskdFile::operator new(size_t unused) { CBDATA_INIT_TYPE(DiskdFile); DiskdFile *result = cbdataAlloc(DiskdFile); /* Mark result as being owned - we want the refcounter to do the delete * call */ debugs(79, 3, "diskdFile with base " << result << " allocating"); return result; } void DiskdFile::operator delete(void *address) { DiskdFile *t = static_cast(address); debugs(79, 3, "diskdFile with base " << t << " deleting"); cbdataFree(t); } @@ -258,58 +259,58 @@ readDone(M); break; case _MQD_WRITE: writeDone(M); break; case _MQD_UNLINK: assert (0); break; default: assert(0); break; } } void DiskdFile::openDone(diomsg *M) { - statCounter.syscalls.disk.opens++; + ++statCounter.syscalls.disk.opens; debugs(79, 3, "storeDiskdOpenDone: status " << M->status); if (M->status < 0) { diskd_stats.open.fail++; errorOccured = true; } else { diskd_stats.open.success++; } ioCompleted(); notifyClient(); } void DiskdFile::createDone(diomsg *M) { - statCounter.syscalls.disk.opens++; + ++statCounter.syscalls.disk.opens; debugs(79, 3, "storeDiskdCreateDone: status " << M->status); if (M->status < 0) { diskd_stats.create.fail++; errorOccured = true; } else { diskd_stats.create.success++; } ioCompleted(); notifyClient(); } void DiskdFile::write(WriteRequest *aRequest) { debugs(79, 3, "DiskdFile::write: this " << (void *)this << ", buf " << (void *)aRequest->buf << ", off " << aRequest->offset << ", len " << aRequest->len); ssize_t shm_offset; char *sbuf = (char *)IO->shm.get(&shm_offset); memcpy(sbuf, aRequest->buf, aRequest->len); @@ -338,86 +339,86 @@ } diskd_stats.write.ops++; } void DiskdFile::ioAway() { ++inProgressIOs; } void DiskdFile::ioCompleted() { --inProgressIOs; } void DiskdFile::closeDone(diomsg * M) { - statCounter.syscalls.disk.closes++; + ++statCounter.syscalls.disk.closes; debugs(79, 3, "DiskdFile::closeDone: status " << M->status); if (M->status < 0) { diskd_stats.close.fail++; errorOccured = true; } else { diskd_stats.close.success++; } ioCompleted(); if (canNotifyClient()) ioRequestor->closeCompleted(); ioRequestor = NULL; } void DiskdFile::readDone(diomsg * M) { - statCounter.syscalls.disk.reads++; + ++statCounter.syscalls.disk.reads; debugs(79, 3, "DiskdFile::readDone: status " << M->status); assert (M->requestor); ReadRequest::Pointer readRequest = dynamic_cast(M->requestor); /* remove the free protection */ readRequest->RefCountDereference(); if (M->status < 0) { diskd_stats.read.fail++; ioCompleted(); errorOccured = true; ioRequestor->readCompleted(NULL, -1, DISK_ERROR, readRequest); return; } diskd_stats.read.success++; ioCompleted(); ioRequestor->readCompleted (IO->shm.buf + M->shm_offset, M->status, DISK_OK, readRequest); } void DiskdFile::writeDone(diomsg *M) { - statCounter.syscalls.disk.writes++; + ++statCounter.syscalls.disk.writes; debugs(79, 3, "storeDiskdWriteDone: status " << M->status); assert (M->requestor); WriteRequest::Pointer writeRequest = dynamic_cast(M->requestor); /* remove the free protection */ writeRequest->RefCountDereference(); if (M->status < 0) { errorOccured = true; diskd_stats.write.fail++; ioCompleted(); ioRequestor->writeCompleted (DISK_ERROR,0, writeRequest); return; } diskd_stats.write.success++; ioCompleted(); ioRequestor->writeCompleted (DISK_OK,M->status, writeRequest); } bool === modified file 'src/DiskIO/DiskDaemon/DiskdIOStrategy.cc' --- src/DiskIO/DiskDaemon/DiskdIOStrategy.cc 2011-10-27 23:14:28 +0000 +++ src/DiskIO/DiskDaemon/DiskdIOStrategy.cc 2011-12-10 15:24:11 +0000 @@ -29,40 +29,41 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * * Copyright (c) 2003, Robert Collins */ #include "squid.h" #include "comm/Loops.h" #include #include #include #include "DiskdIOStrategy.h" #include "ConfigOption.h" #include "DiskIO/DiskFile.h" #include "DiskdFile.h" #include "diomsg.h" /* for statfs */ #include "Store.h" +#include "StatCounters.h" #include "SquidTime.h" diskd_stats_t diskd_stats; size_t DiskdIOStrategy::nextInstanceID (0); const int diomsg::msg_snd_rcv_sz = sizeof(diomsg) - sizeof(mtyp_t); size_t DiskdIOStrategy::newInstance() { return ++nextInstanceID; } bool DiskdIOStrategy::shedLoad() { /* * Fail on open() if there are too many requests queued. */ @@ -276,41 +277,41 @@ buf = (char *)shmat(id, NULL, 0); if (buf == (void *) -1) { debugs(50, 0, "storeDiskdInit: shmat: " << xstrerror()); fatal("shmat failed"); } inuse_map = (char *)xcalloc((nbufs + 7) / 8, 1); diskd_stats.shmbuf_count += nbufs; for (int i = 0; i < nbufs; i++) { CBIT_SET(inuse_map, i); put (i * SHMBUF_BLKSZ); } } void DiskdIOStrategy::unlinkDone(diomsg * M) { debugs(79, 3, "storeDiskdUnlinkDone: file " << shm.buf + M->shm_offset << " status " << M->status); - statCounter.syscalls.disk.unlinks++; + ++statCounter.syscalls.disk.unlinks; if (M->status < 0) diskd_stats.unlink.fail++; else diskd_stats.unlink.success++; } void DiskdIOStrategy::handle(diomsg * M) { if (!cbdataReferenceValid (M->callback_data)) { /* I.e. already closed file * - say when we have a error opening after * a read was already queued */ debugs(79, 3, "storeDiskdHandle: Invalid callback_data " << M->callback_data); cbdataReferenceDone (M->callback_data); return; } === modified file 'src/DiskIO/DiskThreads/DiskThreadsDiskFile.cc' --- src/DiskIO/DiskThreads/DiskThreadsDiskFile.cc 2009-03-31 12:39:30 +0000 +++ src/DiskIO/DiskThreads/DiskThreadsDiskFile.cc 2011-12-10 15:24:11 +0000 @@ -24,40 +24,41 @@ * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * * Copyright (c) 2003, Robert Collins */ #include "squid.h" #include "DiskThreadsDiskFile.h" #include "Store.h" #include "Generic.h" #include "DiskIO/IORequestor.h" #include "DiskIO/ReadRequest.h" #include "DiskIO/WriteRequest.h" +#include "StatCounters.h" /* === PUBLIC =========================================================== */ CBDATA_CLASS_INIT(DiskThreadsDiskFile); void * DiskThreadsDiskFile::operator new (size_t) { CBDATA_INIT_TYPE(DiskThreadsDiskFile); DiskThreadsDiskFile *result = cbdataAlloc(DiskThreadsDiskFile); /* * We used to call squidaio_init() here, but if the first transaction * is to unlink a file (e.g., if Squid starts up over the disk space * limit) then "squidaio" won't be initialized yet. */ return result; } void DiskThreadsDiskFile::operator delete(void *address) @@ -66,90 +67,90 @@ cbdataFree(t); } DiskThreadsDiskFile::DiskThreadsDiskFile(char const *aPath, DiskThreadsIOStrategy *anIO):fd(-1), errorOccured (false), IO(anIO), inProgressIOs (0) { assert (aPath); debugs(79, 3, "UFSFile::UFSFile: " << aPath); path_ = xstrdup (aPath); } DiskThreadsDiskFile::~DiskThreadsDiskFile() { safe_free (path_); doClose(); } void DiskThreadsDiskFile::open(int flags, mode_t mode, RefCount callback) { - statCounter.syscalls.disk.opens++; + ++statCounter.syscalls.disk.opens; #if !ASYNC_OPEN fd = file_open(path_, flags); if (fd < 0) { debugs(79, 3, "DiskThreadsDiskFile::open: got failure (" << errno << ")"); errorOccured = true; return; } #endif Opening_FD++; ioRequestor = callback; ++inProgressIOs; #if ASYNC_OPEN aioOpen(path_, flags, mode, DiskThreadsDiskFile::OpenDone, this); #else openDone(fd, NULL, fd, 0); #endif } void DiskThreadsDiskFile::read(ReadRequest * request) { debugs(79, 3, "DiskThreadsDiskFile::read: " << this << ", size " << request->len); assert (fd > -1); assert (ioRequestor.getRaw()); - statCounter.syscalls.disk.reads++; + ++statCounter.syscalls.disk.reads; ++inProgressIOs; #if ASYNC_READ aioRead(fd, request->offset, request->len, ReadDone, new IoResult(this, request)); #else file_read(fd, request->buf, request->len, request->offset, ReadDone, new IoResult(this, request)); #endif } void DiskThreadsDiskFile::create(int flags, mode_t mode, RefCount callback) { - statCounter.syscalls.disk.opens++; + ++statCounter.syscalls.disk.opens; #if !ASYNC_CREATE int fd = file_open(path_, flags); if (fd < 0) { debugs(79, 3, "DiskThreadsDiskFile::create: got failure (" << errno << ")"); errorOccured = true; return; } #endif Opening_FD++; ioRequestor = callback; ++inProgressIOs; #if ASYNC_CREATE aioOpen(path_, flags, mode, DiskThreadsDiskFile::OpenDone, this); @@ -186,41 +187,41 @@ errno = errflag; debugs(79, 0, "DiskThreadsDiskFile::openDone: " << xstrerror()); debugs(79, 1, "\t" << path_); errorOccured = true; } else { store_open_disk_fd++; commSetCloseOnExec(fd); fd_open(fd, FD_FILE, path_); } IORequestor::Pointer t = ioRequestor; --inProgressIOs; t->ioCompletedNotification(); debugs(79, 3, "DiskThreadsDiskFile::openDone: exiting"); } void DiskThreadsDiskFile::doClose() { if (fd > -1) { - statCounter.syscalls.disk.closes++; + ++statCounter.syscalls.disk.closes; #if ASYNC_CLOSE aioClose(fd); fd_close(fd); #else aioCancel(fd); file_close(fd); #endif store_open_disk_fd--; fd = -1; } } void DiskThreadsDiskFile::close() { debugs(79, 3, "DiskThreadsDiskFile::close: " << this << " closing for " << ioRequestor.getRaw()); @@ -229,41 +230,41 @@ assert (ioRequestor != NULL); ioRequestor->closeCompleted(); return; } else { debugs(79,0,HERE << "DiskThreadsDiskFile::close: " << "did NOT close because ioInProgress() is true. now what?"); } } bool DiskThreadsDiskFile::canRead() const { debugs(79, 3, "DiskThreadsDiskFile::canRead: fd is " << fd); return fd > -1; } void DiskThreadsDiskFile::write(WriteRequest * writeRequest) { debugs(79, 3, "DiskThreadsDiskFile::write: FD " << fd); - statCounter.syscalls.disk.writes++; + ++statCounter.syscalls.disk.writes; ++inProgressIOs; #if ASYNC_WRITE aioWrite(fd, writeRequest->offset, (char *)writeRequest->buf, writeRequest->len, WriteDone, new IoResult(this, writeRequest), writeRequest->free_func); #else file_write(fd, writeRequest->offset, (char *)writeRequest->buf, writeRequest->len, WriteDone, new IoResult(this, writeRequest), writeRequest->free_func); #endif } bool DiskThreadsDiskFile::canWrite() const { return fd > -1; } bool DiskThreadsDiskFile::ioInProgress() const === modified file 'src/DiskIO/DiskThreads/DiskThreadsIOStrategy.cc' --- src/DiskIO/DiskThreads/DiskThreadsIOStrategy.cc 2011-10-27 23:14:28 +0000 +++ src/DiskIO/DiskThreads/DiskThreadsIOStrategy.cc 2011-12-10 15:24:11 +0000 @@ -23,40 +23,41 @@ * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * * Copyright (c) 2003, Robert Collins */ #include "squid.h" #include "DiskThreadsDiskFile.h" #include "DiskThreadsIOStrategy.h" #include "fde.h" #include "mgr/Registration.h" +#include "StatCounters.h" /* for statfs */ #include "Store.h" void DiskThreadsIOStrategy::init(void) { if (initialised) return; squidaio_ctrl_pool = memPoolCreate("aio_ctrl", sizeof(squidaio_ctrl_t)); initialised = true; /* * We'd like to call squidaio_init() here, but the configuration * hasn't been parsed yet and we don't know how many cache_dirs * there are, which means we don't know how many threads to start. */ @@ -246,23 +247,23 @@ DiskFile::Pointer DiskThreadsIOStrategy::newFile (char const *path) { if (shedLoad()) { return NULL; } return new DiskThreadsDiskFile (path, this); } bool DiskThreadsIOStrategy::unlinkdUseful() const { return false; } void DiskThreadsIOStrategy::unlinkFile(char const *path) { - statCounter.syscalls.disk.unlinks++; + ++statCounter.syscalls.disk.unlinks; aioUnlink(path, NULL, NULL); } === modified file 'src/DiskIO/IpcIo/IpcIoFile.cc' --- src/DiskIO/IpcIo/IpcIoFile.cc 2011-10-28 01:07:48 +0000 +++ src/DiskIO/IpcIo/IpcIoFile.cc 2011-12-10 15:24:30 +0000 @@ -1,39 +1,40 @@ /* * $Id$ * * DEBUG: section 47 Store Directory Routines */ #include "config.h" #include "base/RunnersRegistry.h" #include "base/TextException.h" #include "DiskIO/IORequestor.h" #include "DiskIO/IpcIo/IpcIoFile.h" #include "DiskIO/ReadRequest.h" #include "DiskIO/WriteRequest.h" #include "ipc/Messages.h" #include "ipc/Port.h" #include "ipc/Queue.h" #include "ipc/StrandSearch.h" #include "ipc/UdsOp.h" #include "ipc/mem/Pages.h" +#include "StatCounters.h" #include "SquidTime.h" CBDATA_CLASS_INIT(IpcIoFile); /// shared memory segment path to use for IpcIoFile maps static const char *const ShmLabel = "io_file"; /// a single worker-to-disker or disker-to-worker queue capacity; up /// to 2*QueueCapacity I/O requests queued between a single worker and /// a single disker // TODO: make configurable or compute from squid.conf settings if possible static const int QueueCapacity = 1024; const double IpcIoFile::Timeout = 7; // seconds; XXX: ALL,9 may require more IpcIoFile::IpcIoFileList IpcIoFile::WaitingForOpen; IpcIoFile::IpcIoFilesMap IpcIoFile::IpcIoFiles; std::auto_ptr IpcIoFile::queue; bool IpcIoFile::DiskerHandleMoreRequestsScheduled = false; static bool DiskerOpen(const String &path, int flags, mode_t mode); @@ -611,63 +612,63 @@ } } /* XXX: disker code that should probably be moved elsewhere */ static int TheFile = -1; ///< db file descriptor static void diskerRead(IpcIoMsg &ipcIo) { if (!Ipc::Mem::GetPage(Ipc::Mem::PageId::ioPage, ipcIo.page)) { ipcIo.len = 0; debugs(47,2, HERE << "run out of shared memory pages for IPC I/O"); return; } char *const buf = Ipc::Mem::PagePointer(ipcIo.page); const ssize_t read = pread(TheFile, buf, min(ipcIo.len, Ipc::Mem::PageSize()), ipcIo.offset); - statCounter.syscalls.disk.reads++; + ++statCounter.syscalls.disk.reads; fd_bytes(TheFile, read, FD_READ); if (read >= 0) { ipcIo.xerrno = 0; const size_t len = static_cast(read); // safe because read > 0 debugs(47,8, HERE << "disker" << KidIdentifier << " read " << (len == ipcIo.len ? "all " : "just ") << read); ipcIo.len = len; } else { ipcIo.xerrno = errno; ipcIo.len = 0; debugs(47,5, HERE << "disker" << KidIdentifier << " read error: " << ipcIo.xerrno); } } static void diskerWrite(IpcIoMsg &ipcIo) { const char *const buf = Ipc::Mem::PagePointer(ipcIo.page); const ssize_t wrote = pwrite(TheFile, buf, min(ipcIo.len, Ipc::Mem::PageSize()), ipcIo.offset); - statCounter.syscalls.disk.writes++; + ++statCounter.syscalls.disk.writes; fd_bytes(TheFile, wrote, FD_WRITE); if (wrote >= 0) { ipcIo.xerrno = 0; const size_t len = static_cast(wrote); // safe because wrote > 0 debugs(47,8, HERE << "disker" << KidIdentifier << " wrote " << (len == ipcIo.len ? "all " : "just ") << wrote); ipcIo.len = len; } else { ipcIo.xerrno = errno; ipcIo.len = 0; debugs(47,5, HERE << "disker" << KidIdentifier << " write error: " << ipcIo.xerrno); } Ipc::Mem::PutPage(ipcIo.page); } void === modified file 'src/HttpHdrCc.cc' --- src/HttpHdrCc.cc 2011-10-05 00:19:46 +0000 +++ src/HttpHdrCc.cc 2011-12-09 20:34:51 +0000 @@ -15,43 +15,45 @@ * sources; see the CREDITS file for full details. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #include "squid.h" #include "base/StringArea.h" -#include "Store.h" #include "HttpHeader.h" +#include "HttpHeaderStat.h" #include "HttpHdrCc.h" +#include "StatHist.h" +#include "Store.h" #if HAVE_MAP #include #endif /* a row in the table used for parsing cache control header and statistics */ typedef struct { const char *name; http_hdr_cc_type id; HttpHeaderFieldStat stat; } HttpHeaderCcFields; /* order must match that of enum http_hdr_cc_type. The constraint is verified at initialization time */ static HttpHeaderCcFields CcAttrs[CC_ENUM_END] = { {"public", CC_PUBLIC}, {"private", CC_PRIVATE}, {"no-cache", CC_NO_CACHE}, {"no-store", CC_NO_STORE}, {"no-transform", CC_NO_TRANSFORM}, {"must-revalidate", CC_MUST_REVALIDATE}, @@ -268,39 +270,39 @@ break; } ++pcount; } } if (other.size() != 0) packerPrintf(p, (pcount ? ", " SQUIDSTRINGPH : SQUIDSTRINGPH), SQUIDSTRINGPRINT(other)); } void httpHdrCcUpdateStats(const HttpHdrCc * cc, StatHist * hist) { http_hdr_cc_type c; assert(cc); for (c = CC_PUBLIC; c < CC_ENUM_END; ++c) if (cc->isSet(c)) - statHistCount(hist, c); + hist->count(c); } void httpHdrCcStatDumper(StoreEntry * sentry, int idx, double val, double size, int count) { extern const HttpHeaderStat *dump_stat; /* argh! */ const int id = (int) val; const int valid_id = id >= 0 && id < CC_ENUM_END; const char *name = valid_id ? CcAttrs[id].name : "INVALID"; if (count || valid_id) storeAppendPrintf(sentry, "%2d\t %-20s\t %5d\t %6.2f\n", id, name, count, xdiv(count, dump_stat->ccParsedCount)); } #if !_USE_INLINE_ #include "HttpHdrCc.cci" #endif === modified file 'src/HttpHdrSc.cc' --- src/HttpHdrSc.cc 2011-12-04 01:33:38 +0000 +++ src/HttpHdrSc.cc 2011-12-09 20:35:32 +0000 @@ -22,40 +22,41 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #include "squid.h" #include "Store.h" #include "HttpHeader.h" +#include "HttpHeaderStat.h" #include "HttpHdrSc.h" #if HAVE_MAP #include #endif /* a row in the table used for parsing surrogate-control header and statistics */ typedef struct { const char *name; http_hdr_sc_type id; HttpHeaderFieldStat stat; } HttpHeaderScFields; /* this table is used for parsing surrogate control header */ /* order must match that of enum http_hdr_sc_type. The constraint is verified at initialization time */ //todo: implement constraint static const HttpHeaderFieldAttrs ScAttrs[SC_ENUM_END] = { {"no-store", (http_hdr_type)SC_NO_STORE}, {"no-store-remote", (http_hdr_type)SC_NO_STORE_REMOTE}, {"max-age", (http_hdr_type)SC_MAX_AGE}, === modified file 'src/HttpHdrScTarget.cc' --- src/HttpHdrScTarget.cc 2011-12-03 12:40:23 +0000 +++ src/HttpHdrScTarget.cc 2011-12-09 15:14:10 +0000 @@ -20,56 +20,57 @@ * sources; see the CREDITS file for full details. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #include "squid.h" #include "HttpHdrSc.h" +#include "StatHist.h" extern http_hdr_sc_type &operator++ (http_hdr_sc_type &aHeader); /* copies non-extant fields from new_sc to this sc */ void HttpHdrScTarget::mergeWith(const HttpHdrScTarget * new_sc) { assert(new_sc); /* Don't touch the target - this is used to get the operations for a * single surrogate */ if (new_sc->hasNoStore()) noStore(true); if (new_sc->hasNoStoreRemote()) noStoreRemote(true); if (new_sc->hasMaxAge() && !hasMaxAge()) { maxAge(new_sc->maxAge()); maxStale(new_sc->maxStale()); } if (new_sc->hasContent() && !hasContent()) Content(new_sc->content()); } void HttpHdrScTarget::updateStats(StatHist * hist) const { http_hdr_sc_type c; for (c = SC_NO_STORE; c < SC_ENUM_END; ++c) if (isSet(c)) - statHistCount(hist, c); + hist->count(c); } === modified file 'src/HttpHeader.cc' --- src/HttpHeader.cc 2011-12-03 12:40:23 +0000 +++ src/HttpHeader.cc 2011-12-12 18:31:54 +0000 @@ -22,43 +22,45 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #include "squid.h" #include "base64.h" #include "HttpHdrContRange.h" #include "HttpHdrCc.h" #include "HttpHdrSc.h" #include "HttpHeader.h" +#include "HttpHeaderStat.h" #include "MemBuf.h" #include "mgr/Registration.h" #include "rfc1123.h" +#include "StatHist.h" #include "Store.h" #include "TimeOrTag.h" /* * On naming conventions: * * HTTP/1.1 defines message-header as * * message-header = field-name ":" [ field-value ] CRLF * field-name = token * field-value = *( field-content | LWS ) * * HTTP/1.1 does not give a name name a group of all message-headers in a message. * Squid 1.1 seems to refer to that group _plus_ start-line as "headers". * * HttpHeader is an object that represents all message-headers in a message. * HttpHeader does not manage start-line. * * HttpHeader is implemented as a collection of header "entries". * An entry is a (field_id, field_name, field_value) triplet. @@ -353,44 +355,44 @@ httpHeaderRegisterWithCacheManager(); } void httpHeaderCleanModule(void) { httpHeaderDestroyFieldsInfo(Headers, HDR_ENUM_END); Headers = NULL; httpHdrCcCleanModule(); httpHdrScCleanModule(); } static void httpHeaderStatInit(HttpHeaderStat * hs, const char *label) { assert(hs); assert(label); memset(hs, 0, sizeof(HttpHeaderStat)); hs->label = label; - statHistEnumInit(&hs->hdrUCountDistr, 32); /* not a real enum */ - statHistEnumInit(&hs->fieldTypeDistr, HDR_ENUM_END); - statHistEnumInit(&hs->ccTypeDistr, CC_ENUM_END); - statHistEnumInit(&hs->scTypeDistr, SC_ENUM_END); + hs->hdrUCountDistr.enumInit(32); /* not a real enum */ + hs->fieldTypeDistr.enumInit(HDR_ENUM_END); + hs->ccTypeDistr.enumInit(CC_ENUM_END); + hs->scTypeDistr.enumInit(SC_ENUM_END); } /* * HttpHeader Implementation */ HttpHeader::HttpHeader() : owner (hoNone), len (0) { httpHeaderMaskInit(&mask, 0); } HttpHeader::HttpHeader(const http_hdr_owner_type anOwner): owner(anOwner), len(0) { assert(anOwner > hoNone && anOwner < hoEnd); debugs(55, 7, "init-ing hdr: " << this << " owner: " << owner); httpHeaderMaskInit(&mask, 0); } HttpHeader::HttpHeader(const HttpHeader &other): owner(other.owner), len(other.len) { @@ -423,53 +425,53 @@ HttpHeaderEntry *e; assert(owner > hoNone && owner < hoEnd); debugs(55, 7, "cleaning hdr: " << this << " owner: " << owner); PROF_start(HttpHeaderClean); /* * An unfortunate bug. The entries array is initialized * such that count is set to zero. httpHeaderClean() seems to * be called both when 'hdr' is created, and destroyed. Thus, * we accumulate a large number of zero counts for 'hdr' before * it is ever used. Can't think of a good way to fix it, except * adding a state variable that indicates whether or not 'hdr' * has been used. As a hack, just never count zero-sized header * arrays. */ if (owner <= hoReply) { if (0 != entries.count) - statHistCount(&HttpHeaderStats[owner].hdrUCountDistr, entries.count); + HttpHeaderStats[owner].hdrUCountDistr.count(entries.count); HttpHeaderStats[owner].destroyedCount++; HttpHeaderStats[owner].busyDestroyedCount += entries.count > 0; while ((e = getEntry(&pos))) { /* tmp hack to try to avoid coredumps */ if (e->id < 0 || e->id >= HDR_ENUM_END) { debugs(55, 0, "HttpHeader::clean BUG: entry[" << pos << "] is invalid (" << e->id << "). Ignored."); } else { - statHistCount(&HttpHeaderStats[owner].fieldTypeDistr, e->id); + HttpHeaderStats[owner].fieldTypeDistr.count(e->id); /* yes, this deletion leaves us in an inconsistent state */ delete e; } } } // if (owner <= hoReply) entries.clean(); httpHeaderMaskInit(&mask, 0); len = 0; PROF_stop(HttpHeaderClean); } /* append entries (also see httpHeaderUpdate) */ void HttpHeader::append(const HttpHeader * src) { const HttpHeaderEntry *e; HttpHeaderPos pos = HttpHeaderInitPos; assert(src); assert(src != this); debugs(55, 7, "appending hdr: " << this << " += " << src); @@ -1670,53 +1672,53 @@ static void httpHeaderFldsPerHdrDumper(StoreEntry * sentry, int idx, double val, double size, int count) { if (count) storeAppendPrintf(sentry, "%2d\t %5d\t %5d\t %6.2f\n", idx, (int) val, count, xpercent(count, dump_stat->destroyedCount)); } static void httpHeaderStatDump(const HttpHeaderStat * hs, StoreEntry * e) { assert(hs && e); dump_stat = hs; storeAppendPrintf(e, "\nHeader Stats: %s\n", hs->label); storeAppendPrintf(e, "\nField type distribution\n"); storeAppendPrintf(e, "%2s\t %-20s\t %5s\t %6s\n", "id", "name", "count", "#/header"); - statHistDump(&hs->fieldTypeDistr, e, httpHeaderFieldStatDumper); + hs->fieldTypeDistr.dump(e, httpHeaderFieldStatDumper); storeAppendPrintf(e, "\nCache-control directives distribution\n"); storeAppendPrintf(e, "%2s\t %-20s\t %5s\t %6s\n", "id", "name", "count", "#/cc_field"); - statHistDump(&hs->ccTypeDistr, e, httpHdrCcStatDumper); + hs->ccTypeDistr.dump(e, httpHdrCcStatDumper); storeAppendPrintf(e, "\nSurrogate-control directives distribution\n"); storeAppendPrintf(e, "%2s\t %-20s\t %5s\t %6s\n", "id", "name", "count", "#/sc_field"); - statHistDump(&hs->scTypeDistr, e, httpHdrScStatDumper); + hs->scTypeDistr.dump(e, httpHdrScStatDumper); storeAppendPrintf(e, "\nNumber of fields per header distribution\n"); storeAppendPrintf(e, "%2s\t %-5s\t %5s\t %6s\n", "id", "#flds", "count", "%total"); - statHistDump(&hs->hdrUCountDistr, e, httpHeaderFldsPerHdrDumper); + hs->hdrUCountDistr.dump(e, httpHeaderFldsPerHdrDumper); dump_stat = NULL; } void httpHeaderStoreReport(StoreEntry * e) { int i; http_hdr_type ht; assert(e); HttpHeaderStats[0].parsedCount = HttpHeaderStats[hoRequest].parsedCount + HttpHeaderStats[hoReply].parsedCount; HttpHeaderStats[0].ccParsedCount = HttpHeaderStats[hoRequest].ccParsedCount + HttpHeaderStats[hoReply].ccParsedCount; HttpHeaderStats[0].destroyedCount = HttpHeaderStats[hoRequest].destroyedCount + HttpHeaderStats[hoReply].destroyedCount; HttpHeaderStats[0].busyDestroyedCount = HttpHeaderStats[hoRequest].busyDestroyedCount + HttpHeaderStats[hoReply].busyDestroyedCount; for (i = 1; i < HttpHeaderStatCount; i++) { === added file 'src/HttpHeaderStat.h' --- src/HttpHeaderStat.h 1970-01-01 00:00:00 +0000 +++ src/HttpHeaderStat.h 2011-12-09 17:53:59 +0000 @@ -0,0 +1,32 @@ +/* + * HttpHeaderStat.h + * + * Created on: Dec 9, 2011 + * Author: kinkie + */ + +#ifndef HTTPHEADERSTAT_H_ +#define HTTPHEADERSTAT_H_ + +/* per header statistics */ + +#include "StatHist.h" +class HttpHeaderStat { +public: + const char *label; + HttpHeaderMask *owner_mask; + + StatHist hdrUCountDistr; + StatHist fieldTypeDistr; + StatHist ccTypeDistr; + StatHist scTypeDistr; + + int parsedCount; + int ccParsedCount; + int scParsedCount; + int destroyedCount; + int busyDestroyedCount; +}; + + +#endif /* HTTPHEADERSTAT_H_ */ === modified file 'src/Makefile.am' --- src/Makefile.am 2011-12-07 18:56:59 +0000 +++ src/Makefile.am 2011-12-15 06:36:47 +0000 @@ -337,40 +337,41 @@ HelperChildConfig.h \ HelperChildConfig.cc \ hier_code.h \ HierarchyLogEntry.h \ $(HTCPSOURCE) \ http.cc \ http.h \ HttpStatusCode.h \ HttpStatusLine.cc \ HttpStatusLine.h \ HttpHdrCc.h \ HttpHdrCc.cc \ HttpHdrCc.cci \ HttpHdrRange.cc \ HttpHdrSc.cc \ HttpHdrSc.h \ HttpHdrScTarget.cc \ HttpHdrScTarget.h \ HttpHdrContRange.cc \ HttpHdrContRange.h \ + HttpHeaderStat.h \ HttpHeader.cc \ HttpHeader.h \ HttpHeaderMask.h \ HttpHeaderRange.h \ HttpHeaderTools.cc \ HttpBody.h \ HttpBody.cc \ HttpControlMsg.h \ HttpMsg.cc \ HttpMsg.h \ HttpParser.cc \ HttpParser.h \ HttpReply.cc \ HttpReply.h \ HttpRequest.cc \ HttpRequest.h \ HttpRequestMethod.cc \ HttpRequestMethod.h \ HttpVersion.h \ ICP.h \ @@ -408,40 +409,43 @@ peer_digest.cc \ peer_proxy_negotiate_auth.cc \ peer_select.cc \ peer_sourcehash.cc \ peer_userhash.cc \ PeerSelectState.h \ PingData.h \ protos.h \ redirect.cc \ refresh.cc \ RemovalPolicy.cc \ RemovalPolicy.h \ send-announce.cc \ $(SBUF_SOURCE) \ $(SNMP_SOURCE) \ squid.h \ SquidMath.h \ SquidMath.cc \ SquidNew.cc \ stat.cc \ + StatCounters.h \ + StatCounters.cc \ + StatHist.h \ StatHist.cc \ String.cc \ stmem.cc \ stmem.h \ store.cc \ Store.h \ StoreFileSystem.cc \ StoreFileSystem.h \ StoreHashIndex.h \ store_io.cc \ StoreIOBuffer.h \ StoreIOState.cc \ StoreIOState.h \ store_client.cc \ StoreClient.h \ store_digest.cc \ store_dir.cc \ store_key_md5.cc \ store_log.cc \ store_rebuild.cc \ @@ -1064,40 +1068,43 @@ HttpMsg.cc \ HttpMsg.h \ HttpReply.cc \ HttpReply.h \ HttpStatusCode.h \ HttpStatusLine.cc \ HttpStatusLine.h \ mem.cc \ MemBuf.cc \ MemBuf.h \ mime_header.cc \ Packer.cc \ Packer.h \ SquidString.h \ SquidTime.h \ String.cc \ tests/stub_cache_cf.cc \ tests/stub_cache_manager.cc \ tests/stub_debug.cc \ tests/stub_HelperChildConfig.cc \ + StatCounters.h \ + StatCounters.cc \ + StatHist.h \ tests/stub_StatHist.cc \ tests/stub_store.cc \ tests/stub_store_stats.cc \ tests/testHttpReply.cc \ tests/testHttpReply.h \ tests/testMain.cc \ time.cc \ wordlist.cc nodist_tests_testHttpReply_SOURCES=\ $(TESTSOURCES) tests_testHttpReply_LDFLAGS = $(LIBADD_DL) tests_testHttpReply_LDADD=\ acl/libapi.la \ acl/libstate.la \ $(AUTH_LIBS) \ ip/libip.la \ base/libbase.la \ $(top_builddir)/lib/libmisccontainers.la \ $(top_builddir)/lib/libmiscencoding.la \ $(top_builddir)/lib/libmiscutil.la \ @@ -1141,40 +1148,42 @@ filemap.cc \ HelperChildConfig.h \ HelperChildConfig.cc \ HttpHeader.cc \ HttpHeaderTools.cc \ HttpHdrContRange.cc \ HttpHdrRange.cc \ HttpHdrCc.h \ HttpHdrCc.cc \ HttpHdrCc.cci \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ HttpMsg.cc \ HttpRequestMethod.cc \ int.cc \ list.cc \ mem_node.cc \ Packer.cc \ Parsing.cc \ SquidMath.cc \ + StatCounters.h \ + StatHist.h \ StatHist.cc \ stmem.cc \ String.cc \ store_dir.cc \ StoreIOState.cc \ StoreMeta.cc \ StoreMetaMD5.cc \ StoreMetaSTD.cc \ StoreMetaSTDLFS.cc \ StoreMetaUnpacker.cc \ StoreMetaURL.cc \ StoreMetaVary.cc \ StoreSwapLogData.cc \ store_key_md5.cc \ swap_log_op.cc \ swap_log_op.h \ SwapDir.cc \ SwapDir.h \ tests/stub_access_log.cc \ tests/stub_cache_cf.cc \ @@ -1339,40 +1348,43 @@ MemObject.cc \ mime.cc \ mime_header.cc \ neighbors.cc \ Packer.cc \ Parsing.cc \ pconn.cc \ peer_digest.cc \ peer_proxy_negotiate_auth.cc \ peer_select.cc \ peer_sourcehash.cc \ peer_userhash.cc \ redirect.cc \ refresh.cc \ RemovalPolicy.cc \ Server.cc \ $(SNMP_SOURCE) \ SquidMath.h \ SquidMath.cc \ stat.cc \ + StatCounters.h \ + StatCounters.cc \ + StatHist.h \ StatHist.cc \ stmem.cc \ store.cc \ store_client.cc \ store_digest.cc \ store_dir.cc \ store_io.cc \ store_key_md5.cc \ store_log.cc \ store_rebuild.cc \ store_swapin.cc \ store_swapmeta.cc \ store_swapout.cc \ StoreFileSystem.cc \ StoreIOState.cc \ StoreMeta.cc \ StoreMetaMD5.cc \ StoreMetaSTD.cc \ StoreMetaSTDLFS.cc \ StoreMetaUnpacker.cc \ @@ -1462,40 +1474,43 @@ HttpHdrContRange.cc \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ HttpHdrRange.cc \ HttpHeaderTools.cc \ HttpHeader.cc \ HttpMsg.cc \ HttpReply.cc \ HttpRequestMethod.cc \ HttpStatusLine.cc \ int.cc \ list.cc \ MemBuf.cc \ MemObject.cc \ mem_node.cc \ mem.cc \ Packer.cc \ Parsing.cc \ refresh.cc \ RemovalPolicy.cc \ + StatCounters.h \ + StatCounters.cc \ + StatHist.h \ StatHist.cc \ stmem.cc \ StoreFileSystem.cc \ StoreIOState.cc \ StoreMeta.cc \ StoreMetaMD5.cc \ StoreMetaSTD.cc \ StoreMetaSTDLFS.cc \ StoreMetaUnpacker.cc \ StoreMetaURL.cc \ StoreMetaVary.cc \ StoreSwapLogData.cc \ store_dir.cc \ store_io.cc \ store_key_md5.cc \ store_swapout.cc \ store_swapmeta.cc \ store.cc \ String.cc \ SwapDir.cc \ @@ -1666,40 +1681,43 @@ multicast.cc \ neighbors.cc \ Packer.cc \ Parsing.cc \ pconn.cc \ peer_digest.cc \ peer_proxy_negotiate_auth.cc \ peer_select.cc \ peer_sourcehash.cc \ peer_userhash.cc \ ProtoPort.cc \ ProtoPort.h \ redirect.cc \ refresh.cc \ RemovalPolicy.cc \ Server.cc \ $(SNMP_SOURCE) \ SquidMath.cc \ SquidMath.h \ stat.cc \ + StatCounters.h \ + StatCounters.cc \ + StatHist.h \ StatHist.cc \ stmem.cc \ store.cc \ store_client.cc \ store_digest.cc \ store_dir.cc \ store_io.cc \ store_key_md5.cc \ store_log.cc \ store_rebuild.cc \ store_swapin.cc \ store_swapmeta.cc \ store_swapout.cc \ StoreFileSystem.cc \ StoreIOState.cc \ StoreMeta.cc \ StoreMetaMD5.cc \ StoreMetaSTD.cc \ StoreMetaSTDLFS.cc \ StoreMetaUnpacker.cc \ @@ -1856,40 +1874,43 @@ multicast.cc \ neighbors.cc \ Packer.cc \ Parsing.cc \ pconn.cc \ peer_digest.cc \ peer_proxy_negotiate_auth.cc \ peer_select.cc \ peer_sourcehash.cc \ peer_userhash.cc \ ProtoPort.cc \ ProtoPort.h \ RemovalPolicy.cc \ redirect.cc \ refresh.cc \ Server.cc \ $(SNMP_SOURCE) \ SquidMath.h \ SquidMath.cc \ stat.cc \ + StatCounters.h \ + StatCounters.cc \ + StatHist.h \ StatHist.cc \ stmem.cc \ store.cc \ store_client.cc \ store_digest.cc \ store_dir.cc \ store_io.cc \ store_key_md5.cc \ store_log.cc \ store_rebuild.cc \ store_swapin.cc \ store_swapmeta.cc \ store_swapout.cc \ StoreFileSystem.cc \ StoreIOState.cc \ StoreMeta.cc \ StoreMetaMD5.cc \ StoreMetaSTD.cc \ StoreMetaSTDLFS.cc \ StoreMetaUnpacker.cc \ @@ -2042,40 +2063,43 @@ mime.cc \ mime_header.cc \ multicast.cc \ neighbors.cc \ Packer.cc \ Parsing.cc \ peer_digest.cc \ peer_proxy_negotiate_auth.cc \ peer_select.cc \ peer_sourcehash.cc \ peer_userhash.cc \ pconn.cc \ redirect.cc \ refresh.cc \ RemovalPolicy.cc \ Server.cc \ $(SNMP_SOURCE) \ SquidMath.h \ SquidMath.cc \ stat.cc \ + StatCounters.h \ + StatCounters.cc \ + StatHist.h \ StatHist.cc \ stmem.cc \ store.cc \ store_client.cc \ store_digest.cc \ store_dir.cc \ store_key_md5.cc \ store_io.cc \ store_log.cc \ store_rebuild.cc \ store_swapin.cc \ store_swapmeta.cc \ store_swapout.cc \ StoreFileSystem.cc \ StoreIOState.cc \ StoreMeta.cc \ StoreMetaMD5.cc \ StoreMetaSTD.cc \ StoreMetaSTDLFS.cc \ StoreMetaUnpacker.cc \ @@ -2266,40 +2290,43 @@ MemObject.cc \ mime.cc \ mime_header.cc \ neighbors.cc \ Packer.cc \ Parsing.cc \ pconn.cc \ peer_digest.cc \ peer_proxy_negotiate_auth.cc \ peer_select.cc \ peer_sourcehash.cc \ peer_userhash.cc \ redirect.cc \ refresh.cc \ RemovalPolicy.cc \ Server.cc \ $(SNMP_SOURCE) \ SquidMath.h \ SquidMath.cc \ stat.cc \ + StatCounters.h \ + StatCounters.cc \ + StatHist.h \ StatHist.cc \ stmem.cc \ store.cc \ store_client.cc \ store_digest.cc \ store_dir.cc \ store_io.cc \ store_key_md5.cc \ store_log.cc \ store_rebuild.cc \ store_swapin.cc \ store_swapmeta.cc \ store_swapout.cc \ StoreFileSystem.cc \ StoreIOState.cc \ StoreMeta.cc \ StoreMetaMD5.cc \ StoreMetaSTD.cc \ StoreMetaSTDLFS.cc \ StoreMetaUnpacker.cc \ @@ -2381,40 +2408,43 @@ HttpHdrCc.h \ HttpHdrCc.cc \ HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrRange.cc \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ HttpHeaderTools.cc \ HttpHeader.cc \ HttpMsg.cc \ HttpRequestMethod.cc \ int.cc \ list.cc \ mem.cc \ mem_node.cc \ MemBuf.cc \ Packer.cc \ Parsing.cc \ RemovalPolicy.cc \ refresh.cc \ + StatCounters.h \ + StatCounters.cc \ + StatHist.h \ StatHist.cc \ stmem.cc \ store.cc \ store_dir.cc \ store_io.cc \ store_swapout.cc \ StoreIOState.cc \ StoreMeta.cc \ StoreMetaMD5.cc \ StoreMetaSTD.cc \ StoreMetaSTDLFS.cc \ StoreMetaUnpacker.cc \ StoreMetaURL.cc \ StoreMetaVary.cc \ StoreSwapLogData.cc \ store_key_md5.cc \ String.cc \ SwapDir.cc \ tests/CapturingStoreEntry.h \ tests/stub_access_log.cc \ @@ -2613,40 +2643,43 @@ String.cc \ tests/stub_debug.cc \ tests/stub_client_side_request.cc \ tests/stub_http.cc \ mem_node.cc \ stmem.cc \ tests/stub_mime.cc \ HttpHeaderTools.cc \ HttpHeader.cc \ mem.cc \ ClientInfo.h \ MemBuf.cc \ HttpHdrContRange.cc \ Packer.cc \ HttpHdrCc.h \ HttpHdrCc.cc \ HttpHdrCc.cci \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ url.cc \ + StatCounters.h \ + StatCounters.cc \ + StatHist.h \ StatHist.cc \ HttpHdrRange.cc \ ETag.cc \ tests/stub_errorpage.cc \ tests/stub_HttpRequest.cc \ tests/stub_access_log.cc \ refresh.cc \ tests/stub_store_client.cc \ tests/stub_tools.cc \ tests/testStoreSupport.cc \ tests/testStoreSupport.h \ time.cc \ URLScheme.cc \ wordlist.cc \ $(DISKIO_SOURCE) nodist_tests_testUfs_SOURCES = \ $(TESTSOURCES) \ $(DISKIO_GEN_SOURCE) \ SquidMath.cc \ @@ -2706,40 +2739,43 @@ HttpHdrCc.cc \ HttpHdrContRange.cc \ HttpHdrRange.cc \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ HttpHeader.cc \ HttpHeaderTools.cc \ HttpMsg.cc \ HttpReply.cc \ HttpRequestMethod.cc \ HttpStatusLine.cc \ int.cc \ list.cc \ mem.cc \ MemBuf.cc \ MemObject.cc \ mem_node.cc \ Packer.cc \ Parsing.cc \ RemovalPolicy.cc \ + StatCounters.h \ + StatCounters.cc \ + StatHist.h \ StatHist.cc \ stmem.cc \ store.cc \ StoreFileSystem.cc \ StoreIOState.cc \ StoreMeta.cc \ StoreMetaMD5.cc \ StoreMetaSTD.cc \ StoreMetaSTDLFS.cc \ StoreMetaURL.cc \ StoreMetaUnpacker.cc \ StoreMetaVary.cc \ StoreSwapLogData.cc \ store_dir.cc \ store_io.cc \ store_key_md5.cc \ store_swapmeta.cc \ store_swapout.cc \ String.cc \ SwapDir.cc \ @@ -2874,40 +2910,43 @@ cbdata.cc \ String.cc \ tests/stub_client_side_request.cc \ tests/stub_http.cc \ mem_node.cc \ stmem.cc \ tests/stub_mime.cc \ HttpHeaderTools.cc \ HttpHeader.cc \ mem.cc \ ClientInfo.h \ MemBuf.cc \ HttpHdrContRange.cc \ Packer.cc \ HttpHdrCc.h \ HttpHdrCc.cc \ HttpHdrCc.cci \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ url.cc \ + StatCounters.h \ + StatCounters.cc \ + StatHist.h \ StatHist.cc \ HttpHdrRange.cc \ ETag.cc \ tests/stub_errorpage.cc \ tests/stub_HttpRequest.cc \ tests/stub_access_log.cc \ refresh.cc \ tests/stub_MemStore.cc \ tests/stub_Port.cc \ tests/stub_store_client.cc \ tests/stub_store_stats.cc \ tests/stub_tools.cc \ tests/stub_UdsOp.cc \ tests/testStoreSupport.cc \ tests/testStoreSupport.h \ time.cc \ URLScheme.cc \ wordlist.cc \ $(DISKIO_SOURCE) @@ -3009,40 +3048,43 @@ tests/stub_comm.cc \ tests/stub_debug.cc \ tests/stub_client_side_request.cc \ tests/stub_http.cc \ mem_node.cc \ stmem.cc \ tests/stub_mime.cc \ HttpHeaderTools.cc \ HttpHeader.cc \ mem.cc \ ClientInfo.h \ MemBuf.cc \ HttpHdrContRange.cc \ Packer.cc \ HttpHdrCc.h \ HttpHdrCc.cc \ HttpHdrCc.cci \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ url.cc \ + StatCounters.h \ + StatCounters.cc \ + StatHist.h \ StatHist.cc \ HttpHdrRange.cc \ ETag.cc \ tests/stub_errorpage.cc \ tests/stub_HttpRequest.cc \ tests/stub_access_log.cc \ refresh.cc \ tests/stub_store_client.cc \ tests/stub_store_stats.cc \ tests/stub_tools.cc \ tests/testStoreSupport.cc \ tests/testStoreSupport.h \ time.cc \ URLScheme.cc \ wordlist.cc \ $(DISKIO_SOURCE) nodist_tests_testNull_SOURCES = \ $(TESTSOURCES) \ $(DISKIO_GEN_SOURCE) @@ -3159,40 +3201,43 @@ mime_header.cc \ neighbors.cc \ Packer.cc \ Parsing.cc \ pconn.cc \ peer_digest.cc \ peer_proxy_negotiate_auth.cc \ peer_select.cc \ peer_sourcehash.cc \ peer_userhash.cc \ ProtoPort.cc \ ProtoPort.h \ redirect.cc \ refresh.cc \ RemovalPolicy.cc \ Server.cc \ $(SNMP_SOURCE) \ SquidMath.h \ SquidMath.cc \ stat.cc \ + StatCounters.h \ + StatCounters.cc \ + StatHist.h \ StatHist.cc \ stmem.cc \ store.cc \ store_client.cc \ store_digest.cc \ store_dir.cc \ store_io.cc \ store_key_md5.cc \ store_log.cc \ store_rebuild.cc \ store_swapin.cc \ store_swapmeta.cc \ store_swapout.cc \ StoreFileSystem.cc \ StoreIOState.cc \ StoreMeta.cc \ StoreMetaMD5.cc \ StoreMetaSTD.cc \ StoreMetaSTDLFS.cc \ StoreMetaUnpacker.cc \ === modified file 'src/PeerDigest.h' --- src/PeerDigest.h 2009-01-21 03:47:47 +0000 +++ src/PeerDigest.h 2011-12-15 21:17:34 +0000 @@ -23,40 +23,43 @@ * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #ifndef SQUID_PEERDIGEST_H #define SQUID_PEERDIGEST_H #include "squid.h" #if USE_CACHE_DIGESTS #include "cbdata.h" +/* for CacheDigestGuessStats */ +#include "StatCounters.h" + struct _Version { short int current; /* current version */ short int required; /* minimal version that can safely handle current version */ }; /* digest control block; used for transmission and storage */ class StoreDigestCBlock { public: Version ver; int capacity; int count; int del_count; int mask_size; unsigned char bits_per_entry; unsigned char hash_func_count; short int reserved_short; int reserved[32 - 6]; }; @@ -99,38 +102,38 @@ struct { unsigned int needed:1; /**< there were requests for this digest */ unsigned int usable:1; /**< can be used for lookups */ unsigned int requested:1; /**< in process of receiving [fresh] digest */ } flags; struct { /* all times are absolute unless augmented with _delay */ time_t initialized; /* creation */ time_t needed; /* first lookup/use by a peer */ time_t next_check; /* next scheduled check/refresh event */ time_t retry_delay; /* delay before re-checking _invalid_ digest */ time_t requested; /* requested a fresh copy of a digest */ time_t req_delay; /* last request response time */ time_t received; /* received the current copy of a digest */ time_t disabled; /* disabled for good */ } times; struct { - cd_guess_stats guess; + CacheDigestGuessStats guess; int used_count; struct { int msgs; kb_t kbytes; } sent, recv; } stats; private: CBDATA_CLASS(PeerDigest); }; extern const Version CacheDigestVer; #endif /* USE_CACHE_DIGESTS */ #endif /* SQUID_PEERDIGEST_H */ === modified file 'src/Server.cc' --- src/Server.cc 2011-11-27 12:37:35 +0000 +++ src/Server.cc 2011-12-10 15:30:19 +0000 @@ -27,40 +27,41 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #include "squid.h" #include "acl/Gadgets.h" #include "base/TextException.h" #include "comm/Connection.h" #include "comm/forward.h" #include "comm/Write.h" #include "Server.h" #include "Store.h" #include "HttpRequest.h" #include "HttpReply.h" #include "errorpage.h" #include "err_detail_type.h" +#include "StatCounters.h" #include "SquidTime.h" #if USE_ADAPTATION #include "adaptation/AccessCheck.h" #include "adaptation/Answer.h" #include "adaptation/Iterator.h" #include "base/AsyncCall.h" #endif // implemented in client_side_reply.cc until sides have a common parent extern void purgeEntriesByUrl(HttpRequest * req, const char *url); ServerStateData::ServerStateData(FwdState *theFwdState): AsyncJob("ServerStateData"), requestSender(NULL), #if USE_ADAPTATION adaptedHeadSource(NULL), adaptationAccessCheckPending(false), startedAdaptation(false), #endif @@ -348,41 +349,41 @@ if (requestSender != NULL) debugs(9,3, HERE << "fyi: request body aborted while we were sending"); fwd->dontRetry(true); // the problem is not with the server stopConsumingFrom(requestBodySource); // requestSender, if any, will notice // kids extend this } // called when we wrote request headers(!) or a part of the body void ServerStateData::sentRequestBody(const CommIoCbParams &io) { debugs(11, 5, "sentRequestBody: FD " << io.fd << ": size " << io.size << ": errflag " << io.flag << "."); debugs(32,3,HERE << "sentRequestBody called"); requestSender = NULL; if (io.size > 0) { fd_bytes(io.fd, io.size, FD_WRITE); - kb_incr(&statCounter.server.all.kbytes_out, io.size); + kb_incr(&(statCounter.server.all.kbytes_out), io.size); // kids should increment their counters } if (io.flag == COMM_ERR_CLOSING) return; if (!requestBodySource) { debugs(9,3, HERE << "detected while-we-were-sending abort"); return; // do nothing; } if (io.flag) { debugs(11, 1, "sentRequestBody error: FD " << io.fd << ": " << xstrerr(io.xerrno)); ErrorState *err; err = new ErrorState(ERR_WRITE_ERROR, HTTP_BAD_GATEWAY, fwd->request); err->xerrno = io.xerrno; fwd->fail(err); abortTransaction("I/O error while sending request body"); return; } === added file 'src/StatCounters.cc' --- src/StatCounters.cc 1970-01-01 00:00:00 +0000 +++ src/StatCounters.cc 2011-12-10 16:49:40 +0000 @@ -0,0 +1,35 @@ +/* + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + * AUTHOR: Francesco Chemolli (Harvest-derived) + * + */ + +#include "config.h" +#include "StatCounters.h" + +StatCounters statCounter; === added file 'src/StatCounters.h' --- src/StatCounters.h 1970-01-01 00:00:00 +0000 +++ src/StatCounters.h 2011-12-15 21:17:34 +0000 @@ -0,0 +1,186 @@ +/* + * AUTHOR: Francesco Chemolli (Harvest-derived) + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + * + */ +#ifndef STATCOUNTERS_H_ +#define STATCOUNTERS_H_ + +#include "StatHist.h" + +#if USE_CACHE_DIGESTS +/** statistics for cache digests and other hit "predictors" */ +class CacheDigestGuessStats { +public: + int trueHits; + int falseHits; + int trueMisses; + int falseMisses; + int closeHits; /// \todo: temporary remove it later +}; +#endif + + +/** General collection of process-wide statistics. + * + * \note if you add a field to StatCounters, + * you MUST sync statCountersInitSpecial, statCountersClean, and statCountersCopy + */ +class StatCounters { +public: + struct { + int clients; + int requests; + int hits; + int mem_hits; + int disk_hits; + int errors; + kb_t kbytes_in; + kb_t kbytes_out; + kb_t hit_kbytes_out; + StatHist missSvcTime; + StatHist nearMissSvcTime; + StatHist nearHitSvcTime; + StatHist hitSvcTime; + StatHist allSvcTime; + } client_http; + + struct { + + struct { + int requests; + int errors; + kb_t kbytes_in; + kb_t kbytes_out; + } all , http, ftp, other; + } server; + + struct { + int pkts_sent; + int queries_sent; + int replies_sent; + int pkts_recv; + int queries_recv; + int replies_recv; + int hits_sent; + int hits_recv; + int replies_queued; + int replies_dropped; + kb_t kbytes_sent; + kb_t q_kbytes_sent; + kb_t r_kbytes_sent; + kb_t kbytes_recv; + kb_t q_kbytes_recv; + kb_t r_kbytes_recv; + StatHist querySvcTime; + StatHist replySvcTime; + int query_timeouts; + int times_used; + } icp; + + struct { + int pkts_sent; + int pkts_recv; + } htcp; + + struct { + int requests; + } unlink; + + struct { + StatHist svcTime; + } dns; + + struct { + int times_used; + kb_t kbytes_sent; + kb_t kbytes_recv; + kb_t memory; + int msgs_sent; + int msgs_recv; +#if USE_CACHE_DIGESTS + + CacheDigestGuessStats guess; +#endif + + StatHist on_xition_count; + } cd; + + struct { + int times_used; + } netdb; + int page_faults; + unsigned long int select_loops; + int select_fds; + double select_time; + double cputime; + + struct timeval timestamp; + StatHist comm_icp_incoming; + StatHist comm_dns_incoming; + StatHist comm_http_incoming; + StatHist select_fds_hist; + + struct { + struct { + int opens; + int closes; + int reads; + int writes; + int seeks; + int unlinks; + } disk; + + struct { + int accepts; + int sockets; + int connects; + int binds; + int closes; + int reads; + int writes; + int recvfroms; + int sendtos; + } sock; + int selects; + } syscalls; + int aborted_requests; + + struct { + int files_cleaned; + int outs; + int ins; + } swap; + +private: +}; + +extern StatCounters statCounter; + +#endif /* STATCOUNTERS_H_ */ === modified file 'src/StatHist.cc' --- src/StatHist.cc 2010-12-16 02:25:55 +0000 +++ src/StatHist.cc 2011-12-15 23:07:34 +0000 @@ -1,327 +1,287 @@ /* - * $Id$ - * * DEBUG: section 62 Generic Histogram * AUTHOR: Duane Wessels * * SQUID Web Proxy Cache http://www.squid-cache.org/ * ---------------------------------------------------------- * * Squid is the result of efforts by numerous individuals from * the Internet community; see the CONTRIBUTORS file for full * details. Many organizations have provided support for Squid's * development; see the SPONSORS file for full details. Squid is * Copyrighted (C) 2001 by the Regents of the University of * California; see the COPYRIGHT file for full details. Squid * incorporates software developed and/or copyrighted by other * sources; see the CREDITS file for full details. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ -/* - * Important restrictions on val_in and val_out functions: - * - * - val_in: ascending, defined on [0, oo), val_in(0) == 0; - * - val_out: x == val_out(val_in(x)) where val_in(x) is defined - * - * In practice, the requirements are less strict, - * but then it gets hard to define them without math notation. - * val_in is applied after offseting the value but before scaling - * See log and linear based histograms for examples - */ - -#include "squid.h" -#include "Store.h" +#include "config.h" +#include "StatHist.h" /* Local functions */ -static void statHistInit(StatHist * H, int capacity, hbase_f * val_in, hbase_f * val_out, double min, double max); -static int statHistBin(const StatHist * H, double v); -static double statHistVal(const StatHist * H, int bin); static StatHistBinDumper statHistBinDumper; namespace Math { hbase_f Log; hbase_f Exp; hbase_f Null; }; /* low level init, higher level functions has less params */ -static void -statHistInit(StatHist * H, int capacity, hbase_f * val_in, hbase_f * val_out, double min, double max) +void +StatHist::init(int capacity_, hbase_f * val_in_, hbase_f * val_out_, double min_, double max_) { - assert(H); - assert(capacity > 0); - assert(val_in && val_out); + assert(capacity_ > 0); + assert(val_in_ && val_out_); /* check before we divide to get scale */ - assert(val_in(max - min) > 0); - H->bins = (int *)xcalloc(capacity, sizeof(int)); - H->min = min; - H->max = max; - H->capacity = capacity; - H->scale = capacity / val_in(max - min); - H->val_in = val_in; - H->val_out = val_out; - - /* HPUX users: If you get one of the assertions below, please send - * [at least] the values of all variables involved in the assertions - * when reporting a bug! - */ + assert(val_in_(max_ - min_) > 0); + min = min_; + max = max_; + capacity = capacity_; + val_in = val_in_; + val_out = val_out_; + bins = static_cast(xcalloc(capacity, sizeof(int))); + scale = capacity / val_in(max - min); /* check that functions are valid */ /* a min value should go into bin[0] */ - assert(statHistBin(H, min) == 0); + assert(findBin(min) == 0); /* a max value should go into the last bin */ - assert(statHistBin(H, max) == H->capacity - 1); + assert(findBin(max) == capacity - 1); /* it is hard to test val_out, here is a crude test */ - assert(((int) floor(0.99 + statHistVal(H, 0) - min)) == 0); + assert(((int) floor(0.99 + val(0) - min)) == 0); } void -statHistClean(StatHist * H) +StatHist::clear() { - xfree(H->bins); - H->bins = NULL; + for(int i=0;icapacity << " " << Orig->capacity); - assert(Dest->capacity == Orig->capacity); - debugs(62, 3, "statHistCopy: min " << Dest->min << " " << Orig->min ); - assert(Dest->min == Orig->min); - debugs(62, 3, "statHistCopy: max " << Dest->max << " " << Orig->max ); - assert(Dest->max == Orig->max); - debugs(62, 3, "statHistCopy: scale " << Dest->scale << " " << Orig->scale ); - assert(fabs(Dest->scale - Orig->scale) < 0.0000001); - assert(Dest->val_in == Orig->val_in); - assert(Dest->val_out == Orig->val_out); - /* actual copy */ - debugs(62, 3, "statHistCopy: copying " << - (long int) (Dest->capacity * sizeof(*Dest->bins)) << " bytes to " << - Dest->bins << " from " << Orig->bins); - - memcpy(Dest->bins, Orig->bins, Dest->capacity * sizeof(*Dest->bins)); + if (bins != NULL) { + xfree(bins); + bins = NULL; + } } -/* - * same as statHistCopy but will do nothing if capacities do not match; the - * latter happens, for example, when #peers changes during reconfiguration; - * if it happens too often we should think about more general solution.. - */ -void -statHistSafeCopy(StatHist * Dest, const StatHist * Orig) +StatHist& +StatHist::operator =(const StatHist & src) { - assert(Dest && Orig); - assert(Dest->bins); + assert(src.bins != NULL); // TODO: remove after initializing bins at construction time + if (capacity != src.capacity) { + // need to resize. + xfree(bins); + bins = static_cast(xcalloc(src.capacity, sizeof(int))); + capacity=src.capacity; - if (Dest->capacity == Orig->capacity) - statHistCopy(Dest, Orig); + } + min=src.min; + max=src.max; + scale=src.scale; + val_in=src.val_in; + val_out=src.val_out; + memcpy(bins,src.bins,capacity*sizeof(*bins)); + return *this; } void -statHistCount(StatHist * H, double val) +StatHist::count(double val) { - const int bin = statHistBin(H, val); - assert(H->bins); /* make sure it got initialized */ - assert(0 <= bin && bin < H->capacity); - H->bins[bin]++; + const int bin = findBin(val); + assert(bins); /* make sure it got initialized */ + assert(0 <= bin && bin < capacity); + ++bins[bin]; } -static int -statHistBin(const StatHist * H, double v) +int +StatHist::findBin(double v) { int bin; -#if BROKEN_STAT_HIST_BIN - - return 0; - /* NOTREACHED */ -#endif - v -= H->min; /* offset */ + v -= min; /* offset */ if (v <= 0.0) /* too small */ return 0; - bin = (int) floor(H->scale * H->val_in(v) + 0.5); + bin = (int) floor(scale * val_in(v) + 0.5); if (bin < 0) /* should not happen */ - bin = 0; + return 0; - if (bin >= H->capacity) /* too big */ - bin = H->capacity - 1; + if (bin >= capacity) /* too big */ + bin = capacity - 1; return bin; } -static double -statHistVal(const StatHist * H, int bin) +double +StatHist::val(int bin) const { - return H->val_out((double) bin / H->scale) + H->min; + return val_out((double) bin / scale) + min; } double -statHistDeltaMedian(const StatHist * A, const StatHist * B) +statHistDeltaMedian(const StatHist & A, const StatHist & B) { return statHistDeltaPctile(A, B, 0.5); } double -statHistDeltaPctile(const StatHist * A, const StatHist * B, double pctile) +statHistDeltaPctile(const StatHist & A, const StatHist & B, double pctile) +{ + return A.deltaPctile(B, pctile); +} + +double +StatHist::deltaPctile(const StatHist & B, double pctile) const { int i; int s1 = 0; int h = 0; int a = 0; int b = 0; int I = 0; - int J = A->capacity; + int J = capacity; int K; double f; - int *D = (int *)xcalloc(A->capacity, sizeof(int)); - assert(A->capacity == B->capacity); - for (i = 0; i < A->capacity; i++) { - D[i] = B->bins[i] - A->bins[i]; + assert(capacity == B.capacity); + + int *D = static_cast(xcalloc(capacity, sizeof(int))); + + for (i = 0; i < capacity; ++i) { + D[i] = B.bins[i] - bins[i]; assert(D[i] >= 0); } - for (i = 0; i < A->capacity; i++) + for (i = 0; i < capacity; ++i) s1 += D[i]; h = int(s1 * pctile); - for (i = 0; i < A->capacity; i++) { + for (i = 0; i < capacity; ++i) { J = i; b += D[J]; if (a <= h && h <= b) break; I = i; a += D[I]; } xfree(D); if (s1 == 0) return 0.0; if (a > h) return 0.0; if (a >= b) return 0.0; if (I >= J) return 0.0; f = (h - a) / (b - a); K = (int) floor(f * (double) (J - I) + I); - return statHistVal(A, K); + return val(K); } static void statHistBinDumper(StoreEntry * sentry, int idx, double val, double size, int count) { if (count) storeAppendPrintf(sentry, "\t%3d/%f\t%d\t%f\n", idx, val, count, count / size); } void -statHistDump(const StatHist * H, StoreEntry * sentry, StatHistBinDumper * bd) +StatHist::dump(StoreEntry * sentry, StatHistBinDumper * bd) const { int i; - double left_border = H->min; + double left_border = min; if (!bd) bd = statHistBinDumper; - for (i = 0; i < H->capacity; i++) { - const double right_border = statHistVal(H, i + 1); + for (i = 0; i < capacity; ++i) { + const double right_border = val(i + 1); assert(right_border - left_border > 0.0); - bd(sentry, i, left_border, right_border - left_border, H->bins[i]); + bd(sentry, i, left_border, right_border - left_border, bins[i]); left_border = right_border; } } /* log based histogram */ double Math::Log(double x) { assert((x + 1.0) >= 0.0); return log(x + 1.0); } double Math::Exp(double x) { return exp(x) - 1.0; } void -statHistLogInit(StatHist * H, int capacity, double min, double max) +StatHist::logInit(int capacity, double min, double max) { - statHistInit(H, capacity, Math::Log, Math::Exp, min, max); + init(capacity, Math::Log, Math::Exp, min, max); } /* linear histogram for enums */ /* we want to be have [-1,last_enum+1] range to track out of range enums */ double Math::Null(double x) { return x; } void -statHistEnumInit(StatHist * H, int last_enum) +StatHist::enumInit(int last_enum) { - statHistInit(H, last_enum + 3, Math::Null, Math::Null, (double) -1, (double) (last_enum + 1 + 1)); + init(last_enum + 3, Math::Null, Math::Null, -1.0, (2.0 + last_enum)); } void statHistEnumDumper(StoreEntry * sentry, int idx, double val, double size, int count) { if (count) storeAppendPrintf(sentry, "%2d\t %5d\t %5d\n", idx, (int) val, count); } void -statHistIntInit(StatHist * H, int n) -{ - statHistInit(H, n, Math::Null, Math::Null, (double) 0, (double) n - 1); -} - -void statHistIntDumper(StoreEntry * sentry, int idx, double val, double size, int count) { if (count) storeAppendPrintf(sentry, "%9d\t%9d\n", (int) val, count); } === added file 'src/StatHist.h' --- src/StatHist.h 1970-01-01 00:00:00 +0000 +++ src/StatHist.h 2011-12-15 23:06:11 +0000 @@ -0,0 +1,127 @@ +/* + * AUTHOR: Francesco Chemolli + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + */ + +#ifndef STATHIST_H_ +#define STATHIST_H_ + +/* for StoreEntry */ +#include "Store.h" + + +/// function signature for in/out StatHist adaptation +typedef double hbase_f(double); + +/// function signature for StatHist dumping functions +typedef void StatHistBinDumper(StoreEntry *, int idx, double val, double size, int count); + +/** Generic histogram class + * + * see important comments on hbase_f restrictions in StatHist.cc + */ +class StatHist { +public: + /** + * \note the default constructor doesn't fully initialize. + * you have to call one of the *init functions to specialize the + * histogram + * \todo merge functionality from the *init functions to the constructor and + * drop these + * \todo specialize the class in a small hierarchy so that all + * relevant initializations are done at build-time + */ + StatHist() : scale(1.0) {}; + StatHist(const StatHist&); + StatHist &operator=(const StatHist &); + virtual ~StatHist(); + /** clear the contents of the histograms + * + * \todo remove: this function has been replaced in its purpose + * by the destructor + */ + void clear(); + + /** Calculate the percentile for value pctile for the difference between + * this and the supplied histogram. + */ + double deltaPctile(const StatHist &B, double pctile) const; + /** obtain the output-transformed value from the specified bin + * + */ + double val(int bin) const; + /** increment the counter for the histogram entry + * associated to the supplied value + */ + void count(double val); + /** iterate the supplied bd function over the histogram values + */ + void dump(StoreEntry *sentry, StatHistBinDumper * bd) const; + /** Initialize the Histogram using a logarithmic values distribution + * + */ + void logInit(int capacity, double min, double max); + /** initialize the histogram to count occurrences in an enum-represented set + * + */ + void enumInit(int last_enum); +protected: + /** low-level initialize function. called by *Init high-level functions + * \note Important restrictions on val_in and val_out functions: + * + * - val_in: ascending, defined on [0, oo), val_in(0) == 0; + * - val_out: x == val_out(val_in(x)) where val_in(x) is defined + * + * In practice, the requirements are less strict, + * but then it gets hard to define them without math notation. + * val_in is applied after offseting the value but before scaling + * See log and linear based histograms for examples + */ + void init(int capacity, hbase_f * val_in, hbase_f * val_out, double min, double max); + /// find what entry in the histogram corresponds to v, by applying + /// the preset input transformation function + int findBin(double v); + /// the histogram counters + int *bins; + int capacity; + /// minimum value to be stored, corresponding to the first bin + double min; + /// value of the maximum counter in the histogram + double max; + /// scaling factor when looking for a bin + double scale; + hbase_f *val_in; /* e.g., log() for log-based histogram */ + hbase_f *val_out; /* e.g., exp() for log based histogram */ +}; + +double statHistDeltaMedian(const StatHist & A, const StatHist & B); +double statHistDeltaPctile(const StatHist & A, const StatHist & B, double pctile); +StatHistBinDumper statHistEnumDumper; +StatHistBinDumper statHistIntDumper; + +#endif /* STATHIST_H_ */ === modified file 'src/client_db.cc' --- src/client_db.cc 2011-11-18 07:48:25 +0000 +++ src/client_db.cc 2011-12-10 15:26:57 +0000 @@ -23,40 +23,41 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #include "squid.h" #include "event.h" #include "format/Token.h" #include "ClientInfo.h" #include "ip/Address.h" #include "mgr/Registration.h" #include "SquidMath.h" #include "SquidTime.h" +#include "StatCounters.h" #include "Store.h" static hash_table *client_table = NULL; static ClientInfo *clientdbAdd(const Ip::Address &addr); static FREE clientdbFreeItem; static void clientdbStartGC(void); static void clientdbScheduledGC(void *); #if USE_DELAY_POOLS static int max_clients = 32768; #else static int max_clients = 32; #endif static int cleanup_running = 0; static int cleanup_scheduled = 0; static int cleanup_removed; @@ -75,41 +76,41 @@ c = (ClientInfo *)memAllocate(MEM_CLIENT_INFO); c->hash.key = addr.NtoA(buf,MAX_IPSTRLEN); c->addr = addr; #if USE_DELAY_POOLS /* setup default values for client write limiter */ c->writeLimitingActive=false; c->writeSpeedLimit=0; c->bucketSize = 0; c->firstTimeConnection=true; c->quotaQueue = NULL; c->rationedQuota = 0; c->rationedCount = 0; c->selectWaiting = false; c->eventWaiting = false; /* get current time */ getCurrentTime(); c->prevTime=current_dtime;/* put current time to have something sensible here */ #endif hash_join(client_table, &c->hash); - statCounter.client_http.clients++; + ++statCounter.client_http.clients; if ((statCounter.client_http.clients > max_clients) && !cleanup_running && cleanup_scheduled < 2) { cleanup_scheduled++; eventAdd("client_db garbage collector", clientdbScheduledGC, NULL, 90, 0); } return c; } static void clientdbRegisterWithCacheManager(void) { Mgr::RegisterAction("client_list", "Cache Client List", clientdbDump, 0, 1); } void clientdbInit(void) { clientdbRegisterWithCacheManager(); @@ -387,41 +388,41 @@ if (c->n_established) continue; if (age < 24 * 3600 && c->Http.n_requests > 100) continue; if (age < 4 * 3600 && (c->Http.n_requests > 10 || c->Icp.n_requests > 10)) continue; if (age < 5 * 60 && (c->Http.n_requests > 1 || c->Icp.n_requests > 1)) continue; if (age < 60) continue; hash_remove_link(client_table, &c->hash); clientdbFreeItem(c); - statCounter.client_http.clients--; + --statCounter.client_http.clients; cleanup_removed++; } if (bucket < CLIENT_DB_HASH_SIZE) eventAdd("client_db garbage collector", clientdbGC, NULL, 0.15, 0); else { bucket = 0; cleanup_running = 0; max_clients = statCounter.client_http.clients * 3 / 2; if (!cleanup_scheduled) { cleanup_scheduled = 1; eventAdd("client_db garbage collector", clientdbScheduledGC, NULL, 6 * 3600, 0); } debugs(49, 2, "clientdbGC: Removed " << cleanup_removed << " entries"); } } === modified file 'src/client_side.cc' --- src/client_side.cc 2011-12-06 14:06:38 +0000 +++ src/client_side.cc 2011-12-15 21:17:34 +0000 @@ -100,40 +100,42 @@ #include "clientStream.h" #include "comm.h" #include "comm/Connection.h" #include "CommCalls.h" #include "comm/Loops.h" #include "comm/Write.h" #include "comm/TcpAcceptor.h" #include "eui/Config.h" #include "fde.h" #include "HttpHdrContRange.h" #include "HttpReply.h" #include "HttpRequest.h" #include "ident/Config.h" #include "ident/Ident.h" #include "ipc/FdNotes.h" #include "ipc/StartListening.h" #include "MemBuf.h" #include "MemObject.h" #include "ProtoPort.h" #include "rfc1738.h" +#include "StatCounters.h" +#include "StatHist.h" #include "SquidTime.h" #if USE_SSL #include "ssl/context_storage.h" #include "ssl/helper.h" #include "ssl/support.h" #include "ssl/gadgets.h" #endif #if USE_SSL_CRTD #include "ssl/crtd_message.h" #include "ssl/certificate_db.h" #endif #include "Store.h" #include "TimeOrTag.h" #if HAVE_LIMITS #include #endif #if LINGERING_CLOSE #define comm_close comm_lingering_close @@ -408,84 +410,84 @@ /// wroteControlMsg() wrapper: ClientSocketContext is not an AsyncJob void ClientSocketContext::WroteControlMsg(const Comm::ConnectionPointer &conn, char *bufnotused, size_t size, comm_err_t errflag, int xerrno, void *data) { ClientSocketContext *context = static_cast(data); context->wroteControlMsg(conn, bufnotused, size, errflag, xerrno); } #if USE_IDENT static void clientIdentDone(const char *ident, void *data) { ConnStateData *conn = (ConnStateData *)data; xstrncpy(conn->clientConnection->rfc931, ident ? ident : dash_str, USER_IDENT_SZ); } #endif void clientUpdateStatCounters(log_type logType) { - statCounter.client_http.requests++; + ++statCounter.client_http.requests; if (logTypeIsATcpHit(logType)) - statCounter.client_http.hits++; + ++statCounter.client_http.hits; if (logType == LOG_TCP_HIT) - statCounter.client_http.disk_hits++; + ++statCounter.client_http.disk_hits; else if (logType == LOG_TCP_MEM_HIT) - statCounter.client_http.mem_hits++; + ++statCounter.client_http.mem_hits; } void clientUpdateStatHistCounters(log_type logType, int svc_time) { - statHistCount(&statCounter.client_http.all_svc_time, svc_time); + statCounter.client_http.allSvcTime.count(svc_time); /** * The idea here is not to be complete, but to get service times * for only well-defined types. For example, we don't include * LOG_TCP_REFRESH_FAIL because its not really a cache hit * (we *tried* to validate it, but failed). */ switch (logType) { case LOG_TCP_REFRESH_UNMODIFIED: - statHistCount(&statCounter.client_http.nh_svc_time, svc_time); + statCounter.client_http.nearHitSvcTime.count(svc_time); break; case LOG_TCP_IMS_HIT: - statHistCount(&statCounter.client_http.nm_svc_time, svc_time); + statCounter.client_http.nearMissSvcTime.count(svc_time); break; case LOG_TCP_HIT: case LOG_TCP_MEM_HIT: case LOG_TCP_OFFLINE_HIT: - statHistCount(&statCounter.client_http.hit_svc_time, svc_time); + statCounter.client_http.hitSvcTime.count(svc_time); break; case LOG_TCP_MISS: case LOG_TCP_CLIENT_REFRESH_MISS: - statHistCount(&statCounter.client_http.miss_svc_time, svc_time); + statCounter.client_http.missSvcTime.count(svc_time); break; default: /* make compiler warnings go away */ break; } } bool clientPingHasFinished(ping_data const *aPing) { if (0 != aPing->stop.tv_sec && 0 != aPing->start.tv_sec) return true; return false; } void clientUpdateHierCounters(HierarchyLogEntry * someEntry) { @@ -495,42 +497,41 @@ #if USE_CACHE_DIGESTS case CD_PARENT_HIT: case CD_SIBLING_HIT: statCounter.cd.times_used++; break; #endif case SIBLING_HIT: case PARENT_HIT: case FIRST_PARENT_MISS: case CLOSEST_PARENT_MISS: statCounter.icp.times_used++; i = &someEntry->ping; if (clientPingHasFinished(i)) - statHistCount(&statCounter.icp.query_svc_time, - tvSubUsec(i->start, i->stop)); + statCounter.icp.querySvcTime.count(tvSubUsec(i->start, i->stop)); if (i->timeout) statCounter.icp.query_timeouts++; break; case CLOSEST_PARENT: case CLOSEST_DIRECT: statCounter.netdb.times_used++; break; default: break; } } void ClientHttpRequest::updateCounters() @@ -2816,41 +2817,41 @@ } assert(Comm::IsConnOpen(clientConnection)); assert(io.conn->fd == clientConnection->fd); /* * Don't reset the timeout value here. The timeout value will be * set to Config.Timeout.request by httpAccept() and * clientWriteComplete(), and should apply to the request as a * whole, not individual read() calls. Plus, it breaks our * lame half-close detection */ if (connReadWasError(io.flag, io.size, io.xerrno)) { notifyAllContexts(io.xerrno); io.conn->close(); return; } if (io.flag == COMM_OK) { if (io.size > 0) { - kb_incr(&statCounter.client_http.kbytes_in, io.size); + kb_incr(&(statCounter.client_http.kbytes_in), io.size); // may comm_close or setReplyToError if (!handleReadData(io.buf, io.size)) return; } else if (io.size == 0) { debugs(33, 5, HERE << io.conn << " closed?"); if (connFinishedWithConn(io.size)) { clientConnection->close(); return; } /* It might be half-closed, we can't tell */ fd_table[io.conn->fd].flags.socket_eof = 1; commMarkHalfClosed(io.conn->fd); fd_note(io.conn->fd, "half-closed"); === modified file 'src/comm.cc' --- src/comm.cc 2011-12-04 05:43:42 +0000 +++ src/comm.cc 2011-12-10 15:30:14 +0000 @@ -41,40 +41,41 @@ #include "comm/AcceptLimiter.h" #include "comm/comm_internal.h" #include "comm/Connection.h" #include "comm/IoCallback.h" #include "comm/Loops.h" #include "comm/Write.h" #include "comm/TcpAcceptor.h" #include "CommIO.h" #include "CommRead.h" #include "MemBuf.h" #include "pconn.h" #include "SquidTime.h" #include "CommCalls.h" #include "DescriptorSet.h" #include "icmp/net_db.h" #include "ip/Address.h" #include "ip/Intercept.h" #include "ip/QosConfig.h" #include "ip/tools.h" #include "ClientInfo.h" +#include "StatCounters.h" #if USE_SSL #include "ssl/support.h" #endif #include "cbdata.h" #if _SQUID_CYGWIN_ #include #endif #ifdef HAVE_NETINET_TCP_H #include #endif /* * New C-like simple comm code. This stuff is a mess and doesn't really buy us anything. */ static void commStopHalfClosedMonitor(int fd); static IOCB commHalfClosedReader; static void comm_init_opened(const Comm::ConnectionPointer &conn, tos_t tos, nfmark_t nfmark, const char *note, struct addrinfo *AI); static int comm_apply_flags(int new_socket, Ip::Address &addr, int flags, struct addrinfo *AI); === modified file 'src/comm/ModDevPoll.cc' --- src/comm/ModDevPoll.cc 2011-09-02 12:35:57 +0000 +++ src/comm/ModDevPoll.cc 2011-12-10 17:06:28 +0000 @@ -42,40 +42,42 @@ * on August 11, 2010 at 3pm (GMT+0100 Europe/London). * * Last modified 2010-10-08 */ /* * There are several poll types in Squid, ALL of which are compiled and linked * in. Thus conditional compile-time flags are used to prevent the different * modules from creating several versions of the same function simultaneously. */ #include "config.h" #if USE_DEVPOLL #include "squid.h" #include "comm/Loops.h" #include "fde.h" #include "mgr/Registration.h" #include "SquidTime.h" +#include "StatCounters.h" +#include "StatHist.h" #include "Store.h" #if HAVE_SYS_DEVPOLL_H /* Solaris /dev/poll support, see "man -s 7D poll" */ #include #endif #define DEBUG_DEVPOLL 0 /* OPEN_MAX is defined in , presumably included by sys/devpoll.h */ #define DEVPOLL_UPDATESIZE OPEN_MAX #define DEVPOLL_QUERYSIZE OPEN_MAX /* TYPEDEFS */ typedef short pollfd_events_t; /* type of pollfd.events from sys/poll.h */ /* STRUCTURES */ /** \brief Current state */ struct _devpoll_state { pollfd_events_t state; /**< current known state of file handle */ @@ -155,44 +157,43 @@ debugs( 5, DEBUG_DEVPOLL ? 0 : 8, HERE << "FD " << fd << ", events=" << events ); /* Is the array already full and in need of flushing? */ if (devpoll_update.cur != -1 && (devpoll_update.cur == devpoll_update.size)) comm_flush_updates(); /* Push new event onto array */ devpoll_update.cur++; devpoll_update.pfds[devpoll_update.cur].fd = fd; devpoll_update.pfds[devpoll_update.cur].events = events; devpoll_update.pfds[devpoll_update.cur].revents = 0; } static void commIncomingStats(StoreEntry *sentry) { - StatCounters *f = &statCounter; storeAppendPrintf(sentry, "Total number of devpoll loops: %ld\n", statCounter.select_loops); storeAppendPrintf(sentry, "Histogram of returned filedescriptors\n"); - statHistDump(&f->select_fds_hist, sentry, statHistIntDumper); + statCounter.select_fds_hist.dump(sentry, statHistIntDumper); } static void commDevPollRegisterWithCacheManager(void) { Mgr::RegisterAction( "comm_devpoll_incoming", "comm_incoming() stats", commIncomingStats, 0, 1 ); } /* PUBLIC FUNCTIONS */ /** \brief Initialise /dev/poll support * @@ -360,41 +361,41 @@ comm_flush_updates(); /* ensure latest changes are sent to /dev/poll */ num = ioctl(devpoll_fd, DP_POLL, &do_poll); ++statCounter.select_loops; if (num >= 0) break; /* no error, skip out of loop */ if (ignoreErrno(errno)) break; /* error is one we may ignore, skip out of loop */ /* error during poll */ getCurrentTime(); PROF_stop(comm_check_incoming); return COMM_ERROR; } PROF_stop(comm_check_incoming); getCurrentTime(); - statHistCount(&statCounter.select_fds_hist, num); + statCounter.select_fds_hist.count(num); if (num == 0) return COMM_TIMEOUT; /* no error */ PROF_start(comm_handle_ready_fd); for (i = 0; i < num; i++) { int fd = (int)do_poll.dp_fds[i].fd; F = &fd_table[fd]; debugs( 5, DEBUG_DEVPOLL ? 0 : 8, HERE << "got FD " << fd << ",events=" << std::hex << do_poll.dp_fds[i].revents << ",monitoring=" << devpoll_state[fd].state << ",F->read_handler=" << F->read_handler << ",F->write_handler=" << F->write_handler ); /* handle errors */ === modified file 'src/comm/ModEpoll.cc' --- src/comm/ModEpoll.cc 2011-09-02 12:35:57 +0000 +++ src/comm/ModEpoll.cc 2011-12-09 17:31:19 +0000 @@ -43,40 +43,42 @@ * -- David Nicklay */ /* * XXX Currently not implemented / supported by this module XXX * * - delay pools * - deferred reads * */ #include "config.h" #if USE_EPOLL #include "squid.h" #include "comm/Loops.h" #include "fde.h" #include "mgr/Registration.h" #include "SquidTime.h" +#include "StatCounters.h" +#include "StatHist.h" #include "Store.h" #define DEBUG_EPOLL 0 #if HAVE_SYS_EPOLL_H #include #endif static int kdpfd; static int max_poll_time = 1000; static struct epoll_event *pevents; static void commEPollRegisterWithCacheManager(void); /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ /* Public functions */ @@ -210,41 +212,41 @@ SetSelect(fd, 0, NULL, NULL, 0); } static void commIncomingStats(StoreEntry * sentry); static void commEPollRegisterWithCacheManager(void) { Mgr::RegisterAction("comm_epoll_incoming", "comm_incoming() stats", commIncomingStats, 0, 1); } static void commIncomingStats(StoreEntry * sentry) { StatCounters *f = &statCounter; storeAppendPrintf(sentry, "Total number of epoll(2) loops: %ld\n", statCounter.select_loops); storeAppendPrintf(sentry, "Histogram of returned filedescriptors\n"); - statHistDump(&f->select_fds_hist, sentry, statHistIntDumper); + f->select_fds_hist.dump(sentry, statHistIntDumper); } /** * Check all connections for new connections and input data that is to be * processed. Also check for connections with data queued and whether we can * write it out. * * Called to do the new-style IO, courtesy of of squid (like most of this * new IO code). This routine handles the stuff we've hidden in * comm_setselect and fd_table[] and calls callbacks for IO ready * events. */ comm_err_t Comm::DoSelect(int msec) { int num, i,fd; fde *F; PF *hdl; struct epoll_event *cevents; @@ -257,41 +259,41 @@ for (;;) { num = epoll_wait(kdpfd, pevents, SQUID_MAXFD, msec); ++statCounter.select_loops; if (num >= 0) break; if (ignoreErrno(errno)) break; getCurrentTime(); PROF_stop(comm_check_incoming); return COMM_ERROR; } PROF_stop(comm_check_incoming); getCurrentTime(); - statHistCount(&statCounter.select_fds_hist, num); + statCounter.select_fds_hist.count(num); if (num == 0) return COMM_TIMEOUT; /* No error.. */ PROF_start(comm_handle_ready_fd); for (i = 0, cevents = pevents; i < num; i++, cevents++) { fd = cevents->data.fd; F = &fd_table[fd]; debugs(5, DEBUG_EPOLL ? 0 : 8, HERE << "got FD " << fd << " events=" << std::hex << cevents->events << " monitoring=" << F->epoll_state << " F->read_handler=" << F->read_handler << " F->write_handler=" << F->write_handler); // TODO: add EPOLLPRI?? if (cevents->events & (EPOLLIN|EPOLLHUP|EPOLLERR) || F->flags.read_pending) { if ((hdl = F->read_handler) != NULL) { debugs(5, DEBUG_EPOLL ? 0 : 8, HERE << "Calling read handler on FD " << fd); PROF_start(comm_write_handler); F->flags.read_pending = 0; === modified file 'src/comm/ModPoll.cc' --- src/comm/ModPoll.cc 2011-09-02 12:35:57 +0000 +++ src/comm/ModPoll.cc 2011-12-10 20:40:11 +0000 @@ -24,40 +24,41 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #include "config.h" #if USE_POLL #include "squid.h" #include "comm/Connection.h" #include "comm/Loops.h" #include "fde.h" #include "ICP.h" #include "mgr/Registration.h" #include "SquidTime.h" +#include "StatCounters.h" #include "Store.h" #if HAVE_POLL_H #include #endif /* Needed for poll() on Linux at least */ #if USE_POLL #ifndef POLLRDNORM #define POLLRDNORM POLLIN #endif #ifndef POLLWRNORM #define POLLWRNORM POLLOUT #endif #endif static int MAX_POLL_TIME = 1000; /* see also Comm::QuickPollRequired() */ #ifndef howmany #define howmany(x, y) (((x)+((y)-1))/(y)) @@ -288,75 +289,75 @@ if (icpIncomingConn != icpOutgoingConn && Comm::IsConnOpen(icpOutgoingConn)) fds[nfds++] = icpOutgoingConn->fd; if (nfds == 0) return; nevents = comm_check_incoming_poll_handlers(nfds, fds); incoming_icp_interval += Config.comm_incoming.icp_average - nevents; if (incoming_icp_interval < Config.comm_incoming.icp_min_poll) incoming_icp_interval = Config.comm_incoming.icp_min_poll; if (incoming_icp_interval > MAX_INCOMING_INTERVAL) incoming_icp_interval = MAX_INCOMING_INTERVAL; if (nevents > INCOMING_ICP_MAX) nevents = INCOMING_ICP_MAX; - statHistCount(&statCounter.comm_icp_incoming, nevents); + statCounter.comm_icp_incoming.count(nevents); } static void comm_poll_http_incoming(void) { int nfds = 0; int fds[MAXHTTPPORTS]; int j; int nevents; http_io_events = 0; /* only poll sockets that won't be deferred */ for (j = 0; j < NHttpSockets; j++) { if (HttpSockets[j] < 0) continue; fds[nfds++] = HttpSockets[j]; } nevents = comm_check_incoming_poll_handlers(nfds, fds); incoming_http_interval = incoming_http_interval + Config.comm_incoming.http_average - nevents; if (incoming_http_interval < Config.comm_incoming.http_min_poll) incoming_http_interval = Config.comm_incoming.http_min_poll; if (incoming_http_interval > MAX_INCOMING_INTERVAL) incoming_http_interval = MAX_INCOMING_INTERVAL; if (nevents > INCOMING_HTTP_MAX) nevents = INCOMING_HTTP_MAX; - statHistCount(&statCounter.comm_http_incoming, nevents); + statCounter.comm_http_incoming.count(nevents); } /* poll all sockets; call handlers for those that are ready. */ comm_err_t Comm::DoSelect(int msec) { struct pollfd pfds[SQUID_MAXFD]; PF *hdl = NULL; int fd; int maxfd; unsigned long nfds; unsigned long npending; int num; int callicp = 0, callhttp = 0; int calldns = 0; double timeout = current_dtime + (msec / 1000.0); do { double start; @@ -432,41 +433,41 @@ PROF_stop(comm_poll_normal); if (num >= 0 || npending > 0) break; if (ignoreErrno(errno)) continue; debugs(5, 0, "comm_poll: poll failure: " << xstrerror()); assert(errno != EINVAL); return COMM_ERROR; /* NOTREACHED */ } getCurrentTime(); debugs(5, num ? 5 : 8, "comm_poll: " << num << "+" << npending << " FDs ready"); - statHistCount(&statCounter.select_fds_hist, num); + statCounter.select_fds_hist.count(num); if (num == 0 && npending == 0) continue; /* scan each socket but the accept socket. Poll this * more frequently to minimize losses due to the 5 connect * limit in SunOS */ PROF_start(comm_handle_ready_fd); for (size_t loopIndex = 0; loopIndex < nfds; loopIndex++) { fde *F; int revents = pfds[loopIndex].revents; fd = pfds[loopIndex].fd; if (fd == -1) continue; if (fd_table[fd].flags.read_pending) revents |= POLLIN; @@ -603,66 +604,65 @@ if (DnsSocketB >= 0) fds[nfds++] = DnsSocketB; nevents = comm_check_incoming_poll_handlers(nfds, fds); if (nevents < 0) return; incoming_dns_interval += Config.comm_incoming.dns_average - nevents; if (incoming_dns_interval < Config.comm_incoming.dns_min_poll) incoming_dns_interval = Config.comm_incoming.dns_min_poll; if (incoming_dns_interval > MAX_INCOMING_INTERVAL) incoming_dns_interval = MAX_INCOMING_INTERVAL; if (nevents > INCOMING_DNS_MAX) nevents = INCOMING_DNS_MAX; - statHistCount(&statCounter.comm_dns_incoming, nevents); + statCounter.comm_dns_incoming.count(nevents); } static void commPollRegisterWithCacheManager(void) { Mgr::RegisterAction("comm_poll_incoming", "comm_incoming() stats", commIncomingStats, 0, 1); } void Comm::SelectLoopInit(void) { commPollRegisterWithCacheManager(); } static void commIncomingStats(StoreEntry * sentry) { - StatCounters *f = &statCounter; storeAppendPrintf(sentry, "Current incoming_icp_interval: %d\n", incoming_icp_interval >> INCOMING_FACTOR); storeAppendPrintf(sentry, "Current incoming_dns_interval: %d\n", incoming_dns_interval >> INCOMING_FACTOR); storeAppendPrintf(sentry, "Current incoming_http_interval: %d\n", incoming_http_interval >> INCOMING_FACTOR); storeAppendPrintf(sentry, "\n"); storeAppendPrintf(sentry, "Histogram of events per incoming socket type\n"); storeAppendPrintf(sentry, "ICP Messages handled per comm_poll_icp_incoming() call:\n"); - statHistDump(&f->comm_icp_incoming, sentry, statHistIntDumper); + statCounter.comm_icp_incoming.dump(sentry, statHistIntDumper); storeAppendPrintf(sentry, "DNS Messages handled per comm_poll_dns_incoming() call:\n"); - statHistDump(&f->comm_dns_incoming, sentry, statHistIntDumper); + statCounter.comm_dns_incoming.dump(sentry, statHistIntDumper); storeAppendPrintf(sentry, "HTTP Messages handled per comm_poll_http_incoming() call:\n"); - statHistDump(&f->comm_http_incoming, sentry, statHistIntDumper); + statCounter.comm_http_incoming.dump(sentry, statHistIntDumper); } /* Called by async-io or diskd to speed up the polling */ void Comm::QuickPollRequired(void) { MAX_POLL_TIME = 10; } #endif /* USE_POLL */ === modified file 'src/comm/ModSelect.cc' --- src/comm/ModSelect.cc 2011-09-02 12:35:57 +0000 +++ src/comm/ModSelect.cc 2011-12-10 17:18:35 +0000 @@ -23,40 +23,42 @@ * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #include "config.h" #if USE_SELECT #include "squid.h" #include "comm/Connection.h" #include "comm/Loops.h" #include "ICP.h" #include "mgr/Registration.h" #include "SquidTime.h" +#include "StatCounters.h" +#include "StatHist.h" #include "Store.h" #include "fde.h" static int MAX_POLL_TIME = 1000; /* see also Comm::QuickPollRequired() */ #ifndef howmany #define howmany(x, y) (((x)+((y)-1))/(y)) #endif #ifndef NBBY #define NBBY 8 #endif #define FD_MASK_BYTES sizeof(fd_mask) #define FD_MASK_BITS (FD_MASK_BYTES*NBBY) /* STATIC */ static int examine_select(fd_set *, fd_set *); static int fdIsHttp(int fd); static int fdIsIcp(int fd); static int fdIsDns(int fd); static OBJH commIncomingStats; @@ -282,72 +284,72 @@ if (Comm::IsConnOpen(icpOutgoingConn) && icpIncomingConn != icpOutgoingConn) fds[nfds++] = icpOutgoingConn->fd; if (nfds == 0) return; nevents = comm_check_incoming_select_handlers(nfds, fds); incoming_icp_interval += Config.comm_incoming.icp_average - nevents; if (incoming_icp_interval < 0) incoming_icp_interval = 0; if (incoming_icp_interval > MAX_INCOMING_INTERVAL) incoming_icp_interval = MAX_INCOMING_INTERVAL; if (nevents > INCOMING_ICP_MAX) nevents = INCOMING_ICP_MAX; - statHistCount(&statCounter.comm_icp_incoming, nevents); + statCounter.comm_icp_incoming.count(nevents); } static void comm_select_http_incoming(void) { int nfds = 0; int fds[MAXHTTPPORTS]; int j; int nevents; http_io_events = 0; for (j = 0; j < NHttpSockets; j++) { if (HttpSockets[j] < 0) continue; fds[nfds++] = HttpSockets[j]; } nevents = comm_check_incoming_select_handlers(nfds, fds); incoming_http_interval += Config.comm_incoming.http_average - nevents; if (incoming_http_interval < 0) incoming_http_interval = 0; if (incoming_http_interval > MAX_INCOMING_INTERVAL) incoming_http_interval = MAX_INCOMING_INTERVAL; if (nevents > INCOMING_HTTP_MAX) nevents = INCOMING_HTTP_MAX; - statHistCount(&statCounter.comm_http_incoming, nevents); + statCounter.comm_http_incoming.count(nevents); } #define DEBUG_FDBITS 0 /* Select on all sockets; call handlers for those that are ready. */ comm_err_t Comm::DoSelect(int msec) { fd_set readfds; fd_set pendingfds; fd_set writefds; PF *hdl = NULL; int fd; int maxfd; int num; int pending; int callicp = 0, callhttp = 0; int calldns = 0; int maxindex; unsigned int k; @@ -453,41 +455,41 @@ if (ignoreErrno(errno)) break; debugs(5, 0, "comm_select: select failure: " << xstrerror()); examine_select(&readfds, &writefds); return COMM_ERROR; /* NOTREACHED */ } if (num < 0 && !pending) continue; getCurrentTime(); debugs(5, num ? 5 : 8, "comm_select: " << num << "+" << pending << " FDs ready"); - statHistCount(&statCounter.select_fds_hist, num); + statCounter.select_fds_hist.count(num); if (num == 0 && pending == 0) continue; /* Scan return fd masks for ready descriptors */ fdsp = (fd_mask *) & readfds; pfdsp = (fd_mask *) & pendingfds; maxindex = howmany(maxfd, FD_MASK_BITS); for (j = 0; j < maxindex; j++) { if ((tmask = (fdsp[j] | pfdsp[j])) == 0) continue; /* no bits here */ for (k = 0; k < FD_MASK_BITS; k++) { if (tmask == 0) break; /* no more bits left */ if (!EBIT_TEST(tmask, k)) @@ -643,41 +645,41 @@ if (DnsSocketB >= 0) fds[nfds++] = DnsSocketB; nevents = comm_check_incoming_select_handlers(nfds, fds); if (nevents < 0) return; incoming_dns_interval += Config.comm_incoming.dns_average - nevents; if (incoming_dns_interval < Config.comm_incoming.dns_min_poll) incoming_dns_interval = Config.comm_incoming.dns_min_poll; if (incoming_dns_interval > MAX_INCOMING_INTERVAL) incoming_dns_interval = MAX_INCOMING_INTERVAL; if (nevents > INCOMING_DNS_MAX) nevents = INCOMING_DNS_MAX; - statHistCount(&statCounter.comm_dns_incoming, nevents); + statCounter.comm_dns_incoming.count(nevents); } void Comm::SelectLoopInit(void) { zero_tv.tv_sec = 0; zero_tv.tv_usec = 0; FD_ZERO(&global_readfds); FD_ZERO(&global_writefds); nreadfds = nwritefds = 0; Mgr::RegisterAction("comm_select_incoming", "comm_incoming() stats", commIncomingStats, 0, 1); } /* * examine_select - debug routine. * * I spend the day chasing this core dump that occurs when both the client @@ -735,55 +737,54 @@ } else if (F->timeoutHandler != NULL) { debugs(5, 0, "examine_select: Calling Timeout Handler"); ScheduleCallHere(F->timeoutHandler); } F->closeHandler = NULL; F->timeoutHandler = NULL; F->read_handler = NULL; F->write_handler = NULL; FD_CLR(fd, readfds); FD_CLR(fd, writefds); } return 0; } static void commIncomingStats(StoreEntry * sentry) { - StatCounters *f = &statCounter; storeAppendPrintf(sentry, "Current incoming_icp_interval: %d\n", incoming_icp_interval >> INCOMING_FACTOR); storeAppendPrintf(sentry, "Current incoming_dns_interval: %d\n", incoming_dns_interval >> INCOMING_FACTOR); storeAppendPrintf(sentry, "Current incoming_http_interval: %d\n", incoming_http_interval >> INCOMING_FACTOR); storeAppendPrintf(sentry, "\n"); storeAppendPrintf(sentry, "Histogram of events per incoming socket type\n"); storeAppendPrintf(sentry, "ICP Messages handled per comm_select_icp_incoming() call:\n"); - statHistDump(&f->comm_icp_incoming, sentry, statHistIntDumper); + statCounter.comm_icp_incoming.dump(sentry, statHistIntDumper); storeAppendPrintf(sentry, "DNS Messages handled per comm_select_dns_incoming() call:\n"); - statHistDump(&f->comm_dns_incoming, sentry, statHistIntDumper); + statCounter.comm_dns_incoming.dump(sentry, statHistIntDumper); storeAppendPrintf(sentry, "HTTP Messages handled per comm_select_http_incoming() call:\n"); - statHistDump(&f->comm_http_incoming, sentry, statHistIntDumper); + statCounter.comm_http_incoming.dump(sentry, statHistIntDumper); } void commUpdateReadBits(int fd, PF * handler) { if (handler && !FD_ISSET(fd, &global_readfds)) { FD_SET(fd, &global_readfds); nreadfds++; } else if (!handler && FD_ISSET(fd, &global_readfds)) { FD_CLR(fd, &global_readfds); nreadfds--; } } void commUpdateWriteBits(int fd, PF * handler) { if (handler && !FD_ISSET(fd, &global_writefds)) { FD_SET(fd, &global_writefds); nwritefds++; === modified file 'src/comm/ModSelectWin32.cc' --- src/comm/ModSelectWin32.cc 2011-09-02 12:35:57 +0000 +++ src/comm/ModSelectWin32.cc 2011-12-10 17:07:16 +0000 @@ -23,40 +23,42 @@ * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #include "config.h" #if USE_SELECT_WIN32 #include "squid.h" #include "comm/Loops.h" #include "fde.h" #include "mgr/Registration.h" #include "SquidTime.h" +#include "StatCounters.h" +#include "StatHist.h" #include "Store.h" static int MAX_POLL_TIME = 1000; /* see also Comm::QuickPollRequired() */ #ifndef howmany #define howmany(x, y) (((x)+((y)-1))/(y)) #endif #ifndef NBBY #define NBBY 8 #endif #define FD_MASK_BYTES sizeof(fd_mask) #define FD_MASK_BITS (FD_MASK_BYTES*NBBY) /* STATIC */ static int examine_select(fd_set *, fd_set *); static int fdIsHttp(int fd); static int fdIsIcp(int fd); static int fdIsDns(int fd); static OBJH commIncomingStats; static int comm_check_incoming_select_handlers(int nfds, int *fds); @@ -285,72 +287,72 @@ if (theInIcpConnection != theOutIcpConnection) if (theOutIcpConnection >= 0) fds[nfds++] = theOutIcpConnection; if (nfds == 0) return; nevents = comm_check_incoming_select_handlers(nfds, fds); incoming_icp_interval += Config.comm_incoming.icp_average - nevents; if (incoming_icp_interval < 0) incoming_icp_interval = 0; if (incoming_icp_interval > MAX_INCOMING_INTERVAL) incoming_icp_interval = MAX_INCOMING_INTERVAL; if (nevents > INCOMING_ICP_MAX) nevents = INCOMING_ICP_MAX; - statHistCount(&statCounter.comm_icp_incoming, nevents); + statCounter.comm_icp_incoming.count(nevents); } static void comm_select_http_incoming(void) { int nfds = 0; int fds[MAXHTTPPORTS]; int j; int nevents; http_io_events = 0; for (j = 0; j < NHttpSockets; j++) { if (HttpSockets[j] < 0) continue; fds[nfds++] = HttpSockets[j]; } nevents = comm_check_incoming_select_handlers(nfds, fds); incoming_http_interval += Config.comm_incoming.http_average - nevents; if (incoming_http_interval < 0) incoming_http_interval = 0; if (incoming_http_interval > MAX_INCOMING_INTERVAL) incoming_http_interval = MAX_INCOMING_INTERVAL; if (nevents > INCOMING_HTTP_MAX) nevents = INCOMING_HTTP_MAX; - statHistCount(&statCounter.comm_http_incoming, nevents); + statCounter.comm_http_incoming.count(nevents); } #define DEBUG_FDBITS 0 /* Select on all sockets; call handlers for those that are ready. */ comm_err_t Comm::DoSelect(int msec) { fd_set readfds; fd_set pendingfds; fd_set writefds; PF *hdl = NULL; int fd; int maxfd; int num; int pending; int callicp = 0, callhttp = 0; int calldns = 0; int j; #if DEBUG_FDBITS @@ -453,41 +455,41 @@ if (ignoreErrno(errno)) break; debugs(5, 0, "comm_select: select failure: " << xstrerror()); examine_select(&readfds, &writefds); return COMM_ERROR; /* NOTREACHED */ } if (num < 0 && !pending) continue; getCurrentTime(); debugs(5, num ? 5 : 8, "comm_select: " << num << "+" << pending << " FDs ready"); - statHistCount(&statCounter.select_fds_hist, num); + statCounter.select_fds_hist.count(num); if (num == 0 && pending == 0) continue; /* Scan return fd masks for ready descriptors */ assert(readfds.fd_count <= (unsigned int) Biggest_FD); assert(pendingfds.fd_count <= (unsigned int) Biggest_FD); for (j = 0; j < (int) readfds.fd_count; j++) { register int readfds_handle = readfds.fd_array[j]; register int pendingfds_handle = pendingfds.fd_array[j]; register int osfhandle; no_bits = 1; for ( fd = Biggest_FD; fd; fd-- ) { osfhandle = fd_table[fd].win32.handle; if (( osfhandle == readfds_handle ) || ( osfhandle == pendingfds_handle )) { if (fd_table[fd].flags.open) { @@ -665,41 +667,41 @@ if (DnsSocketB >= 0) fds[nfds++] = DnsSocketB; nevents = comm_check_incoming_select_handlers(nfds, fds); if (nevents < 0) return; incoming_dns_interval += Config.comm_incoming.dns_average - nevents; if (incoming_dns_interval < Config.comm_incoming.dns_min_poll) incoming_dns_interval = Config.comm_incoming.dns_min_poll; if (incoming_dns_interval > MAX_INCOMING_INTERVAL) incoming_dns_interval = MAX_INCOMING_INTERVAL; if (nevents > INCOMING_DNS_MAX) nevents = INCOMING_DNS_MAX; - statHistCount(&statCounter.comm_dns_incoming, nevents); + statCounter.comm_dns_incoming.count(nevents); } void Comm::SelectLoopInit(void) { zero_tv.tv_sec = 0; zero_tv.tv_usec = 0; FD_ZERO(&global_readfds); FD_ZERO(&global_writefds); nreadfds = nwritefds = 0; Mgr::RegisterAction("comm_select_incoming", "comm_incoming() stats", commIncomingStats, 0, 1); } /* * examine_select - debug routine. * * I spend the day chasing this core dump that occurs when both the client @@ -757,55 +759,54 @@ } else if (F->timeoutHandler != NULL) { debugs(5, 0, "examine_select: Calling Timeout Handler"); ScheduleCallHere(F->timeoutHandler); } F->closeHandler = NULL; F->timeoutHandler = NULL; F->read_handler = NULL; F->write_handler = NULL; FD_CLR(fd, readfds); FD_CLR(fd, writefds); } return 0; } static void commIncomingStats(StoreEntry * sentry) { - StatCounters *f = &statCounter; storeAppendPrintf(sentry, "Current incoming_icp_interval: %d\n", incoming_icp_interval >> INCOMING_FACTOR); storeAppendPrintf(sentry, "Current incoming_dns_interval: %d\n", incoming_dns_interval >> INCOMING_FACTOR); storeAppendPrintf(sentry, "Current incoming_http_interval: %d\n", incoming_http_interval >> INCOMING_FACTOR); storeAppendPrintf(sentry, "\n"); storeAppendPrintf(sentry, "Histogram of events per incoming socket type\n"); storeAppendPrintf(sentry, "ICP Messages handled per comm_select_icp_incoming() call:\n"); - statHistDump(&f->comm_icp_incoming, sentry, statHistIntDumper); + statCounter.comm_icp_incoming.dump(sentry, statHistIntDumper); storeAppendPrintf(sentry, "DNS Messages handled per comm_select_dns_incoming() call:\n"); - statHistDump(&f->comm_dns_incoming, sentry, statHistIntDumper); + statCounter.comm_dns_incoming.dump(sentry, statHistIntDumper); storeAppendPrintf(sentry, "HTTP Messages handled per comm_select_http_incoming() call:\n"); - statHistDump(&f->comm_http_incoming, sentry, statHistIntDumper); + statCounter.comm_http_incoming.dump(sentry, statHistIntDumper); } void commUpdateReadBits(int fd, PF * handler) { if (handler && !__WSAFDIsSet(fd_table[fd].win32.handle, &global_readfds)) { FD_SET(fd, &global_readfds); nreadfds++; } else if (!handler && __WSAFDIsSet(fd_table[fd].win32.handle, &global_readfds)) { FD_CLR(fd, &global_readfds); nreadfds--; } } void commUpdateWriteBits(int fd, PF * handler) { if (handler && !__WSAFDIsSet(fd_table[fd].win32.handle, &global_writefds)) { FD_SET(fd, &global_writefds); nwritefds++; === modified file 'src/comm/TcpAcceptor.cc' --- src/comm/TcpAcceptor.cc 2011-02-25 03:38:04 +0000 +++ src/comm/TcpAcceptor.cc 2011-12-10 15:21:36 +0000 @@ -27,40 +27,41 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * * * Copyright (c) 2003, Robert Collins */ #include "squid.h" #include "base/TextException.h" #include "CommCalls.h" #include "comm/AcceptLimiter.h" #include "comm/comm_internal.h" #include "comm/Connection.h" #include "comm/Loops.h" #include "comm/TcpAcceptor.h" #include "fde.h" #include "ip/Intercept.h" #include "protos.h" #include "SquidTime.h" +#include "StatCounters.h" namespace Comm { CBDATA_CLASS_INIT(TcpAcceptor); }; Comm::TcpAcceptor::TcpAcceptor(const Comm::ConnectionPointer &newConn, const char *note, const Subscription::Pointer &aSub) : AsyncJob("Comm::TcpAcceptor"), errcode(0), isLimited(0), theCallSub(aSub), conn(newConn) {} void Comm::TcpAcceptor::subscribe(const Subscription::Pointer &aSub) { debugs(5, 5, HERE << status() << " AsyncCall Subscription: " << aSub); unsubscribe("subscription change"); theCallSub = aSub; @@ -279,41 +280,41 @@ params.conn = newConnDetails; params.flag = flag; params.xerrno = errcode; ScheduleCallHere(call); } } /** * accept() and process * Wait for an incoming connection on our listener socket. * * \retval COMM_OK success. details parameter filled. * \retval COMM_NOMESSAGE attempted accept() but nothing useful came in. * \retval COMM_ERROR an outright failure occured. * Or if this client has too many connections already. */ comm_err_t Comm::TcpAcceptor::oldAccept(Comm::ConnectionPointer &details) { PROF_start(comm_accept); - statCounter.syscalls.sock.accepts++; + ++statCounter.syscalls.sock.accepts; int sock; struct addrinfo *gai = NULL; details->local.InitAddrInfo(gai); errcode = 0; // reset local errno copy. if ((sock = accept(conn->fd, gai->ai_addr, &gai->ai_addrlen)) < 0) { errcode = errno; // store last accept errno locally. details->local.FreeAddrInfo(gai); PROF_stop(comm_accept); if (ignoreErrno(errno)) { debugs(50, 5, HERE << status() << ": " << xstrerror()); return COMM_NOMESSAGE; } else if (ENFILE == errno || EMFILE == errno) { debugs(50, 3, HERE << status() << ": " << xstrerror()); return COMM_ERROR; } else { debugs(50, 1, HERE << status() << ": " << xstrerror()); === modified file 'src/comm/Write.cc' --- src/comm/Write.cc 2010-12-03 00:18:43 +0000 +++ src/comm/Write.cc 2011-12-10 15:21:36 +0000 @@ -1,28 +1,29 @@ #include "config.h" #if USE_DELAY_POOLS #include "ClientInfo.h" #endif #include "comm/Connection.h" #include "comm/IoCallback.h" #include "comm/Write.h" #include "fde.h" +#include "StatCounters.h" #include "SquidTime.h" #include "MemBuf.h" void Comm::Write(const Comm::ConnectionPointer &conn, MemBuf *mb, AsyncCall::Pointer &callback) { Comm::Write(conn, mb->buf, mb->size, callback, mb->freeFunc()); } void Comm::Write(const Comm::ConnectionPointer &conn, const char *buf, int size, AsyncCall::Pointer &callback, FREE * free_func) { debugs(5, 5, HERE << conn << ": sz " << size << ": asynCall " << callback); /* Make sure we are open, not closing, and not writing */ assert(fd_table[conn->fd].flags.open); assert(!fd_table[conn->fd].closing()); Comm::IoCallback *ccb = COMMIO_FD_WRITECB(conn->fd); assert(!ccb->active()); @@ -91,41 +92,41 @@ len = FD_WRITE_METHOD(fd, state->buf + state->offset, nleft); debugs(5, 5, HERE << "write() returns " << len); #if USE_DELAY_POOLS if (clientInfo) { if (len > 0) { /* we wrote data - drain them from bucket */ clientInfo->bucketSize -= len; if (clientInfo->bucketSize < 0.0) { debugs(5,1, HERE << "drained too much"); // should not happen clientInfo->bucketSize = 0; } } // even if we wrote nothing, we were served; give others a chance clientInfo->kickQuotaQueue(); } #endif /* USE_DELAY_POOLS */ fd_bytes(fd, len, FD_WRITE); - statCounter.syscalls.sock.writes++; + ++statCounter.syscalls.sock.writes; // After each successful partial write, // reset fde::writeStart to the current time. fd_table[fd].writeStart = squid_curtime; if (len == 0) { /* Note we even call write if nleft == 0 */ /* We're done */ if (nleft != 0) debugs(5, DBG_IMPORTANT, "FD " << fd << " write failure: connection closed with " << nleft << " bytes remaining."); state->finish(nleft ? COMM_ERROR : COMM_OK, errno); } else if (len < 0) { /* An error */ if (fd_table[fd].flags.socket_eof) { debugs(50, 2, HERE << "FD " << fd << " write failure: " << xstrerror() << "."); state->finish(nleft ? COMM_ERROR : COMM_OK, errno); } else if (ignoreErrno(errno)) { debugs(50, 9, HERE << "FD " << fd << " write failure: " << xstrerror() << "."); state->selectOrQueueWrite(); } else { === modified file 'src/disk.cc' --- src/disk.cc 2011-04-14 16:58:28 +0000 +++ src/disk.cc 2011-12-10 15:30:14 +0000 @@ -19,40 +19,41 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #include "squid.h" #include "comm/Loops.h" #include "fde.h" #include "MemBuf.h" +#include "StatCounters.h" static PF diskHandleRead; static PF diskHandleWrite; #if _SQUID_WINDOWS_ || _SQUID_OS2_ static int diskWriteIsComplete(int fd) { return fd_table[fd].disk.write_q ? 0 : 1; } #endif void disk_init(void) { (void) 0; } /* hack needed on SunStudio to avoid linkage convention mismatch */ @@ -425,41 +426,41 @@ int rc = DISK_OK; /* * FD < 0 indicates premature close; we just have to free * the state data. */ if (fd < 0) { memFree(ctrl_dat, MEM_DREAD_CTRL); return; } PROF_start(diskHandleRead); #if WRITES_MAINTAIN_DISK_OFFSET if (F->disk.offset != ctrl_dat->offset) { #else { #endif debugs(6, 3, "diskHandleRead: FD " << fd << " seeking to offset " << ctrl_dat->offset); lseek(fd, ctrl_dat->offset, SEEK_SET); /* XXX ignore return? */ - statCounter.syscalls.disk.seeks++; + ++statCounter.syscalls.disk.seeks; F->disk.offset = ctrl_dat->offset; } errno = 0; len = FD_READ_METHOD(fd, ctrl_dat->buf, ctrl_dat->req_len); if (len > 0) F->disk.offset += len; statCounter.syscalls.disk.reads++; fd_bytes(fd, len, FD_READ); if (len < 0) { if (ignoreErrno(errno)) { Comm::SetSelect(fd, COMM_SELECT_READ, diskHandleRead, ctrl_dat, 0); PROF_stop(diskHandleRead); return; } === modified file 'src/fqdncache.cc' --- src/fqdncache.cc 2011-08-10 15:54:51 +0000 +++ src/fqdncache.cc 2011-12-15 21:17:34 +0000 @@ -21,40 +21,41 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #include "squid.h" #include "cbdata.h" #include "DnsLookupDetails.h" #include "event.h" #include "mgr/Registration.h" #include "SquidTime.h" +#include "StatCounters.h" #include "Store.h" #include "wordlist.h" /** \defgroup FQDNCacheAPI FQDN Cache API \ingroup Components \section Introduction Introduction \par * The FQDN cache is a built-in component of squid providing * Hostname to IP-Number translation functionality and managing * the involved data-structures. Efficiency concerns require * mechanisms that allow non-blocking access to these mappings. * The FQDN cache usually doesn't block on a request except for * special cases where this is desired (see below). * \todo FQDN Cache should have its own API *.h file. */ /** \defgroup FQDNCacheInternal FQDN Cache Internals @@ -484,41 +485,41 @@ #endif /** \ingroup FQDNCacheAPI * * Callback for handling DNS results. */ static void #if USE_DNSSERVERS fqdncacheHandleReply(void *data, char *reply) #else fqdncacheHandleReply(void *data, rfc1035_rr * answers, int na, const char *error_message) #endif { fqdncache_entry *f; static_cast(data)->unwrap(&f); ++FqdncacheStats.replies; const int age = f->age(); - statHistCount(&statCounter.dns.svc_time, age); + statCounter.dns.svcTime.count(age); #if USE_DNSSERVERS fqdncacheParse(f, reply); #else fqdncacheParse(f, answers, na, error_message); #endif fqdncacheAddEntry(f); fqdncacheCallback(f, age); } /** \ingroup FQDNCacheAPI * \param addr IP address of domain to resolve. \param handler A pointer to the function to be called when * the reply from the FQDN cache * (or the DNS if the FQDN cache misses) === modified file 'src/fs/ufs/store_dir_ufs.cc' --- src/fs/ufs/store_dir_ufs.cc 2011-12-07 18:56:59 +0000 +++ src/fs/ufs/store_dir_ufs.cc 2011-12-13 17:33:34 +0000 @@ -28,40 +28,41 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #include "squid.h" #include "Store.h" #include "fde.h" #include "ufscommon.h" #include "StoreSwapLogData.h" #include "ConfigOption.h" #include "DiskIO/DiskIOStrategy.h" #include "DiskIO/DiskIOModule.h" #include "FileMap.h" #include "Parsing.h" #include "SquidMath.h" #include "SquidTime.h" +#include "StatCounters.h" #include "SwapDir.h" #include "swap_log_op.h" int UFSSwapDir::NumberOfUFSDirs = 0; int *UFSSwapDir::UFSDirToGlobalDirMapping = NULL; /* * storeUfsDirCheckObj * * This routine is called by storeDirSelectSwapDir to see if the given * object is able to be stored on this filesystem. UFS filesystems will * happily store anything as long as the LRU time isn't too small. */ bool UFSSwapDir::canStore(const StoreEntry &e, int64_t diskSpaceNeeded, int &load) const { if (!SwapDir::canStore(e, diskSpaceNeeded, load)) return false; if (IO->shedLoad()) @@ -1128,41 +1129,41 @@ if (UFSSwapDir::FilenoBelongsHere(fn, D0, D1, D2)) continue; files[k++] = swapfileno; } closedir(dir_pointer); if (k == 0) return 0; qsort(files, k, sizeof(int), rev_int_sort); if (k > 10) k = 10; for (n = 0; n < k; n++) { debugs(36, 3, "storeDirClean: Cleaning file "<< std::setfill('0') << std::hex << std::uppercase << std::setw(8) << files[n]); snprintf(p2, MAXPATHLEN + 1, "%s/%08X", p1, files[n]); safeunlink(p2, 0); - statCounter.swap.files_cleaned++; + ++statCounter.swap.files_cleaned; } debugs(36, 3, "Cleaned " << k << " unused files from " << p1); return k; } void UFSSwapDir::CleanEvent(void *unused) { static int swap_index = 0; int i; int j = 0; int n = 0; /* * Assert that there are UFS cache_dirs configured, otherwise * we should never be called. */ assert(NumberOfUFSDirs); if (NULL == UFSDirToGlobalDirMapping) { === modified file 'src/ftp.cc' --- src/ftp.cc 2011-11-28 02:22:22 +0000 +++ src/ftp.cc 2011-12-10 15:30:15 +0000 @@ -37,40 +37,41 @@ #include "comm/ConnOpener.h" #include "CommCalls.h" #include "comm/TcpAcceptor.h" #include "comm/Write.h" #include "compat/strtoll.h" #include "errorpage.h" #include "fde.h" #include "forward.h" #include "html_quote.h" #include "HttpHdrContRange.h" #include "HttpHeaderRange.h" #include "HttpHeader.h" #include "HttpRequest.h" #include "HttpReply.h" #include "ip/tools.h" #include "MemBuf.h" #include "rfc1738.h" #include "Server.h" #include "SquidString.h" #include "SquidTime.h" +#include "StatCounters.h" #include "Store.h" #include "URLScheme.h" #include "wordlist.h" #if USE_DELAY_POOLS #include "DelayPools.h" #include "MemObject.h" #endif /** \defgroup ServerProtocolFTPInternal Server-Side FTP Internals \ingroup ServerProtocolFTPAPI */ /// \ingroup ServerProtocolFTPInternal static const char *const crlf = "\r\n"; #define CTRL_BUFLEN 1024 /// \ingroup ServerProtocolFTPInternal static char cbuf[CTRL_BUFLEN]; @@ -1240,42 +1241,42 @@ commSetConnTimeout(data.conn, Config.Timeout.read, timeoutCall); debugs(9,5,HERE << "queueing read on FD " << data.conn->fd); typedef CommCbMemFunT Dialer; entry->delayAwareRead(data.conn, data.readBuf->space(), read_sz, JobCallback(9, 5, Dialer, this, FtpStateData::dataRead)); } void FtpStateData::dataRead(const CommIoCbParams &io) { int j; int bin; data.read_pending = false; debugs(9, 3, HERE << "ftpDataRead: FD " << io.fd << " Read " << io.size << " bytes"); if (io.size > 0) { - kb_incr(&statCounter.server.all.kbytes_in, io.size); - kb_incr(&statCounter.server.ftp.kbytes_in, io.size); + kb_incr(&(statCounter.server.all.kbytes_in), io.size); + kb_incr(&(statCounter.server.ftp.kbytes_in), io.size); } if (io.flag == COMM_ERR_CLOSING) return; assert(io.fd == data.conn->fd); if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { abortTransaction("entry aborted during dataRead"); return; } if (io.flag == COMM_OK && io.size > 0) { debugs(9,5,HERE << "appended " << io.size << " bytes to readBuf"); data.readBuf->appended(io.size); #if USE_DELAY_POOLS DelayId delayId = entry->mem_obj->mostBytesAllowed(); delayId.bytesIn(io.size); #endif IOStats.Ftp.reads++; @@ -1596,42 +1597,42 @@ debugs(9, 2, HERE << "cannot send to closing ctrl " << ctrl.conn); // TODO: assert(ctrl.closer != NULL); return; } typedef CommCbMemFunT Dialer; AsyncCall::Pointer call = JobCallback(9, 5, Dialer, this, FtpStateData::ftpWriteCommandCallback); Comm::Write(ctrl.conn, ctrl.last_command, strlen(ctrl.last_command), call, NULL); scheduleReadControlReply(0); } void FtpStateData::ftpWriteCommandCallback(const CommIoCbParams &io) { debugs(9, 5, "ftpWriteCommandCallback: wrote " << io.size << " bytes"); if (io.size > 0) { fd_bytes(io.fd, io.size, FD_WRITE); - kb_incr(&statCounter.server.all.kbytes_out, io.size); - kb_incr(&statCounter.server.ftp.kbytes_out, io.size); + kb_incr(&(statCounter.server.all.kbytes_out), io.size); + kb_incr(&(statCounter.server.ftp.kbytes_out), io.size); } if (io.flag == COMM_ERR_CLOSING) return; if (io.flag) { debugs(9, DBG_IMPORTANT, "ftpWriteCommandCallback: " << io.conn << ": " << xstrerr(io.xerrno)); failed(ERR_WRITE_ERROR, io.xerrno); /* failed closes ctrl.conn and frees ftpState */ return; } } wordlist * FtpStateData::ftpParseControlReply(char *buf, size_t len, int *codep, size_t *used) { char *s; char *sbuf; char *end; int usable; @@ -1737,42 +1738,42 @@ */ if (Comm::IsConnOpen(data.conn)) { commUnsetConnTimeout(data.conn); } typedef CommCbMemFunT TimeoutDialer; AsyncCall::Pointer timeoutCall = JobCallback(9, 5, TimeoutDialer, this, FtpStateData::ftpTimeout); commSetConnTimeout(ctrl.conn, Config.Timeout.read, timeoutCall); typedef CommCbMemFunT Dialer; AsyncCall::Pointer reader = JobCallback(9, 5, Dialer, this, FtpStateData::ftpReadControlReply); comm_read(ctrl.conn, ctrl.buf + ctrl.offset, ctrl.size - ctrl.offset, reader); } } void FtpStateData::ftpReadControlReply(const CommIoCbParams &io) { debugs(9, 3, "ftpReadControlReply: FD " << io.fd << ", Read " << io.size << " bytes"); if (io.size > 0) { - kb_incr(&statCounter.server.all.kbytes_in, io.size); - kb_incr(&statCounter.server.ftp.kbytes_in, io.size); + kb_incr(&(statCounter.server.all.kbytes_in), io.size); + kb_incr(&(statCounter.server.ftp.kbytes_in), io.size); } if (io.flag == COMM_ERR_CLOSING) return; if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { abortTransaction("entry aborted during control reply read"); return; } assert(ctrl.offset < ctrl.size); if (io.flag == COMM_OK && io.size > 0) { fd_bytes(io.fd, io.size, FD_READ); } if (io.flag != COMM_OK) { debugs(50, ignoreErrno(io.xerrno) ? 3 : DBG_IMPORTANT, "ftpReadControlReply: read error: " << xstrerr(io.xerrno)); @@ -3300,41 +3301,41 @@ return; } } // premature end of the request body void FtpStateData::handleRequestBodyProducerAborted() { ServerStateData::handleRequestBodyProducerAborted(); debugs(9, 3, HERE << "ftpState=" << this); failed(ERR_READ_ERROR, 0); } /** * This will be called when the put write is completed */ void FtpStateData::sentRequestBody(const CommIoCbParams &io) { if (io.size > 0) - kb_incr(&statCounter.server.ftp.kbytes_out, io.size); + kb_incr(&(statCounter.server.ftp.kbytes_out), io.size); ServerStateData::sentRequestBody(io); } /// \ingroup ServerProtocolFTPInternal static void ftpWriteTransferDone(FtpStateData * ftpState) { int code = ftpState->ctrl.replycode; debugs(9, 3, HERE); if (!(code == 226 || code == 250)) { debugs(9, DBG_IMPORTANT, HERE << "Got code " << code << " after sending data"); ftpState->failed(ERR_FTP_PUT_ERROR, 0); return; } ftpState->entry->timestampsSet(); /* XXX Is this needed? */ ftpSendReply(ftpState); } === modified file 'src/globals.h' --- src/globals.h 2011-08-10 15:54:51 +0000 +++ src/globals.h 2011-12-10 07:08:39 +0000 @@ -24,41 +24,41 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #ifndef SQUID_GLOBALS_H #define SQUID_GLOBALS_H #if HAVE_STDIO_H #include #endif #include "rfc2181.h" /* for ERROR_BUF_SZ, BUFSIZ, MAXHTTPPORTS */ #include "defines.h" -/* for iostats, StatCounters */ +/* for iostats */ #include "structs.h" #ifdef __cplusplus extern "C" { #endif //MOVED:Debug.h extern FILE *debug_log; /* NULL */ //MOVED:structs.h extern SquidConfig Config; //MOVED:structs.h extern SquidConfig2 Config2; extern char *ConfigFile; /* NULL */ extern char *IcpOpcodeStr[]; extern char tmp_error_buf[ERROR_BUF_SZ]; extern char ThisCache[RFC2181_MAXHOSTNAMELEN << 1]; extern char ThisCache2[RFC2181_MAXHOSTNAMELEN << 1]; extern char config_input_line[BUFSIZ]; extern const char *DefaultConfigFile; /* DEFAULT_CONFIG_FILE */ extern const char *cfg_filename; /* NULL */ //MOVED:version.h:APP_SHORTNAME extern const char *const appname; /* "squid" */ extern const char *const dash_str; /* "-" */ @@ -92,41 +92,40 @@ extern int opt_foreground_rebuild; /* 0 */ extern char *opt_forwarded_for; /* NULL */ extern int opt_reload_hit_only; /* 0 */ extern int opt_udp_hit_obj; /* 0 */ extern int opt_create_swap_dirs; /* 0 */ extern int opt_store_doublecheck; /* 0 */ extern int syslog_enable; /* 0 */ extern int DnsSocketA; /* -1 */ extern int DnsSocketB; /* -1 */ extern int n_disk_objects; /* 0 */ extern iostats IOStats; extern struct acl_deny_info_list *DenyInfoList; /* NULL */ extern struct timeval squid_start; extern int starting_up; /* 1 */ extern int shutting_down; /* 0 */ extern int reconfiguring; /* 0 */ extern time_t hit_only_mode_until; /* 0 */ - extern StatCounters statCounter; extern double request_failure_ratio; /* 0.0 */ extern int store_hash_buckets; /* 0 */ extern hash_table *store_table; /* NULL */ //MOVED:dlink.h extern dlink_list ClientActiveRequests; extern int hot_obj_count; /* 0 */ extern const int CacheDigestHashFuncCount; /* 4 */ extern CacheDigest *store_digest; /* NULL */ extern const char *StoreDigestFileName; /* "store_digest" */ extern const char *StoreDigestMimeStr; /* "application/cache-digest" */ extern const char *MultipartMsgBoundaryStr; /* "Unique-Squid-Separator" */ #if USE_HTTP_VIOLATIONS extern int refresh_nocache_hack; /* 0 */ #endif extern int store_open_disk_fd; /* 0 */ extern const char *SwapDirType[]; extern int store_swap_low; /* 0 */ extern int store_swap_high; /* 0 */ === modified file 'src/gopher.cc' --- src/gopher.cc 2011-11-27 12:37:35 +0000 +++ src/gopher.cc 2011-12-10 15:30:15 +0000 @@ -31,40 +31,41 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #include "squid.h" #include "comm/Write.h" #include "errorpage.h" #include "Store.h" #include "html_quote.h" #include "HttpRequest.h" #include "HttpReply.h" #include "comm.h" #if USE_DELAY_POOLS #include "DelayPools.h" #include "MemObject.h" #endif #include "MemBuf.h" #include "forward.h" #include "rfc1738.h" +#include "StatCounters.h" #include "SquidTime.h" /** \defgroup ServerProtocolGopherInternal Server-Side Gopher Internals \ingroup ServerProtocolGopherAPI * Gopher is somewhat complex and gross because it must convert from * the Gopher protocol to HTTP. */ /* gopher type code from rfc. Anawat. */ /// \ingroup ServerProtocolGopherInternal #define GOPHER_FILE '0' /// \ingroup ServerProtocolGopherInternal #define GOPHER_DIRECTORY '1' /// \ingroup ServerProtocolGopherInternal #define GOPHER_CSO '2' /// \ingroup ServerProtocolGopherInternal #define GOPHER_ERROR '3' /// \ingroup ServerProtocolGopherInternal #define GOPHER_MACBINHEX '4' @@ -752,42 +753,42 @@ assert(buf == gopherState->replybuf); if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { gopherState->serverConn->close(); return; } errno = 0; #if USE_DELAY_POOLS read_sz = delayId.bytesWanted(1, read_sz); #endif /* leave one space for \0 in gopherToHTML */ if (flag == COMM_OK && len > 0) { #if USE_DELAY_POOLS delayId.bytesIn(len); #endif - kb_incr(&statCounter.server.all.kbytes_in, len); - kb_incr(&statCounter.server.other.kbytes_in, len); + kb_incr(&(statCounter.server.all.kbytes_in), len); + kb_incr(&(statCounter.server.other.kbytes_in), len); } debugs(10, 5, HERE << conn << " read len=" << len); if (flag == COMM_OK && len > 0) { AsyncCall::Pointer nil; commSetConnTimeout(conn, Config.Timeout.read, nil); IOStats.Gopher.reads++; for (clen = len - 1, bin = 0; clen; bin++) clen >>= 1; IOStats.Gopher.read_hist[bin]++; HttpRequest *req = gopherState->fwd->request; if (req->hier.bodyBytesRead < 0) req->hier.bodyBytesRead = 0; req->hier.bodyBytesRead += len; } @@ -827,42 +828,42 @@ } AsyncCall::Pointer call = commCbCall(5,4, "gopherReadReply", CommIoCbPtrFun(gopherReadReply, gopherState)); comm_read(conn, buf, read_sz, call); } } /** \ingroup ServerProtocolGopherInternal * This will be called when request write is complete. Schedule read of reply. */ static void gopherSendComplete(const Comm::ConnectionPointer &conn, char *buf, size_t size, comm_err_t errflag, int xerrno, void *data) { GopherStateData *gopherState = (GopherStateData *) data; StoreEntry *entry = gopherState->entry; debugs(10, 5, HERE << conn << " size: " << size << " errflag: " << errflag); if (size > 0) { fd_bytes(conn->fd, size, FD_WRITE); - kb_incr(&statCounter.server.all.kbytes_out, size); - kb_incr(&statCounter.server.other.kbytes_out, size); + kb_incr(&(statCounter.server.all.kbytes_out), size); + kb_incr(&(statCounter.server.other.kbytes_out), size); } if (errflag) { ErrorState *err; err = new ErrorState(ERR_WRITE_ERROR, HTTP_SERVICE_UNAVAILABLE, gopherState->fwd->request); err->xerrno = errno; err->port = gopherState->fwd->request->port; err->url = xstrdup(entry->url()); gopherState->fwd->fail(err); gopherState->serverConn->close(); if (buf) memFree(buf, MEM_4K_BUF); /* Allocated by gopherSendRequest. */ return; } /* * OK. We successfully reach remote site. Start MIME typing * stuff. Do it anyway even though request is not HTML type. === modified file 'src/htcp.cc' --- src/htcp.cc 2011-12-03 12:40:23 +0000 +++ src/htcp.cc 2011-12-10 15:30:16 +0000 @@ -30,40 +30,41 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #include "squid.h" #include "AccessLogEntry.h" #include "acl/FilledChecklist.h" #include "acl/Acl.h" #include "comm.h" #include "comm/Loops.h" #include "htcp.h" #include "http.h" #include "HttpRequest.h" #include "icmp/net_db.h" #include "ipc/StartListening.h" #include "ip/tools.h" #include "MemBuf.h" #include "SquidTime.h" +#include "StatCounters.h" #include "Store.h" #include "StoreClient.h" #include "compat/xalloc.h" /// dials htcpIncomingConnectionOpened call class HtcpListeningStartedDialer: public CallDialer, public Ipc::StartListeningCb { public: typedef void (*Handler)(int errNo); HtcpListeningStartedDialer(Handler aHandler): handler(aHandler) {} virtual void print(std::ostream &os) const { startPrint(os) << ')'; } virtual bool canDial(AsyncCall &) const { return true; } virtual void dial(AsyncCall &) { (handler)(errNo); } public: Handler handler; }; === modified file 'src/http.cc' --- src/http.cc 2011-12-03 12:40:23 +0000 +++ src/http.cc 2011-12-10 15:30:17 +0000 @@ -51,40 +51,41 @@ #include "comm/Write.h" #if USE_DELAY_POOLS #include "DelayPools.h" #endif #include "err_detail_type.h" #include "errorpage.h" #include "fde.h" #include "http.h" #include "HttpControlMsg.h" #include "HttpHdrContRange.h" #include "HttpHdrCc.h" #include "HttpHdrSc.h" #include "HttpHdrScTarget.h" #include "HttpReply.h" #include "HttpRequest.h" #include "MemBuf.h" #include "MemObject.h" #include "protos.h" #include "rfc1738.h" #include "SquidTime.h" +#include "StatCounters.h" #include "Store.h" #define SQUID_ENTER_THROWING_CODE() try { #define SQUID_EXIT_THROWING_CODE(status) \ status = true; \ } \ catch (const std::exception &e) { \ debugs (11, 1, "Exception error:" << e.what()); \ status = false; \ } CBDATA_CLASS_INIT(HttpStateData); static const char *const crlf = "\r\n"; static void httpMaybeRemovePublic(StoreEntry *, http_status); static void copyOneHeaderFromClientsideRequestToUpstreamRequest(const HttpHeaderEntry *e, const String strConnection, const HttpRequest * request, HttpHeader * hdr_out, const int we_do_ranges, const http_state_flags); @@ -1078,42 +1079,42 @@ } else { ErrorState *err = new ErrorState(ERR_READ_ERROR, HTTP_BAD_GATEWAY, fwd->request); err->xerrno = io.xerrno; fwd->fail(err); flags.do_next_read = 0; serverConnection->close(); } return; } // update I/O stats if (len > 0) { readBuf->appended(len); reply_bytes_read += len; #if USE_DELAY_POOLS DelayId delayId = entry->mem_obj->mostBytesAllowed(); delayId.bytesIn(len); #endif - kb_incr(&statCounter.server.all.kbytes_in, len); - kb_incr(&statCounter.server.http.kbytes_in, len); + kb_incr(&(statCounter.server.all.kbytes_in), len); + kb_incr(&(statCounter.server.http.kbytes_in), len); IOStats.Http.reads++; for (clen = len - 1, bin = 0; clen; bin++) clen >>= 1; IOStats.Http.read_hist[bin]++; // update peer response time stats (%hier.peer_http_request_sent; request->hier.peer_response_time = sent.tv_sec ? tvSubMsec(sent, current_time) : -1; } /** \par * Here the RFC says we should ignore whitespace between replies, but we can't as * doing so breaks HTTP/0.9 replies beginning with witespace, and in addition * the response splitting countermeasures is extremely likely to trigger on this, * not allowing connection reuse in the first place. */ #if DONT_DO_THIS @@ -1448,42 +1449,42 @@ if (flags.do_next_read) { flags.do_next_read = 0; typedef CommCbMemFunT Dialer; entry->delayAwareRead(serverConnection, readBuf->space(read_size), read_size, JobCallback(11, 5, Dialer, this, HttpStateData::readReply)); } } /// called after writing the very last request byte (body, last-chunk, etc) void HttpStateData::wroteLast(const CommIoCbParams &io) { debugs(11, 5, HERE << serverConnection << ": size " << io.size << ": errflag " << io.flag << "."); #if URL_CHECKSUM_DEBUG entry->mem_obj->checkUrlChecksum(); #endif if (io.size > 0) { fd_bytes(io.fd, io.size, FD_WRITE); - kb_incr(&statCounter.server.all.kbytes_out, io.size); - kb_incr(&statCounter.server.http.kbytes_out, io.size); + kb_incr(&(statCounter.server.all.kbytes_out), io.size); + kb_incr(&(statCounter.server.http.kbytes_out), io.size); } if (io.flag == COMM_ERR_CLOSING) return; if (io.flag) { ErrorState *err = new ErrorState(ERR_WRITE_ERROR, HTTP_BAD_GATEWAY, fwd->request); err->xerrno = io.xerrno; fwd->fail(err); serverConnection->close(); return; } sendComplete(); } /// successfully wrote the entire request (including body, last-chunk, etc.) void HttpStateData::sendComplete() { === modified file 'src/icp_v2.cc' --- src/icp_v2.cc 2011-07-27 13:38:06 +0000 +++ src/icp_v2.cc 2011-12-15 21:17:34 +0000 @@ -29,40 +29,41 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ /** \defgroup ServerProtocolICPInternal2 ICPv2 Internals \ingroup ServerProtocolICPAPI */ #include "squid.h" #include "Store.h" #include "comm.h" #include "comm/Loops.h" #include "ICP.h" #include "comm/Connection.h" #include "HttpRequest.h" #include "acl/FilledChecklist.h" #include "acl/Acl.h" #include "AccessLogEntry.h" #include "wordlist.h" +#include "StatCounters.h" #include "SquidTime.h" #include "SwapDir.h" #include "icmp/net_db.h" #include "ip/Address.h" #include "ip/tools.h" #include "ipc/StartListening.h" #include "ipcache.h" #include "rfc1738.h" /// dials icpIncomingConnectionOpened call class IcpListeningStartedDialer: public CallDialer, public Ipc::StartListeningCb { public: typedef void (*Handler)(int errNo); IcpListeningStartedDialer(Handler aHandler): handler(aHandler) {} virtual void print(std::ostream &os) const { startPrint(os) << ')'; } virtual bool canDial(AsyncCall &) const { return true; } @@ -793,56 +794,56 @@ static void icpCount(void *buf, int which, size_t len, int delay) { icp_common_t *icp = (icp_common_t *) buf; if (len < sizeof(*icp)) return; if (SENT == which) { statCounter.icp.pkts_sent++; kb_incr(&statCounter.icp.kbytes_sent, len); if (ICP_QUERY == icp->opcode) { statCounter.icp.queries_sent++; kb_incr(&statCounter.icp.q_kbytes_sent, len); } else { statCounter.icp.replies_sent++; kb_incr(&statCounter.icp.r_kbytes_sent, len); /* this is the sent-reply service time */ - statHistCount(&statCounter.icp.reply_svc_time, delay); + statCounter.icp.replySvcTime.count(delay); } if (ICP_HIT == icp->opcode) statCounter.icp.hits_sent++; } else if (RECV == which) { statCounter.icp.pkts_recv++; kb_incr(&statCounter.icp.kbytes_recv, len); if (ICP_QUERY == icp->opcode) { statCounter.icp.queries_recv++; kb_incr(&statCounter.icp.q_kbytes_recv, len); } else { statCounter.icp.replies_recv++; kb_incr(&statCounter.icp.r_kbytes_recv, len); - /* statCounter.icp.query_svc_time set in clientUpdateCounters */ + /* statCounter.icp.querySvcTime set in clientUpdateCounters */ } if (ICP_HIT == icp->opcode) statCounter.icp.hits_recv++; } } #define N_QUERIED_KEYS 8192 #define N_QUERIED_KEYS_MASK 8191 static cache_key queried_keys[N_QUERIED_KEYS][SQUID_MD5_DIGEST_LENGTH]; int icpSetCacheKey(const cache_key * key) { static int reqnum = 0; if (++reqnum < 0) reqnum = 1; storeKeyCopy(queried_keys[reqnum & N_QUERIED_KEYS_MASK], key); === modified file 'src/ipcache.cc' --- src/ipcache.cc 2011-09-04 18:28:39 +0000 +++ src/ipcache.cc 2011-12-15 21:17:34 +0000 @@ -23,40 +23,41 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #include "squid.h" #include "cbdata.h" #include "CacheManager.h" #include "DnsLookupDetails.h" #include "event.h" #include "ip/Address.h" #include "ip/tools.h" #include "ipcache.h" #include "mgr/Registration.h" #include "SquidTime.h" +#include "StatCounters.h" #include "Store.h" #include "wordlist.h" /** \defgroup IPCacheAPI IP Cache API \ingroup Components \section Introduction Introduction \par * The IP cache is a built-in component of squid providing * Hostname to IP-Number translation functionality and managing * the involved data-structures. Efficiency concerns require * mechanisms that allow non-blocking access to these mappings. * The IP cache usually doesn't block on a request except for * special cases where this is desired (see below). * \todo IP Cache should have its own API *.h header file. */ /** \defgroup IPCacheInternal IP Cache Internals @@ -580,41 +581,41 @@ i->flags.negcached = 0; return i->addrs.count; } #endif /// \ingroup IPCacheInternal static void #if USE_DNSSERVERS ipcacheHandleReply(void *data, char *reply) #else ipcacheHandleReply(void *data, rfc1035_rr * answers, int na, const char *error_message) #endif { ipcache_entry *i; static_cast(data)->unwrap(&i); IpcacheStats.replies++; const int age = i->age(); - statHistCount(&statCounter.dns.svc_time, age); + statCounter.dns.svcTime.count(age); #if USE_DNSSERVERS ipcacheParse(i, reply); #else int done = ipcacheParse(i, answers, na, error_message); /* If we have not produced either IPs or Error immediately, wait for recursion to finish. */ if (done != 0 || error_message != NULL) #endif { ipcacheAddEntry(i); ipcacheCallback(i, age); } } /** \ingroup IPCacheAPI * === modified file 'src/main.cc' --- src/main.cc 2011-11-18 07:48:25 +0000 +++ src/main.cc 2011-12-10 15:30:19 +0000 @@ -65,40 +65,41 @@ #include "ExternalACL.h" #include "format/Token.h" #include "fs/Module.h" #include "PeerSelectState.h" #include "Store.h" #include "ICP.h" #include "ident/Ident.h" #include "HttpReply.h" #include "pconn.h" #include "Mem.h" #include "acl/Asn.h" #include "acl/Acl.h" #include "htcp.h" #include "StoreFileSystem.h" #include "DiskIO/DiskIOModule.h" #include "ipc/Kids.h" #include "ipc/Coordinator.h" #include "ipc/Strand.h" #include "ip/tools.h" #include "SquidTime.h" +#include "StatCounters.h" #include "SwapDir.h" #include "forward.h" #include "MemPool.h" #include "icmp/IcmpSquid.h" #include "icmp/net_db.h" #if USE_LOADABLE_MODULES #include "LoadableModules.h" #endif #if USE_SSL_CRTD #include "ssl/helper.h" #include "ssl/certificate_db.h" #endif #if USE_SSL #include "ssl/context_storage.h" #endif #if ICAP_CLIENT === modified file 'src/protos.h' --- src/protos.h 2011-12-07 18:56:59 +0000 +++ src/protos.h 2011-12-15 21:17:34 +0000 @@ -194,40 +194,42 @@ /// \ingroup ServerProtocolWhoisAPI SQUIDCEXTERN void whoisStart(FwdState *); /* http.c */ /* for http_hdr_type field */ #include "HttpHeader.h" SQUIDCEXTERN int httpCachable(const HttpRequestMethod&); SQUIDCEXTERN void httpStart(FwdState *); SQUIDCEXTERN mb_size_t httpBuildRequestPrefix(HttpRequest * request, HttpRequest * orig_request, StoreEntry * entry, MemBuf * mb, http_state_flags); SQUIDCEXTERN const char *httpMakeVaryMark(HttpRequest * request, HttpReply const * reply); #include "HttpStatusCode.h" SQUIDCEXTERN const char *httpStatusString(http_status status); +class StatHist; + /* Http Cache Control Header Field */ SQUIDCEXTERN void httpHdrCcInitModule(void); SQUIDCEXTERN void httpHdrCcCleanModule(void); SQUIDCEXTERN void httpHdrCcUpdateStats(const HttpHdrCc * cc, StatHist * hist); void httpHdrCcStatDumper(StoreEntry * sentry, int idx, double val, double size, int count); /* Http Header Tools */ class HttpHeaderFieldInfo; SQUIDCEXTERN HttpHeaderFieldInfo *httpHeaderBuildFieldsInfo(const HttpHeaderFieldAttrs * attrs, int count); SQUIDCEXTERN void httpHeaderDestroyFieldsInfo(HttpHeaderFieldInfo * info, int count); SQUIDCEXTERN http_hdr_type httpHeaderIdByName(const char *name, size_t name_len, const HttpHeaderFieldInfo * attrs, int end); SQUIDCEXTERN http_hdr_type httpHeaderIdByNameDef(const char *name, int name_len); SQUIDCEXTERN const char *httpHeaderNameById(int id); SQUIDCEXTERN int httpHeaderHasConnDir(const HttpHeader * hdr, const char *directive); SQUIDCEXTERN void strListAdd(String * str, const char *item, char del); SQUIDCEXTERN int strListIsMember(const String * str, const char *item, char del); SQUIDCEXTERN int strListIsSubstr(const String * list, const char *s, char del); SQUIDCEXTERN int strListGetItem(const String * str, char del, const char **item, int *ilen, const char **pos); SQUIDCEXTERN const char *getStringPrefix(const char *str, const char *end); SQUIDCEXTERN int httpHeaderParseInt(const char *start, int *val); @@ -372,55 +374,40 @@ extern void shut_down(int); extern void rotate_logs(int); extern void reconfigure(int); extern void start_announce(void *unused); extern void waisStart(FwdState *); SQUIDCEXTERN void statInit(void); SQUIDCEXTERN void statFreeMemory(void); SQUIDCEXTERN double median_svc_get(int, int); SQUIDCEXTERN void pconnHistCount(int, int); SQUIDCEXTERN int stat5minClientRequests(void); SQUIDCEXTERN double stat5minCPUUsage(void); SQUIDCEXTERN double statRequestHitRatio(int minutes); SQUIDCEXTERN double statRequestHitMemoryRatio(int minutes); SQUIDCEXTERN double statRequestHitDiskRatio(int minutes); SQUIDCEXTERN double statByteHitRatio(int minutes); -/* StatHist */ -SQUIDCEXTERN void statHistClean(StatHist * H); -SQUIDCEXTERN void statHistCount(StatHist * H, double val); -SQUIDCEXTERN void statHistCopy(StatHist * Dest, const StatHist * Orig); -SQUIDCEXTERN void statHistSafeCopy(StatHist * Dest, const StatHist * Orig); -SQUIDCEXTERN double statHistDeltaMedian(const StatHist * A, const StatHist * B); -SQUIDCEXTERN double statHistDeltaPctile(const StatHist * A, const StatHist * B, double pctile); -SQUIDCEXTERN void statHistDump(const StatHist * H, StoreEntry * sentry, StatHistBinDumper * bd); -SQUIDCEXTERN void statHistLogInit(StatHist * H, int capacity, double min, double max); -SQUIDCEXTERN void statHistEnumInit(StatHist * H, int last_enum); -SQUIDCEXTERN void statHistIntInit(StatHist * H, int n); -SQUIDCEXTERN StatHistBinDumper statHistEnumDumper; -SQUIDCEXTERN StatHistBinDumper statHistIntDumper; - - /* mem */ SQUIDCEXTERN void memClean(void); SQUIDCEXTERN void memInitModule(void); SQUIDCEXTERN void memCleanModule(void); SQUIDCEXTERN void memConfigure(void); SQUIDCEXTERN void *memAllocate(mem_type); SQUIDCEXTERN void *memAllocString(size_t net_size, size_t * gross_size); SQUIDCEXTERN void *memAllocBuf(size_t net_size, size_t * gross_size); SQUIDCEXTERN void *memReallocBuf(void *buf, size_t net_size, size_t * gross_size); SQUIDCEXTERN void memFree(void *, int type); void memFree2K(void *); void memFree4K(void *); void memFree8K(void *); void memFree16K(void *); void memFree32K(void *); void memFree64K(void *); SQUIDCEXTERN void memFreeString(size_t size, void *); SQUIDCEXTERN void memFreeBuf(size_t size, void *); SQUIDCEXTERN FREE *memFreeBufFunc(size_t size); SQUIDCEXTERN int memInUse(mem_type); @@ -610,54 +597,54 @@ SQUIDCEXTERN void parseEtcHosts(void); SQUIDCEXTERN int getMyPort(void); SQUIDCEXTERN void setUmask(mode_t mask); SQUIDCEXTERN char *strwordtok(char *buf, char **t); SQUIDCEXTERN void strwordquote(MemBuf * mb, const char *str); /* * ipc.c */ SQUIDCEXTERN pid_t ipcCreate(int type, const char *prog, const char *const args[], const char *name, Ip::Address &local_addr, int *rfd, int *wfd, void **hIpc); - +class CacheDigestGuessStats; /* CacheDigest */ SQUIDCEXTERN CacheDigest *cacheDigestCreate(int capacity, int bpe); SQUIDCEXTERN void cacheDigestDestroy(CacheDigest * cd); SQUIDCEXTERN CacheDigest *cacheDigestClone(const CacheDigest * cd); SQUIDCEXTERN void cacheDigestClear(CacheDigest * cd); SQUIDCEXTERN void cacheDigestChangeCap(CacheDigest * cd, int new_cap); SQUIDCEXTERN int cacheDigestTest(const CacheDigest * cd, const cache_key * key); SQUIDCEXTERN void cacheDigestAdd(CacheDigest * cd, const cache_key * key); SQUIDCEXTERN void cacheDigestDel(CacheDigest * cd, const cache_key * key); SQUIDCEXTERN size_t cacheDigestCalcMaskSize(int cap, int bpe); SQUIDCEXTERN int cacheDigestBitUtil(const CacheDigest * cd); -SQUIDCEXTERN void cacheDigestGuessStatsUpdate(cd_guess_stats * stats, int real_hit, int guess_hit); -SQUIDCEXTERN void cacheDigestGuessStatsReport(const cd_guess_stats * stats, StoreEntry * sentry, const char *label); +SQUIDCEXTERN void cacheDigestGuessStatsUpdate(CacheDigestGuessStats * stats, int real_hit, int guess_hit); +SQUIDCEXTERN void cacheDigestGuessStatsReport(const CacheDigestGuessStats * stats, StoreEntry * sentry, const char *label); SQUIDCEXTERN void cacheDigestReport(CacheDigest * cd, const char *label, StoreEntry * e); SQUIDCEXTERN void internalStart(const Comm::ConnectionPointer &clientConn, HttpRequest *, StoreEntry *); SQUIDCEXTERN int internalCheck(const char *urlpath); SQUIDCEXTERN int internalStaticCheck(const char *urlpath); SQUIDCEXTERN char *internalLocalUri(const char *dir, const char *name); SQUIDCEXTERN char *internalRemoteUri(const char *, unsigned short, const char *, const char *); SQUIDCEXTERN const char *internalHostname(void); SQUIDCEXTERN int internalHostnameIs(const char *); SQUIDCEXTERN void carpInit(void); SQUIDCEXTERN peer *carpSelectParent(HttpRequest *); SQUIDCEXTERN void peerUserHashInit(void); SQUIDCEXTERN peer * peerUserHashSelectParent(HttpRequest * request); SQUIDCEXTERN void peerSourceHashInit(void); SQUIDCEXTERN peer * peerSourceHashSelectParent(HttpRequest * request); #if USE_LEAKFINDER @@ -667,40 +654,41 @@ SQUIDCEXTERN void *leakFreeFL(void *, const char *, int); #endif /* * prototypes for system functions missing from system includes */ #if _SQUID_SOLARIS_ SQUIDCEXTERN int getrusage(int, struct rusage *); SQUIDCEXTERN int getpagesize(void); #if !defined(_XPG4_2) && !(defined(__EXTENSIONS__) || \ (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE))) SQUIDCEXTERN int gethostname(char *, int); #endif #endif /* * hack to allow snmp access to the statistics counters */ +class StatCounters; SQUIDCEXTERN StatCounters *snmpStatGet(int); /* Vary support functions */ SQUIDCEXTERN int varyEvaluateMatch(StoreEntry * entry, HttpRequest * req); /* CygWin & Windows NT Port */ /* win32.c */ #if _SQUID_WINDOWS_ SQUIDCEXTERN int WIN32_Subsystem_Init(int *, char ***); SQUIDCEXTERN void WIN32_sendSignal(int); SQUIDCEXTERN void WIN32_Abort(int); SQUIDCEXTERN void WIN32_Exit(void); SQUIDCEXTERN void WIN32_SetServiceCommandLine(void); SQUIDCEXTERN void WIN32_InstallService(void); SQUIDCEXTERN void WIN32_RemoveService(void); SQUIDCEXTERN int SquidMain(int, char **); #endif /* _SQUID_WINDOWS_ */ #if _SQUID_MSWIN_ SQUIDCEXTERN int WIN32_pipe(int[2]); === modified file 'src/snmp_agent.cc' --- src/snmp_agent.cc 2011-04-27 23:34:13 +0000 +++ src/snmp_agent.cc 2011-12-15 21:17:34 +0000 @@ -19,40 +19,42 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #include "squid.h" #include "cache_snmp.h" #include "Store.h" #include "mem_node.h" +#include "StatCounters.h" +#include "StatHist.h" #include "SquidMath.h" #include "SquidTime.h" /************************************************************************ SQUID MIB Implementation ************************************************************************/ /* * cacheSystem group */ variable_list * snmp_sysFn(variable_list * Var, snint * ErrP) { variable_list *Answer = NULL; MemBuf tmp; debugs(49, 5, "snmp_sysFn: Processing request:" << snmpDebugOid(Var->name, Var->name_length, tmp)); *ErrP = SNMP_ERR_NOERROR; @@ -555,77 +557,77 @@ else break; if ((minutes < 1) || (minutes > 60)) break; f = snmpStatGet(0); l = snmpStatGet(minutes); debugs(49, 8, "median: min= " << minutes << ", " << Var->name[LEN_SQ_PRF + 3] << " l= " << l << " , f = " << f); debugs(49, 8, "median: l= " << l << " , f = " << f); switch (Var->name[LEN_SQ_PRF + 3]) { case PERF_MEDIAN_TIME: x = minutes; break; case PERF_MEDIAN_HTTP_ALL: - x = statHistDeltaMedian(&l->client_http.all_svc_time, - &f->client_http.all_svc_time); + x = statHistDeltaMedian(l->client_http.allSvcTime, + f->client_http.allSvcTime); break; case PERF_MEDIAN_HTTP_MISS: - x = statHistDeltaMedian(&l->client_http.miss_svc_time, - &f->client_http.miss_svc_time); + x = statHistDeltaMedian(l->client_http.missSvcTime, + f->client_http.missSvcTime); break; case PERF_MEDIAN_HTTP_NM: - x = statHistDeltaMedian(&l->client_http.nm_svc_time, - &f->client_http.nm_svc_time); + x = statHistDeltaMedian(l->client_http.nearMissSvcTime, + f->client_http.nearMissSvcTime); break; case PERF_MEDIAN_HTTP_HIT: - x = statHistDeltaMedian(&l->client_http.hit_svc_time, - &f->client_http.hit_svc_time); + x = statHistDeltaMedian(l->client_http.hitSvcTime, + f->client_http.hitSvcTime); break; case PERF_MEDIAN_ICP_QUERY: - x = statHistDeltaMedian(&l->icp.query_svc_time, &f->icp.query_svc_time); + x = statHistDeltaMedian(l->icp.querySvcTime, f->icp.querySvcTime); break; case PERF_MEDIAN_ICP_REPLY: - x = statHistDeltaMedian(&l->icp.reply_svc_time, &f->icp.reply_svc_time); + x = statHistDeltaMedian(l->icp.replySvcTime, f->icp.replySvcTime); break; case PERF_MEDIAN_DNS: - x = statHistDeltaMedian(&l->dns.svc_time, &f->dns.svc_time); + x = statHistDeltaMedian(l->dns.svcTime, f->dns.svcTime); break; case PERF_MEDIAN_RHR: x = statRequestHitRatio(minutes); break; case PERF_MEDIAN_BHR: x = statByteHitRatio(minutes); break; case PERF_MEDIAN_HTTP_NH: - x = statHistDeltaMedian(&l->client_http.nh_svc_time, - &f->client_http.nh_svc_time); + x = statHistDeltaMedian(l->client_http.nearHitSvcTime, + f->client_http.nearHitSvcTime); break; default: *ErrP = SNMP_ERR_NOSUCHNAME; return NULL; } return snmp_var_new_integer(Var->name, Var->name_length, (snint) x, SMI_INTEGER); } *ErrP = SNMP_ERR_NOSUCHNAME; return NULL; } === modified file 'src/stat.cc' --- src/stat.cc 2011-11-18 07:48:25 +0000 +++ src/stat.cc 2011-12-15 21:17:34 +0000 @@ -37,40 +37,41 @@ #include "format/Token.h" #include "StoreClient.h" #if USE_AUTH #include "auth/UserRequest.h" #endif #include "comm/Connection.h" #include "mgr/Registration.h" #include "Store.h" #include "HttpRequest.h" #include "MemObject.h" #include "fde.h" #include "mem_node.h" #if USE_DELAY_POOLS #include "DelayId.h" #endif #include "client_side_request.h" #include "client_side.h" #include "MemBuf.h" #include "SquidMath.h" #include "SquidTime.h" +#include "StatCounters.h" #include "mgr/CountersAction.h" #include "mgr/FunAction.h" #include "mgr/InfoAction.h" #include "mgr/IntervalAction.h" #include "mgr/IoAction.h" #include "mgr/ServiceTimesAction.h" #if USE_SSL #include "ssl/support.h" #endif /* these are included because they expose stats calls */ /* TODO: provide a self registration mechanism for those classes * to use during static construction */ #include "comm.h" #include "StoreSearch.h" #define DEBUG_OPENFD 1 typedef int STOBJFLT(const StoreEntry *); @@ -1073,101 +1074,101 @@ hours = N_COUNT_HOUR_HIST - 1; l = &CountHourHist[hours]; } else { debugs(18, 1, "statAvgDump: Invalid args, minutes=" << minutes << ", hours=" << hours); return; } dt = tvSubDsec(l->timestamp, f->timestamp); ct = f->cputime - l->cputime; stats.sample_start_time = l->timestamp; stats.sample_end_time = f->timestamp; stats.client_http_requests = XAVG(client_http.requests); stats.client_http_hits = XAVG(client_http.hits); stats.client_http_errors = XAVG(client_http.errors); stats.client_http_kbytes_in = XAVG(client_http.kbytes_in.kb); stats.client_http_kbytes_out = XAVG(client_http.kbytes_out.kb); - stats.client_http_all_median_svc_time = statHistDeltaMedian(&l->client_http.all_svc_time, - &f->client_http.all_svc_time) / 1000.0; - stats.client_http_miss_median_svc_time = statHistDeltaMedian(&l->client_http.miss_svc_time, - &f->client_http.miss_svc_time) / 1000.0; - stats.client_http_nm_median_svc_time = statHistDeltaMedian(&l->client_http.nm_svc_time, - &f->client_http.nm_svc_time) / 1000.0; - stats.client_http_nh_median_svc_time = statHistDeltaMedian(&l->client_http.nh_svc_time, - &f->client_http.nh_svc_time) / 1000.0; - stats.client_http_hit_median_svc_time = statHistDeltaMedian(&l->client_http.hit_svc_time, - &f->client_http.hit_svc_time) / 1000.0; + stats.client_http_all_median_svc_time = statHistDeltaMedian(l->client_http.allSvcTime, + f->client_http.allSvcTime) / 1000.0; + stats.client_http_miss_median_svc_time = statHistDeltaMedian(l->client_http.missSvcTime, + f->client_http.missSvcTime) / 1000.0; + stats.client_http_nm_median_svc_time = statHistDeltaMedian(l->client_http.nearMissSvcTime, + f->client_http.nearMissSvcTime) / 1000.0; + stats.client_http_nh_median_svc_time = statHistDeltaMedian(l->client_http.nearHitSvcTime, + f->client_http.nearHitSvcTime) / 1000.0; + stats.client_http_hit_median_svc_time = statHistDeltaMedian(l->client_http.hitSvcTime, + f->client_http.hitSvcTime) / 1000.0; stats.server_all_requests = XAVG(server.all.requests); stats.server_all_errors = XAVG(server.all.errors); stats.server_all_kbytes_in = XAVG(server.all.kbytes_in.kb); stats.server_all_kbytes_out = XAVG(server.all.kbytes_out.kb); stats.server_http_requests = XAVG(server.http.requests); stats.server_http_errors = XAVG(server.http.errors); stats.server_http_kbytes_in = XAVG(server.http.kbytes_in.kb); stats.server_http_kbytes_out = XAVG(server.http.kbytes_out.kb); stats.server_ftp_requests = XAVG(server.ftp.requests); stats.server_ftp_errors = XAVG(server.ftp.errors); stats.server_ftp_kbytes_in = XAVG(server.ftp.kbytes_in.kb); stats.server_ftp_kbytes_out = XAVG(server.ftp.kbytes_out.kb); stats.server_other_requests = XAVG(server.other.requests); stats.server_other_errors = XAVG(server.other.errors); stats.server_other_kbytes_in = XAVG(server.other.kbytes_in.kb); stats.server_other_kbytes_out = XAVG(server.other.kbytes_out.kb); stats.icp_pkts_sent = XAVG(icp.pkts_sent); stats.icp_pkts_recv = XAVG(icp.pkts_recv); stats.icp_queries_sent = XAVG(icp.queries_sent); stats.icp_replies_sent = XAVG(icp.replies_sent); stats.icp_queries_recv = XAVG(icp.queries_recv); stats.icp_replies_recv = XAVG(icp.replies_recv); stats.icp_replies_queued = XAVG(icp.replies_queued); stats.icp_query_timeouts = XAVG(icp.query_timeouts); stats.icp_kbytes_sent = XAVG(icp.kbytes_sent.kb); stats.icp_kbytes_recv = XAVG(icp.kbytes_recv.kb); stats.icp_q_kbytes_sent = XAVG(icp.q_kbytes_sent.kb); stats.icp_r_kbytes_sent = XAVG(icp.r_kbytes_sent.kb); stats.icp_q_kbytes_recv = XAVG(icp.q_kbytes_recv.kb); stats.icp_r_kbytes_recv = XAVG(icp.r_kbytes_recv.kb); - stats.icp_query_median_svc_time = statHistDeltaMedian(&l->icp.query_svc_time, - &f->icp.query_svc_time) / 1000000.0; - stats.icp_reply_median_svc_time = statHistDeltaMedian(&l->icp.reply_svc_time, - &f->icp.reply_svc_time) / 1000000.0; - stats.dns_median_svc_time = statHistDeltaMedian(&l->dns.svc_time, - &f->dns.svc_time) / 1000.0; + stats.icp_query_median_svc_time = statHistDeltaMedian(l->icp.querySvcTime, + f->icp.querySvcTime) / 1000000.0; + stats.icp_reply_median_svc_time = statHistDeltaMedian(l->icp.replySvcTime, + f->icp.replySvcTime) / 1000000.0; + stats.dns_median_svc_time = statHistDeltaMedian(l->dns.svcTime, + f->dns.svcTime) / 1000.0; stats.unlink_requests = XAVG(unlink.requests); stats.page_faults = XAVG(page_faults); stats.select_loops = XAVG(select_loops); stats.select_fds = XAVG(select_fds); stats.average_select_fd_period = f->select_fds > l->select_fds ? (f->select_time - l->select_time) / (f->select_fds - l->select_fds) : 0.0; - stats.median_select_fds = statHistDeltaMedian(&l->select_fds_hist, &f->select_fds_hist); + stats.median_select_fds = statHistDeltaMedian(l->select_fds_hist, f->select_fds_hist); stats.swap_outs = XAVG(swap.outs); stats.swap_ins = XAVG(swap.ins); stats.swap_files_cleaned = XAVG(swap.files_cleaned); stats.aborted_requests = XAVG(aborted_requests); stats.syscalls_disk_opens = XAVG(syscalls.disk.opens); stats.syscalls_disk_closes = XAVG(syscalls.disk.closes); stats.syscalls_disk_reads = XAVG(syscalls.disk.reads); stats.syscalls_disk_writes = XAVG(syscalls.disk.writes); stats.syscalls_disk_seeks = XAVG(syscalls.disk.seeks); stats.syscalls_disk_unlinks = XAVG(syscalls.disk.unlinks); stats.syscalls_sock_accepts = XAVG(syscalls.sock.accepts); stats.syscalls_sock_sockets = XAVG(syscalls.sock.sockets); stats.syscalls_sock_connects = XAVG(syscalls.sock.connects); stats.syscalls_sock_binds = XAVG(syscalls.sock.binds); stats.syscalls_sock_closes = XAVG(syscalls.sock.closes); stats.syscalls_sock_reads = XAVG(syscalls.sock.reads); stats.syscalls_sock_writes = XAVG(syscalls.sock.writes); stats.syscalls_sock_recvfroms = XAVG(syscalls.sock.recvfroms); stats.syscalls_sock_sendtos = XAVG(syscalls.sock.sendtos); @@ -1468,131 +1469,131 @@ debugs(18, 0, "WARNING: Memory usage at " << ((unsigned long int)(i >> 20)) << " MB"); } } static void statCountersInit(StatCounters * C) { assert(C); memset(C, 0, sizeof(*C)); C->timestamp = current_time; statCountersInitSpecial(C); } /* add special cases here as they arrive */ static void statCountersInitSpecial(StatCounters * C) { /* * HTTP svc_time hist is kept in milli-seconds; max of 3 hours. */ - statHistLogInit(&C->client_http.all_svc_time, 300, 0.0, 3600000.0 * 3.0); - statHistLogInit(&C->client_http.miss_svc_time, 300, 0.0, 3600000.0 * 3.0); - statHistLogInit(&C->client_http.nm_svc_time, 300, 0.0, 3600000.0 * 3.0); - statHistLogInit(&C->client_http.nh_svc_time, 300, 0.0, 3600000.0 * 3.0); - statHistLogInit(&C->client_http.hit_svc_time, 300, 0.0, 3600000.0 * 3.0); + C->client_http.allSvcTime.logInit(300, 0.0, 3600000.0 * 3.0); + C->client_http.missSvcTime.logInit(300, 0.0, 3600000.0 * 3.0); + C->client_http.nearMissSvcTime.logInit(300, 0.0, 3600000.0 * 3.0); + C->client_http.nearHitSvcTime.logInit(300, 0.0, 3600000.0 * 3.0); + C->client_http.hitSvcTime.logInit(300, 0.0, 3600000.0 * 3.0); /* * ICP svc_time hist is kept in micro-seconds; max of 1 minute. */ - statHistLogInit(&C->icp.query_svc_time, 300, 0.0, 1000000.0 * 60.0); - statHistLogInit(&C->icp.reply_svc_time, 300, 0.0, 1000000.0 * 60.0); + C->icp.querySvcTime.logInit(300, 0.0, 1000000.0 * 60.0); + C->icp.replySvcTime.logInit(300, 0.0, 1000000.0 * 60.0); /* * DNS svc_time hist is kept in milli-seconds; max of 10 minutes. */ - statHistLogInit(&C->dns.svc_time, 300, 0.0, 60000.0 * 10.0); + C->dns.svcTime.logInit(300, 0.0, 60000.0 * 10.0); /* * Cache Digest Stuff */ - statHistEnumInit(&C->cd.on_xition_count, CacheDigestHashFuncCount); - statHistEnumInit(&C->comm_icp_incoming, INCOMING_ICP_MAX); - statHistEnumInit(&C->comm_dns_incoming, INCOMING_DNS_MAX); - statHistEnumInit(&C->comm_http_incoming, INCOMING_HTTP_MAX); - statHistIntInit(&C->select_fds_hist, 256); /* was SQUID_MAXFD, but it is way too much. It is OK to crop this statistics */ + C->cd.on_xition_count.enumInit(CacheDigestHashFuncCount); + C->comm_icp_incoming.enumInit(INCOMING_ICP_MAX); + C->comm_dns_incoming.enumInit(INCOMING_DNS_MAX); + C->comm_http_incoming.enumInit(INCOMING_HTTP_MAX); + C->select_fds_hist.enumInit(256); /* was SQUID_MAXFD, but it is way too much. It is OK to crop this statistics */ } /* add special cases here as they arrive */ static void statCountersClean(StatCounters * C) { assert(C); - statHistClean(&C->client_http.all_svc_time); - statHistClean(&C->client_http.miss_svc_time); - statHistClean(&C->client_http.nm_svc_time); - statHistClean(&C->client_http.nh_svc_time); - statHistClean(&C->client_http.hit_svc_time); - statHistClean(&C->icp.query_svc_time); - statHistClean(&C->icp.reply_svc_time); - statHistClean(&C->dns.svc_time); - statHistClean(&C->cd.on_xition_count); - statHistClean(&C->comm_icp_incoming); - statHistClean(&C->comm_dns_incoming); - statHistClean(&C->comm_http_incoming); - statHistClean(&C->select_fds_hist); + C->client_http.allSvcTime.clear(); + C->client_http.missSvcTime.clear(); + C->client_http.nearMissSvcTime.clear(); + C->client_http.nearHitSvcTime.clear(); + C->client_http.hitSvcTime.clear(); + C->icp.querySvcTime.clear(); + C->icp.replySvcTime.clear(); + C->dns.svcTime.clear(); + C->cd.on_xition_count.clear(); + C->comm_icp_incoming.clear(); + C->comm_dns_incoming.clear(); + C->comm_http_incoming.clear(); + C->select_fds_hist.clear(); } /* add special cases here as they arrive */ static void statCountersCopy(StatCounters * dest, const StatCounters * orig) { assert(dest && orig); /* this should take care of all the fields, but "special" ones */ memcpy(dest, orig, sizeof(*dest)); /* prepare space where to copy special entries */ statCountersInitSpecial(dest); /* now handle special cases */ /* note: we assert that histogram capacities do not change */ - statHistCopy(&dest->client_http.all_svc_time, &orig->client_http.all_svc_time); - statHistCopy(&dest->client_http.miss_svc_time, &orig->client_http.miss_svc_time); - statHistCopy(&dest->client_http.nm_svc_time, &orig->client_http.nm_svc_time); - statHistCopy(&dest->client_http.nh_svc_time, &orig->client_http.nh_svc_time); - statHistCopy(&dest->client_http.hit_svc_time, &orig->client_http.hit_svc_time); - statHistCopy(&dest->icp.query_svc_time, &orig->icp.query_svc_time); - statHistCopy(&dest->icp.reply_svc_time, &orig->icp.reply_svc_time); - statHistCopy(&dest->dns.svc_time, &orig->dns.svc_time); - statHistCopy(&dest->cd.on_xition_count, &orig->cd.on_xition_count); - statHistCopy(&dest->comm_icp_incoming, &orig->comm_icp_incoming); - statHistCopy(&dest->comm_http_incoming, &orig->comm_http_incoming); - statHistCopy(&dest->select_fds_hist, &orig->select_fds_hist); + dest->client_http.allSvcTime=orig->client_http.allSvcTime; + dest->client_http.missSvcTime=orig->client_http.missSvcTime; + dest->client_http.nearMissSvcTime=orig->client_http.nearMissSvcTime; + dest->client_http.nearHitSvcTime=orig->client_http.nearHitSvcTime; + + dest->client_http.hitSvcTime=orig->client_http.hitSvcTime; + dest->icp.querySvcTime=orig->icp.querySvcTime; + dest->icp.replySvcTime=orig->icp.replySvcTime; + dest->dns.svcTime=orig->dns.svcTime; + dest->cd.on_xition_count=orig->cd.on_xition_count; + dest->comm_icp_incoming=orig->comm_icp_incoming; + dest->comm_http_incoming=orig->comm_http_incoming; + dest->select_fds_hist=orig->select_fds_hist; } static void statCountersHistograms(StoreEntry * sentry) { - StatCounters *f = &statCounter; - storeAppendPrintf(sentry, "client_http.all_svc_time histogram:\n"); - statHistDump(&f->client_http.all_svc_time, sentry, NULL); - storeAppendPrintf(sentry, "client_http.miss_svc_time histogram:\n"); - statHistDump(&f->client_http.miss_svc_time, sentry, NULL); - storeAppendPrintf(sentry, "client_http.nm_svc_time histogram:\n"); - statHistDump(&f->client_http.nm_svc_time, sentry, NULL); - storeAppendPrintf(sentry, "client_http.nh_svc_time histogram:\n"); - statHistDump(&f->client_http.nh_svc_time, sentry, NULL); - storeAppendPrintf(sentry, "client_http.hit_svc_time histogram:\n"); - statHistDump(&f->client_http.hit_svc_time, sentry, NULL); - storeAppendPrintf(sentry, "icp.query_svc_time histogram:\n"); - statHistDump(&f->icp.query_svc_time, sentry, NULL); - storeAppendPrintf(sentry, "icp.reply_svc_time histogram:\n"); - statHistDump(&f->icp.reply_svc_time, sentry, NULL); + storeAppendPrintf(sentry, "client_http.allSvcTime histogram:\n"); + statCounter.client_http.allSvcTime.dump(sentry, NULL); + storeAppendPrintf(sentry, "client_http.missSvcTime histogram:\n"); + statCounter.client_http.missSvcTime.dump(sentry, NULL); + storeAppendPrintf(sentry, "client_http.nearMissSvcTime histogram:\n"); + statCounter.client_http.nearMissSvcTime.dump(sentry, NULL); + storeAppendPrintf(sentry, "client_http.nearHitSvcTime histogram:\n"); + statCounter.client_http.nearHitSvcTime.dump(sentry, NULL); + storeAppendPrintf(sentry, "client_http.hitSvcTime histogram:\n"); + statCounter.client_http.hitSvcTime.dump(sentry, NULL); + storeAppendPrintf(sentry, "icp.querySvcTime histogram:\n"); + statCounter.icp.querySvcTime.dump(sentry, NULL); + storeAppendPrintf(sentry, "icp.replySvcTime histogram:\n"); + statCounter.icp.replySvcTime.dump(sentry, NULL); storeAppendPrintf(sentry, "dns.svc_time histogram:\n"); - statHistDump(&f->dns.svc_time, sentry, NULL); + statCounter.dns.svcTime.dump(sentry, NULL); storeAppendPrintf(sentry, "select_fds_hist histogram:\n"); - statHistDump(&f->select_fds_hist, sentry, NULL); + statCounter.select_fds_hist.dump(sentry, NULL); } static void statCountersDump(StoreEntry * sentry) { Mgr::CountersActionData stats; GetCountersStats(stats); DumpCountersStats(stats, sentry); } void GetCountersStats(Mgr::CountersActionData& stats) { StatCounters *f = &statCounter; struct rusage rusage; squid_getrusage(&rusage); f->page_faults = rusage_pagefaults(&rusage); f->cputime = rusage_cputime(&rusage); @@ -1854,65 +1855,65 @@ { StatCounters *f; StatCounters *l; double x; assert(interval > 0); if (interval > N_COUNT_HIST - 1) interval = N_COUNT_HIST - 1; f = &CountHist[0]; l = &CountHist[interval]; assert(f); assert(l); switch (which) { case PCTILE_HTTP: - x = statHistDeltaPctile(&l->client_http.all_svc_time, &f->client_http.all_svc_time, pctile); + x = statHistDeltaPctile(l->client_http.allSvcTime,f->client_http.allSvcTime, pctile); break; case PCTILE_HIT: - x = statHistDeltaPctile(&l->client_http.hit_svc_time, &f->client_http.hit_svc_time, pctile); + x = statHistDeltaPctile(l->client_http.hitSvcTime,f->client_http.hitSvcTime, pctile); break; case PCTILE_MISS: - x = statHistDeltaPctile(&l->client_http.miss_svc_time, &f->client_http.miss_svc_time, pctile); + x = statHistDeltaPctile(l->client_http.missSvcTime,f->client_http.missSvcTime, pctile); break; case PCTILE_NM: - x = statHistDeltaPctile(&l->client_http.nm_svc_time, &f->client_http.nm_svc_time, pctile); + x = statHistDeltaPctile(l->client_http.nearMissSvcTime,f->client_http.nearMissSvcTime, pctile); break; case PCTILE_NH: - x = statHistDeltaPctile(&l->client_http.nh_svc_time, &f->client_http.nh_svc_time, pctile); + x = statHistDeltaPctile(l->client_http.nearHitSvcTime,f->client_http.nearHitSvcTime, pctile); break; case PCTILE_ICP_QUERY: - x = statHistDeltaPctile(&l->icp.query_svc_time, &f->icp.query_svc_time, pctile); + x = statHistDeltaPctile(l->icp.querySvcTime,f->icp.querySvcTime, pctile); break; case PCTILE_DNS: - x = statHistDeltaPctile(&l->dns.svc_time, &f->dns.svc_time, pctile); + x = statHistDeltaPctile(l->dns.svcTime,f->dns.svcTime, pctile); break; default: debugs(49, 5, "statPctileSvc: unknown type."); x = 0; } return x; } StatCounters * snmpStatGet(int minutes) { return &CountHist[minutes]; } int stat5minClientRequests(void) { assert(N_COUNT_HIST > 5); === modified file 'src/store.cc' --- src/store.cc 2011-12-04 13:52:07 +0000 +++ src/store.cc 2011-12-10 15:30:20 +0000 @@ -30,40 +30,41 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #include "squid.h" #include "CacheManager.h" #include "comm/Connection.h" #include "ETag.h" #include "event.h" #include "fde.h" #include "Store.h" #include "mgr/Registration.h" #include "StoreClient.h" #include "stmem.h" #include "HttpReply.h" #include "HttpRequest.h" #include "MemObject.h" #include "mem_node.h" +#include "StatCounters.h" #include "StoreMeta.h" #include "SwapDir.h" #include "StoreIOState.h" #if USE_DELAY_POOLS #include "DelayPools.h" #endif #include "Stack.h" #include "SquidTime.h" #include "swap_log_op.h" #include "mgr/StoreIoAction.h" static STMCB storeWriteComplete; #define REBUILD_TIMESTAMP_DELTA_MAX 2 #define STORE_IN_MEM_BUCKETS (229) /** \todo Convert these string constants to enum string-arrays generated */ === modified file 'src/store_client.cc' --- src/store_client.cc 2011-11-18 16:53:45 +0000 +++ src/store_client.cc 2011-12-10 15:30:19 +0000 @@ -23,40 +23,41 @@ * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * * Portions copyright (c) 2003 Robert Collins */ #include "squid.h" #include "event.h" #include "StoreClient.h" #include "Store.h" #include "HttpReply.h" #include "MemObject.h" +#include "StatCounters.h" #include "StoreMeta.h" #include "StoreMetaUnpacker.h" #if USE_DELAY_POOLS #include "DelayPools.h" #endif #include "HttpRequest.h" #include "MemBuf.h" /* * NOTE: 'Header' refers to the swapfile metadata header. * 'OBJHeader' refers to the object header, with cannonical * processed object headers (which may derive from FTP/HTTP etc * upstream protocols * 'Body' refers to the swapfile body, which is the full * HTTP reply (including HTTP headers and body). */ static StoreIOState::STRCB storeClientReadBody; static StoreIOState::STRCB storeClientReadHeader; static void storeClientCopy2(StoreEntry * e, store_client * sc); static EVH storeClientCopyEvent; === modified file 'src/store_rebuild.cc' --- src/store_rebuild.cc 2011-09-06 22:32:30 +0000 +++ src/store_rebuild.cc 2011-12-10 15:30:19 +0000 @@ -18,40 +18,41 @@ * sources; see the CREDITS file for full details. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #include "squid.h" #include "event.h" +#include "StatCounters.h" #include "Store.h" #include "SwapDir.h" #include "StoreSearch.h" #include "SquidTime.h" static struct _store_rebuild_data counts; static struct timeval rebuild_start; static void storeCleanup(void *); typedef struct { /* total number of "swap.state" entries that will be read */ int total; /* number of entries read so far */ int scanned; } store_rebuild_progress; static store_rebuild_progress *RebuildProgress = NULL; static int === modified file 'src/store_swapin.cc' --- src/store_swapin.cc 2011-02-04 22:18:41 +0000 +++ src/store_swapin.cc 2011-12-10 15:30:19 +0000 @@ -17,40 +17,41 @@ * incorporates software developed and/or copyrighted by other * sources; see the CREDITS file for full details. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #include "squid.h" +#include "StatCounters.h" #include "StoreClient.h" #include "Store.h" static StoreIOState::STIOCB storeSwapInFileClosed; static StoreIOState::STFNCB storeSwapInFileNotify; void storeSwapInStart(store_client * sc) { StoreEntry *e = sc->entry; if (!EBIT_TEST(e->flags, ENTRY_VALIDATED)) { /* We're still reloading and haven't validated this entry yet */ return; } if (e->mem_status != NOT_IN_MEMORY) debugs(20, 3, HERE << "already IN_MEMORY"); debugs(20, 3, "storeSwapInStart: called for : " << e->swap_dirn << " " << @@ -67,37 +68,37 @@ return; } assert(e->mem_obj != NULL); debugs(20, 3, "storeSwapInStart: Opening fileno " << std::hex << std::setw(8) << std::setfill('0') << std::uppercase << e->swap_filen); sc->swapin_sio = storeOpen(e, storeSwapInFileNotify, storeSwapInFileClosed, sc); } static void storeSwapInFileClosed(void *data, int errflag, StoreIOState::Pointer self) { store_client *sc = (store_client *)data; debugs(20, 3, "storeSwapInFileClosed: sio=" << sc->swapin_sio.getRaw() << ", errflag=" << errflag); sc->swapin_sio = NULL; if (sc->_callback.pending()) { assert (errflag <= 0); sc->callback(0, errflag ? true : false); } - statCounter.swap.ins++; + ++statCounter.swap.ins; } static void storeSwapInFileNotify(void *data, int errflag, StoreIOState::Pointer self) { store_client *sc = (store_client *)data; StoreEntry *e = sc->entry; debugs(1, 3, "storeSwapInFileNotify: changing " << e->swap_filen << "/" << e->swap_dirn << " to " << sc->swapin_sio->swap_filen << "/" << sc->swapin_sio->swap_dirn); assert(e->swap_filen < 0); // if this fails, call SwapDir::disconnect(e) e->swap_filen = sc->swapin_sio->swap_filen; e->swap_dirn = sc->swapin_sio->swap_dirn; } === modified file 'src/store_swapout.cc' --- src/store_swapout.cc 2011-09-06 22:32:30 +0000 +++ src/store_swapout.cc 2011-12-10 15:30:20 +0000 @@ -24,40 +24,41 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #include "squid.h" #include "cbdata.h" #include "StoreClient.h" #include "Store.h" /* FIXME: Abstract the use of this more */ #include "mem_node.h" #include "MemObject.h" #include "SwapDir.h" +#include "StatCounters.h" #include "swap_log_op.h" static void storeSwapOutStart(StoreEntry * e); static StoreIOState::STIOCB storeSwapOutFileClosed; static StoreIOState::STFNCB storeSwapOutFileNotify; // wrapper to cross C/C++ ABI boundary. xfree is extern "C" for libraries. static void xfree_cppwrapper(void *x) { xfree(x); } /* start swapping object to disk */ static void storeSwapOutStart(StoreEntry * e) { MemObject *mem = e->mem_obj; StoreIOState::Pointer sio; assert(mem); /* Build the swap metadata, so the filesystem will know how much @@ -348,41 +349,41 @@ /* swapping complete */ debugs(20, 3, "storeSwapOutFileClosed: SwapOut complete: '" << e->url() << "' to " << e->swap_dirn << ", " << std::hex << std::setw(8) << std::setfill('0') << std::uppercase << e->swap_filen); debugs(20, 5, HERE << "swap_file_sz = " << e->objectLen() << " + " << mem->swap_hdr_sz); e->swap_file_sz = e->objectLen() + mem->swap_hdr_sz; e->swap_status = SWAPOUT_DONE; e->store()->swappedOut(*e); // XXX: For some Stores, it is pointless to re-check cachability here // and it leads to double counts in store_check_cachable_hist. We need // another way to signal a completed but failed swapout. Or, better, // each Store should handle its own logging and LOG state setting. if (e->checkCachable()) { storeLog(STORE_LOG_SWAPOUT, e); storeDirSwapLog(e, SWAP_LOG_ADD); } - statCounter.swap.outs++; + ++statCounter.swap.outs; } debugs(20, 3, "storeSwapOutFileClosed: " << __FILE__ << ":" << __LINE__); mem->swapout.sio = NULL; e->unlock(); } /* * Is this entry a candidate for writing to disk? */ bool StoreEntry::swapOutAble() const { dlink_node *node; if (mem_obj->swapout.sio != NULL) return true; if (mem_obj->inmem_lo > 0) return false; === modified file 'src/structs.h' --- src/structs.h 2011-12-08 21:58:09 +0000 +++ src/structs.h 2011-12-13 17:33:34 +0000 @@ -740,55 +740,40 @@ unsigned int request_sent:1; unsigned int do_next_read:1; unsigned int consume_body_data:1; unsigned int chunked:1; ///< reading a chunked response; TODO: rename unsigned int chunked_request:1; ///< writing a chunked request unsigned int sentLastChunk:1; ///< do not try to write last-chunk again }; struct _domain_ping { char *domain; int do_ping; /* boolean */ domain_ping *next; }; struct _domain_type { char *domain; peer_t type; domain_type *next; }; -#if USE_CACHE_DIGESTS - -/* statistics for cache digests and other hit "predictors" */ - -struct _cd_guess_stats { - /* public, read-only */ - int true_hits; - int false_hits; - int true_misses; - int false_misses; - int close_hits; /* tmp, remove it later */ -}; - -#endif - class PeerDigest; struct peer { u_int index; char *name; char *host; peer_t type; Ip::Address in_addr; struct { int pings_sent; int pings_acked; int fetches; int rtt; int ignored_replies; int n_keepalives_sent; int n_keepalives_recv; time_t probe_start; time_t last_query; @@ -1067,205 +1052,40 @@ struct { unsigned int icase:1; unsigned int refresh_ims:1; unsigned int store_stale:1; #if USE_HTTP_VIOLATIONS unsigned int override_expire:1; unsigned int override_lastmod:1; unsigned int reload_into_ims:1; unsigned int ignore_reload:1; unsigned int ignore_no_cache:1; unsigned int ignore_no_store:1; unsigned int ignore_must_revalidate:1; unsigned int ignore_private:1; unsigned int ignore_auth:1; #endif } flags; int max_stale; }; -/* - * "very generic" histogram; - * see important comments on hbase_f restrictions in StatHist.c - */ - -struct _StatHist { - int *bins; - int capacity; - double min; - double max; - double scale; - hbase_f *val_in; /* e.g., log() for log-based histogram */ - hbase_f *val_out; /* e.g., exp() for log based histogram */ -}; - -/* - * if you add a field to StatCounters, - * you MUST sync statCountersInitSpecial, statCountersClean, and statCountersCopy - */ - -struct _StatCounters { - - struct { - int clients; - int requests; - int hits; - int mem_hits; - int disk_hits; - int errors; - kb_t kbytes_in; - kb_t kbytes_out; - kb_t hit_kbytes_out; - StatHist miss_svc_time; - StatHist nm_svc_time; - StatHist nh_svc_time; - StatHist hit_svc_time; - StatHist all_svc_time; - } client_http; - - struct { - - struct { - int requests; - int errors; - kb_t kbytes_in; - kb_t kbytes_out; - } all , http, ftp, other; - } server; - - struct { - int pkts_sent; - int queries_sent; - int replies_sent; - int pkts_recv; - int queries_recv; - int replies_recv; - int hits_sent; - int hits_recv; - int replies_queued; - int replies_dropped; - kb_t kbytes_sent; - kb_t q_kbytes_sent; - kb_t r_kbytes_sent; - kb_t kbytes_recv; - kb_t q_kbytes_recv; - kb_t r_kbytes_recv; - StatHist query_svc_time; - StatHist reply_svc_time; - int query_timeouts; - int times_used; - } icp; - - struct { - int pkts_sent; - int pkts_recv; - } htcp; - - struct { - int requests; - } unlink; - - struct { - StatHist svc_time; - } dns; - - struct { - int times_used; - kb_t kbytes_sent; - kb_t kbytes_recv; - kb_t memory; - int msgs_sent; - int msgs_recv; -#if USE_CACHE_DIGESTS - - cd_guess_stats guess; -#endif - - StatHist on_xition_count; - } cd; - - struct { - int times_used; - } netdb; - int page_faults; - unsigned long int select_loops; - int select_fds; - double select_time; - double cputime; - - struct timeval timestamp; - StatHist comm_icp_incoming; - StatHist comm_dns_incoming; - StatHist comm_http_incoming; - StatHist select_fds_hist; - - struct { - struct { - int opens; - int closes; - int reads; - int writes; - int seeks; - int unlinks; - } disk; - - struct { - int accepts; - int sockets; - int connects; - int binds; - int closes; - int reads; - int writes; - int recvfroms; - int sendtos; - } sock; - int selects; - } syscalls; - int aborted_requests; - - struct { - int files_cleaned; - int outs; - int ins; - } swap; -}; - -/* per header statistics */ - -struct _HttpHeaderStat { - const char *label; - HttpHeaderMask *owner_mask; - - StatHist hdrUCountDistr; - StatHist fieldTypeDistr; - StatHist ccTypeDistr; - StatHist scTypeDistr; - - int parsedCount; - int ccParsedCount; - int scParsedCount; - int destroyedCount; - int busyDestroyedCount; -}; - struct _CacheDigest { /* public, read-only */ char *mask; /* bit mask */ int mask_size; /* mask size in bytes */ int capacity; /* expected maximum for .count, not a hard limit */ int bits_per_entry; /* number of bits allocated for each entry from capacity */ int count; /* number of digested entries */ int del_count; /* number of deletions performed so far */ }; struct _store_rebuild_data { int objcount; /* # objects successfully reloaded */ int expcount; /* # objects expired */ int scancount; /* # entries scanned or read from state file */ int clashcount; /* # swapfile clashes avoided */ int dupcount; /* # duplicates purged */ int cancelcount; /* # SWAP_LOG_DEL objects purged */ int invalid; /* # bad lines */ === modified file 'src/tests/stub_StatHist.cc' --- src/tests/stub_StatHist.cc 2009-07-26 09:24:07 +0000 +++ src/tests/stub_StatHist.cc 2011-12-15 07:00:14 +0000 @@ -1,22 +1,24 @@ -#include "squid.h" +#include "config.h" +#include "STUB.h" +#include "StatHist.h" -// for StatHist definitions -#include "protos.h" +#define STUB_API "StatHist.cc" void -statHistDump(const StatHist * H, StoreEntry * sentry, StatHistBinDumper * bd) -{ - fatal("statHistDump: Not implemented"); -} +StatHist::init(int capacity_, hbase_f * val_in_, hbase_f * val_out_, double min_, double max_) +{} + +StatHist::~StatHist() +{} + +void +StatHist::enumInit(int last_enum) +{} void -statHistCount(StatHist * H, double val) -{ - fatal("statHistCount: Not implemented"); -} +StatHist::count(double val) +{} void -statHistEnumInit(StatHist * H, int last_enum) -{ -//NO-OP fatal("statHistEnumInit: Not implemented"); -} +StatHist::dump(StoreEntry * sentry, StatHistBinDumper * bd) const +{} === modified file 'src/tunnel.cc' --- src/tunnel.cc 2011-11-28 01:39:47 +0000 +++ src/tunnel.cc 2011-12-10 15:30:20 +0000 @@ -34,40 +34,41 @@ */ #include "squid.h" #include "errorpage.h" #include "HttpRequest.h" #include "fde.h" #include "Array.h" #include "comm.h" #include "comm/Connection.h" #include "comm/ConnOpener.h" #include "comm/Write.h" #include "client_side_request.h" #include "acl/FilledChecklist.h" #if USE_DELAY_POOLS #include "DelayId.h" #endif #include "client_side.h" #include "MemBuf.h" #include "http.h" #include "PeerSelectState.h" +#include "StatCounters.h" class TunnelStateData { public: class Connection; void *operator new(size_t); void operator delete (void *); static void ReadClient(const Comm::ConnectionPointer &, char *buf, size_t len, comm_err_t errcode, int xerrno, void *data); static void ReadServer(const Comm::ConnectionPointer &, char *buf, size_t len, comm_err_t errcode, int xerrno, void *data); static void WriteClientDone(const Comm::ConnectionPointer &, char *buf, size_t len, comm_err_t flag, int xerrno, void *data); static void WriteServerDone(const Comm::ConnectionPointer &, char *buf, size_t len, comm_err_t flag, int xerrno, void *data); bool noConnections() const; char *url; HttpRequest *request; Comm::ConnectionList serverDestinations; const char * getHost() const { @@ -232,42 +233,42 @@ debugs(26, 3, HERE << c); tunnelState->readServer(buf, len, errcode, xerrno); } void TunnelStateData::readServer(char *buf, size_t len, comm_err_t errcode, int xerrno) { debugs(26, 3, HERE << server.conn << ", read " << len << " bytes, err=" << errcode); /* * Bail out early on COMM_ERR_CLOSING * - close handlers will tidy up for us */ if (errcode == COMM_ERR_CLOSING) return; if (len > 0) { server.bytesIn(len); - kb_incr(&statCounter.server.all.kbytes_in, len); - kb_incr(&statCounter.server.other.kbytes_in, len); + kb_incr(&(statCounter.server.all.kbytes_in), len); + kb_incr(&(statCounter.server.other.kbytes_in), len); } copy (len, errcode, xerrno, server, client, WriteClientDone); } void TunnelStateData::Connection::error(int const xerrno) { /* XXX fixme xstrerror and xerrno... */ errno = xerrno; debugs(50, debugLevelForError(xerrno), HERE << conn << ": read/write failure: " << xstrerror()); if (!ignoreErrno(xerrno)) conn->close(); } /* Read from client side and queue it for writing to the server */ void TunnelStateData::ReadClient(const Comm::ConnectionPointer &, char *buf, size_t len, comm_err_t errcode, int xerrno, void *data) @@ -276,41 +277,41 @@ assert (cbdataReferenceValid (tunnelState)); tunnelState->readClient(buf, len, errcode, xerrno); } void TunnelStateData::readClient(char *buf, size_t len, comm_err_t errcode, int xerrno) { debugs(26, 3, HERE << client.conn << ", read " << len << " bytes, err=" << errcode); /* * Bail out early on COMM_ERR_CLOSING * - close handlers will tidy up for us */ if (errcode == COMM_ERR_CLOSING) return; if (len > 0) { client.bytesIn(len); - kb_incr(&statCounter.client_http.kbytes_in, len); + kb_incr(&(statCounter.client_http.kbytes_in), len); } copy (len, errcode, xerrno, client, server, WriteServerDone); } void TunnelStateData::copy (size_t len, comm_err_t errcode, int xerrno, Connection &from, Connection &to, IOCB *completion) { debugs(26, 3, HERE << "from={" << from.conn << "}, to={" << to.conn << "}"); /* I think this is to prevent free-while-in-a-callback behaviour * - RBC 20030229 * from.conn->close() / to.conn->close() done here trigger close callbacks which may free TunnelStateData */ cbdataInternalLock(this); /* ??? should be locked by the caller... */ /* Bump the source connection read timeout on any activity */ if (Comm::IsConnOpen(from.conn)) { AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "tunnelTimeout", CommTimeoutCbPtrFun(tunnelTimeout, this)); @@ -352,42 +353,42 @@ { debugs(26, 3, HERE << server.conn << ", " << len << " bytes written, flag=" << flag); /* Error? */ if (flag != COMM_OK) { if (flag != COMM_ERR_CLOSING) { debugs(26, 4, HERE << "calling TunnelStateData::server.error(" << xerrno <<")"); server.error(xerrno); // may call comm_close } return; } /* EOF? */ if (len == 0) { debugs(26, 4, HERE << "No read input. Closing server connection."); server.conn->close(); return; } /* Valid data */ - kb_incr(&statCounter.server.all.kbytes_out, len); - kb_incr(&statCounter.server.other.kbytes_out, len); + kb_incr(&(statCounter.server.all.kbytes_out), len); + kb_incr(&(statCounter.server.other.kbytes_out), len); client.dataSent(len); /* If the other end has closed, so should we */ if (!Comm::IsConnOpen(client.conn)) { debugs(26, 4, HERE << "Client gone away. Shutting down server connection."); server.conn->close(); return; } cbdataInternalLock(this); /* ??? should be locked by the caller... */ if (cbdataReferenceValid(this)) copyRead(client, ReadClient); cbdataInternalUnlock(this); /* ??? */ } /* Writes data from the server buffer to the client side */ void TunnelStateData::WriteClientDone(const Comm::ConnectionPointer &, char *buf, size_t len, comm_err_t flag, int xerrno, void *data) @@ -415,41 +416,41 @@ { debugs(26, 3, HERE << client.conn << ", " << len << " bytes written, flag=" << flag); /* Error? */ if (flag != COMM_OK) { if (flag != COMM_ERR_CLOSING) { debugs(26, 4, HERE << "Closing client connection due to comm flags."); client.error(xerrno); // may call comm_close } return; } /* EOF? */ if (len == 0) { debugs(26, 4, HERE << "Closing client connection due to 0 byte read."); client.conn->close(); return; } /* Valid data */ - kb_incr(&statCounter.client_http.kbytes_out, len); + kb_incr(&(statCounter.client_http.kbytes_out), len); server.dataSent(len); /* If the other end has closed, so should we */ if (!Comm::IsConnOpen(server.conn)) { debugs(26, 4, HERE << "Server has gone away. Terminating client connection."); client.conn->close(); return; } cbdataInternalLock(this); /* ??? should be locked by the caller... */ if (cbdataReferenceValid(this)) copyRead(server, ReadServer); cbdataInternalUnlock(this); /* ??? */ } static void tunnelTimeout(const CommTimeoutCbParams &io) { === modified file 'src/typedefs.h' --- src/typedefs.h 2011-12-07 18:56:59 +0000 +++ src/typedefs.h 2011-12-15 22:48:06 +0000 @@ -41,76 +41,68 @@ typedef uint32_t nfmark_t; typedef unsigned char tos_t; typedef struct { size_t bytes; size_t kb; } kb_t; struct http_port_list; struct https_port_list; typedef struct _close_handler close_handler; typedef struct _dread_ctrl dread_ctrl; typedef struct _dwrite_q dwrite_q; typedef struct _HttpHeaderFieldAttrs HttpHeaderFieldAttrs; -typedef struct _HttpHeaderStat HttpHeaderStat; - typedef struct _domain_ping domain_ping; typedef struct _domain_type domain_type; typedef struct _DigestFetchState DigestFetchState; typedef struct _net_db_name net_db_name; typedef struct _net_db_peer net_db_peer; typedef struct _netdbEntry netdbEntry; typedef struct _icp_common_t icp_common_t; typedef struct _iostats iostats; typedef struct _http_state_flags http_state_flags; typedef struct _header_mangler header_mangler; typedef struct _cachemgr_passwd cachemgr_passwd; typedef struct _refresh_t refresh_t; typedef struct _CommWriteStateData CommWriteStateData; -typedef struct _StatCounters StatCounters; - typedef struct _storeSwapLogData storeSwapLogData; -typedef struct _StatHist StatHist; - -typedef struct _cd_guess_stats cd_guess_stats; - typedef struct _CacheDigest CacheDigest; typedef struct _Version Version; typedef struct _link_list link_list; typedef struct _customlog customlog; #if SQUID_SNMP typedef variable_list *(oid_ParseFn) (variable_list *, snint *); typedef struct _snmp_request_t snmp_request_t; #endif typedef void FREE(void *); typedef void CBDUNL(void *); typedef void FOCB(void *, int fd, int errcode); typedef void PF(int, void *); /* disk.c / diskd.c callback typedefs */ @@ -133,34 +125,31 @@ /* in wordlist.h */ class wordlist; typedef void UH(void *data, wordlist *); typedef int READ_HANDLER(int, char *, int); typedef int WRITE_HANDLER(int, const char *, int); typedef int QS(const void *, const void *); /* qsort */ typedef void STABH(void *); typedef void ERCB(int fd, void *, size_t); class StoreEntry; typedef void OBJH(StoreEntry *); typedef void SIGHDLR(int sig); typedef void STVLDCB(void *, int, int); typedef void HLPCB(void *, char *buf); typedef int HLPSAVAIL(void *); typedef void HLPSONEQ(void *); typedef void HLPCMDOPTS(int *argc, char **argv); typedef void IDNSCB(void *, rfc1035_rr *, int, const char *); -typedef double hbase_f(double); -typedef void StatHistBinDumper(StoreEntry *, int idx, double val, double size, int count); - /* MD5 cache keys */ typedef unsigned char cache_key; /* in case we want to change it later */ typedef ssize_t mb_size_t; typedef int STDIRSELECT(const StoreEntry *); /*Use uint64_t to store miliseconds*/ typedef uint64_t time_msec_t; #endif /* SQUID_TYPEDEFS_H */ === modified file 'src/unlinkd.cc' --- src/unlinkd.cc 2011-11-26 12:12:26 +0000 +++ src/unlinkd.cc 2011-12-10 15:30:21 +0000 @@ -18,40 +18,41 @@ * sources; see the CREDITS file for full details. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #include "squid.h" #include "SquidTime.h" +#include "StatCounters.h" #include "SwapDir.h" #include "fde.h" #include "xusleep.h" /* This code gets linked to Squid */ static int unlinkd_wfd = -1; static int unlinkd_rfd = -1; static void * hIpc; static pid_t pid; #define UNLINKD_QUEUE_LIMIT 20 void unlinkdUnlink(const char *path) { char buf[MAXPATHLEN]; int l; int bytes_written; @@ -114,47 +115,47 @@ assert(queuelen >= 0); } } l = strlen(path); assert(l < MAXPATHLEN); xstrncpy(buf, path, MAXPATHLEN); buf[l++] = '\n'; bytes_written = write(unlinkd_wfd, buf, l); if (bytes_written < 0) { debugs(2, 1, "unlinkdUnlink: write FD " << unlinkd_wfd << " failed: " << xstrerror()); safeunlink(path, 0); return; } else if (bytes_written != l) { debugs(2, 1, "unlinkdUnlink: FD " << unlinkd_wfd << " only wrote " << bytes_written << " of " << l << " bytes"); safeunlink(path, 0); return; } - statCounter.unlink.requests++; + ++statCounter.unlink.requests; /* * Increment this syscalls counter here, even though the syscall * is executed by the helper process. We try to be consistent * in counting unlink operations. */ - statCounter.syscalls.disk.unlinks++; + ++statCounter.syscalls.disk.unlinks; queuelen++; } void unlinkdClose(void) #if _SQUID_MSWIN_ { if (unlinkd_wfd > -1) { debugs(2, 1, "Closing unlinkd pipe on FD " << unlinkd_wfd); shutdown(unlinkd_wfd, SD_BOTH); comm_close(unlinkd_wfd); if (unlinkd_wfd != unlinkd_rfd) comm_close(unlinkd_rfd); unlinkd_wfd = -1; unlinkd_rfd = -1; } === modified file 'src/whois.cc' --- src/whois.cc 2011-11-27 12:37:35 +0000 +++ src/whois.cc 2011-12-10 15:30:21 +0000 @@ -25,40 +25,41 @@ * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #include "squid.h" #include "comm/Write.h" #include "errorpage.h" #include "Store.h" #include "HttpReply.h" #include "HttpRequest.h" #include "comm.h" #include "HttpRequest.h" #include "forward.h" +#include "StatCounters.h" #define WHOIS_PORT 43 class WhoisState { public: ~WhoisState(); void readReply(const Comm::ConnectionPointer &, char *aBuffer, size_t aBufferLength, comm_err_t flag, int xerrno); void setReplyToOK(StoreEntry *sentry); StoreEntry *entry; HttpRequest *request; FwdState::Pointer fwd; char buf[BUFSIZ+1]; /* readReply adds terminating NULL */ bool dataWritten; }; static CLCB whoisClose; static CTCB whoisTimeout; static IOCB whoisReadReply; @@ -152,42 +153,42 @@ if (flag != COMM_OK) { debugs(50, 2, HERE << conn << ": read failure: " << xstrerror() << "."); if (ignoreErrno(errno)) { AsyncCall::Pointer call = commCbCall(5,4, "whoisReadReply", CommIoCbPtrFun(whoisReadReply, this)); comm_read(conn, aBuffer, BUFSIZ, call); } else { ErrorState *err = new ErrorState(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR, fwd->request); err->xerrno = errno; fwd->fail(err); conn->close(); } return; } if (aBufferLength > 0) { if (!dataWritten) setReplyToOK(entry); - kb_incr(&statCounter.server.all.kbytes_in, aBufferLength); - kb_incr(&statCounter.server.http.kbytes_in, aBufferLength); + kb_incr(&(statCounter.server.all.kbytes_in), aBufferLength); + kb_incr(&(statCounter.server.http.kbytes_in), aBufferLength); /* No range support, we always grab it all */ dataWritten = true; entry->append(aBuffer, aBufferLength); entry->flush(); AsyncCall::Pointer call = commCbCall(5,4, "whoisReadReply", CommIoCbPtrFun(whoisReadReply, this)); comm_read(conn, aBuffer, BUFSIZ, call); return; } /* no bytes read. stop reading */ entry->timestampsSet(); entry->flush(); if (!EBIT_TEST(entry->flags, RELEASE_REQUEST)) entry->setPublicKey(); fwd->complete();