From: Francesco Chemolli Date: Thu, 8 Dec 2011 11:00:12 +0000 (-0700) Subject: SourceLayout: C++ refactor FileMap X-Git-Tag: SQUID_3_2_0_14~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9a8af158cb51a0d8760d7bf5fc1b7f445ba89d28;p=thirdparty%2Fsquid.git SourceLayout: C++ refactor FileMap --- diff --git a/src/FileMap.h b/src/FileMap.h new file mode 100644 index 0000000000..3167534cff --- /dev/null +++ b/src/FileMap.h @@ -0,0 +1,102 @@ +/* + * FileMap.h + * + * DEBUG: section 08 Swap File Bitmap + * AUTHOR: 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 FILEMAP_H_ +#define FILEMAP_H_ + +#include "typedefs.h" + +/** A bitmap used for managing UFS StoreEntry "file numbers". + * + * Nth bit represents whether file number N is used. + * The map automatically grows to hold up to 2^24 bits. + * New bit is "off" or zero by default, representing unused fileno. + * TODO: consider using std::bitset instead. + */ +class FileMap +{ +public: + FileMap(); + ~FileMap(); + + /** Set the num-th bit in the FileMap + * + * \warning FileMap's backing storage will be extended as needed to + * hold the representation, but if the bit is already set + * it will break the file number accounting, so the caller must + * ensure that setBit is only called if the bit is not already set, + * by using testBit on it before. + */ + bool setBit(sfileno num); + + /// Test whether the num-th bit in the FileMap is set + bool testBit(sfileno num) const; + + /** Clear the num-th bit in the FileMap + * + * \warning that clearBit doesn't do any bounds checking, nor it + * checks that the bit is set before clearing. The caller will have + * to ensure that both are true using testBit before clearing. + */ + void clearBit(sfileno num); + + /** locate an unused slot in the FileMap, possibly at or after position suggestion + * + * Obtain the location of an unused slot in the FileMap, + * growing it if needed. + * The suggestion is only an advice; there is no guarantee + * that it will be followed. + */ + sfileno allocate(sfileno suggestion); + + /// return the max number of slots in the FileMap + int capacity() const {return capacity_;} + + /// return the number of used slots in the FileMap + int numFilesInMap() const {return usedSlots_;} +private: + /// grow the FileMap (size is doubled each time, up to 2^24 bits) + void grow(); + FileMap(const FileMap &); //no copying + FileMap& operator=(const FileMap &); //no assignments + + /// max number of files which can be tracked in the current store + sfileno capacity_; + /// used slots in the map + unsigned int usedSlots_; + /// number of "long ints" making up the filemap + unsigned int nwords; + unsigned long *bitmap; +}; + +#endif /* FILEMAP_H_ */ diff --git a/src/Makefile.am b/src/Makefile.am index a981692874..346e4dd588 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -323,6 +323,7 @@ squid_SOURCES = \ fd.cc \ fde.cc \ fde.h \ + FileMap.h \ filemap.cc \ forward.cc \ forward.h \ @@ -1136,6 +1137,7 @@ tests_testACLMaxUserIP_SOURCES= \ DiskIO/WriteRequest.cc \ ETag.cc \ event.cc \ + FileMap.h \ filemap.cc \ HelperChildConfig.h \ HelperChildConfig.cc \ @@ -1298,6 +1300,7 @@ tests_testCacheManager_SOURCES = \ ExternalACLEntry.cc \ fd.cc \ fde.cc \ + FileMap.h \ filemap.cc \ forward.cc \ fqdncache.cc \ @@ -1449,6 +1452,7 @@ tests_testDiskIO_SOURCES = \ EventLoop.cc \ event.cc \ fd.cc \ + FileMap.h \ filemap.cc \ HttpBody.h \ HttpBody.cc \ @@ -1616,6 +1620,7 @@ tests_testEvent_SOURCES = \ FadingCounter.cc \ fd.cc \ fde.cc \ + FileMap.h \ filemap.cc \ forward.cc \ fqdncache.cc \ @@ -1805,6 +1810,7 @@ tests_testEventLoop_SOURCES = \ FadingCounter.cc \ fd.cc \ fde.cc \ + FileMap.h \ filemap.cc \ forward.cc \ fqdncache.cc \ @@ -1992,6 +1998,7 @@ tests_test_http_range_SOURCES = \ FadingCounter.cc \ fd.cc \ fde.cc \ + FileMap.h \ filemap.cc \ forward.cc \ fqdncache.cc \ @@ -2369,6 +2376,7 @@ tests_testStore_SOURCES= \ ETag.cc \ event.cc \ EventLoop.cc \ + FileMap.h \ filemap.cc \ HttpHdrCc.h \ HttpHdrCc.cc \ @@ -2560,6 +2568,7 @@ tests_testUfs_SOURCES = \ tests/stub_store_stats.cc \ fd.cc \ disk.cc \ + FileMap.h \ filemap.cc \ HttpBody.h \ HttpBody.cc \ @@ -2690,6 +2699,7 @@ tests_testRock_SOURCES = \ EventLoop.cc \ event.cc \ fd.cc \ + FileMap.h \ filemap.cc \ HttpBody.h \ HttpBody.cc \ @@ -2820,6 +2830,7 @@ tests_testCoss_SOURCES = \ tests/stub_store_stats.cc \ fd.cc \ disk.cc \ + FileMap.h \ filemap.cc \ HttpBody.h \ HttpBody.cc \ @@ -2952,6 +2963,7 @@ tests_testNull_SOURCES = \ tests/stub_store_stats.cc \ fd.cc \ disk.cc \ + FileMap.h \ filemap.cc \ HttpBody.h \ HttpBody.cc \ @@ -3101,6 +3113,7 @@ tests_testURL_SOURCES = \ ExternalACLEntry.cc \ fd.cc \ fde.cc \ + FileMap.h \ filemap.cc \ forward.cc \ fqdncache.cc \ diff --git a/src/filemap.cc b/src/filemap.cc index 10bcb0091f..23d11e38eb 100644 --- a/src/filemap.cc +++ b/src/filemap.cc @@ -1,6 +1,4 @@ /* - * $Id$ - * * DEBUG: section 08 Swap File Bitmap * AUTHOR: Harvest Derived * @@ -32,7 +30,9 @@ * */ -#include "squid.h" +#include "config.h" +#include "Debug.h" +#include "FileMap.h" /* Number of bits in a long */ #if SIZEOF_LONG == 8 @@ -54,133 +54,107 @@ #define FM_INITIAL_NUMBER (1<<14) -fileMap * -file_map_create(void) +FileMap::FileMap() : + capacity_(FM_INITIAL_NUMBER), usedSlots_(0), + nwords(capacity_ >> LONG_BIT_SHIFT) { - fileMap *fm = (fileMap *)xcalloc(1, sizeof(fileMap)); - fm->max_n_files = FM_INITIAL_NUMBER; - fm->nwords = fm->max_n_files >> LONG_BIT_SHIFT; - debugs(8, 3, "file_map_create: creating space for " << fm->max_n_files << " files"); - debugs(8, 5, "--> " << fm->nwords << " words of " << sizeof(*fm->file_map) << " bytes each"); - fm->file_map = (unsigned long *)xcalloc(fm->nwords, sizeof(*fm->file_map)); - /* XXX account fm->file_map */ - return fm; + debugs(8, 3, HERE << "creating space for " << capacity_ << " files"); + debugs(8, 5, "--> " << nwords << " words of " << sizeof(*bitmap) << " bytes each"); + bitmap = (unsigned long *)xcalloc(nwords, sizeof(*bitmap)); } -static void -file_map_grow(fileMap * fm) +void +FileMap::grow() { - int old_sz = fm->nwords * sizeof(*fm->file_map); - void *old_map = fm->file_map; - fm->max_n_files <<= 1; - assert(fm->max_n_files <= (1 << 24)); /* swap_filen is 25 bits, signed */ - fm->nwords = fm->max_n_files >> LONG_BIT_SHIFT; - debugs(8, 3, "file_map_grow: creating space for " << fm->max_n_files << " files"); - debugs(8, 5, "--> " << fm->nwords << " words of " << sizeof(*fm->file_map) << " bytes each"); - fm->file_map = (unsigned long *)xcalloc(fm->nwords, sizeof(*fm->file_map)); + int old_sz = nwords * sizeof(*bitmap); + void *old_map = bitmap; + capacity_ <<= 1; + assert(capacity_ <= (1 << 24)); /* swap_filen is 25 bits, signed */ + nwords = capacity_ >> LONG_BIT_SHIFT; + debugs(8, 3, HERE << " creating space for " << capacity_ << " files"); + debugs(8, 5, "--> " << nwords << " words of " << sizeof(*bitmap) << " bytes each"); + bitmap = (unsigned long *)xcalloc(nwords, sizeof(*bitmap)); debugs(8, 3, "copying " << old_sz << " old bytes"); - memcpy(fm->file_map, old_map, old_sz); + memcpy(bitmap, old_map, old_sz); xfree(old_map); - /* XXX account fm->file_map */ + /* XXX account fm->bitmap */ } -int -file_map_bit_set(fileMap * fm, int file_number) +bool +FileMap::setBit(sfileno file_number) { unsigned long bitmask = (1L << (file_number & LONG_BIT_MASK)); - while (file_number >= fm->max_n_files) - file_map_grow(fm); + while (file_number >= capacity_) + grow(); - fm->file_map[file_number >> LONG_BIT_SHIFT] |= bitmask; + bitmap[file_number >> LONG_BIT_SHIFT] |= bitmask; - fm->n_files_in_map++; + usedSlots_++; return file_number; } /* - * WARNING: file_map_bit_reset does not perform array bounds + * WARNING: clearBit does not perform array bounds * checking! It assumes that 'file_number' is valid, and that the * bit is already set. The caller must verify both of those - * conditions by calling file_map_bit_test() first. + * conditions by calling testBit + * () first. */ void -file_map_bit_reset(fileMap * fm, int file_number) +FileMap::clearBit(sfileno file_number) { unsigned long bitmask = (1L << (file_number & LONG_BIT_MASK)); - fm->file_map[file_number >> LONG_BIT_SHIFT] &= ~bitmask; - fm->n_files_in_map--; + bitmap[file_number >> LONG_BIT_SHIFT] &= ~bitmask; + usedSlots_--; } -int -file_map_bit_test(fileMap * fm, int file_number) +bool +FileMap::testBit(sfileno file_number) const { unsigned long bitmask = (1L << (file_number & LONG_BIT_MASK)); - if (file_number >= fm->max_n_files) + if (file_number >= capacity_) return 0; /* be sure the return value is an int, not a u_long */ - return (fm->file_map[file_number >> LONG_BIT_SHIFT] & bitmask ? 1 : 0); + return (bitmap[file_number >> LONG_BIT_SHIFT] & bitmask ? 1 : 0); } -int -file_map_allocate(fileMap * fm, int suggestion) +sfileno +FileMap::allocate(sfileno suggestion) { int word; - int bit; - int count; - if (suggestion >= fm->max_n_files) + if (suggestion >= capacity_) suggestion = 0; - if (!file_map_bit_test(fm, suggestion)) + if (!testBit(suggestion)) return suggestion; word = suggestion >> LONG_BIT_SHIFT; - for (count = 0; count < fm->nwords; count++) { - if (fm->file_map[word] != ALL_ONES) + for (unsigned int count = 0; count < nwords; count++) { + if (bitmap[word] != ALL_ONES) break; - word = (word + 1) % fm->nwords; + word = (word + 1) % nwords; } - for (bit = 0; bit < BITS_IN_A_LONG; bit++) { + for (unsigned char bit = 0; bit < BITS_IN_A_LONG; bit++) { suggestion = ((unsigned long) word << LONG_BIT_SHIFT) | bit; - if (!file_map_bit_test(fm, suggestion)) { + if (!testBit(suggestion)) { return suggestion; } } - debugs(8, 3, "growing from file_map_allocate"); - file_map_grow(fm); - return file_map_allocate(fm, fm->max_n_files >> 1); -} - -void -filemapFreeMemory(fileMap * fm) -{ - safe_free(fm->file_map); - safe_free(fm); + grow(); + return allocate(capacity_ >> 1); } -#ifdef TEST - -#define TEST_SIZE 1<<16 -main(argc, argv) +FileMap::~FileMap() { - int i; - - fm = file_map_create(TEST_SIZE); - - for (i = 0; i < TEST_SIZE; ++i) { - file_map_bit_set(i); - assert(file_map_bit_test(i)); - file_map_bit_reset(i); - } + safe_free(bitmap); } - -#endif diff --git a/src/fs/coss/store_dir_coss.cc b/src/fs/coss/store_dir_coss.cc index b9767ce7fb..f46e398ad7 100644 --- a/src/fs/coss/store_dir_coss.cc +++ b/src/fs/coss/store_dir_coss.cc @@ -981,8 +981,8 @@ CossSwapDir::statfs(StoreEntry & sentry) const #if 0 /* is this applicable? I Hope not .. */ storeAppendPrintf(sentry, "Filemap bits in use: %d of %d (%d%%)\n", - SD->map->n_files_in_map, SD->map->max_n_files, - Math::intPercent(SD->map->n_files_in_map, SD->map->max_n_files)); + SD->map->numFilesInMap(), SD->map->capacity(), + Math::intPercent(SD->map->numFilesInMap(), SD->map->capacity())); #endif // storeAppendPrintf(&sentry, "Pending operations: %d out of %d\n", io->aq.aq_numpending, MAX_ASYNCOP); diff --git a/src/fs/ufs/store_dir_ufs.cc b/src/fs/ufs/store_dir_ufs.cc index 609c32842c..e9f1676355 100644 --- a/src/fs/ufs/store_dir_ufs.cc +++ b/src/fs/ufs/store_dir_ufs.cc @@ -41,6 +41,7 @@ #include "ConfigOption.h" #include "DiskIO/DiskIOStrategy.h" #include "DiskIO/DiskIOModule.h" +#include "FileMap.h" #include "Parsing.h" #include "SquidMath.h" #include "SquidTime.h" @@ -246,7 +247,7 @@ UFSSwapDir::create() createSwapSubDirs(); } -UFSSwapDir::UFSSwapDir(char const *aType, const char *anIOType) : SwapDir(aType), IO(NULL), map(file_map_create()), suggest(0), swaplog_fd (-1), currentIOOptions(new ConfigOptionVector()), ioType(xstrdup(anIOType)), cur_size(0), n_disk_objects(0) +UFSSwapDir::UFSSwapDir(char const *aType, const char *anIOType) : SwapDir(aType), IO(NULL), map(new FileMap()), suggest(0), swaplog_fd (-1), currentIOOptions(new ConfigOptionVector()), ioType(xstrdup(anIOType)), cur_size(0), n_disk_objects(0) { /* modulename is only set to disk modules that are built, by configure, * so the Find call should never return NULL here. @@ -261,7 +262,7 @@ UFSSwapDir::~UFSSwapDir() swaplog_fd = -1; } - filemapFreeMemory(map); + delete map; if (IO) delete IO; @@ -321,8 +322,8 @@ UFSSwapDir::statfs(StoreEntry & sentry) const storeAppendPrintf(&sentry, "Percent Used: %0.2f%%\n", Math::doublePercent(currentSize(), maxSize())); storeAppendPrintf(&sentry, "Filemap bits in use: %d of %d (%d%%)\n", - map->n_files_in_map, map->max_n_files, - Math::intPercent(map->n_files_in_map, map->max_n_files)); + map->numFilesInMap(), map->capacity(), + Math::intPercent(map->numFilesInMap(), map->capacity())); x = storeDirGetUFSStats(path, &totl_kb, &free_kb, &totl_in, &free_in); if (0 == x) { @@ -450,36 +451,36 @@ UFSSwapDir::openStoreIO(StoreEntry &e, StoreIOState::STFNCB * file_callback, Sto int UFSSwapDir::mapBitTest(sfileno filn) { - return file_map_bit_test(map, filn); + return map->testBit(filn); } void UFSSwapDir::mapBitSet(sfileno filn) { - file_map_bit_set(map, filn); + map->setBit(filn); } void UFSSwapDir::mapBitReset(sfileno filn) { /* - * We have to test the bit before calling file_map_bit_reset. - * file_map_bit_reset doesn't do bounds checking. It assumes + * We have to test the bit before calling clearBit as + * it doesn't do bounds checking and blindly assumes * filn is a valid file number, but it might not be because * the map is dynamic in size. Also clearing an already clear * bit puts the map counter of-of-whack. */ - if (file_map_bit_test(map, filn)) - file_map_bit_reset(map, filn); + if (map->testBit(filn)) + map->clearBit(filn); } int UFSSwapDir::mapBitAllocate() { int fn; - fn = file_map_allocate(map, suggest); - file_map_bit_set(map, fn); + fn = map->allocate(suggest); + map->setBit(fn); suggest = fn + 1; return fn; } @@ -1263,7 +1264,7 @@ UFSSwapDir::validFileno(sfileno filn, int flag) const * be considered invalid. */ if (flag) - if (filn > map->max_n_files) + if (filn > map->capacity()) return 0; return 1; diff --git a/src/fs/ufs/ufscommon.h b/src/fs/ufs/ufscommon.h index 3af061937a..20d1981803 100644 --- a/src/fs/ufs/ufscommon.h +++ b/src/fs/ufs/ufscommon.h @@ -40,6 +40,7 @@ class UFSStrategy; class ConfigOptionVector; class DiskIOModule; class StoreSearch; +class FileMap; #include "SwapDir.h" @@ -116,7 +117,7 @@ public: void replacementRemove(StoreEntry *e); protected: - fileMap *map; + FileMap *map; int suggest; int l1; int l2; diff --git a/src/ipc/StoreMap.h b/src/ipc/StoreMap.h index fe4458d6d4..c7a2e81f88 100644 --- a/src/ipc/StoreMap.h +++ b/src/ipc/StoreMap.h @@ -195,7 +195,7 @@ StoreMapWithExtras::extras(const sfileno fileno) const } // namespace Ipc -// We do not reuse struct _fileMap because we cannot control its size, +// We do not reuse FileMap because we cannot control its size, // resulting in sfilenos that are pointing beyond the database. #endif /* SQUID_IPC_STORE_MAP_H */ diff --git a/src/protos.h b/src/protos.h index dd38345cbd..fa3f8870f4 100644 --- a/src/protos.h +++ b/src/protos.h @@ -144,14 +144,6 @@ SQUIDCEXTERN void fdDumpOpen(void); SQUIDCEXTERN int fdUsageHigh(void); SQUIDCEXTERN void fdAdjustReserved(void); -SQUIDCEXTERN fileMap *file_map_create(void); -SQUIDCEXTERN int file_map_allocate(fileMap *, int); -SQUIDCEXTERN int file_map_bit_set(fileMap *, int); -SQUIDCEXTERN int file_map_bit_test(fileMap *, int); -SQUIDCEXTERN void file_map_bit_reset(fileMap *, int); -SQUIDCEXTERN void filemapFreeMemory(fileMap *); - - SQUIDCEXTERN void fqdncache_nbgethostbyaddr(const Ip::Address &, FQDNH *, void *); SQUIDCEXTERN const char *fqdncache_gethostbyaddr(const Ip::Address &, int flags); @@ -214,9 +206,6 @@ SQUIDCEXTERN mb_size_t httpBuildRequestPrefix(HttpRequest * request, StoreEntry * entry, MemBuf * mb, http_state_flags); -SQUIDCEXTERN void httpAnonInitModule(void); -SQUIDCEXTERN int httpAnonHdrAllowed(http_hdr_type hdr_id); -SQUIDCEXTERN int httpAnonHdrDenied(http_hdr_type hdr_id); SQUIDCEXTERN const char *httpMakeVaryMark(HttpRequest * request, HttpReply const * reply); #include "HttpStatusCode.h" diff --git a/src/structs.h b/src/structs.h index 49e16e9ae1..94f55a114d 100644 --- a/src/structs.h +++ b/src/structs.h @@ -696,13 +696,6 @@ struct _fde_disk { off_t offset; }; -struct _fileMap { - int max_n_files; - int n_files_in_map; - int toggle; - int nwords; - unsigned long *file_map; -}; #include "SquidString.h" /* http header extention field */ diff --git a/src/typedefs.h b/src/typedefs.h index 6b3f2164b7..73f960e268 100644 --- a/src/typedefs.h +++ b/src/typedefs.h @@ -56,8 +56,6 @@ typedef struct _dread_ctrl dread_ctrl; typedef struct _dwrite_q dwrite_q; -typedef struct _fileMap fileMap; - typedef struct _HttpHeaderFieldAttrs HttpHeaderFieldAttrs; typedef struct _HttpHeaderStat HttpHeaderStat;