Make squid -z for cache_dir rock work like UFS instead of like COSS. When a startup script runs squid -z by mistake against a cache_dir that is already initialized and full of cached entries, some admins prefer that nothing happens. Rock store now skips reinitialization if both the cache_dir directory and the db file in that directory exist. If one or both are missing, the missing pieces are created. UFS does something similar because it creates missing L1 and L2 directories but does not erase any entries already present in the cache_dir path. COSS, OTOH, re-initializes the existing db (but nobody noticed or complained loud enough, apparently). Rock behavior will now be closer to UFS. To clean a corrupted cache_dir, the admin must remove it before running squid-z. === modified file 'src/fs/rock/RockSwapDir.cc' --- src/fs/rock/RockSwapDir.cc 2013-01-21 07:15:09 +0000 +++ src/fs/rock/RockSwapDir.cc 2013-02-04 19:36:56 +0000 @@ -143,51 +143,63 @@ { const int64_t eLimitLo = map ? map->entryLimit() : 0; // dynamic shrinking unsupported const int64_t eWanted = (maxSize() - HeaderSize)/maxObjectSize(); return min(max(eLimitLo, eWanted), entryLimitHigh()); } // TODO: encapsulate as a tool; identical to CossSwapDir::create() void Rock::SwapDir::create() { assert(path); assert(filePath); if (UsingSmp() && !IamDiskProcess()) { debugs (47,3, HERE << "disker will create in " << path); return; } debugs (47,3, HERE << "creating in " << path); - struct stat swap_sb; - if (::stat(path, &swap_sb) < 0) { + struct stat dir_sb; + if (::stat(path, &dir_sb) == 0) { + struct stat file_sb; + if (::stat(filePath, &file_sb) == 0) { + debugs (47, DBG_IMPORTANT, "Skipping existing Rock db: " << filePath); + return; + } + // else the db file is not there or is not accessible, and we will try + // to create it later below, generating a detailed error on failures. + } else { // path does not exist or is inaccessible + // If path exists but is not accessible, mkdir() below will fail, and + // the admin should see the error and act accordingly, so there is + // no need to distinguish ENOENT from other possible stat() errors. debugs (47, DBG_IMPORTANT, "Creating Rock db directory: " << path); const int res = mkdir(path, 0700); if (res != 0) { debugs(47, DBG_CRITICAL, "Failed to create Rock db dir " << path << ": " << xstrerror()); fatal("Rock Store db creation error"); } } + debugs (47, DBG_IMPORTANT, "Creating Rock db: " << filePath); #if SLOWLY_FILL_WITH_ZEROS char block[1024]; Must(maxSize() % sizeof(block) == 0); memset(block, '\0', sizeof(block)); const int swap = open(filePath, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0600); for (off_t offset = 0; offset < maxSize(); offset += sizeof(block)) { if (write(swap, block, sizeof(block)) != sizeof(block)) { debugs(47, DBG_CRITICAL, "ERROR: Failed to create Rock Store db in " << filePath << ": " << xstrerror()); fatal("Rock Store db creation error"); } } close(swap); #else const int swap = open(filePath, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0600); if (swap < 0) { debugs(47, DBG_CRITICAL, "ERROR: Failed to initialize Rock Store db in " << filePath << "; create error: " << xstrerror()); fatal("Rock Store db creation error");