Apply 9 patches from upstream

This commit is contained in:
Jaroslav Mracek 2016-03-08 13:12:00 +01:00
parent a48fd05882
commit 78b212e337
10 changed files with 2566 additions and 1 deletions

View File

@ -0,0 +1,79 @@
From f362259ac2f92c6c1914974032f2f7c436ac00d4 Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Fri, 26 Feb 2016 11:45:09 +0100
Subject: [PATCH 1/9] Add repodata_lookup_dirstrarray_uninternalized method
Needed for next commit.
---
src/libsolv.ver | 1 +
src/repodata.c | 25 +++++++++++++++++++++++++
src/repodata.h | 3 +++
3 files changed, 29 insertions(+)
diff --git a/src/libsolv.ver b/src/libsolv.ver
index 6508288..cc79704 100644
--- a/src/libsolv.ver
+++ b/src/libsolv.ver
@@ -201,6 +201,7 @@ SOLV_1.0 {
repodata_key2id;
repodata_localize_id;
repodata_lookup_bin_checksum;
+ repodata_lookup_bin_checksum_uninternalized;
repodata_lookup_binary;
repodata_lookup_dirstrarray_uninternalized;
repodata_lookup_id;
diff --git a/src/repodata.c b/src/repodata.c
index ad3e71a..b611afc 100644
--- a/src/repodata.c
+++ b/src/repodata.c
@@ -881,6 +881,31 @@ repodata_lookup_dirstrarray_uninternalized(Repodata *data, Id solvid, Id keyname
return 0;
}
+const unsigned char *
+repodata_lookup_bin_checksum_uninternalized(Repodata *data, Id solvid, Id keyname, Id *typep)
+{
+ Id *ap;
+ if (!data->attrs)
+ return 0;
+ ap = data->attrs[solvid - data->start];
+ if (!ap)
+ return 0;
+ for (; *ap; ap += 2)
+ {
+ if (data->keys[*ap].name != keyname)
+ continue;
+ switch (data->keys[*ap].type)
+ {
+ case_CHKSUM_TYPES:
+ *typep = data->keys[*ap].type;
+ return (const unsigned char *)data->attrdata + ap[1];
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+
/************************************************************************
* data search
*/
diff --git a/src/repodata.h b/src/repodata.h
index c18c688..d72c60f 100644
--- a/src/repodata.h
+++ b/src/repodata.h
@@ -300,8 +300,11 @@ const char *repodata_chk2str(Repodata *data, Id type, const unsigned char *buf);
void repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, const char *file);
void repodata_set_deltalocation(Repodata *data, Id handle, int medianr, const char *dir, const char *file);
void repodata_set_sourcepkg(Repodata *data, Id solvid, const char *sourcepkg);
+
+/* uninternalized data lookup */
Id repodata_lookup_id_uninternalized(Repodata *data, Id solvid, Id keyname, Id voidid);
const char *repodata_lookup_dirstrarray_uninternalized(Repodata *data, Id solvid, Id keyname, Id *didp, Id *iterp);
+const unsigned char *repodata_lookup_bin_checksum_uninternalized(Repodata *data, Id solvid, Id keyname, Id *typep);
/* stats */
unsigned int repodata_memused(Repodata *data);
--
2.5.0

View File

@ -0,0 +1,272 @@
From 0280a6a08344a11c8fd0e0226263cc8a808fd4c1 Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Fri, 26 Feb 2016 11:45:27 +0100
Subject: [PATCH 2/9] Do not create a checksum hash when we're not extending
Many repos don't have extension data, so we postpone the
hash creation until we need it.
---
ext/repo_rpmmd.c | 165 +++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 117 insertions(+), 48 deletions(-)
diff --git a/ext/repo_rpmmd.c b/ext/repo_rpmmd.c
index a45d491..cc54b3e 100644
--- a/ext/repo_rpmmd.c
+++ b/ext/repo_rpmmd.c
@@ -258,12 +258,18 @@ struct parsedata {
Id changelog_handle;
- /** Hash to maps checksums to solv */
+ int extending; /* are we extending an existing solvable? */
+
+ /* first solvable we added */
+ int first;
+ /* cspool ok to use */
+ int cshash_filled;
+ /* Hash to maps checksums to solv */
Stringpool cspool;
- /** Cache of known checksums to solvable id */
- Id *cscache;
+ /* Cache of known checksums to solvable id */
+ Id *cshash;
/* the current longest index in the table */
- int ncscache;
+ int ncshash;
};
static Id
@@ -576,6 +582,83 @@ set_description_author(Repodata *data, Id handle, char *str, struct parsedata *p
}
+
+static void
+init_cshash(struct parsedata *pd)
+{
+ /* initialize the string pool where we will store
+ the package checksums we know about, to get an Id
+ we can use in a cache */
+ stringpool_init_empty(&pd->cspool);
+}
+
+static void
+free_cshash(struct parsedata *pd)
+{
+ stringpool_free(&pd->cspool);
+ solv_free(pd->cshash);
+}
+
+/* save the checksum as key to solvable id relationship for
+ metadata extension */
+static void
+put_in_cshash(struct parsedata *pd, const char *key, Id id)
+{
+ Id index = stringpool_str2id(&pd->cspool, key, 1);
+ if (index >= pd->ncshash)
+ {
+ pd->cshash = solv_zextend(pd->cshash, pd->ncshash, index + 1 - pd->ncshash, sizeof(Id), 255);
+ pd->ncshash = index + 1;
+ }
+ /* add the checksum to the cache */
+ pd->cshash[index] = id;
+}
+
+static Id
+lookup_cshash(struct parsedata *pd, const char *key)
+{
+ Id index = stringpool_str2id(&pd->cspool, key, 0);
+ if (!index || index >= pd->ncshash || !pd->cshash[index])
+ return 0;
+ return pd->cshash[index];
+}
+
+static void
+fill_cshash_from_repo(struct parsedata *pd)
+{
+ Dataiterator di;
+ /* setup join data */
+ dataiterator_init(&di, pd->pool, pd->repo, 0, SOLVABLE_CHECKSUM, 0, 0);
+ while (dataiterator_step(&di))
+ {
+ const char *str;
+
+ if (!solv_chksum_len(di.key->type))
+ continue;
+ str = repodata_chk2str(di.data, di.key->type, (const unsigned char *)di.kv.str);
+ put_in_cshash(pd, str, di.solvid);
+ }
+ dataiterator_free(&di);
+}
+
+static void
+fill_cshash_from_new_solvables(struct parsedata *pd)
+{
+ Pool *pool = pd->pool;
+ Id cstype;
+ unsigned const char *cs;
+ int i;
+
+ for (i = pd->first; i < pool->nsolvables; i++)
+ {
+ if (pool->solvables[i].repo != pd->repo)
+ continue;
+ cs = repodata_lookup_bin_checksum_uninternalized(pd->data, i, SOLVABLE_CHECKSUM, &cstype);
+ if (cs)
+ put_in_cshash(pd, repodata_chk2str(pd->data, cstype, cs), i);
+ }
+}
+
/*-----------------------------------------------*/
/* XML callbacks */
@@ -664,26 +747,35 @@ startElement(void *userData, const char *name, const char **atts)
a new solvable but just append the attributes to the existing
one.
*/
+ pd->extending = 0;
if ((pkgid = find_attr("pkgid", atts)) != NULL)
{
+ if (!pd->cshash_filled)
+ {
+ pd->cshash_filled = 1;
+ fill_cshash_from_new_solvables(pd);
+ }
/* look at the checksum cache */
- Id index = stringpool_str2id(&pd->cspool, pkgid, 0);
- if (!index || index >= pd->ncscache || !pd->cscache[index])
+ handle = lookup_cshash(pd, pkgid);
+ if (!handle)
{
pool_debug(pool, SOLV_WARN, "the repository specifies extra information about package with checksum '%s', which does not exist in the repository.\n", pkgid);
- pd->solvable = 0;
pd->handle = 0;
+ pd->solvable = 0;
break;
}
- pd->solvable = pool_id2solvable(pool, pd->cscache[index]);
+ pd->extending = 1;
}
else
{
/* this is a new package */
- pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->repo));
+ handle = repo_add_solvable(pd->repo);
+ if (!pd->first)
+ pd->first = handle;
pd->freshens = 0;
}
- pd->handle = handle = pd->solvable - pool->solvables;
+ pd->handle = handle;
+ pd->solvable = pool_id2solvable(pool, handle);
if (pd->kind && pd->kind[1] == 'r')
{
/* products can have a type */
@@ -697,6 +789,8 @@ startElement(void *userData, const char *name, const char **atts)
break;
case STATE_VERSION:
+ if (pd->extending && s->evr)
+ break; /* ignore version tag repetition in extend data */
s->evr = makeevr_atts(pool, pd, atts);
break;
case STATE_PROVIDES:
@@ -923,6 +1017,11 @@ endElement(void *userData, const char *name)
switch (pd->state)
{
case STATE_SOLVABLE:
+ if (pd->extending)
+ {
+ pd->solvable = 0;
+ break;
+ }
if (pd->kind && !s->name) /* add namespace in case of NULL name */
s->name = pool_str2id(pool, join2(&pd->jd, pd->kind, ":", 0), 1);
if (!s->arch)
@@ -935,7 +1034,7 @@ endElement(void *userData, const char *name)
s->conflicts = repo_fix_conflicts(repo, s->conflicts);
pd->freshens = 0;
pd->kind = 0;
- pd->solvable = s = 0;
+ pd->solvable = 0;
break;
case STATE_NAME:
if (pd->kind)
@@ -957,8 +1056,6 @@ endElement(void *userData, const char *name)
break;
case STATE_CHECKSUM:
{
- Id index;
-
if (!pd->chksumtype)
break;
if (strlen(pd->content) != 2 * solv_chksum_len(pd->chksumtype))
@@ -967,16 +1064,9 @@ endElement(void *userData, const char *name)
break;
}
repodata_set_checksum(pd->data, handle, SOLVABLE_CHECKSUM, pd->chksumtype, pd->content);
- /* we save the checksum to solvable id relationship for extended
- metadata */
- index = stringpool_str2id(&pd->cspool, pd->content, 1 /* create it */);
- if (index >= pd->ncscache)
- {
- pd->cscache = solv_zextend(pd->cscache, pd->ncscache, index + 1 - pd->ncscache, sizeof(Id), 255);
- pd->ncscache = index + 1;
- }
- /* add the checksum to the cache */
- pd->cscache[index] = s - pool->solvables;
+ /* we save the checksum to solvable id relationship for extending metadata */
+ if (pd->cshash_filled)
+ put_in_cshash(pd, pd->content, s - pool->solvables);
break;
}
case STATE_FILE:
@@ -1165,32 +1255,12 @@ repo_add_rpmmd(Repo *repo, FILE *fp, const char *language, int flags)
pd.kind = 0;
pd.language = language && *language && strcmp(language, "en") != 0 ? language : 0;
- /* initialize the string pool where we will store
- the package checksums we know about, to get an Id
- we can use in a cache */
- stringpool_init_empty(&pd.cspool);
+ init_cshash(&pd);
if ((flags & REPO_EXTEND_SOLVABLES) != 0)
{
/* setup join data */
- Dataiterator di;
- dataiterator_init(&di, pool, repo, 0, SOLVABLE_CHECKSUM, 0, 0);
- while (dataiterator_step(&di))
- {
- const char *str;
- int index;
-
- if (!solv_chksum_len(di.key->type))
- continue;
- str = repodata_chk2str(di.data, di.key->type, (const unsigned char *)di.kv.str);
- index = stringpool_str2id(&pd.cspool, str, 1);
- if (index >= pd.ncscache)
- {
- pd.cscache = solv_zextend(pd.cscache, pd.ncscache, index + 1 - pd.ncscache, sizeof(Id), 255);
- pd.ncscache = index + 1;
- }
- pd.cscache[index] = di.solvid;
- }
- dataiterator_free(&di);
+ pd.cshash_filled = 1;
+ fill_cshash_from_repo(&pd);
}
parser = XML_ParserCreate(NULL);
@@ -1213,8 +1283,7 @@ repo_add_rpmmd(Repo *repo, FILE *fp, const char *language, int flags)
solv_free(pd.content);
solv_free(pd.lastdirstr);
join_freemem(&pd.jd);
- stringpool_free(&pd.cspool);
- solv_free(pd.cscache);
+ free_cshash(&pd);
repodata_free_dircache(data);
if (!(flags & REPO_NO_INTERNALIZE))
--
2.5.0

View File

@ -0,0 +1,34 @@
From 4cebb81db05fd9281a6d482adce25c93605ed5da Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Fri, 26 Feb 2016 13:40:28 +0100
Subject: [PATCH 3/9] solv_hex2bin: don't eat nibbles
---
src/util.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/util.c b/src/util.c
index d611297..b2e9179 100644
--- a/src/util.c
+++ b/src/util.c
@@ -235,7 +235,7 @@ solv_hex2bin(const char **strp, unsigned char *buf, int bufl)
d = c - ('A' - 10);
else
break;
- c = *++str;
+ c = str[1];
d <<= 4;
if (c >= '0' && c <= '9')
d |= c - '0';
@@ -246,7 +246,7 @@ solv_hex2bin(const char **strp, unsigned char *buf, int bufl)
else
break;
buf[i] = d;
- ++str;
+ str += 2;
}
*strp = str;
return i;
--
2.5.0

View File

@ -0,0 +1,265 @@
From d06562f7b70f6ceb7d52e717efd1963ce6e8ecf0 Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Mon, 29 Feb 2016 13:49:48 +0100
Subject: [PATCH 4/9] Use less memory when extending packages
Implement a hash instead of mis-using a string pool.
---
ext/repo_rpmmd.c | 166 +++++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 126 insertions(+), 40 deletions(-)
diff --git a/ext/repo_rpmmd.c b/ext/repo_rpmmd.c
index cc54b3e..77366c2 100644
--- a/ext/repo_rpmmd.c
+++ b/ext/repo_rpmmd.c
@@ -264,12 +264,12 @@ struct parsedata {
int first;
/* cspool ok to use */
int cshash_filled;
- /* Hash to maps checksums to solv */
- Stringpool cspool;
- /* Cache of known checksums to solvable id */
- Id *cshash;
- /* the current longest index in the table */
- int ncshash;
+
+ Hashtable cshash; /* checksum hash -> offset into csdata */
+ Hashval cshashm; /* hash mask */
+ int ncshash; /* entries used */
+ unsigned char *csdata; /* [len, checksum, id] */
+ int ncsdata; /* used bytes */
};
static Id
@@ -582,45 +582,125 @@ set_description_author(Repodata *data, Id handle, char *str, struct parsedata *p
}
+/*-----------------------------------------------*/
+/* checksum hash functions
+ *
+ * used to look up a solvable with the checksum for solvable extension purposes.
+ *
+ */
static void
init_cshash(struct parsedata *pd)
{
- /* initialize the string pool where we will store
- the package checksums we know about, to get an Id
- we can use in a cache */
- stringpool_init_empty(&pd->cspool);
}
static void
free_cshash(struct parsedata *pd)
{
- stringpool_free(&pd->cspool);
+ pd->cshash = solv_free(pd->cshash);
+ pd->ncshash = 0;
+ pd->cshashm = 0;
+ pd->csdata = solv_free(pd->csdata);
+ pd->ncsdata = 0;
+}
+
+static inline Hashval
+hashkey(const unsigned char *key, int keyl)
+{
+ return key[0] << 24 | key[1] << 16 | key[2] << 8 | key[3];
+}
+
+static void
+rebuild_cshash(struct parsedata *pd)
+{
+ Hashval h, hh, hm;
+ Hashtable ht;
+ unsigned char *d, *de;
+
+ hm = pd->cshashm;
+#if 0
+ fprintf(stderr, "rebuild cshash with mask 0x%x\n", hm);
+#endif
solv_free(pd->cshash);
+ ht = pd->cshash = (Hashtable)solv_calloc(hm + 1, sizeof(Id));
+ d = pd->csdata;
+ de = d + pd->ncsdata;
+ while (d != de)
+ {
+ h = hashkey(d + 1, d[0] + 1) & hm;
+ hh = HASHCHAIN_START;
+ while (ht[h])
+ h = HASHCHAIN_NEXT(h, hh, hm);
+ ht[h] = d + 1 - pd->csdata;
+ d += 2 + d[0] + sizeof(Id);
+ }
}
-/* save the checksum as key to solvable id relationship for
- metadata extension */
static void
-put_in_cshash(struct parsedata *pd, const char *key, Id id)
+put_in_cshash(struct parsedata *pd, const unsigned char *key, int keyl, Id id)
{
- Id index = stringpool_str2id(&pd->cspool, key, 1);
- if (index >= pd->ncshash)
+ Hashtable ht;
+ Hashval h, hh, hm;
+ unsigned char *d;
+
+ if (keyl < 4 || keyl > 256)
+ return;
+ ht = pd->cshash;
+ hm = pd->cshashm;
+ h = hashkey(key, keyl) & hm;
+ hh = HASHCHAIN_START;
+ if (ht)
{
- pd->cshash = solv_zextend(pd->cshash, pd->ncshash, index + 1 - pd->ncshash, sizeof(Id), 255);
- pd->ncshash = index + 1;
+ while (ht[h])
+ {
+ unsigned char *d = pd->csdata + ht[h];
+ if (d[-1] == keyl && !memcmp(key, d, keyl))
+ return; /* XXX: first id wins... */
+ h = HASHCHAIN_NEXT(h, hh, hm);
+ }
}
- /* add the checksum to the cache */
- pd->cshash[index] = id;
+ /* a new entry. put in csdata */
+ pd->csdata = solv_extend(pd->csdata, pd->ncsdata, 1, 1 + keyl + sizeof(Id), 4095);
+ d = pd->csdata + pd->ncsdata;
+ d[0] = keyl - 1;
+ memcpy(d + 1, key, keyl);
+ memcpy(d + 1 + keyl, &id, sizeof(Id));
+ pd->ncsdata += 1 + keyl + sizeof(Id);
+ if ((Hashval)++pd->ncshash * 2 > hm)
+ {
+ pd->cshashm = pd->cshashm ? (2 * pd->cshashm + 1) : 4095;
+ rebuild_cshash(pd);
+ }
+ else
+ ht[h] = pd->ncsdata - (keyl + sizeof(Id));
}
static Id
-lookup_cshash(struct parsedata *pd, const char *key)
+lookup_cshash(struct parsedata *pd, const unsigned char *key, int keyl)
{
- Id index = stringpool_str2id(&pd->cspool, key, 0);
- if (!index || index >= pd->ncshash || !pd->cshash[index])
+ Hashtable ht;
+ Hashval h, hh, hm;
+
+ if (keyl < 4 || keyl > 256)
+ return 0;
+ ht = pd->cshash;
+ if (!ht)
return 0;
- return pd->cshash[index];
+ hm = pd->cshashm;
+ h = hashkey(key, keyl) & hm;
+ hh = HASHCHAIN_START;
+ while (ht[h])
+ {
+ unsigned char *d = pd->csdata + ht[h];
+ if (d[-1] == keyl - 1 && !memcmp(key, d, keyl))
+ {
+ Id id;
+ memcpy(&id, d + keyl, sizeof(Id));
+ return id;
+ }
+ h = HASHCHAIN_NEXT(h, hh, hm);
+ }
+ return 0;
}
static void
@@ -630,14 +710,7 @@ fill_cshash_from_repo(struct parsedata *pd)
/* setup join data */
dataiterator_init(&di, pd->pool, pd->repo, 0, SOLVABLE_CHECKSUM, 0, 0);
while (dataiterator_step(&di))
- {
- const char *str;
-
- if (!solv_chksum_len(di.key->type))
- continue;
- str = repodata_chk2str(di.data, di.key->type, (const unsigned char *)di.kv.str);
- put_in_cshash(pd, str, di.solvid);
- }
+ put_in_cshash(pd, (const unsigned char *)di.kv.str, solv_chksum_len(di.key->type), di.solvid);
dataiterator_free(&di);
}
@@ -645,7 +718,7 @@ static void
fill_cshash_from_new_solvables(struct parsedata *pd)
{
Pool *pool = pd->pool;
- Id cstype;
+ Id cstype = 0;
unsigned const char *cs;
int i;
@@ -655,7 +728,7 @@ fill_cshash_from_new_solvables(struct parsedata *pd)
continue;
cs = repodata_lookup_bin_checksum_uninternalized(pd->data, i, SOLVABLE_CHECKSUM, &cstype);
if (cs)
- put_in_cshash(pd, repodata_chk2str(pd->data, cstype, cs), i);
+ put_in_cshash(pd, cs, solv_chksum_len(cstype), i);
}
}
@@ -750,13 +823,23 @@ startElement(void *userData, const char *name, const char **atts)
pd->extending = 0;
if ((pkgid = find_attr("pkgid", atts)) != NULL)
{
+ unsigned char chk[256];
+ int l;
+ const char *str = pkgid;
if (!pd->cshash_filled)
{
pd->cshash_filled = 1;
fill_cshash_from_new_solvables(pd);
}
+ handle = 0;
+ /* convert into bin checksum */
+ l = solv_hex2bin(&str, chk, sizeof(chk));
/* look at the checksum cache */
- handle = lookup_cshash(pd, pkgid);
+ if (l >= 4 && !pkgid[2 * l])
+ handle = lookup_cshash(pd, chk, l);
+#if 0
+ fprintf(stderr, "Lookup %s -> %d\n", pkgid, handle);
+#endif
if (!handle)
{
pool_debug(pool, SOLV_WARN, "the repository specifies extra information about package with checksum '%s', which does not exist in the repository.\n", pkgid);
@@ -1056,17 +1139,20 @@ endElement(void *userData, const char *name)
break;
case STATE_CHECKSUM:
{
- if (!pd->chksumtype)
+ unsigned char chk[256];
+ int l = solv_chksum_len(pd->chksumtype);
+ const char *str = pd->content;
+ if (!l || l > sizeof(chk))
break;
- if (strlen(pd->content) != 2 * solv_chksum_len(pd->chksumtype))
+ if (solv_hex2bin(&str, chk, l) != l || pd->content[2 * l])
{
- pd->ret = pool_error(pool, -1, "line %d: invalid checksum length for %s", (unsigned int)XML_GetCurrentLineNumber(*pd->parser), solv_chksum_type2str(pd->chksumtype));
+ pd->ret = pool_error(pool, -1, "line %u: invalid %s checksum", (unsigned int)XML_GetCurrentLineNumber(*pd->parser), solv_chksum_type2str(pd->chksumtype));
break;
}
- repodata_set_checksum(pd->data, handle, SOLVABLE_CHECKSUM, pd->chksumtype, pd->content);
+ repodata_set_bin_checksum(pd->data, handle, SOLVABLE_CHECKSUM, pd->chksumtype, chk);
/* we save the checksum to solvable id relationship for extending metadata */
if (pd->cshash_filled)
- put_in_cshash(pd, pd->content, s - pool->solvables);
+ put_in_cshash(pd, chk, l, s - pool->solvables);
break;
}
case STATE_FILE:
--
2.5.0

30
0006-Fix-comments.patch Normal file
View File

@ -0,0 +1,30 @@
From 4bcff7d8e7fadcc0b314aa654ce97579db3bbe1a Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Mon, 29 Feb 2016 14:14:05 +0100
Subject: [PATCH 5/9] Fix comments
---
ext/repo_rpmmd.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/ext/repo_rpmmd.c b/ext/repo_rpmmd.c
index 77366c2..5ef5c25 100644
--- a/ext/repo_rpmmd.c
+++ b/ext/repo_rpmmd.c
@@ -259,11 +259,8 @@ struct parsedata {
Id changelog_handle;
int extending; /* are we extending an existing solvable? */
-
- /* first solvable we added */
- int first;
- /* cspool ok to use */
- int cshash_filled;
+ int first; /* first solvable we added */
+ int cshash_filled; /* hash is filled with data */
Hashtable cshash; /* checksum hash -> offset into csdata */
Hashval cshashm; /* hash mask */
--
2.5.0

View File

@ -0,0 +1,50 @@
From 5218114520e47f50bef59606d32d9434ee4b6f47 Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Thu, 3 Mar 2016 12:59:18 +0100
Subject: [PATCH 6/9] rpmmd diskusage: prepend a '/' to the dir if not already
there
Makes the code consistent with repo_susetags.
---
ext/repo_rpmmd.c | 23 ++++++++++++++++-------
1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/ext/repo_rpmmd.c b/ext/repo_rpmmd.c
index 5ef5c25..78264cc 100644
--- a/ext/repo_rpmmd.c
+++ b/ext/repo_rpmmd.c
@@ -1014,15 +1014,24 @@ startElement(void *userData, const char *name, const char **atts)
{
long filesz = 0, filenum = 0;
Id dirid;
- if ((str = find_attr("name", atts)) != 0)
- dirid = repodata_str2dir(pd->data, str, 1);
- else
- {
+ if ((str = find_attr("name", atts)) == 0)
+ {
pd->ret = pool_error(pool, -1, "<dir .../> tag without 'name' attribute");
break;
- }
- if (!dirid)
- dirid = repodata_str2dir(pd->data, "/", 1);
+ }
+ if (*str != '/')
+ {
+ int l = strlen(str) + 2;
+ if (l > pd->acontent)
+ {
+ pd->content = solv_realloc(pd->content, l + 256);
+ pd->acontent = l + 256;
+ }
+ *pd->content = '/';
+ strcpy(pd->content + 1, str);
+ str = pd->content;
+ }
+ dirid = repodata_str2dir(pd->data, str, 1);
if ((str = find_attr("size", atts)) != 0)
filesz = strtol(str, 0, 0);
if ((str = find_attr("count", atts)) != 0)
--
2.5.0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,47 @@
From e1f29013dd6eeb77db7fb0ad6e9343cd880ccbde Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Thu, 3 Mar 2016 15:18:34 +0100
Subject: [PATCH 8/9] Make _Pool_tmpspace definition internal
---
src/pool.h | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/src/pool.h b/src/pool.h
index 4a2089d..b9e2ed6 100644
--- a/src/pool.h
+++ b/src/pool.h
@@ -34,9 +34,6 @@ extern "C" {
#define SYSTEMSOLVABLE 1
-/* how many strings to maintain (round robin) */
-#define POOL_TMPSPACEBUF 16
-
/*----------------------------------------------- */
struct _Repo;
@@ -52,12 +49,20 @@ typedef struct _Datapos {
Id dp;
} Datapos;
+
+#ifdef LIBSOLV_INTERNAL
+
+/* how many strings to maintain (round robin) */
+#define POOL_TMPSPACEBUF 16
+
struct _Pool_tmpspace {
char *buf[POOL_TMPSPACEBUF];
int len[POOL_TMPSPACEBUF];
int n;
};
+#endif
+
struct _Pool {
void *appdata; /* application private pointer */
--
2.5.0

View File

@ -0,0 +1,311 @@
From 6c9cef4ef810cd32ffeee20986a16e0871fc0bae Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Mon, 7 Mar 2016 14:09:40 +0100
Subject: [PATCH 9/9] Rework orphan handling in dup mode
The old code had problems when the updaters contained other
installed packages.
---
src/rules.c | 193 +++++++++++++++++++++++++++++++++++++++++++----------------
src/rules.h | 3 +-
src/solver.c | 7 ++-
3 files changed, 149 insertions(+), 54 deletions(-)
diff --git a/src/rules.c b/src/rules.c
index 4cd53d3..0e2c955 100644
--- a/src/rules.c
+++ b/src/rules.c
@@ -1170,35 +1170,56 @@ solver_addpkgrulesforupdaters(Solver *solv, Solvable *s, Map *m, int allow_all)
***
***/
+static int
+dup_maykeepinstalled(Solver *solv, Solvable *s)
+{
+ Pool *pool = solv->pool;
+ Id ip, pp;
+
+ if (solv->dupmap.size && MAPTST(&solv->dupmap, s - pool->solvables))
+ return 1;
+ /* is installed identical to a good one? */
+ FOR_PROVIDES(ip, pp, s->name)
+ {
+ Solvable *is = pool->solvables + ip;
+ if (is->evr != s->evr)
+ continue;
+ if (solv->dupmap.size)
+ {
+ if (!MAPTST(&solv->dupmap, ip))
+ continue;
+ }
+ else if (is->repo == pool->installed)
+ continue;
+ if (solvable_identical(s, is))
+ return 1;
+ }
+ return 0;
+}
+
+
static Id
-finddistupgradepackages(Solver *solv, Solvable *s, Queue *qs, int allow_all)
+finddistupgradepackages(Solver *solv, Solvable *s, Queue *qs)
{
Pool *pool = solv->pool;
- int i;
+ int i, j;
- policy_findupdatepackages(solv, s, qs, allow_all ? allow_all : 2);
- if (!qs->count)
+ policy_findupdatepackages(solv, s, qs, 2);
+ if (qs->count)
{
- if (allow_all)
- return 0; /* orphaned, don't create feature rule */
- /* check if this is an orphaned package */
- policy_findupdatepackages(solv, s, qs, 1);
- if (!qs->count)
- return 0; /* orphaned, don't create update rule */
- qs->count = 0;
- return -SYSTEMSOLVABLE; /* supported but not installable */
+ /* remove installed packages we can't keep */
+ for (i = j = 0; i < qs->count; i++)
+ {
+ Solvable *ns = pool->solvables + qs->elements[i];
+ if (ns->repo == pool->installed && !dup_maykeepinstalled(solv, ns))
+ continue;
+ qs->elements[j++] = qs->elements[i];
+ }
+ queue_truncate(qs, j);
}
- if (allow_all)
- return s - pool->solvables;
/* check if it is ok to keep the installed package */
- if (solv->dupmap.size && MAPTST(&solv->dupmap, s - pool->solvables))
+ if (dup_maykeepinstalled(solv, s))
return s - pool->solvables;
- for (i = 0; i < qs->count; i++)
- {
- Solvable *ns = pool->solvables + qs->elements[i];
- if (s->evr == ns->evr && solvable_identical(s, ns))
- return s - pool->solvables;
- }
/* nope, it must be some other package */
return -SYSTEMSOLVABLE;
}
@@ -1240,6 +1261,73 @@ set_specialupdaters(Solver *solv, Solvable *s, Id d)
solv->specialupdaters[s - solv->pool->solvables - installed->start] = d;
}
+#ifdef ENABLE_LINKED_PKGS
+/* Check if this is a linked pseudo package. As it is linked, we do not need an update/feature rule */
+static inline int
+is_linked_pseudo_package(Solver *solv, Solvable *s)
+{
+ Pool *pool = solv->pool;
+ if (solv->instbuddy && solv->instbuddy[s - pool->solvables - solv->installed->start])
+ {
+ const char *name = pool_id2str(pool, s->name);
+ if (strncmp(name, "pattern:", 8) == 0 || strncmp(name, "application:", 12) == 0)
+ return 1;
+ }
+ return 0;
+}
+#endif
+
+void
+solver_addfeaturerule(Solver *solv, Solvable *s)
+{
+ Pool *pool = solv->pool;
+ int i;
+ Id p;
+ Queue qs;
+ Id qsbuf[64];
+
+#ifdef ENABLE_LINKED_PKGS
+ if (is_linked_pseudo_package(solv, s))
+ {
+ solver_addrule(solv, 0, 0, 0); /* no feature rules for those */
+ return;
+ }
+#endif
+ queue_init_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf));
+ p = s - pool->solvables;
+ policy_findupdatepackages(solv, s, &qs, 1);
+ if (solv->dupmap_all || (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p)))
+ {
+ if (!dup_maykeepinstalled(solv, s))
+ {
+ for (i = 0; i < qs.count; i++)
+ {
+ Solvable *ns = pool->solvables + qs.elements[i];
+ if (ns->repo != pool->installed || dup_maykeepinstalled(solv, ns))
+ break;
+ }
+ if (i == qs.count)
+ {
+ solver_addrule(solv, 0, 0, 0); /* this is an orphan */
+ queue_free(&qs);
+ return;
+ }
+ }
+ }
+ if (qs.count > 1)
+ {
+ Id d = pool_queuetowhatprovides(pool, &qs);
+ queue_free(&qs);
+ solver_addrule(solv, p, 0, d); /* allow update of s */
+ }
+ else
+ {
+ Id d = qs.count ? qs.elements[0] : 0;
+ queue_free(&qs);
+ solver_addrule(solv, p, d, 0); /* allow update of s */
+ }
+}
+
/*-------------------------------------------------------------------
*
* add rule for update
@@ -1249,7 +1337,7 @@ set_specialupdaters(Solver *solv, Solvable *s, Id d)
*/
void
-solver_addupdaterule(Solver *solv, Solvable *s, int allow_all)
+solver_addupdaterule(Solver *solv, Solvable *s)
{
/* installed packages get a special upgrade allowed rule */
Pool *pool = solv->pool;
@@ -1257,48 +1345,53 @@ solver_addupdaterule(Solver *solv, Solvable *s, int allow_all)
Queue qs;
Id qsbuf[64];
int isorphaned = 0;
+ Rule *r;
+ int islinkedpseudo = 0;
- queue_init_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf));
p = s - pool->solvables;
+#ifdef ENABLE_LINKED_PKGS
+ islinkedpseudo = is_linked_pseudo_package(solv, s);
+#endif
+
+ /* Orphan detection. We cheat by looking at the feature rule, which
+ * we already calculated */
+ r = solv->rules + solv->featurerules + (p - solv->installed->start);
+ if (!r->p && !islinkedpseudo)
+ {
+ p = 0;
+ queue_push(&solv->orphaned, s - pool->solvables); /* an orphaned package */
+ if (solv->keep_orphans && !(solv->droporphanedmap_all || (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, s - pool->solvables - solv->installed->start))))
+ p = s - pool->solvables; /* keep this orphaned package installed */
+ solver_addrule(solv, p, 0, 0);
+ return;
+ }
+
+ queue_init_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf));
/* find update candidates for 's' */
if (solv->dupmap_all || (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p)))
- p = finddistupgradepackages(solv, s, &qs, allow_all);
+ p = finddistupgradepackages(solv, s, &qs);
else
- policy_findupdatepackages(solv, s, &qs, allow_all);
+ policy_findupdatepackages(solv, s, &qs, 0);
#ifdef ENABLE_LINKED_PKGS
- if (solv->instbuddy && solv->instbuddy[s - pool->solvables - solv->installed->start])
+ if (islinkedpseudo)
{
- const char *name = pool_id2str(pool, s->name);
- if (strncmp(name, "pattern:", 8) == 0 || strncmp(name, "application:", 12) == 0)
+ /* a linked pseudo package. As it is linked, we do not need an update/feature rule */
+ /* nevertheless we set specialupdaters so we can update */
+ solver_addrule(solv, 0, 0, 0);
+ if (qs.count)
{
- /* a linked pseudo package. As it is linked, we do not need an update/feature rule */
- /* nevertheless we set specialupdaters so we can update */
- solver_addrule(solv, 0, 0, 0);
- if (!allow_all && qs.count)
- {
- if (p != -SYSTEMSOLVABLE)
- queue_unshift(&qs, p);
- if (qs.count)
- set_specialupdaters(solv, s, pool_queuetowhatprovides(pool, &qs));
- }
- queue_free(&qs);
- return;
+ if (p != -SYSTEMSOLVABLE)
+ queue_unshift(&qs, p);
+ if (qs.count)
+ set_specialupdaters(solv, s, pool_queuetowhatprovides(pool, &qs));
}
- }
-#endif
-
- if (!allow_all && !p) /* !p implies qs.count == 0 */
- {
- queue_push(&solv->orphaned, s - pool->solvables); /* an orphaned package */
- if (solv->keep_orphans && !(solv->droporphanedmap_all || (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, s - pool->solvables - solv->installed->start))))
- p = s - pool->solvables; /* keep this orphaned package installed */
queue_free(&qs);
- solver_addrule(solv, p, 0, 0);
return;
}
+#endif
- if (!allow_all && qs.count && solv->multiversion.size)
+ if (qs.count && solv->multiversion.size)
{
int i, j;
diff --git a/src/rules.h b/src/rules.h
index 606819b..29325ea 100644
--- a/src/rules.h
+++ b/src/rules.h
@@ -111,7 +111,8 @@ extern void solver_addpkgrulesforlinked(struct _Solver *solv, Map *m);
extern void solver_addpkgrulesforupdaters(struct _Solver *solv, Solvable *s, Map *m, int allow_all);
/* update/feature rules */
-extern void solver_addupdaterule(struct _Solver *solv, Solvable *s, int allow_all);
+extern void solver_addfeaturerule(struct _Solver *solv, Solvable *s);
+extern void solver_addupdaterule(struct _Solver *solv, Solvable *s);
/* infarch rules */
extern void solver_addinfarchrules(struct _Solver *solv, Map *addedmap);
diff --git a/src/solver.c b/src/solver.c
index 261f367..15a3114 100644
--- a/src/solver.c
+++ b/src/solver.c
@@ -3716,7 +3716,7 @@ solver_solve(Solver *solv, Queue *job)
solver_addrule(solv, 0, 0, 0); /* create dummy rule */
continue;
}
- solver_addupdaterule(solv, s, 1); /* allow s to be updated */
+ solver_addfeaturerule(solv, s);
}
/* make sure we accounted for all rules */
assert(solv->nrules - solv->featurerules == installed->end - installed->start);
@@ -3744,7 +3744,7 @@ solver_solve(Solver *solv, Queue *job)
solver_addrule(solv, 0, 0, 0); /* create dummy rule */
continue;
}
- solver_addupdaterule(solv, s, 0); /* allowall = 0: downgrades not allowed */
+ solver_addupdaterule(solv, s);
/*
* check for and remove duplicate
*/
@@ -3759,9 +3759,10 @@ solver_solve(Solver *solv, Queue *job)
/* it's also orphaned if the feature rule consists just of the installed package */
if (!solv->dupmap_all && sr->p == i && !sr->d && !sr->w2)
queue_push(&solv->orphaned, i);
+
if (!solver_rulecmp(solv, r, sr))
memset(sr, 0, sizeof(*sr)); /* delete unneeded feature rule */
- else
+ else if (sr->p)
solver_disablerule(solv, sr); /* disable feature rule for now */
}
/* consistency check: we added a rule for _every_ installed solvable */
--
2.5.0

