commit: f83a84c2d8907914bb2c4cf3079a16e73e870677
Author: Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Mon Aug 25 11:39:36 2025 +0000
Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Mon Aug 25 11:39:36 2025 +0000
URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=f83a84c2
q: drop entries for cache in gtree
It appears archive entries are expensive in storage, so cut back by
stashing all of the cache entries in a single file, much like md5-cache
does. There appears to be no use for these separately that would be
seriously punished by having to grab all of them together (and parse the
rows).
Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>
q.c | 97 +++++++++++++++++++++++++++++++++++++++++++++------------------------
1 file changed, 64 insertions(+), 33 deletions(-)
diff --git a/q.c b/q.c
index d29c686..325d19c 100644
--- a/q.c
+++ b/q.c
@@ -109,6 +109,9 @@ int lookup_applet_idx(const char *applet)
struct q_cache_ctx {
struct archive *archive;
time_t buildtime;
+ char *cbuf;
+ size_t cbufsiz;
+ size_t cbuflen;
};
static int q_build_cache_pkg_process_dir(struct q_cache_ctx *ctx,
char *path,
@@ -187,25 +190,33 @@ int q_build_cache_pkg(tree_pkg_ctx *pkg, void *priv)
siz = sizeof(buf) - len;
/* - ebuilds/CAT/PF
- * + cache/ (keys from md5-cache except _md5_, _eclasses_ and
- * repository, the latter is stored at the top level
+ * + cache keys from md5-cache except _md5_, _eclasses_ and
+ * repository (the latter is stored at the top level)
* in addition to this the required eclass names are
- * stored in a new key called eclasses) */
+ * stored in a new key called eclasses
+ * all of this is stored as key-value file, because
+ * storing it as individual keys takes much more storage
+ * for no particular benefit */
+
+ /* start over, reusing previous buf allocation */
+ ctx->cbuflen = 0;
+
#define q_cache_add_cache_entry_val(K,V) \
do { \
qc = V; \
- if (qc != NULL) { \
+ if (qc != NULL) \
qclen = strlen(qc); \
- entry = archive_entry_new(); \
- snprintf(p, siz, "cache/" #K); \
- archive_entry_set_pathname(entry, buf); \
- archive_entry_set_size(entry, qclen); \
- archive_entry_set_mtime(entry, ctx->buildtime, 0); \
- archive_entry_set_filetype(entry, AE_IFREG); \
- archive_entry_set_perm(entry, 0644); \
- archive_write_header(a, entry); \
- archive_write_data(a, qc, qclen); \
- archive_entry_free(entry); \
+ else \
+ qclen = 0; \
+ if (qclen > 0) { \
+ if (ctx->cbuflen + qclen + 1 > ctx->cbufsiz) { \
+ ctx->cbufsiz = ctx->cbuflen + qclen + 1; \
+ ctx->cbufsiz = ((ctx->cbufsiz + (1024 - 1)) /
1024) * 1024; \
+ ctx->cbuf = xrealloc(ctx->cbuf,
ctx->cbufsiz); \
+ } \
+ ctx->cbuflen += snprintf(ctx->cbuf + ctx->cbuflen, \
+
ctx->cbufsiz - ctx->cbuflen, \
+ #K
"=%s\n", qc); \
} \
} while (false)
#define q_cache_add_cache_entry(K) \
@@ -246,7 +257,8 @@ int q_build_cache_pkg(tree_pkg_ctx *pkg, void *priv)
char *tp;
bool write;
- /* eclasses, drop the md5 hashes, just leave a list of names */
+ /* eclasses, drop the md5 hashes, just leave a list of names
+ * we don't expect selections on these, so store as data */
qc = tree_pkg_meta_get(pkg, _eclasses_);
if (qc != NULL) {
for (tp = tmpbuf, write = true; *qc != '\0'; qc++) {
@@ -264,7 +276,18 @@ int q_build_cache_pkg(tree_pkg_ctx *pkg, void *priv)
#undef q_cache_add_cache_entry
#undef q_cache_add_cache_entry_val
- /* + ebuild (the file from the tree)
+ entry = archive_entry_new();
+ snprintf(p, siz, "cache");
+ archive_entry_set_pathname(entry, buf);
+ archive_entry_set_size(entry, ctx->cbuflen);
+ archive_entry_set_mtime(entry, ctx->buildtime, 0);
+ archive_entry_set_filetype(entry, AE_IFREG);
+ archive_entry_set_perm(entry, 0644);
+ archive_write_header(a, entry);
+ archive_write_data(a, ctx->cbuf, ctx->cbuflen);
+ archive_entry_free(entry);
+
+ /* + <PF>.ebuild (the file from the tree)
* + Manifest (the file from the tree, to verify distfiles)
* + files/ (the directory from the tree) */
if (pkg->cat_ctx->ctx->treetype == TREE_EBUILD) {
@@ -288,7 +311,7 @@ int q_build_cache_pkg(tree_pkg_ctx *pkg, void *priv)
if (ffd >= 0) {
if (fstat(ffd, &st) == 0) {
entry = archive_entry_new();
- snprintf(p, siz, "ebuild");
+ snprintf(p, siz, "%s.ebuild", atom->PF);
archive_entry_set_pathname(entry, buf);
archive_entry_set_size(entry, st.st_size);
archive_entry_set_mtime(entry, ctx->buildtime,
0);
@@ -672,15 +695,17 @@ int q_main(int argc, char **argv)
/* traverse all overlays, create a cache for each
* the cache basically is one giant tar with:
* - gtree-1 (mandatory, first file ident)
- * - repository
- * - ebuilds/CAT/PF
- * + cache/
- * + ebuild (the file from the tree)
- * + metadata.xml (the file from the tree)
- * + Manifest (the file from the tree, to verify distfiles)
- * + files/ (the directory from the tree)
- * - eclasses/ (the directory from the tree)
- * but all of them within are guaranteed to be consistant with
+ * - repo.tar{compr}
+ * - repository
+ * - ebuilds/CAT/PF
+ * + cache (extracted info from the ebuild)
+ * + PF.ebuild (the file from the tree)
+ * + metadata.xml (the file from the tree)
+ * + Manifest (the file from the tree, to verify distfiles)
+ * + files/ (the directory from the tree)
+ * - eclasses/ (the directory from the tree)
+ * - repo.tar{compr}.sig
+ * but all of them within are guaranteed to be consistent with
* each other (it is one snapshot)
* the cache is suitable for distribution
*
@@ -702,13 +727,22 @@ int q_main(int argc, char **argv)
size_t len;
int dfd;
-
memset(&qcctx, 0, sizeof(qcctx));
array_for_each(overlays, n, overlay) {
if (verbose)
printf("building cache for %s\n", overlay);
+ /* we store the cache inside the metadata dir, which
means
+ * it gets wiped on portage sync (good because that
would
+ * invalidate it) and tree_open can transparently
locate and
+ * use it */
+ snprintf(buf, sizeof(buf),
+ "%s/metadata/repo.gtree.tar.zst",
overlay);
+ /* because we're building a new one here, make sure
+ * tree_open doesn't pick it up */
+ unlink(buf);
+
t = tree_open(portroot, overlay);
if (t == NULL) {
warn("could not open overlay at %s", overlay);
@@ -722,12 +756,7 @@ int q_main(int argc, char **argv)
continue;
}
- /* we store the cache inside the metadata dir, which
means
- * it gets wiped on portage sync (good because that
would
- * invalidate it) and tree_open can transparently
locate and
- * use it */
- snprintf(buf, sizeof(buf),
- "%s/metadata/repo.gtree.tar.zst",
t->path);
+ /* ensure we can actually write the new cache */
mkdir_p_at(t->tree_fd, "metadata", 0755);
a = archive_write_new();
@@ -784,6 +813,8 @@ int q_main(int argc, char **argv)
archive_write_free(a);
}
+ free(qcctx.cbuf);
+
return 0;
}