?? filecache.c++
字號:
/* $Id: FileCache.c++,v 1.2 1999/06/13 07:41:12 robert Exp $ *//* * Copyright (c) 1995-1996 Sam Leffler * Copyright (c) 1995-1996 Silicon Graphics, Inc. * HylaFAX is a trademark of Silicon Graphics * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */#include "FileCache.h"#include "Sys.h"u_int FileCache::master = 0; // master serial numberFileCache* FileCache::cache[4096]; // cache of stat results#define CACHESIZE (sizeof (cache) / sizeof (cache[0])) // statisticsu_int FileCache::lookups = 0; // total # lookupsu_int FileCache::hits = 0; // # lookups that hit in the cacheu_int FileCache::probes = 0; // total # probes during lookupsu_int FileCache::displaced = 0; // # entries reusedu_int FileCache::flushed = 0; // # entries flushedvoidFileCache::printStats(FILE* fd){ fprintf(fd, " File cache: %u lookups, %u hits (%.1f%%), %.1f avg probes\r\n" , lookups , hits#define NZ(v) ((v) == 0 ? 1 : (v)) , (100.*hits)/NZ(lookups) , float(lookups+probes)/float(NZ(lookups)) ); u_int n = 0; u_int space = 0; for (u_int i = 0; i < CACHESIZE; i++) { const FileCache* fi = cache[i]; if (fi) { n++; space += sizeof (*fi) + fi->name.length(); } } fprintf(fd, " %u entries (%.1f KB), %u entries displaced, %u entries flushed\r\n" , n , space / 1024. , displaced , flushed );}FileCache::FileCache() {}FileCache::~FileCache() {}voidFileCache::reset(void){ for (u_int i = 0; i < CACHESIZE; i++) delete cache[i]; memset(cache, 0, sizeof (cache)); master = 0; // doesn't matter???}u_intFileCache::hash(const char* pathname){ u_int h = 0; while (*pathname) h ^= *pathname++; return (h % CACHESIZE);}boolFileCache::lookup(const char* pathname, struct stat& sb, bool addToCache){ lookups++; u_int h = hash(pathname); u_int maxprobes = 5; FileCache* fi = cache[h]; FileCache* oldest = fi; while (fi && --maxprobes) { probes++; if (fi->name == pathname) { fi->serial = master++; sb = fi->sb; hits++; return (true); } if (fi->serial < oldest->serial) oldest = fi; h = (u_int)(h*h) % CACHESIZE; fi = cache[h]; } /* * Pathname not found in the cache. */ if (Sys::stat(pathname, sb) < 0) return (false); if (addToCache && pathname[0] != '.') { if (fi) { fi = oldest; displaced++; } else fi = cache[h] = new FileCache; fi->name = pathname; fi->serial = master++; fi->sb = sb; } return (true);}/* * Update the file mode for any in-cache entry. */boolFileCache::chmod(const char* pathname, mode_t mode){ if (Sys::chmod(pathname, mode) < 0) return (false); lookups++; u_int h = hash(pathname); u_int maxprobes = 5; FileCache* fi = cache[h]; while (fi && --maxprobes) { probes++; if (fi->name == pathname) { hits++; fi->sb.st_mode = (fi->sb.st_mode&~0777) | (mode&0777); break; } h = (u_int)(h*h) % CACHESIZE; fi = cache[h]; } return (true);}/* * Update the file ownership for any in-cache entry. */boolFileCache::chown(const char* pathname, uid_t uid, gid_t gid){ /* * For BSD-based systems chown is only permitted * by the super-user. We could optimize this work * to not swap the effective uid on System V-based * systems but it's not worth it since the majority * the calls to chown a file will be done only for * BSD-based systems (to deal with the filesystem * semantics forcing us to manually set the gid on * newly created files. */ uid_t ouid = geteuid(); (void) seteuid(0); bool ok = (Sys::chown(pathname, uid, gid) >= 0); (void) seteuid(ouid); if (ok) { lookups++; u_int h = hash(pathname); u_int maxprobes = 5; FileCache* fi = cache[h]; while (fi && --maxprobes) { probes++; if (fi->name == pathname) { hits++; fi->sb.st_uid = uid; fi->sb.st_gid = gid; break; } h = (u_int)(h*h) % CACHESIZE; fi = cache[h]; } } return (ok);}/* * Like lookup, but if found in the cache, re-do the stat. */boolFileCache::update(const char* pathname, struct stat& sb, bool addToCache){ lookups++; u_int h = hash(pathname); u_int maxprobes = 5; FileCache* fi = cache[h]; FileCache* oldest = fi; while (fi && --maxprobes) { probes++; if (fi->name == pathname) { if (Sys::stat(pathname, sb) >= 0) { hits++; fi->serial = master++; fi->sb = sb; return (true); } else { flushed++; cache[h] = NULL; delete fi; return (false); } } if (fi->serial < oldest->serial) oldest = fi; h = (u_int)(h*h) % CACHESIZE; fi = cache[h]; } /* * Pathname not found in the cache. */ if (Sys::stat(pathname, sb) < 0) return (false); if (addToCache && pathname[0] != '.') { if (fi) { fi = oldest; displaced++; } else fi = cache[h] = new FileCache; fi->name = pathname; fi->serial = master++; fi->sb = sb; } return (true);}voidFileCache::flush(const char* pathname){ u_int h = hash(pathname); u_int maxprobes = 5; FileCache* fi = cache[h]; while (fi && --maxprobes) { if (fi->name == pathname) { flushed++; cache[h] = NULL; delete fi; break; } h = (u_int)(h*h) % CACHESIZE; fi = cache[h]; }}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -