join_freemem(&pd.jd);
stringpool_free(&pd.cspool);
solv_free(pd.cscache);
+ repodata_free_dircache(data);
if (!(flags & REPO_NO_INTERNALIZE))
repodata_internalize(data);
}
solv_free(joinhash);
+ repodata_free_dircache(data);
if (!(flags & REPO_NO_INTERNALIZE))
repodata_internalize(data);
finish_solvable(pool, data, s, filelist, nfilelist);
solv_free(line);
solv_free(filelist);
+ repodata_free_dircache(data);
if (!(flags & REPO_NO_INTERNALIZE))
repodata_internalize(data);
return 0;
repodata_extend;
repodata_extend_block;
repodata_free;
+ repodata_free_dircache;
repodata_free_schemahash;
repodata_freedata;
repodata_globalize_id;
if (did)
MAPSET(&cbd->useddirs, did);
}
+ repodata_free_dircache(data);
}
if (value->id >= data->dirpool.ndirs || !MAPTST(&cbd->useddirs, value->id))
return 0;
solv_free(data->attrdata);
solv_free(data->attriddata);
+
+ solv_free(data->dircache);
}
void
}
#endif
+#define DIRCACHE_SIZE 41 /* < 1k */
+
+#ifdef DIRCACHE_SIZE
+struct dircache {
+ Id ids[DIRCACHE_SIZE];
+ char str[(DIRCACHE_SIZE * (DIRCACHE_SIZE - 1)) / 2];
+};
+#endif
+
Id
repodata_str2dir(Repodata *data, const char *dir, int create)
{
Id id, parent;
+#ifdef DIRCACHE_SIZE
+ const char *dirs;
+#endif
const char *dire;
parent = 0;
+ if (!*dir)
+ return 0;
while (*dir == '/' && dir[1] == '/')
dir++;
if (*dir == '/' && !dir[1])
return 1;
return dirpool_add_dir(&data->dirpool, 0, 1, create);
}
+#ifdef DIRCACHE_SIZE
+ dirs = dir;
+ if (data->dircache)
+ {
+ int l;
+ struct dircache *dircache = data->dircache;
+ l = strlen(dir);
+ while (l > 0)
+ {
+ if (l < DIRCACHE_SIZE && dircache->ids[l] && !memcmp(dircache->str + l * (l - 1) / 2, dir, l))
+ {
+ parent = dircache->ids[l];
+ dir += l;
+ if (!*dir)
+ return parent;
+ while (*dir == '/')
+ dir++;
+ break;
+ }
+ while (--l)
+ if (dir[l] == '/')
+ break;
+ }
+ }
+#endif
while (*dir)
{
dire = strchrnul(dir, '/');
parent = dirpool_add_dir(&data->dirpool, parent, id, create);
if (!parent)
return 0;
+#ifdef DIRCACHE_SIZE
+ if (!data->dircache)
+ data->dircache = solv_calloc(1, sizeof(struct dircache));
+ if (data->dircache)
+ {
+ int l = dire - dirs;
+ if (l < DIRCACHE_SIZE)
+ {
+ data->dircache->ids[l] = parent;
+ memcpy(data->dircache->str + l * (l - 1) / 2, dirs, l);
+ }
+ }
+#endif
if (!*dire)
break;
dir = dire + 1;
return parent;
}
+void
+repodata_free_dircache(Repodata *data)
+{
+ data->dircache = solv_free(data->dircache);
+}
+
const char *
repodata_dir2str(Repodata *data, Id did, const char *suf)
{
#define KEY_STORAGE_INCORE 2
#define KEY_STORAGE_VERTICAL_OFFSET 3
+#ifdef LIBSOLV_INTERNAL
+struct dircache;
+#endif
typedef struct _Repodata {
Id repodataid; /* our id */
Id lasthandle;
Id lastkey;
Id lastdatalen;
+
+ /* directory cache to speed up repodata_str2dir */
+ struct dircache *dircache;
#endif
} Repodata;
/* directory (for package file list) */
void repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2);
void repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str);
+void repodata_free_dircache(Repodata *data);
/* Arrays */