Rewrite global cache handling code in fontconfig to eliminate per-file

syscalls
This commit is contained in:
Keith Packard 2002-07-28 10:50:59 +00:00
parent 23cd70c4ef
commit 327a7fd491
6 changed files with 852 additions and 506 deletions

View File

@ -191,7 +191,7 @@ typedef enum { FcEndianBig, FcEndianLittle } FcEndian;
typedef struct _FcConfig FcConfig;
typedef struct _FcFileCache FcFileCache;
typedef struct _FcGlobalCache FcFileCache;
typedef struct _FcBlanks FcBlanks;
@ -365,9 +365,6 @@ FcDirScan (FcFontSet *set,
FcBool
FcDirSave (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir);
FcBool
FcDirCacheValid (const FcChar8 *dir);
/* fcfreetype.c */
FcPattern *
FcFreeTypeQuery (const FcChar8 *file, int id, FcBlanks *blanks, int *count);

File diff suppressed because it is too large Load Diff

View File

@ -171,20 +171,20 @@ FcConfigDestroy (FcConfig *config)
FcBool
FcConfigBuildFonts (FcConfig *config)
{
FcFontSet *fonts;
FcFileCache *cache;
FcStrList *list;
FcChar8 *dir;
FcFontSet *fonts;
FcGlobalCache *cache;
FcStrList *list;
FcChar8 *dir;
fonts = FcFontSetCreate ();
if (!fonts)
goto bail0;
cache = FcFileCacheCreate ();
cache = FcGlobalCacheCreate ();
if (!cache)
goto bail1;
FcFileCacheLoad (cache, config->cache);
FcGlobalCacheLoad (cache, config->cache);
list = FcConfigGetFontDirs (config);
if (!list)
@ -202,8 +202,8 @@ FcConfigBuildFonts (FcConfig *config)
if (FcDebug () & FC_DBG_FONTSET)
FcFontSetPrint (fonts);
FcFileCacheSave (cache, config->cache);
FcFileCacheDestroy (cache);
FcGlobalCacheSave (cache, config->cache);
FcGlobalCacheDestroy (cache);
FcConfigSetFonts (config, fonts, FcSetSystem);
@ -456,8 +456,6 @@ typedef struct _FcSubState {
FcValueList *value;
} FcSubState;
static const FcMatrix FcIdentityMatrix = { 1, 0, 0, 1 };
static FcValue
FcConfigPromote (FcValue v, FcValue u)
{
@ -468,9 +466,8 @@ FcConfigPromote (FcValue v, FcValue u)
}
else if (v.type == FcTypeVoid && u.type == FcTypeMatrix)
{
v.u.m = FcMatrixCopy (&FcIdentityMatrix);
if (v.u.m)
v.type = FcTypeMatrix;
v.u.m = &FcIdentityMatrix;
v.type = FcTypeMatrix;
}
return v;
}

View File

@ -38,44 +38,71 @@ FcFileIsDir (const FcChar8 *file)
FcBool
FcFileScan (FcFontSet *set,
FcStrSet *dirs,
FcFileCache *cache,
FcGlobalCache *cache,
FcBlanks *blanks,
const FcChar8 *file,
FcBool force)
{
int id;
FcChar8 *name;
FcPattern *font;
FcBool ret = FcTrue;
FcBool isDir;
int count;
int id;
FcChar8 *name;
FcPattern *font;
FcBool ret = FcTrue;
FcBool isDir;
int count = 0;
FcGlobalCacheFile *cache_file;
FcGlobalCacheDir *cache_dir;
FcBool need_scan;
if (force)
cache = 0;
id = 0;
do
{
if (!force && cache)
name = FcFileCacheFind (cache, file, id, &count);
else
name = 0;
if (name)
need_scan = FcTrue;
font = 0;
/*
* Check the cache
*/
if (cache)
{
/* "." means the file doesn't contain a font */
if (FcStrCmp (name, FC_FONT_FILE_INVALID) == 0)
font = 0;
else if (FcStrCmp (name, FC_FONT_FILE_DIR) == 0)
if ((cache_file = FcGlobalCacheFileGet (cache, file, id, &count)))
{
ret = FcStrSetAdd (dirs, file);
font = 0;
/*
* Found a cache entry for the file
*/
if (FcGlobalCacheCheckTime (&cache_file->info))
{
name = cache_file->name;
need_scan = FcFalse;
FcGlobalCacheReferenced (cache, &cache_file->info);
/* "." means the file doesn't contain a font */
if (FcStrCmp (name, FC_FONT_FILE_INVALID) != 0)
{
font = FcNameParse (name);
if (font)
if (!FcPatternAddString (font, FC_FILE, file))
ret = FcFalse;
}
}
}
else
else if ((cache_dir = FcGlobalCacheDirGet (cache, file,
strlen ((const char *) file),
FcFalse)))
{
font = FcNameParse (name);
if (font)
if (!FcPatternAddString (font, FC_FILE, file))
if (FcGlobalCacheCheckTime (&cache_dir->info))
{
font = 0;
need_scan = FcFalse;
FcGlobalCacheReferenced (cache, &cache_dir->info);
if (!FcStrSetAdd (dirs, file))
ret = FcFalse;
}
}
}
else
/*
* Nothing in the cache, scan the file
*/
if (need_scan)
{
if (FcDebug () & FC_DBG_SCAN)
{
@ -91,35 +118,24 @@ FcFileScan (FcFontSet *set,
isDir = FcTrue;
ret = FcStrSetAdd (dirs, file);
}
if (!force && cache)
/*
* Update the cache
*/
if (cache && font)
{
if (font)
{
FcChar8 *unparse;
FcChar8 *unparse;
unparse = FcNameUnparse (font);
if (unparse)
{
(void) FcFileCacheUpdate (cache, file, id, unparse);
free (unparse);
}
}
else
unparse = FcNameUnparse (font);
if (unparse)
{
if (isDir)
{
FcFileCacheUpdate (cache, file, id, (FcChar8 *)
FC_FONT_FILE_DIR);
}
else
{
/* negative cache files not containing fonts */
FcFileCacheUpdate (cache, file, id, (FcChar8 *)
FC_FONT_FILE_INVALID);
}
(void) FcGlobalCacheUpdate (cache, file, id, unparse);
free (unparse);
}
}
}
/*
* Add the font
*/
if (font)
{
if (!FcFontSetAdd (set, font))
@ -134,40 +150,37 @@ FcFileScan (FcFontSet *set,
return ret;
}
FcBool
FcDirCacheValid (const FcChar8 *dir)
{
FcChar8 *path;
FcBool ret;
path = (FcChar8 *) malloc (strlen ((const char *) dir) + 1 +
strlen ((const char *) FC_DIR_CACHE_FILE) + 1);
if (!path)
return FcFalse;
strcpy ((char *) path, (const char *) dir);
strcat ((char *) path, (const char *) "/");
strcat ((char *) path, (const char *) FC_DIR_CACHE_FILE);
ret = FcFileCacheValid (path);
free (path);
return ret;
}
#define FC_MAX_FILE_LEN 4096
FcBool
FcDirScan (FcFontSet *set,
FcStrSet *dirs,
FcFileCache *cache,
FcGlobalCache *cache,
FcBlanks *blanks,
const FcChar8 *dir,
FcBool force)
{
DIR *d;
struct dirent *e;
FcChar8 *file;
FcChar8 *base;
FcBool ret = FcTrue;
DIR *d;
struct dirent *e;
FcChar8 *file;
FcChar8 *base;
FcBool ret = FcTrue;
if (!force)
{
/*
* Check fonts.cache file
*/
if (FcDirCacheReadDir (set, dirs, dir))
return FcTrue;
/*
* Check ~/.fonts.cache file
*/
if (cache && FcGlobalCacheScanDir (set, dirs, cache, dir))
return FcTrue;
}
file = (FcChar8 *) malloc (strlen ((char *) dir) + 1 + FC_MAX_FILE_LEN + 1);
if (!file)
return FcFalse;
@ -175,18 +188,9 @@ FcDirScan (FcFontSet *set,
strcpy ((char *) file, (char *) dir);
strcat ((char *) file, "/");
base = file + strlen ((char *) file);
if (!force)
{
strcpy ((char *) base, FC_DIR_CACHE_FILE);
if (FcFileCacheReadDir (set, dirs, file))
{
free (file);
return FcTrue;
}
}
d = opendir ((char *) dir);
if (!d)
{
free (file);
@ -205,25 +209,14 @@ FcDirScan (FcFontSet *set,
}
free (file);
closedir (d);
if (ret && cache)
FcGlobalCacheUpdate (cache, dir, 0, 0);
return ret;
}
FcBool
FcDirSave (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
{
FcChar8 *file;
FcChar8 *base;
FcBool ret;
file = (FcChar8 *) malloc (strlen ((char *) dir) + 1 + 256 + 1);
if (!file)
return FcFalse;
strcpy ((char *) file, (char *) dir);
strcat ((char *) file, "/");
base = file + strlen ((char *) file);
strcpy ((char *) base, FC_DIR_CACHE_FILE);
ret = FcFileCacheWriteDir (set, dirs, file);
free (file);
return ret;
return FcDirCacheWriteDir (set, dirs, dir);
}

View File

@ -195,24 +195,53 @@ typedef struct _FcStrBuf {
int size;
} FcStrBuf;
typedef struct _FcFileCacheEnt {
struct _FcFileCacheEnt *next;
unsigned int hash;
FcChar8 *file;
int id;
time_t time;
FcChar8 *name;
FcBool referenced;
} FcFileCacheEnt;
/*
* The per-user ~/.fonts.cache file is loaded into
* this data structure. Each directory gets a substructure
* which is validated by comparing the directory timestamp with
* that saved in the cache. When valid, the entire directory cache
* can be immediately loaded without reading the directory. Otherwise,
* the files are checked individually; updated files are loaded into the
* cache which is then rewritten to the users home directory
*/
#define FC_FILE_CACHE_HASH_SIZE 509
#define FC_GLOBAL_CACHE_DIR_HASH_SIZE 37
#define FC_GLOBAL_CACHE_FILE_HASH_SIZE 67
struct _FcFileCache {
FcFileCacheEnt *ents[FC_FILE_CACHE_HASH_SIZE];
FcBool updated;
int entries;
int referenced;
};
typedef struct _FcGlobalCacheInfo {
unsigned int hash;
FcChar8 *file;
time_t time;
FcBool referenced;
} FcGlobalCacheInfo;
typedef struct _FcGlobalCacheFile {
struct _FcGlobalCacheFile *next;
FcGlobalCacheInfo info;
int id;
FcChar8 *name;
} FcGlobalCacheFile;
typedef struct _FcGlobalCacheSubdir {
struct _FcGlobalCacheSubdir *next;
FcChar8 *file;
} FcGlobalCacheSubdir;
typedef struct _FcGlobalCacheDir {
struct _FcGlobalCacheDir *next;
FcGlobalCacheInfo info;
int len;
FcGlobalCacheFile *ents[FC_GLOBAL_CACHE_FILE_HASH_SIZE];
FcGlobalCacheSubdir *subdirs;
} FcGlobalCacheDir;
typedef struct _FcGlobalCache {
FcGlobalCacheDir *ents[FC_GLOBAL_CACHE_DIR_HASH_SIZE];
FcBool updated;
FcBool broken;
int entries;
int referenced;
} FcGlobalCache;
struct _FcAtomic {
FcChar8 *file; /* original file name */
@ -284,40 +313,60 @@ typedef struct _FcCharMap FcCharMap;
/* fccache.c */
FcFileCache *
FcFileCacheCreate (void);
FcChar8 *
FcFileCacheFind (FcFileCache *cache,
const FcChar8 *file,
int id,
int *count);
FcGlobalCache *
FcGlobalCacheCreate (void);
void
FcFileCacheDestroy (FcFileCache *cache);
FcGlobalCacheDestroy (FcGlobalCache *cache);
FcBool
FcFileCacheValid (const FcChar8 *cache_file);
FcGlobalCacheCheckTime (FcGlobalCacheInfo *info);
void
FcFileCacheLoad (FcFileCache *cache,
const FcChar8 *cache_file);
FcGlobalCacheReferenced (FcGlobalCache *cache,
FcGlobalCacheInfo *info);
FcGlobalCacheDir *
FcGlobalCacheDirGet (FcGlobalCache *cache,
const FcChar8 *dir,
int len,
FcBool create_missing);
FcBool
FcFileCacheUpdate (FcFileCache *cache,
const FcChar8 *file,
int id,
const FcChar8 *name);
FcGlobalCacheScanDir (FcFontSet *set,
FcStrSet *dirs,
FcGlobalCache *cache,
const FcChar8 *dir);
FcGlobalCacheFile *
FcGlobalCacheFileGet (FcGlobalCache *cache,
const FcChar8 *file,
int id,
int *count);
void
FcGlobalCacheLoad (FcGlobalCache *cache,
const FcChar8 *cache_file);
FcBool
FcFileCacheSave (FcFileCache *cache,
const FcChar8 *cache_file);
FcGlobalCacheUpdate (FcGlobalCache *cache,
const FcChar8 *file,
int id,
const FcChar8 *name);
FcBool
FcFileCacheReadDir (FcFontSet *set, FcStrSet *dirs, const FcChar8 *cache_file);
FcGlobalCacheSave (FcGlobalCache *cache,
const FcChar8 *cache_file);
FcBool
FcFileCacheWriteDir (FcFontSet *set, FcStrSet *dirs, const FcChar8 *cache_file);
FcDirCacheValid (const FcChar8 *cache_file);
FcBool
FcDirCacheReadDir (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir);
FcBool
FcDirCacheWriteDir (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir);
/* fccfg.c */
@ -523,6 +572,9 @@ FcPatternAddWithBinding (FcPattern *p,
/* fcrender.c */
/* fcmatrix.c */
extern const FcMatrix FcIdentityMatrix;
void
FcMatrixFree (FcMatrix *mat);

View File

@ -27,6 +27,8 @@
#include <ctype.h>
#include "fcint.h"
const FcMatrix FcIdentityMatrix = { 1, 0, 0, 1 };
FcMatrix *
FcMatrixCopy (const FcMatrix *mat)
{
@ -44,8 +46,11 @@ FcMatrixCopy (const FcMatrix *mat)
void
FcMatrixFree (FcMatrix *mat)
{
FcMemFree (FC_MEM_MATRIX, sizeof (FcMatrix));
free (mat);
if (mat != &FcIdentityMatrix)
{
FcMemFree (FC_MEM_MATRIX, sizeof (FcMatrix));
free (mat);
}
}
FcBool