--- /dev/null
+/*
+ * 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_ */
fd.cc \
fde.cc \
fde.h \
+ FileMap.h \
filemap.cc \
forward.cc \
forward.h \
DiskIO/WriteRequest.cc \
ETag.cc \
event.cc \
+ FileMap.h \
filemap.cc \
HelperChildConfig.h \
HelperChildConfig.cc \
ExternalACLEntry.cc \
fd.cc \
fde.cc \
+ FileMap.h \
filemap.cc \
forward.cc \
fqdncache.cc \
EventLoop.cc \
event.cc \
fd.cc \
+ FileMap.h \
filemap.cc \
HttpBody.h \
HttpBody.cc \
FadingCounter.cc \
fd.cc \
fde.cc \
+ FileMap.h \
filemap.cc \
forward.cc \
fqdncache.cc \
FadingCounter.cc \
fd.cc \
fde.cc \
+ FileMap.h \
filemap.cc \
forward.cc \
fqdncache.cc \
FadingCounter.cc \
fd.cc \
fde.cc \
+ FileMap.h \
filemap.cc \
forward.cc \
fqdncache.cc \
ETag.cc \
event.cc \
EventLoop.cc \
+ FileMap.h \
filemap.cc \
HttpHdrCc.h \
HttpHdrCc.cc \
tests/stub_store_stats.cc \
fd.cc \
disk.cc \
+ FileMap.h \
filemap.cc \
HttpBody.h \
HttpBody.cc \
EventLoop.cc \
event.cc \
fd.cc \
+ FileMap.h \
filemap.cc \
HttpBody.h \
HttpBody.cc \
tests/stub_store_stats.cc \
fd.cc \
disk.cc \
+ FileMap.h \
filemap.cc \
HttpBody.h \
HttpBody.cc \
tests/stub_store_stats.cc \
fd.cc \
disk.cc \
+ FileMap.h \
filemap.cc \
HttpBody.h \
HttpBody.cc \
ExternalACLEntry.cc \
fd.cc \
fde.cc \
+ FileMap.h \
filemap.cc \
forward.cc \
fqdncache.cc \
/*
- * $Id$
- *
* DEBUG: section 08 Swap File Bitmap
* AUTHOR: Harvest Derived
*
*
*/
-#include "squid.h"
+#include "config.h"
+#include "Debug.h"
+#include "FileMap.h"
/* Number of bits in a long */
#if SIZEOF_LONG == 8
#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
#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);
#include "ConfigOption.h"
#include "DiskIO/DiskIOStrategy.h"
#include "DiskIO/DiskIOModule.h"
+#include "FileMap.h"
#include "Parsing.h"
#include "SquidMath.h"
#include "SquidTime.h"
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.
swaplog_fd = -1;
}
- filemapFreeMemory(map);
+ delete map;
if (IO)
delete IO;
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) {
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;
}
* be considered invalid.
*/
if (flag)
- if (filn > map->max_n_files)
+ if (filn > map->capacity())
return 0;
return 1;
class ConfigOptionVector;
class DiskIOModule;
class StoreSearch;
+class FileMap;
#include "SwapDir.h"
void replacementRemove(StoreEntry *e);
protected:
- fileMap *map;
+ FileMap *map;
int suggest;
int l1;
int l2;
} // 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 */
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);
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"
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 */
typedef struct _dwrite_q dwrite_q;
-typedef struct _fileMap fileMap;
-
typedef struct _HttpHeaderFieldAttrs HttpHeaderFieldAttrs;
typedef struct _HttpHeaderStat HttpHeaderStat;