X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=src%2Ffccache.c;h=a6b532fa118c148c7eb80b49bf362941e2f79da4;hb=144ca878311af885db820a35db31563ba87ee6ad;hp=69a29f2e94658c627c2417cc63d108352275e30e;hpb=9e612141df7e693ef98071f102cecb5d777ceecb;p=fontconfig.git diff --git a/src/fccache.c b/src/fccache.c index 69a29f2..a6b532f 100644 --- a/src/fccache.c +++ b/src/fccache.c @@ -47,7 +47,7 @@ struct MD5Context { }; static void MD5Init(struct MD5Context *ctx); -static void MD5Update(struct MD5Context *ctx, unsigned char *buf, unsigned len); +static void MD5Update(struct MD5Context *ctx, const unsigned char *buf, unsigned len); static void MD5Final(unsigned char digest[16], struct MD5Context *ctx); static void MD5Transform(FcChar32 buf[4], FcChar32 in[16]); @@ -67,7 +67,7 @@ FcDirCacheBasename (const FcChar8 * dir, FcChar8 cache_base[CACHEBASE_LEN]) struct MD5Context ctx; MD5Init (&ctx); - MD5Update (&ctx, (unsigned char *)dir, strlen ((char *) dir)); + MD5Update (&ctx, (const unsigned char *)dir, strlen ((const char *) dir)); MD5Final (hash, &ctx); @@ -104,6 +104,7 @@ FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config) if (!cache_hashed) break; (void) unlink ((char *) cache_hashed); + FcStrFree (cache_hashed); } FcStrListDone (list); /* return FcFalse if something went wrong */ @@ -135,7 +136,8 @@ FcDirCacheOpenFile (const FcChar8 *cache_file, struct stat *file_stat) */ static FcBool FcDirCacheProcess (FcConfig *config, const FcChar8 *dir, - FcBool (*callback) (int fd, struct stat *stat, void *closure), + FcBool (*callback) (int fd, struct stat *fd_stat, + struct stat *dir_stat, void *closure), void *closure, FcChar8 **cache_file_ret) { int fd = -1; @@ -161,20 +163,16 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir, break; fd = FcDirCacheOpenFile (cache_hashed, &file_stat); if (fd >= 0) { - if (dir_stat.st_mtime <= file_stat.st_mtime) + ret = (*callback) (fd, &file_stat, &dir_stat, closure); + close (fd); + if (ret) { - ret = (*callback) (fd, &file_stat, closure); - if (ret) - { - if (cache_file_ret) - *cache_file_ret = cache_hashed; - else - FcStrFree (cache_hashed); - close (fd); - break; - } + if (cache_file_ret) + *cache_file_ret = cache_hashed; + else + FcStrFree (cache_hashed); + break; } - close (fd); } FcStrFree (cache_hashed); } @@ -213,6 +211,17 @@ struct _FcCacheSkip { static FcCacheSkip *fcCacheChains[FC_CACHE_MAX_LEVEL]; static int fcCacheMaxLevel; +#if HAVE_RANDOM +# define FcRandom() random() +#else +# if HAVE_LRAND48 +# define FcRandom() lrand48() +# else +# if HAVE_RAND +# define FcRandom() rand() +# endif +# endif +#endif /* * Generate a random level number, distributed * so that each level is 1/4 as likely as the one before @@ -223,7 +232,7 @@ static int random_level (void) { /* tricky bit -- each bit is '1' 75% of the time */ - long int bits = random () | random (); + long int bits = FcRandom () | FcRandom (); int level = 0; while (++level < FC_CACHE_MAX_LEVEL) @@ -275,9 +284,18 @@ FcCacheInsert (FcCache *cache, struct stat *cache_stat) s->cache = cache; s->size = cache->size; s->ref = 1; - s->cache_dev = cache_stat->st_dev; - s->cache_ino = cache_stat->st_ino; - s->cache_mtime = cache_stat->st_mtime; + if (cache_stat) + { + s->cache_dev = cache_stat->st_dev; + s->cache_ino = cache_stat->st_ino; + s->cache_mtime = cache_stat->st_mtime; + } + else + { + s->cache_dev = 0; + s->cache_ino = 0; + s->cache_mtime = 0; + } /* * Insert into all fcCacheChains @@ -331,7 +349,6 @@ FcCacheRemove (FcCache *cache) update[i] = &next[i]; } s = next[0]; - assert (s->cache == cache); for (i = 0; i < fcCacheMaxLevel && *update[i] == s; i++) *update[i] = s->next[i]; while (fcCacheMaxLevel > 0 && fcCacheChains[fcCacheMaxLevel - 1] == NULL) @@ -348,7 +365,10 @@ FcCacheFindByStat (struct stat *cache_stat) if (s->cache_dev == cache_stat->st_dev && s->cache_ino == cache_stat->st_ino && s->cache_mtime == cache_stat->st_mtime) + { + s->ref++; return s->cache; + } return NULL; } @@ -402,11 +422,28 @@ FcCacheFini (void) assert (fcCacheMaxLevel == 0); } +static FcBool +FcCacheTimeValid (FcCache *cache, struct stat *dir_stat) +{ + struct stat dir_static; + + if (!dir_stat) + { + if (stat ((const char *) FcCacheDir (cache), &dir_static) < 0) + return FcFalse; + dir_stat = &dir_static; + } + if (FcDebug () & FC_DBG_CACHE) + printf ("FcCacheTimeValid dir \"%s\" cache time %d dir time %d\n", + FcCacheDir (cache), cache->mtime, (int) dir_stat->st_mtime); + return cache->mtime == (int) dir_stat->st_mtime; +} + /* * Map a cache file into memory */ static FcCache * -FcDirCacheMapFd (int fd, struct stat *fd_stat) +FcDirCacheMapFd (int fd, struct stat *fd_stat, struct stat *dir_stat) { FcCache *cache; FcBool allocated = FcFalse; @@ -417,7 +454,8 @@ FcDirCacheMapFd (int fd, struct stat *fd_stat) if (cache) return cache; /* - * For small cache files, just read them into memory + * Lage cache files are mmap'ed, smaller cache files are read. This + * balances the system cost of mmap against per-process memory usage. */ if (fd_stat->st_size >= FC_CACHE_MIN_MMAP) { @@ -432,7 +470,8 @@ FcDirCacheMapFd (int fd, struct stat *fd_stat) PAGE_READONLY, 0, 0, NULL); if (hFileMap != NULL) { - cache = MapViewOfFile (hFileMap, FILE_MAP_READ, 0, 0, size); + cache = MapViewOfFile (hFileMap, FILE_MAP_READ, 0, 0, + fd_stat->st_size); CloseHandle (hFileMap); } } @@ -454,7 +493,8 @@ FcDirCacheMapFd (int fd, struct stat *fd_stat) if (cache->magic != FC_CACHE_MAGIC_MMAP || cache->version < FC_CACHE_CONTENT_VERSION || cache->size != fd_stat->st_size || - !FcCacheInsert (cache, fd_stat)) + !FcCacheInsert (cache, fd_stat) || + !FcCacheTimeValid (cache, dir_stat)) { if (allocated) free (cache); @@ -476,6 +516,15 @@ FcDirCacheMapFd (int fd, struct stat *fd_stat) return cache; } +void +FcDirCacheReference (FcCache *cache, int nref) +{ + FcCacheSkip *skip = FcCacheFindByAddr (cache); + + if (skip) + skip->ref += nref; +} + void FcDirCacheUnload (FcCache *cache) { @@ -483,9 +532,9 @@ FcDirCacheUnload (FcCache *cache) } static FcBool -FcDirCacheMapHelper (int fd, struct stat *fd_stat, void *closure) +FcDirCacheMapHelper (int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure) { - FcCache *cache = FcDirCacheMapFd (fd, fd_stat); + FcCache *cache = FcDirCacheMapFd (fd, fd_stat, dir_stat); if (!cache) return FcFalse; @@ -514,7 +563,7 @@ FcDirCacheLoadFile (const FcChar8 *cache_file, struct stat *file_stat) fd = FcDirCacheOpenFile (cache_file, file_stat); if (fd < 0) return NULL; - cache = FcDirCacheMapFd (fd, file_stat); + cache = FcDirCacheMapFd (fd, file_stat, NULL); close (fd); return cache; } @@ -524,7 +573,7 @@ FcDirCacheLoadFile (const FcChar8 *cache_file, struct stat *file_stat) * the magic number and the size field */ static FcBool -FcDirCacheValidateHelper (int fd, struct stat *fd_stat, void *closure) +FcDirCacheValidateHelper (int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure) { FcBool ret = FcTrue; FcCache c; @@ -537,6 +586,8 @@ FcDirCacheValidateHelper (int fd, struct stat *fd_stat, void *closure) ret = FcFalse; else if (fd_stat->st_size != c.size) ret = FcFalse; + else if (c.mtime != (int) dir_stat->st_mtime) + ret = FcFalse; return ret; } @@ -564,7 +615,7 @@ FcDirCacheValid (const FcChar8 *dir) * Build a cache structure from the given contents */ FcCache * -FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, FcStrSet *dirs) +FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, struct stat *dir_stat, FcStrSet *dirs) { FcSerialize *serialize = FcSerializeCreate (); FcCache *cache; @@ -612,6 +663,7 @@ FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, FcStrSet *dirs) cache->magic = FC_CACHE_MAGIC_ALLOC; cache->version = FC_CACHE_CONTENT_VERSION; cache->size = serialize->size; + cache->mtime = (int) dir_stat->st_mtime; /* * Serialize directory name @@ -647,6 +699,8 @@ FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, FcStrSet *dirs) FcSerializeDestroy (serialize); + FcCacheInsert (cache, NULL); + return cache; bail2: @@ -656,6 +710,11 @@ bail1: return NULL; } + +#ifdef _WIN32 +#define mkdir(path,mode) _mkdir(path) +#endif + static FcBool FcMakeDirectory (const FcChar8 *dir) { @@ -787,16 +846,17 @@ FcDirCacheWrite (FcCache *cache, FcConfig *config) * Hokey little macro trick to permit the definitions of C functions * with the same name as CPP macros */ -#define args(x...) (x) +#define args1(x) (x) +#define args2(x,y) (x,y) const FcChar8 * -FcCacheDir args(const FcCache *c) +FcCacheDir args1(const FcCache *c) { return FcCacheDir (c); } FcFontSet * -FcCacheCopySet args(const FcCache *c) +FcCacheCopySet args1(const FcCache *c) { FcFontSet *old = FcCacheSet (c); FcFontSet *new = FcFontSetCreate (); @@ -805,28 +865,33 @@ FcCacheCopySet args(const FcCache *c) if (!new) return NULL; for (i = 0; i < old->nfont; i++) - if (!FcFontSetAdd (new, FcFontSetFont (old, i))) + { + FcPattern *font = FcFontSetFont (old, i); + + FcPatternReference (font); + if (!FcFontSetAdd (new, font)) { FcFontSetDestroy (new); return NULL; } + } return new; } const FcChar8 * -FcCacheSubdir args(const FcCache *c, int i) +FcCacheSubdir args2(const FcCache *c, int i) { return FcCacheSubdir (c, i); } int -FcCacheNumSubdir args(const FcCache *c) +FcCacheNumSubdir args1(const FcCache *c) { return c->dirs_count; } int -FcCacheNumFont args(const FcCache *c) +FcCacheNumFont args1(const FcCache *c) { return FcCacheSet(c)->nfont; } @@ -885,7 +950,7 @@ static void MD5Init(struct MD5Context *ctx) * Update context to reflect the concatenation of another buffer full * of bytes. */ -static void MD5Update(struct MD5Context *ctx, unsigned char *buf, unsigned len) +static void MD5Update(struct MD5Context *ctx, const unsigned char *buf, unsigned len) { FcChar32 t; @@ -1074,3 +1139,6 @@ static void MD5Transform(FcChar32 buf[4], FcChar32 in[16]) buf[2] += c; buf[3] += d; } +#define __fccache__ +#include "fcaliastail.h" +#undef __fccache__