diff --git src/SwapDir.h src/SwapDir.h index 723443c..b5772d8 100644 --- src/SwapDir.h +++ src/SwapDir.h @@ -115,40 +115,42 @@ SQUIDCEXTERN void storeDirLRUDelete(StoreEntry *); SQUIDCEXTERN void storeDirLRUAdd(StoreEntry *); SQUIDCEXTERN int storeDirGetBlkSize(const char *path, int *blksize); SQUIDCEXTERN int storeDirGetUFSStats(const char *, int *, int *, int *, int *); /// manages a single cache_dir class SwapDir : public Store { public: typedef RefCount Pointer; SwapDir(char const *aType); virtual ~SwapDir(); virtual void reconfigure() = 0; char const *type() const; virtual bool needsDiskStrand() const; ///< needs a dedicated kid process virtual bool active() const; ///< may be used in this strand /// whether stat should be reported by this SwapDir virtual bool doReportStat() const { return active(); } + /// whether SwapDir unlinks files a lot and may benefit from unlinkd + virtual bool unlinks() const { return false; } /* official Store interface functions */ virtual void diskFull(); virtual StoreEntry * get(const cache_key *); virtual void get(String const, STOREGETCLIENT, void * cbdata); virtual uint64_t maxSize() const { return max_size;} virtual uint64_t minSize() const; virtual int64_t maxObjectSize() const { return max_objsize; } virtual void stat (StoreEntry &anEntry) const; virtual StoreSearch *search(String const url, HttpRequest *) = 0; /* migrated from store_dir.cc */ bool objectSizeIsAcceptable(int64_t objsize) const; diff --git src/fs/ufs/store_dir_ufs.cc src/fs/ufs/store_dir_ufs.cc index 129629c..439a33b 100644 --- src/fs/ufs/store_dir_ufs.cc +++ src/fs/ufs/store_dir_ufs.cc @@ -1284,40 +1284,46 @@ UFSSwapDir::unlinkFile(sfileno f) std::hex << std::uppercase << std::setw(8) << f << " '" << fullPath(f,NULL) << "'"); /* commonUfsDirMapBitReset(this, f); */ IO->unlinkFile(fullPath(f,NULL)); } void UFSSwapDir::unlink(StoreEntry & e) { debugs(79, 3, "storeUfsUnlink: dirno " << index << ", fileno "<< std::setfill('0') << std::hex << std::uppercase << std::setw(8) << e.swap_filen); if (e.swap_status == SWAPOUT_DONE && EBIT_TEST(e.flags, ENTRY_VALIDATED)) { cur_size -= fs.blksize * sizeInBlocks(e.swap_file_sz); --n_disk_objects; } replacementRemove(&e); mapBitReset(e.swap_filen); UFSSwapDir::unlinkFile(e.swap_filen); } +bool +UFSSwapDir::unlinks() const +{ + return IamWorkerProcess(); +} + /* * Add and remove the given StoreEntry from the replacement policy in * use. */ void UFSSwapDir::replacementAdd(StoreEntry * e) { debugs(47, 4, "UFSSwapDir::replacementAdd: added node " << e << " to dir " << index); repl->Add(repl, e, &e->repl); } void UFSSwapDir::replacementRemove(StoreEntry * e) { StorePointer SD; if (e->swap_dirn < 0) return; diff --git src/fs/ufs/ufscommon.h src/fs/ufs/ufscommon.h index 7561e8b..ae169d4 100644 --- src/fs/ufs/ufscommon.h +++ src/fs/ufs/ufscommon.h @@ -43,40 +43,41 @@ class StoreSearch; #include "SwapDir.h" /// \ingroup UFS class UFSSwapDir : public SwapDir { public: static int IsUFSDir(SwapDir* sd); static int DirClean(int swap_index); static int FilenoBelongsHere(int fn, int F0, int F1, int F2); UFSSwapDir(char const *aType, const char *aModuleType); virtual void init(); virtual void create(); virtual void dump(StoreEntry &) const; ~UFSSwapDir(); virtual StoreSearch *search(String const url, HttpRequest *); virtual bool doubleCheck(StoreEntry &); virtual void unlink(StoreEntry &); + virtual bool unlinks() const; virtual void statfs(StoreEntry &)const; virtual void maintain(); virtual bool canStore(const StoreEntry &e, int64_t diskSpaceNeeded, int &load) const; virtual void reference(StoreEntry &); virtual bool dereference(StoreEntry &); virtual StoreIOState::Pointer createStoreIO(StoreEntry &, StoreIOState::STFNCB *, StoreIOState::STIOCB *, void *); virtual StoreIOState::Pointer openStoreIO(StoreEntry &, StoreIOState::STFNCB *, StoreIOState::STIOCB *, void *); virtual void openLog(); virtual void closeLog(); virtual int writeCleanStart(); virtual void writeCleanDone(); virtual void logEntry(const StoreEntry & e, int op) const; virtual void parse(int index, char *path); virtual void reconfigure(); virtual int callback(); virtual void sync(); virtual void swappedOut(const StoreEntry &e); virtual uint64_t currentSize() const { return cur_size; } virtual uint64_t currentCount() const { return n_disk_objects; } diff --git src/main.cc src/main.cc index 546eb92..da19f40 100644 --- src/main.cc +++ src/main.cc @@ -1068,41 +1068,42 @@ mainInitialize(void) icapLogOpen(); #endif #if USE_IDENT Ident::Init(); #endif #if SQUID_SNMP snmpInit(); #endif #if MALLOC_DBG malloc_debug(0, malloc_debug_level); #endif if (!configured_once) { #if USE_UNLINKD - unlinkdInit(); + if (unlinkdNeeded()) + unlinkdInit(); #endif urlInitialize(); statInit(); storeInit(); mainSetCwd(); /* after this point we want to see the mallinfo() output */ do_mallinfo = 1; mimeInit(Config.mimeTablePathname); refreshInit(); #if USE_DELAY_POOLS DelayPools::Init(); #endif FwdState::initModule(); /* register the modules in the cache manager menus */ cbdataRegisterWithCacheManager(); /* These use separate calls so that the comm loops can eventually * coexist. diff --git src/protos.h src/protos.h index 46cb7b8..00bae33 100644 --- src/protos.h +++ src/protos.h @@ -574,40 +574,41 @@ SQUIDCEXTERN int DebugSignal; /* AYJ debugs function to show locations being reset with memset() */ SQUIDCEXTERN void *xmemset(void *dst, int, size_t); SQUIDCEXTERN void debug_trap(const char *); SQUIDCEXTERN void logsFlush(void); SQUIDCEXTERN const char *checkNullString(const char *p); SQUIDCEXTERN void squid_getrusage(struct rusage *r); SQUIDCEXTERN double rusage_cputime(struct rusage *r); SQUIDCEXTERN int rusage_maxrss(struct rusage *r); SQUIDCEXTERN int rusage_pagefaults(struct rusage *r); SQUIDCEXTERN void releaseServerSockets(void); SQUIDCEXTERN void PrintRusage(void); SQUIDCEXTERN void dumpMallocStats(void); #if USE_UNLINKD +SQUIDCEXTERN bool unlinkdNeeded(void); SQUIDCEXTERN void unlinkdInit(void); SQUIDCEXTERN void unlinkdClose(void); SQUIDCEXTERN void unlinkdUnlink(const char *); #endif SQUIDCEXTERN AnyP::ProtocolType urlParseProtocol(const char *, const char *e = NULL); SQUIDCEXTERN void urlInitialize(void); SQUIDCEXTERN HttpRequest *urlParse(const HttpRequestMethod&, char *, HttpRequest *request = NULL); SQUIDCEXTERN const char *urlCanonical(HttpRequest *); SQUIDCEXTERN char *urlCanonicalClean(const HttpRequest *); SQUIDCEXTERN const char *urlCanonicalFakeHttps(const HttpRequest * request); SQUIDCEXTERN bool urlIsRelative(const char *); SQUIDCEXTERN char *urlMakeAbsolute(const HttpRequest *, const char *); SQUIDCEXTERN char *urlRInternal(const char *host, unsigned short port, const char *dir, const char *name); SQUIDCEXTERN char *urlInternal(const char *dir, const char *name); SQUIDCEXTERN int matchDomainName(const char *host, const char *domain); SQUIDCEXTERN int urlCheckRequest(const HttpRequest *); SQUIDCEXTERN int urlDefaultPort(AnyP::ProtocolType p); SQUIDCEXTERN char *urlHostname(const char *url); SQUIDCEXTERN void urlExtMethodConfigure(void); diff --git src/unlinkd.cc src/unlinkd.cc index c46e1c2..9007cab 100644 --- src/unlinkd.cc +++ src/unlinkd.cc @@ -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 "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; static int queuelen = 0; @@ -139,72 +140,88 @@ unlinkdUnlink(const char *path) 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; - } else - debugs(2, 0, "unlinkdClose: WARNING: unlinkd_wfd is " << unlinkd_wfd); + } if (hIpc) { if (WaitForSingleObject(hIpc, 5000) != WAIT_OBJECT_0) { getCurrentTime(); debugs(2, 1, "unlinkdClose: WARNING: (unlinkd," << pid << "d) didn't exit in 5 seconds"); } CloseHandle(hIpc); } } #else { if (unlinkd_wfd < 0) return; debugs(2, 1, "Closing unlinkd pipe on FD " << unlinkd_wfd); file_close(unlinkd_wfd); if (unlinkd_wfd != unlinkd_rfd) file_close(unlinkd_rfd); unlinkd_wfd = -1; unlinkd_rfd = -1; } #endif +bool +unlinkdNeeded(void) +{ + // do not start unlinkd in non-daemon mode + if (!InDaemonMode()) + return false; + + // we should start unlinkd if there are any cache_dirs using it + for (int i = 0; i < Config.cacheSwap.n_configured; ++i) { + const RefCount sd = Config.cacheSwap.swapDirs[i]; + if (sd->unlinks()) + return true; + } + + return false; +} + void unlinkdInit(void) { const char *args[2]; Ip::Address localhost; args[0] = "(unlinkd)"; args[1] = NULL; localhost.SetLocalhost(); pid = ipcCreate( #if USE_POLL && defined(_SQUID_OSF_) /* pipes and poll() don't get along on DUNIX -DW */ IPC_STREAM, #elif defined(_SQUID_MSWIN_) /* select() will fail on a pipe */ IPC_TCP_SOCKET, #else /* We currently need to use FIFO.. see below */ IPC_FIFO,