#ifdef out old cache stuff, replace with first version of new mmapping

cache. Add *Read and *Write procedures which mmap in and write out the
    fontconfig data structures to disk. Currently, create cache in /tmp,
    with different sections for each architecture (as returned by uname's
    .machine field. Run the fc-cache binary to create a new cache file;
    fontconfig then uses this cache file on subsequent runs, saving lots of
    memory. Also fixes a few bugs and leaks.
This commit is contained in:
Patrick Lam 2005-07-25 04:10:09 +00:00
parent e1b9d091c6
commit 212c9f437e
13 changed files with 964 additions and 894 deletions

View File

@ -93,6 +93,7 @@ usage (char *program)
exit (1);
}
#if 0
static int
nsubdirs (FcStrSet *set)
{
@ -222,6 +223,7 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool
FcStrListDone (list);
return ret;
}
#endif
int
main (int argc, char **argv)
@ -268,12 +270,20 @@ main (int argc, char **argv)
if (systemOnly)
FcConfigEnableHome (FcFalse);
config = FcInitLoadConfig ();
FcCacheForce (FcTrue);
/* need to use FcInitLoadConfig when we use dirs */
FcInit ();
config = FcConfigGetCurrent ();
if (!config)
{
fprintf (stderr, "%s: Can't init font config library\n", argv[0]);
return 1;
}
/* We don't yet have per-directory caches. */
ret = (FcCacheWrite (config) == FcFalse);
#if 0
if (argv[i])
{
dirs = FcStrSetCreate ();
@ -298,6 +308,7 @@ main (int argc, char **argv)
else
list = FcConfigGetConfigDirs (config);
ret = scanDirs (list, config, argv[0], force, verbose);
#endif
/*
* Now we need to sleep a second (or two, to be extra sure), to make
* sure that timestamps for changes after this run of fc-cache are later

View File

@ -47,6 +47,12 @@ FcMemFree (int kind, int size)
{
}
int
FcCacheNextOffset (int fd)
{
return -1;
}
FcChar8 *
FcConfigHome (void)
{

File diff suppressed because it is too large Load Diff

View File

@ -252,16 +252,22 @@ FcConfigBuildFonts (FcConfig *config)
FcStrList *list;
FcChar8 *dir;
#if 0
if (config->cache)
FcGlobalCacheLoad (cache, config->cache);
#endif
if (config->fonts[FcSetSystem])
return FcTrue;
fonts = FcFontSetCreate ();
if (!fonts)
goto bail0;
#if 0
cache = FcGlobalCacheCreate ();
if (!cache)
goto bail1;
if (config->cache)
FcGlobalCacheLoad (cache, config->cache);
#endif
list = FcConfigGetFontDirs (config);
if (!list)
@ -280,9 +286,11 @@ FcConfigBuildFonts (FcConfig *config)
if (FcDebug () & FC_DBG_FONTSET)
FcFontSetPrint (fonts);
#if 0
if (config->cache)
FcGlobalCacheSave (cache, config->cache);
FcGlobalCacheDestroy (cache);
#endif
FcConfigSetFonts (config, fonts, FcSetSystem);

View File

@ -23,6 +23,7 @@
*/
#include <stdlib.h>
#include <sys/mman.h>
#include "fcint.h"
/* #define CHECK */
@ -383,6 +384,14 @@ FcCharSetCopy (FcCharSet *src)
return src;
}
FcCharSetPtr
FcCharSetCopyPtr (FcCharSetPtr src)
{
if (FcCharSetPtrU(src)->ref != FC_REF_CONSTANT)
FcCharSetPtrU(src)->ref++;
return src;
}
FcBool
FcCharSetEqual (const FcCharSet *a, const FcCharSet *b)
{
@ -1369,10 +1378,11 @@ FcCharSetSerialize(FcCharSet *c)
if (!leaf_idx) goto bail3;
}
new.ref = c->ref;
new.ref = FC_REF_CONSTANT;
new.storage = FcStorageStatic;
new.u.stat.leafidx_offset = charset_leaf_ptr;
new.u.stat.leafidx_offset = charset_leaf_idx_ptr;
new.u.stat.numbers_offset = charset_numbers_ptr;
new.num = c->num;
newp.storage = FcStorageStatic;
newp.u.stat = charset_ptr;
@ -1398,6 +1408,95 @@ FcCharSetSerialize(FcCharSet *c)
return FcCharSetPtrCreateDynamic(0);
}
FcBool
FcCharSetRead (int fd, FcCache metadata)
{
charsets = mmap(NULL,
metadata.charsets_length * sizeof (FcCharSet),
PROT_READ,
MAP_SHARED, fd, metadata.charsets_offset);
if (charsets == MAP_FAILED)
goto bail;
charset_count = charset_ptr = metadata.charsets_length;
leaves = mmap(NULL,
metadata.charset_num_sum * sizeof (FcCharLeaf),
PROT_READ,
MAP_SHARED, fd, metadata.charset_leaf_offset);
if (leaves == MAP_FAILED)
goto bail1;
charset_leaf_count = charset_leaf_ptr = metadata.charset_num_sum;
leaf_idx = mmap(NULL,
metadata.charsets_length * sizeof (FcCharLeaf*),
PROT_READ,
MAP_SHARED, fd, metadata.charset_leafidx_offset);
if (leaf_idx == MAP_FAILED)
goto bail2;
charset_leaf_idx_count = charset_leaf_idx_ptr = metadata.charsets_length;
numbers = mmap(NULL,
metadata.charset_num_sum * sizeof (FcChar16),
PROT_READ,
MAP_SHARED, fd, metadata.charset_numbers_offset);
if (numbers == MAP_FAILED)
goto bail3;
charset_numbers_count = charset_numbers_ptr = metadata.charset_num_sum;
return FcTrue;
bail3:
munmap (leaf_idx, metadata.charsets_length * sizeof (FcCharLeaf*));
bail2:
munmap (leaves, metadata.charset_num_sum * sizeof (FcCharLeaf));
bail1:
munmap (charsets, metadata.charsets_length * sizeof (FcCharSet));
bail:
return FcFalse;
}
FcBool
FcCharSetWrite (int fd, FcCache *metadata)
{
metadata->charsets_length = charset_ptr;
metadata->charsets_offset = FcCacheNextOffset(fd);
if (charset_ptr > 0)
{
lseek (fd, metadata->charsets_offset, SEEK_SET);
if (write (fd, charsets, charset_ptr * sizeof(FcCharSet)) == -1)
return FcFalse;
}
metadata->charset_leaf_offset = FcCacheNextOffset(fd);
metadata->charset_num_sum = charset_leaf_ptr;
if (charset_leaf_ptr > 0)
{
lseek (fd, metadata->charset_leaf_offset, SEEK_SET);
if (write (fd, leaves, charset_leaf_ptr * sizeof(FcCharLeaf)) == -1)
return FcFalse;
}
metadata->charset_leafidx_offset = FcCacheNextOffset(fd);
if (charset_leaf_idx_ptr > 0)
{
lseek (fd, metadata->charset_leafidx_offset, SEEK_SET);
if (write (fd, leaf_idx, charset_leaf_idx_ptr * sizeof(FcCharLeaf*)) == -1)
return FcFalse;
}
metadata->charset_numbers_offset = FcCacheNextOffset(fd);
if (charset_leaf_ptr > 0)
{
lseek (fd, metadata->charset_numbers_offset, SEEK_SET);
if (write (fd, numbers, charset_leaf_ptr * sizeof(FcChar16)) == -1)
return FcFalse;
}
return FcTrue;
}
FcCharLeaf *
FcCharSetGetLeaf(const FcCharSet *c, int i)
{

View File

@ -45,13 +45,15 @@ FcFileScanConfig (FcFontSet *set,
FcConfig *config)
{
int id;
#if 0
FcChar8 *name;
FcGlobalCacheFile *cache_file;
FcGlobalCacheDir *cache_dir;
#endif
FcPattern *font;
FcBool ret = FcTrue;
FcBool isDir;
int count = 0;
FcGlobalCacheFile *cache_file;
FcGlobalCacheDir *cache_dir;
FcBool need_scan;
if (config && !FcConfigAcceptFilename (config, file))
@ -64,6 +66,7 @@ FcFileScanConfig (FcFontSet *set,
{
need_scan = FcTrue;
font = 0;
#if 0
/*
* Check the cache
*/
@ -104,6 +107,7 @@ FcFileScanConfig (FcFontSet *set,
}
}
}
#endif
/*
* Nothing in the cache, scan the file
*/
@ -123,6 +127,7 @@ FcFileScanConfig (FcFontSet *set,
isDir = FcTrue;
ret = FcStrSetAdd (dirs, file);
}
#if 0
/*
* Update the cache
*/
@ -137,6 +142,7 @@ FcFileScanConfig (FcFontSet *set,
FcStrFree (unparse);
}
}
#endif
}
/*
* Add the font
@ -193,6 +199,7 @@ FcDirScanConfig (FcFontSet *set,
if (!force)
{
#if 0
/*
* Check fonts.cache-<version> file
*/
@ -208,6 +215,7 @@ FcDirScanConfig (FcFontSet *set,
*/
if (cache && FcGlobalCacheScanDir (set, dirs, cache, dir, config))
return FcTrue;
#endif
}
/* freed below */
@ -246,8 +254,10 @@ FcDirScanConfig (FcFontSet *set,
* Now that the directory has been scanned,
* add the cache entry
*/
#if 0
if (ret && cache)
FcGlobalCacheUpdate (cache, dir, 0, 0);
#endif
return ret;
}
@ -266,5 +276,8 @@ FcDirScan (FcFontSet *set,
FcBool
FcDirSave (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
{
#if 0
return FcDirCacheWriteDir (set, dirs, dir);
#endif
return FcTrue;
}

View File

@ -116,3 +116,98 @@ FcFontSetClearStatic (void)
{
FcPatternClearStatic();
}
FcBool
FcFontSetRead(int fd, FcConfig * config, FcCache metadata)
{
int i, mz, j;
FcPattern * buf;
lseek(fd, metadata.fontsets_offset, SEEK_SET);
for (i = FcSetSystem; i <= FcSetApplication; i++)
{
if (config->fonts[i])
{
if (config->fonts[i]->nfont > 0 && config->fonts[i]->fonts)
free (config->fonts[i]->fonts);
free (config->fonts[i]);
}
}
for (i = FcSetSystem; i <= FcSetApplication; i++)
{
read(fd, &mz, sizeof(int));
if (mz != FC_CACHE_MAGIC)
continue;
config->fonts[i] = malloc(sizeof(FcFontSet));
if (!config->fonts[i])
return FcFalse;
FcMemAlloc(FC_MEM_FONTSET, sizeof(FcFontSet));
if (read(fd, config->fonts[i], sizeof(FcFontSet)) == -1)
goto bail;
if (config->fonts[i]->sfont > 0)
{
config->fonts[i]->fonts = malloc
(config->fonts[i]->sfont*sizeof(FcPattern *));
buf = malloc (config->fonts[i]->sfont * sizeof(FcPattern));
if (!config->fonts[i]->fonts || !buf)
goto bail;
for (j = 0; j < config->fonts[i]->nfont; j++)
{
config->fonts[i]->fonts[j] = buf+j;
if (read(fd, buf+j, sizeof(FcPattern)) == -1)
goto bail;
}
}
}
return FcTrue;
bail:
for (i = FcSetSystem; i <= FcSetApplication; i++)
{
if (config->fonts[i])
{
if (config->fonts[i]->fonts)
free (config->fonts[i]->fonts);
free(config->fonts[i]);
}
config->fonts[i] = 0;
}
return FcFalse;
}
FcBool
FcFontSetWrite(int fd, FcConfig * config, FcCache * metadata)
{
int c, t, i, j;
int m = FC_CACHE_MAGIC, z = 0;
metadata->fontsets_offset = FcCacheNextOffset(fd);
lseek(fd, metadata->fontsets_offset, SEEK_SET);
for (i = FcSetSystem; i <= FcSetApplication; i++)
{
if (!config->fonts[i])
{
write(fd, &z, sizeof(int));
continue;
}
else
write(fd, &m, sizeof(int));
if ((c = write(fd, config->fonts[i], sizeof(FcFontSet))) == -1)
return FcFalse;
t = c;
if (config->fonts[i]->nfont > 0)
{
for (j = 0; j < config->fonts[i]->nfont; j++)
{
if ((c = write(fd, config->fonts[i]->fonts[j],
sizeof(FcPattern))) == -1)
return FcFalse;
}
}
}
return FcTrue;
}

View File

@ -61,6 +61,9 @@ FcInitLoadConfig (void)
if (!config)
return FcFalse;
if (!FcCacheRead(config))
FcCacheForce(FcTrue);
if (!FcConfigParseAndLoad (config, 0, FcTrue))
{
FcConfigDestroy (config);

View File

@ -259,6 +259,25 @@ typedef struct _FcStrBuf {
int size;
} FcStrBuf;
typedef struct _FcCache {
int magic;
off_t fontsets_offset;
off_t pattern_offset; int pattern_length;
off_t patternelt_offset; int patternelt_length;
off_t valuelist_offset; int valuelist_length;
off_t object_offset; int object_length;
off_t objectcontent_offset; int objectcontent_length;
off_t langsets_offset; int langsets_length;
off_t charsets_offset; int charsets_length;
off_t charset_leaf_offset; int charset_num_sum;
off_t charset_leafidx_offset;
off_t charset_numbers_offset;
off_t matrices_offset; int matrices_length;
off_t strsets_offset; int strsets_length;
off_t strsets_idx_offset; int strsets_idx_length;
off_t strset_buf_offset; int strset_buf_length;
} FcCache;
/*
* To map adobe glyph names to unicode values, a precomputed hash
* table is used
@ -312,6 +331,7 @@ typedef struct _FcCaseFold {
* cache which is then rewritten to the users home directory
*/
#define FC_CACHE_MAGIC 0x12345678
#define FC_GLOBAL_CACHE_DIR_HASH_SIZE 37
#define FC_GLOBAL_CACHE_FILE_HASH_SIZE 67
@ -429,65 +449,26 @@ typedef struct _FcCharMap FcCharMap;
/* fccache.c */
FcGlobalCache *
FcGlobalCacheCreate (void);
int
FcCacheNextOffset(int fd);
void
FcGlobalCacheDestroy (FcGlobalCache *cache);
FcBool
FcGlobalCacheCheckTime (const FcChar8*file, FcGlobalCacheInfo *info);
FcCacheForce(FcBool force);
void
FcGlobalCacheReferenced (FcGlobalCache *cache,
FcGlobalCacheInfo *info);
void
FcGlobalCacheReferenceSubdir (FcGlobalCache *cache,
const FcChar8 *dir);
FcGlobalCacheDir *
FcGlobalCacheDirGet (FcGlobalCache *cache,
const FcChar8 *dir,
int len,
FcBool create_missing);
FcCacheClearStatic(void);
FcBool
FcGlobalCacheScanDir (FcFontSet *set,
FcStrSet *dirs,
FcGlobalCache *cache,
const FcChar8 *dir,
FcConfig *config);
FcGlobalCacheFile *
FcGlobalCacheFileGet (FcGlobalCache *cache,
const FcChar8 *file,
int id,
int *count);
void
FcGlobalCacheLoad (FcGlobalCache *cache,
const FcChar8 *cache_file);
FcCachePrepareSerialize(FcConfig * config);
FcBool
FcGlobalCacheUpdate (FcGlobalCache *cache,
const FcChar8 *file,
int id,
const FcChar8 *name);
FcCacheSerialize (FcConfig * config);
FcBool
FcGlobalCacheSave (FcGlobalCache *cache,
const FcChar8 *cache_file);
FcCacheRead (FcConfig *config);
FcBool
FcDirCacheReadDir (FcFontSet *set,
FcStrSet *dirs,
const FcChar8 *dir,
FcConfig *config);
FcBool
FcDirCacheWriteDir (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir);
FcCacheWrite (FcConfig * config);
/* fccfg.c */
@ -553,6 +534,9 @@ FcConfigAcceptFont (FcConfig *config,
FcCharSet *
FcCharSetFreeze (FcCharSet *cs);
FcCharSetPtr
FcCharSetCopyPtr (FcCharSetPtr src);
void
FcCharSetThawAll (void);
@ -586,6 +570,12 @@ FcCharSetGetLeaf(const FcCharSet *c, int i);
FcChar16 *
FcCharSetGetNumbers(const FcCharSet *c);
FcBool
FcCharSetRead (int fd, FcCache metadata);
FcBool
FcCharSetWrite (int fd, FcCache *metadata);
/* fcdbg.c */
void
FcValueListPrint (const FcValueListPtr l);
@ -668,6 +658,12 @@ FcFontSetPrepareSerialize (FcFontSet * s);
FcBool
FcFontSetSerialize (FcFontSet * s);
FcBool
FcFontSetRead(int fd, FcConfig * config, FcCache metadata);
FcBool
FcFontSetWrite(int fd, FcConfig * config, FcCache * metadata);
/* fcgram.y */
int
FcConfigparse (void);
@ -766,6 +762,12 @@ FcLangSetPtrCreateDynamic (FcLangSet *l);
void
FcLangSetPtrDestroy (FcLangSetPtr li);
FcBool
FcLangSetRead (int fd, FcCache metadata);
FcBool
FcLangSetWrite (int fd, FcCache *metadata);
/* fclist.c */
FcBool
@ -774,18 +776,6 @@ FcListPatternMatchAny (const FcPattern *p,
/* fcmatch.c */
/* fcmmap.c */
void
FcCacheClearStatic(void);
FcBool
FcCachePrepareSerialize(FcConfig * config);
FcBool
FcCacheSerialize (FcConfig * config);
/* fcname.c */
FcBool
@ -824,7 +814,10 @@ FcObjectPtr
FcObjectStaticName (const char *name);
FcBool
FcObjectPrepareSerialize (FcObjectPtr si);
FcObjectRead (int fd, FcCache metadata);
FcBool
FcObjectWrite (int fd, FcCache * metadata);
const char *
FcObjectPtrU (FcObjectPtr p);
@ -832,9 +825,6 @@ FcObjectPtrU (FcObjectPtr p);
int
FcObjectPtrCompare (FcObjectPtr a, FcObjectPtr b);
FcObjectPtr
FcObjectPtrCreateDynamic (const char * s);
void
FcObjectPtrDestroy (FcObjectPtr p);
@ -865,6 +855,24 @@ FcValueListSerialize(FcValueList *pi);
FcPattern *
FcPatternSerialize (FcPattern * p);
FcBool
FcPatternRead (int fd, FcCache metadata);
FcBool
FcPatternWrite (int fd, FcCache *metadata);
FcBool
FcPatternEltRead (int fd, FcCache metadata);
FcBool
FcPatternEltWrite (int fd, FcCache *metadata);
FcBool
FcValueListRead (int fd, FcCache metadata);
FcBool
FcValueListWrite (int fd, FcCache *metadata);
/* fcrender.c */
/* fcmatrix.c */
@ -892,6 +900,12 @@ FcMatrixPtrCreateDynamic (FcMatrix *m);
void
FcMatrixClearStatic (void);
FcBool
FcMatrixWrite (int fd, FcCache *metadata);
FcBool
FcMatrixRead (int fd, FcCache metadata);
/* fcstr.c */
FcStrSet *
FcStrSetPtrU (const FcStrSetPtr set);
@ -938,6 +952,12 @@ FcStrBufData (FcStrBuf *buf, const FcChar8 *s, int len);
FcStrSetPtr
FcStrSetSerialize (FcStrSet *set);
FcBool
FcStrSetRead (int fd, FcCache metadata);
FcBool
FcStrSetWrite (int fd, FcCache *metadata);
int
FcStrCmpIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2);

View File

@ -774,3 +774,31 @@ FcLangSetSerialize(FcLangSet *l)
new.u.stat = p;
return new;
}
FcBool
FcLangSetWrite (int fd, FcCache *metadata)
{
metadata->langsets_length = langset_ptr;
metadata->langsets_offset = FcCacheNextOffset(fd);
if (langset_ptr > 0)
{
lseek (fd, metadata->langsets_offset, SEEK_SET);
return write(fd, langsets,
metadata->langsets_length * sizeof(FcLangSet)) != -1;
}
return FcTrue;
}
FcBool
FcLangSetRead (int fd, FcCache metadata)
{
langsets = mmap(NULL,
metadata.langsets_length * sizeof (FcLangSet),
PROT_READ,
MAP_SHARED, fd, metadata.langsets_offset);
if (langsets == MAP_FAILED)
return FcFalse;
langset_count = langset_ptr = metadata.langsets_length;
return FcTrue;
}

View File

@ -25,6 +25,7 @@
#include <math.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/mman.h>
#include "fcint.h"
FcMatrix _id = { 1, 0, 0, 1 };
@ -182,3 +183,31 @@ FcMatrixSerialize(FcMatrix *m)
return new;
}
FcBool
FcMatrixRead (int fd, FcCache metadata)
{
matrices = mmap(NULL,
metadata.matrices_length * sizeof (FcMatrix),
PROT_READ,
MAP_SHARED, fd, metadata.matrices_offset);
if (matrices == MAP_FAILED)
return FcFalse;
matrix_count = matrix_ptr = metadata.matrices_length;
return FcTrue;
}
FcBool
FcMatrixWrite (int fd, FcCache *metadata)
{
metadata->matrices_length = matrix_ptr;
metadata->matrices_offset = FcCacheNextOffset(fd);
if (matrix_ptr > 0)
{
lseek(fd, metadata->matrices_offset, SEEK_SET);
return write(fd, matrices,
metadata->matrices_length * sizeof(FcMatrix)) != -1;
}
return FcTrue;
}

View File

@ -94,8 +94,7 @@ FcValueSave (FcValue v)
v.type = FcTypeVoid;
break;
case FcTypeCharSet:
v.u.ci = FcCharSetPtrCreateDynamic
(FcCharSetCopy (FcCharSetPtrU(v.u.ci)));
v.u.ci = FcCharSetCopyPtr (v.u.ci);
if (!FcCharSetPtrU(v.u.ci))
v.type = FcTypeVoid;
break;
@ -1270,7 +1269,6 @@ FcPatternEltU (FcPatternEltPtr pei)
switch (pei.storage)
{
case FcStorageStatic:
if (pei.u.stat == 0) return 0;
return &fcpatternelts[pei.u.stat];
case FcStorageDynamic:
return pei.u.dyn;
@ -1324,6 +1322,8 @@ FcValueListClearStatic (void)
fcvaluelist_count = 0;
}
static FcBool
FcObjectPrepareSerialize (FcObjectPtr si);
static FcObjectPtr
FcObjectSerialize (FcObjectPtr si);
@ -1408,11 +1408,12 @@ FcPatternSerialize (FcPattern *old)
fcpatternelt_ptr = 0;
}
p = FcPatternCreate();
p = &fcpatterns[fcpattern_ptr++];
elts = fcpatternelt_ptr;
nep = &fcpatternelts[elts];
if (!nep)
return FcFalse;
fcpatternelt_ptr += old->num;
for (e = FcPatternEltU(old->elts), i=0; i < old->num; i++, e++)
@ -1438,12 +1439,13 @@ FcPatternSerialize (FcPattern *old)
}
nep[i].values = nv_head;
nep[i].object = FcObjectSerialize
(FcObjectStaticName(FcObjectPtrU(e->object)));
nep[i].object = FcObjectSerialize (e->object);
}
p->elts = old->elts;
p->elts = FcPatternEltPtrCreateStatic(elts);
p->size = old->num;
p->num = old->num;
p->ref = FC_REF_CONSTANT;
return p;
@ -1453,7 +1455,69 @@ FcPatternSerialize (FcPattern *old)
free (fcpatterns);
bail:
return 0;
}
}
FcBool
FcPatternRead (int fd, FcCache metadata)
{
fcpatterns = mmap(NULL,
metadata.pattern_length * sizeof (FcPattern),
PROT_READ,
MAP_SHARED, fd, metadata.pattern_offset);
if (fcpatterns == MAP_FAILED)
return FcFalse;
fcpattern_count = fcpattern_ptr = metadata.pattern_length;
return FcTrue;
}
FcBool
FcPatternWrite (int fd, FcCache *metadata)
{
int c = fcpattern_ptr;
off_t w = FcCacheNextOffset(fd);
metadata->pattern_offset = w;
metadata->pattern_length = c;
if (c > 0)
{
lseek(fd, w, SEEK_SET);
return write(fd, fcpatterns, c*sizeof(FcPattern)) != -1;
}
return FcTrue;
}
FcBool
FcPatternEltRead (int fd, FcCache metadata)
{
fcpatternelts = mmap(NULL,
metadata.patternelt_length * sizeof (FcPatternElt),
PROT_READ,
MAP_SHARED, fd, metadata.patternelt_offset);
if (fcpatternelts == MAP_FAILED)
return FcFalse;
fcpatternelt_count = fcpatternelt_ptr = metadata.patternelt_length;
return FcTrue;
}
FcBool
FcPatternEltWrite (int fd, FcCache *metadata)
{
int c = fcpatternelt_ptr;
off_t w = FcCacheNextOffset(fd);
metadata->patternelt_offset = w;
metadata->patternelt_length = c;
if (c > 0)
{
lseek(fd, w, SEEK_SET);
return write(fd, fcpatternelts, c*sizeof(FcPatternElt)) != -1;
}
return FcTrue;
}
FcValueListPtr
FcValueListSerialize(FcValueList *pi)
@ -1480,13 +1544,18 @@ FcValueListSerialize(FcValueList *pi)
switch (v->type)
{
case FcTypeString:
if (FcObjectPtrU(v->u.si))
/* this departs from the usual convention of dereferencing
* foo before serialization; FcObjectSerialize does the
* translation itself. */
/* also, v->u.si is 0 iff the string is null. */
/* also, have to update the old pi */
if (v->u.si)
{
FcObjectPtr si =
FcObjectSerialize(FcObjectStaticName(FcObjectPtrU(v->u.si)));
if (!FcObjectPtrU(v->u.si))
FcObjectPtr si = FcObjectSerialize(v->u.si);
if (!FcObjectPtrU(si))
return FcValueListPtrCreateDynamic(pi);
v->u.si = si;
pi->value.u.si = si;
}
break;
case FcTypeMatrix:
@ -1503,7 +1572,7 @@ FcValueListSerialize(FcValueList *pi)
if (FcCharSetPtrU(v->u.ci))
{
FcCharSetPtr ci = FcCharSetSerialize(FcCharSetPtrU(v->u.ci));
if (!FcCharSetPtrU(v->u.ci))
if (!FcCharSetPtrU(ci))
return FcValueListPtrCreateDynamic(pi);
v->u.ci = ci;
}
@ -1512,7 +1581,7 @@ FcValueListSerialize(FcValueList *pi)
if (FcLangSetPtrU(v->u.li))
{
FcLangSetPtr li = FcLangSetSerialize(FcLangSetPtrU(v->u.li));
if (!FcLangSetPtrU(v->u.li))
if (!FcLangSetPtrU(li))
return FcValueListPtrCreateDynamic(pi);
v->u.li = li;
}
@ -1523,13 +1592,41 @@ FcValueListSerialize(FcValueList *pi)
return new;
}
FcBool
FcValueListRead (int fd, FcCache metadata)
{
fcvaluelists = mmap(NULL,
metadata.valuelist_length * sizeof (FcValueList),
PROT_READ,
MAP_SHARED, fd, metadata.valuelist_offset);
if (fcvaluelists == MAP_FAILED)
return FcFalse;
fcvaluelist_count = fcvaluelist_ptr = metadata.valuelist_length;
return FcTrue;
}
FcBool
FcValueListWrite (int fd, FcCache *metadata)
{
metadata->valuelist_offset = FcCacheNextOffset(fd);
metadata->valuelist_length = fcvaluelist_ptr;
if (fcvaluelist_ptr > 0)
{
lseek(fd, metadata->valuelist_offset, SEEK_SET);
return write(fd, fcvaluelists,
fcvaluelist_ptr * sizeof(FcValueList)) != -1;
}
return FcTrue;
}
FcValueList *
FcValueListPtrU (FcValueListPtr pi)
{
switch (pi.storage)
{
case FcStorageStatic:
if (pi.u.stat == 0) return 0;
return &fcvaluelists[pi.u.stat];
case FcStorageDynamic:
return pi.u.dyn;
@ -1642,7 +1739,7 @@ FcObjectStaticName (const char *name)
objectptr_alloc = s;
}
size = sizeof (struct objectBucket) + strlen (name) + 1;
size = sizeof (struct objectBucket) + sizeof (char *);
b = malloc (size);
if (!b)
return 0;
@ -1687,6 +1784,9 @@ FcObjectPtrDestroy (FcObjectPtr p)
const char *
FcObjectPtrU (FcObjectPtr si)
{
if (si == 0)
return 0;
if (objectptr_indices[si] > 0)
return &objectcontent_static_buf[objectptr_indices[si]];
else
@ -1750,7 +1850,7 @@ FcObjectRebuildStaticNameHashtable (void)
/* Hmm. This will have a terrible effect on the memory size,
* because the mmapped strings now get reallocated on the heap.
* Is it all worth it? (Of course, the Serialization codepath is
* not problematic.) */
* not problematic, because the program quits just afterwards.) */
static FcBool
FcObjectPtrConvertToStatic(FcBool renumber)
{
@ -1784,6 +1884,8 @@ FcObjectPtrConvertToStatic(FcBool renumber)
new_indices = malloc (active_count * sizeof(int));
if (!new_indices)
goto bail2;
new_indices[0] = 0;
new_static_buf[0] = 0;
FcMemAlloc (FC_MEM_STATICSTR, new_static_bytes);
FcMemFree (FC_MEM_STATICSTR, objectptr_count * sizeof (int));
@ -1817,8 +1919,8 @@ FcObjectPtrConvertToStatic(FcBool renumber)
int n = FcObjectStaticName(fixed_length_buf+i*(longest_string+1));
if (renumber)
{
object_old_id_to_new[n] = i;
new_indices[i] = p-new_static_buf;
object_old_id_to_new[n] = i+1;
new_indices[i+1] = p-new_static_buf;
}
else
new_indices[n] = p-new_static_buf;
@ -1907,21 +2009,11 @@ FcObjectClearStatic(void)
object_old_id_to_new = 0;
}
static FcObjectPtr
FcObjectSerialize (FcObjectPtr si)
{
if (objectptr_first_serialization)
if (!FcObjectPtrConvertToStatic(FcTrue))
return 0;
return object_old_id_to_new[si];
}
/* In the pre-serialization phase, mark the used strings with
* -1 in the mapping array. */
/* The first call to the serialization phase assigns actual
* static indices to the strings (sweep). */
FcBool
static FcBool
FcObjectPrepareSerialize (FcObjectPtr si)
{
if (object_old_id_to_new == 0)
@ -1942,6 +2034,93 @@ FcObjectPrepareSerialize (FcObjectPtr si)
return FcFalse;
}
static FcObjectPtr
FcObjectSerialize (FcObjectPtr si)
{
if (objectptr_first_serialization)
if (!FcObjectPtrConvertToStatic(FcTrue))
return 0;
return object_old_id_to_new[si];
}
FcBool
FcObjectRead (int fd, FcCache metadata)
{
/* do we have to merge strings?
* it's possible to merge dynamic strings, as long as we only store
* static strings to disk and as long as all static strings have lower
* ids than any dynamic strings. */
objectcontent_dynamic_count = 1;
objectcontent_dynamic_alloc = 0;
objectcontent_dynamic = 0;
objectcontent_dynamic_refcount = 0;
/* well, we do need to allocate dynamic strings all the time,
* so this would just have to be converted. It takes 1.4k on
* my system. - PL */
/* objectptr_indices = mmap(NULL, */
/* metadata.object_length * sizeof (int), */
/* PROT_READ, */
/* MAP_SHARED, fd, metadata.object_offset); */
/* if (objectptr_indices == MAP_FAILED) */
/* goto bail; */
objectptr_count = metadata.object_length;
objectptr_alloc = metadata.object_length;
objectptr_indices = malloc (metadata.object_length * sizeof (int));
if (!objectptr_indices)
goto bail;
FcMemAlloc (FC_MEM_STATICSTR, metadata.object_length * sizeof (int));
lseek (fd, metadata.object_offset, SEEK_SET);
read (fd, objectptr_indices, metadata.object_length * sizeof (int));
objectcontent_static_buf =
mmap(NULL,
metadata.objectcontent_length * sizeof (char),
PROT_READ,
MAP_SHARED, fd, metadata.objectcontent_offset);
if (objectptr_indices == MAP_FAILED)
goto bail1;
objectcontent_static_bytes = metadata.objectcontent_length;
FcObjectRebuildStaticNameHashtable ();
return FcTrue;
bail1:
/*munmap(objectptr_indices, metadata.object_length * sizeof(int));*/
free (objectptr_indices);
bail:
return FcFalse;
}
FcBool
FcObjectWrite (int fd, FcCache * metadata)
{
/* there should be no dynamic strings:
* serialize ought to have zapped 'em. */
if (objectcontent_dynamic_alloc)
return FcFalse;
metadata->object_length = objectptr_count;
metadata->object_offset = FcCacheNextOffset(fd);
lseek(fd, metadata->object_offset, SEEK_SET);
if (write (fd, objectptr_indices,
metadata->object_length * sizeof (int)) == -1)
return FcFalse;
metadata->objectcontent_length = objectcontent_static_bytes;
metadata->objectcontent_offset = FcCacheNextOffset(fd);
lseek(fd, metadata->objectcontent_offset, SEEK_SET);
if (write (fd, objectcontent_static_buf,
metadata->objectcontent_length * sizeof (char)) == -1)
return FcFalse;
return FcTrue;
}
static void
FcObjectStaticNameFini (void)
{

View File

@ -25,6 +25,7 @@
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <sys/mman.h>
#include "fcint.h"
FcChar8 *
@ -1129,8 +1130,8 @@ FcStrSetSerialize (FcStrSet *set)
if (strset_ptr > strset_count || strset_idx_ptr > strset_idx_count)
return FcStrSetPtrCreateDynamic(0);
// problem with multiple ptrs to the same LangSet.
// should hash LangSets or something.
// problem with multiple ptrs to the same StrSet.
// should hash StrSets or something.
// FcStrSetDestroy (set);
return newp;
@ -1143,6 +1144,77 @@ FcStrSetSerialize (FcStrSet *set)
return FcStrSetPtrCreateDynamic(0);
}
FcBool
FcStrSetRead (int fd, FcCache metadata)
{
strsets = mmap(NULL,
metadata.strsets_length * sizeof (FcStrSet),
PROT_READ,
MAP_SHARED, fd, metadata.strsets_offset);
if (strsets == MAP_FAILED)
goto bail;
strset_count = strset_ptr = metadata.strsets_length;
strset_idx = mmap(NULL,
metadata.strsets_idx_length * sizeof (int),
PROT_READ,
MAP_SHARED, fd, metadata.strsets_idx_offset);
if (strset_idx == MAP_FAILED)
goto bail1;
strset_idx_count = strset_idx_ptr = metadata.strsets_length;
strset_buf = mmap(NULL,
metadata.strset_buf_length * sizeof (char),
PROT_READ,
MAP_SHARED, fd, metadata.strset_buf_offset);
if (strset_buf == MAP_FAILED)
goto bail2;
strset_buf_count = strset_buf_ptr = metadata.strset_buf_length;
return FcTrue;
bail2:
munmap (strset_idx, metadata.strsets_idx_length * sizeof (int));
bail1:
munmap (strsets, metadata.strsets_length * sizeof (FcStrSet));
bail:
return FcFalse;
}
FcBool
FcStrSetWrite (int fd, FcCache *metadata)
{
metadata->strsets_length = strset_ptr;
metadata->strsets_offset = FcCacheNextOffset(fd);
if (strset_ptr > 0)
{
lseek (fd, metadata->strsets_offset, SEEK_SET);
if (write (fd, strsets, strset_ptr * sizeof(FcStrSet)) == -1)
return FcFalse;
}
metadata->strsets_idx_length = strset_idx_ptr;
metadata->strsets_idx_offset = FcCacheNextOffset(fd);
if (strset_idx_ptr > 0)
{
lseek (fd, metadata->strsets_idx_offset, SEEK_SET);
if (write (fd, strset_idx, strset_idx_ptr * sizeof (int)) == -1)
return FcFalse;
}
metadata->strset_buf_offset = FcCacheNextOffset(fd);
metadata->strset_buf_length = strset_buf_ptr;
if (strset_buf_ptr > 0)
{
lseek (fd, metadata->strset_buf_offset, SEEK_SET);
if (write (fd, strset_buf,
metadata->strset_buf_length * sizeof (char)) == -1)
return FcFalse;
}
return FcTrue;
}
FcStrList *
FcStrListCreate (FcStrSet *set)
{