View File

@ -30,11 +30,20 @@
Name: libsolv
Version: 0.6.19
Release: 1%{?dist}
Release: 2%{?dist}
License: BSD
Url: https://github.com/openSUSE/libsolv
Source: https://github.com/openSUSE/libsolv/archive/%{version}.tar.gz#/%{name}-%{version}.tar.gz
Patch0: 0001-ruby-make-compatible-with-ruby-2.2.patch
Patch1: 0002-Add-repodata_lookup_dirstrarray_uninternalized-metho.patch
Patch2: 0003-Do-not-create-a-checksum-hash-when-we-re-not-extendi.patch
Patch3: 0004-solv_hex2bin-don-t-eat-nibbles.patch
Patch4: 0005-Use-less-memory-when-extending-packages.patch
Patch5: 0006-Fix-comments.patch
Patch6: 0007-rpmmd-diskusage-prepend-a-to-the-dir-if-not-already-.patch
Patch7: 0008-Split-diskusage-and-fileprovides-code-into-separate-.patch
Patch8: 0009-Make-_Pool_tmpspace-definition-internal.patch
Patch9: 0010-Rework-orphan-handling-in-dup-mode.patch
Group: Development/Libraries
Summary: Package dependency solver
@ -225,6 +234,9 @@ make ARGS="-V" test
%endif
%changelog
* Tue Mar 8 2016 Jaroslav Mracek <jmracek@redhat.com> - 0.6.19-2
- Apply 9 patches from upstream
* Sat Feb 27 2016 Igor Gnatenko <i.gnatenko.brain@gmail.com> - 0.6.19-1
- Update to 0.6.19