From b8811fd0903deb48940d7edf5f369f897c677aa0 Mon Sep 17 00:00:00 2001 From: Michael Schroeder Date: Fri, 17 Jul 2009 11:20:19 +0200 Subject: [PATCH] - add repodata_write and repo_empty functions - make solv tool switch to written solv files to activate paging --- examples/solv.c | 54 ++++++++++++++++++++++++++++++++++++++++-------------- ext/repo_write.c | 32 ++++++++++++++++++++++++++++++++ ext/repo_write.h | 2 ++ src/repo.c | 35 ++++++++++++++++++++++++++++------- src/repo.h | 3 ++- src/repodata.c | 2 +- 6 files changed, 105 insertions(+), 23 deletions(-) diff --git a/examples/solv.c b/examples/solv.c index a7ce9b8..5a6c8ea 100644 --- a/examples/solv.c +++ b/examples/solv.c @@ -646,19 +646,6 @@ usecachedrepo(Repo *repo, const char *repoext, unsigned char *cookie) return 1; } -static int -myrepodatafilter(Repo *repo, Repokey *key, void *kfdata) -{ - Repodata *data = kfdata; - - /* XXX: special repodata selection hack */ - if (key->name == 1 && key->size != data - repo->repodata) - return -1; - if (key->storage == KEY_STORAGE_SOLVABLE) - return KEY_STORAGE_DROPPED; - return repo_write_stdkeyfilter(repo, key, kfdata); -} - void writecachedrepo(Repo *repo, Repodata *info, const char *repoext, unsigned char *cookie) { @@ -668,6 +655,7 @@ writecachedrepo(Repo *repo, Repodata *info, const char *repoext, unsigned char * char *tmpl; int myinfo = 0; struct repoinfo *cinfo; + int onepiece; cinfo = repo->appdata; mkdir(SOLVCACHE_PATH, 0755); @@ -686,6 +674,14 @@ writecachedrepo(Repo *repo, Repodata *info, const char *repoext, unsigned char * free(tmpl); return; } + + onepiece = 1; + for (i = repo->start; i < repo->end; i++) + if (repo->pool->solvables[i].repo != repo) + break; + if (i < repo->end) + onepiece = 0; + if (!repoext) { if (!info) @@ -704,7 +700,7 @@ writecachedrepo(Repo *repo, Repodata *info, const char *repoext, unsigned char * repo_write(repo, fp, repo_write_stdkeyfilter, 0, 0); } else - repo_write(repo, fp, myrepodatafilter, info, 0); + repodata_write(info, fp, repo_write_stdkeyfilter, 0); if (myinfo) repodata_free(info); if (fwrite(cookie, 32, 1, fp) != 1) @@ -727,6 +723,36 @@ writecachedrepo(Repo *repo, Repodata *info, const char *repoext, unsigned char * if (!stat(tmpl, &stb)) calc_checksum_stat(&stb, REPOKEY_TYPE_SHA256, cinfo->extcookie); } + if (onepiece) + { + /* switch to just saved repo to activate paging and save memory */ + FILE *fp = fopen(tmpl, "r"); + if (fp) + { + if (!repoext) + { + /* main repo */ + repo_empty(repo, 1); + if (repo_add_solv(repo, fp)) + { + /* oops, no way to recover from here */ + fprintf(stderr, "internal error\n"); + exit(1); + } + } + else + { + /* make sure repodata contains complete repo */ + /* (this is how repodata_write saves it) */ + repodata_extend_block(info, repo->start, repo->end - repo->start); + info->state = REPODATA_LOADING; + /* no need for LOCALPOOL as pool already contains ids */ + repo_add_solv_flags(repo, fp, REPO_USE_LOADING|REPO_EXTEND_SOLVABLES); + info->state = REPODATA_AVAILABLE; /* in case the load failed */ + } + fclose(fp); + } + } if (!rename(tmpl, calccachepath(repo, repoext))) unlink(tmpl); free(tmpl); diff --git a/ext/repo_write.c b/ext/repo_write.c index c17ead4..33cdfd2 100644 --- a/ext/repo_write.c +++ b/ext/repo_write.c @@ -1994,3 +1994,35 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1); sat_free(repodataused); sat_free(repodataschemata); } + +struct repodata_write_data { + int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata); + void *kfdata; + int repodataid; +}; + +static int +repodata_write_keyfilter(Repo *repo, Repokey *key, void *kfdata) +{ + struct repodata_write_data *wd = kfdata; + + /* XXX: special repodata selection hack */ + if (key->name == 1 && key->size != wd->repodataid) + return -1; + if (key->storage == KEY_STORAGE_SOLVABLE) + return KEY_STORAGE_DROPPED; /* not part of this repodata */ + if (wd->keyfilter) + return (*wd->keyfilter)(repo, key, wd->kfdata); + return key->storage; +} + +void +repodata_write(Repodata *data, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata), void *kfdata) +{ + struct repodata_write_data wd; + + wd.keyfilter = keyfilter; + wd.kfdata = kfdata; + wd.repodataid = data - data->repo->repodata; + repo_write(data->repo, fp, repodata_write_keyfilter, &wd, 0); +} diff --git a/ext/repo_write.h b/ext/repo_write.h index 5fc9bf2..87a79d4 100644 --- a/ext/repo_write.h +++ b/ext/repo_write.h @@ -20,4 +20,6 @@ void repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata), void *kfdata, Id **keyarrayp); int repo_write_stdkeyfilter(Repo *repo, Repokey *key, void *kfdata); +void repodata_write(Repodata *data , FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata), void *kfdata); + #endif diff --git a/src/repo.c b/src/repo.c index 0897b77..44d8790 100644 --- a/src/repo.c +++ b/src/repo.c @@ -68,13 +68,10 @@ repo_freedata(Repo *repo) sat_free(repo); } -/* - * remove repo from pool, zero out (i.e. free) solvables - * - */ +/* delete all solvables and repodata blocks from this repo */ void -repo_free(Repo *repo, int reuseids) +repo_empty(Repo *repo, int reuseids) { Pool *pool = repo->pool; Solvable *s; @@ -91,13 +88,37 @@ repo_free(Repo *repo, int reuseids) for (i = repo->end - 1, s = pool->solvables + i; i >= repo->start; i--, s--) if (s->repo != repo) break; - repo->end = i + 1; - pool->nsolvables = i + 1; + pool_free_solvable_block(pool, i + 1, repo->end - (i + 1), reuseids); } /* zero out (i.e. free) solvables belonging to this repo */ for (i = repo->start, s = pool->solvables + i; i < repo->end; i++, s++) if (s->repo == repo) memset(s, 0, sizeof(*s)); + repo->nsolvables = 0; + + /* free all data belonging to this repo */ + repo->idarraydata = sat_free(repo->idarraydata); + repo->idarraysize = 0; + repo->lastoff = 0; + repo->rpmdbid = sat_free(repo->rpmdbid); + for (i = 0; i < repo->nrepodata; i++) + repodata_freedata(repo->repodata + i); + repo->repodata = 0; + repo->nrepodata = 0; +} + +/* + * remove repo from pool, delete solvables + * + */ + +void +repo_free(Repo *repo, int reuseids) +{ + Pool *pool = repo->pool; + int i; + + repo_empty(repo, reuseids); for (i = 0; i < pool->nrepos; i++) /* find repo in pool */ if (pool->repos[i] == repo) break; diff --git a/src/repo.h b/src/repo.h index b66631b..3d16151 100644 --- a/src/repo.h +++ b/src/repo.h @@ -20,7 +20,7 @@ typedef struct _Repo { - const char *name; /* application private name pointer */ + const char *name; /* name pointer */ Id repoid; /* our id */ void *appdata; /* application private pointer */ @@ -46,6 +46,7 @@ typedef struct _Repo { extern Repo *repo_create(Pool *pool, const char *name); extern void repo_free(Repo *repo, int reuseids); +extern void repo_empty(Repo *repo, int reuseids); extern void repo_freeallrepos(Pool *pool, int reuseids); extern void repo_free_solvable_block(Repo *repo, Id start, int count, int reuseids); extern void *repo_sidedata_create(Repo *repo, size_t size); diff --git a/src/repodata.c b/src/repodata.c index e256245..6a3194a 100644 --- a/src/repodata.c +++ b/src/repodata.c @@ -116,7 +116,7 @@ repodata_free(Repodata *data) int i = data - repo->repodata; repodata_freedata(data); if (i < repo->nrepodata - 1) - memmove(repo->repodata + i, repo->repodata + i + 1, (repo->nrepodata - 1 - i) * sizeof(Repodata)); + memmove(repo->repodata + i, repo->repodata + i + 1, (repo->nrepodata - 1 - i) * sizeof(Repodata)); repo->nrepodata--; } -- 2.7.4