#include "pool.h"
#include "poolid_private.h"
#include "util.h"
+#include "attr_store_p.h"
#define IDARRAY_BLOCK 4095
repo->name = name ? strdup(name) : 0;
repo->pool = pool;
repo->start = pool->nsolvables;
+ repo->end = pool->nsolvables;
repo->nsolvables = 0;
return repo;
}
/*
- * remove repo from pool
+ * remove repo from pool, zero out solvables
*
*/
void
-repo_free(Repo *repo)
+repo_free(Repo *repo, int reuseids)
{
Pool *pool = repo->pool;
- int i, nsolvables;
+ Solvable *s;
+ int i;
pool_freewhatprovides(pool);
- for (i = 0; i < pool->nrepos; i++) /* find repo in pool */
+ if (reuseids && repo->end == pool->nsolvables)
{
- if (pool->repos[i] == repo)
- break;
+ /* it's ok to reuse the ids. As this is the last repo, we can
+ just shrink the solvable array */
+ 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;
}
+ /* zero out 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));
+ for (i = 0; i < pool->nrepos; i++) /* find repo in pool */
+ if (pool->repos[i] == repo)
+ break;
if (i == pool->nrepos) /* repo not in pool, return */
return;
-
- /* close gap
- * all repos point into pool->solvables _relatively_ to repo->start
- * so closing the gap only needs adaption of repo->start for all
- * other repos.
- */
-
- nsolvables = repo->nsolvables;
- if (pool->nsolvables > repo->start + nsolvables)
- memmove(pool->solvables + repo->start, pool->solvables + repo->start + nsolvables, (pool->nsolvables - repo->start - nsolvables) * sizeof(Solvable));
- pool->nsolvables -= nsolvables;
-
- for (; i < pool->nrepos - 1; i++)
- {
- pool->repos[i] = pool->repos[i + 1]; /* remove repo */
- pool->repos[i]->start -= nsolvables; /* adapt start offset of remaining repos */
- }
- pool->nrepos = i;
+ if (i < pool->nrepos - 1)
+ memmove(pool->repos + i, pool->repos + i + 1, (pool->nrepos - 1 - i) * sizeof(Repo *));
+ pool->nrepos--;
repo_freedata(repo);
}
void
-pool_freeallrepos(Pool *pool)
+repo_freeallrepos(Pool *pool, int reuseids)
{
int i;
+
+ pool_freewhatprovides(pool);
for (i = 0; i < pool->nrepos; i++)
repo_freedata(pool->repos[i]);
pool->repos = xfree(pool->repos);
pool->nrepos = 0;
+ /* the first two solvables don't belong to a repo */
+ pool_free_solvable_block(pool, 2, pool->nsolvables - 2, reuseids);
}
Offset
return supplements;
}
+void
+repodata_search(Repodata *data, Id key)
+{
+}
+
+unsigned char *
+data_read_id(unsigned char *dp, Id *idp)
+{
+ Id x = 0;
+ unsigned char c;
+ for (;;)
+ {
+ c = *dp++;
+ if (!(c & 0x80))
+ {
+ *idp = (x << 7) ^ c;
+ return dp;
+ }
+ x = (x << 7) ^ c ^ 128;
+ }
+}
+
+unsigned char *
+data_skip(unsigned char *dp, int type)
+{
+ switch (type)
+ {
+ case TYPE_VOID:
+ return dp;
+ case TYPE_ID:
+ while ((*dp & 0x80) != 0)
+ dp++;
+ return dp;
+ case TYPE_IDARRAY:
+ case TYPE_REL_IDARRAY:
+ case TYPE_IDVALUEARRAY:
+ case TYPE_IDVALUEVALUEARRAY:
+ while ((*dp & 0xc0) != 0)
+ dp++;
+ return dp;
+ default:
+ fprintf(stderr, "unknown type in data_skip\n");
+ exit(1);
+ }
+}
+
+const char *
+repodata_lookup_str(Repodata *data, Id entry, Id key)
+{
+ Id schema;
+ Id id, k, *kp, *keyp;
+ unsigned char *dp;
+
+ if (data->entryschemau8)
+ schema = data->entryschemau8[entry];
+ else
+ schema = data->entryschema[entry];
+ keyp = data->schemadata + schema;
+ /* make sure the schema of this solvable contains the key */
+ for (kp = keyp; (k = *kp++) != 0; )
+ if (k == key)
+ break;
+ if (k == 0)
+ return 0;
+ switch (data->keys[key].storage)
+ {
+ case KEY_STORAGE_VERTICAL_OFFSET:
+ case KEY_STORAGE_INCORE:
+ dp = data->incoredata + data->incoreoffset[entry];
+ while ((k = *keyp++) != 0)
+ {
+ if (k == key)
+ break;
+ if (data->keys[k].storage == KEY_STORAGE_VERTICAL_OFFSET)
+ {
+ /* skip that offset */
+ dp = data_skip(dp, TYPE_ID);
+ continue;
+ }
+ if (data->keys[k].storage != KEY_STORAGE_INCORE)
+ continue;
+ dp = data_skip(dp, data->keys[k].type);
+ }
+ if (data->keys[key].storage == KEY_STORAGE_VERTICAL_OFFSET)
+ {
+ int i, oi, max;
+ if (!data->fp)
+ return 0;
+ dp = data_read_id(dp, &id);
+ max = data->keys[key].size - id;
+ if (max <= 0)
+ return 0;
+ /* we now have the offset, go into vertical */
+ for (i = 1; i < key; i++)
+ if (data->keys[i].storage == KEY_STORAGE_VERTICAL_OFFSET)
+ id += data->keys[i].size;
+ if (fseek(data->fp, data->verticaloffset + id, SEEK_SET))
+ return 0;
+ i = max > 256 ? 256 : max;
+ for (oi = 0;; oi = i, i += 256)
+ {
+ if (i > max)
+ i = max;
+ if (i == oi)
+ return 0;
+ if (i > data->strbuflen)
+ {
+ data->strbuf = xrealloc(data->strbuf, i);
+ data->strbuflen = i;
+ }
+ if (fread(data->strbuf + oi, i - oi, 1, data->fp) != 1)
+ return 0;
+ if (memchr(data->strbuf + oi, 0, i - oi))
+ return data->strbuf;
+ }
+ }
+ if (data->keys[key].type == TYPE_STR)
+ return (const char *)dp;
+ /* id type, must either use global or local string strore*/
+ dp = data_read_id(dp, &id);
+#if 0
+ /* not yet working */
+ return data->ss.stringspace + data->ss.strings[id];
+#else
+ return id2str(data->repo->pool, id);
+#endif
+ }
+ return 0;
+}
+
+const char *
+repo_lookup_str(Solvable *s, Id key)
+{
+ Repo *repo = s->repo;
+ Pool *pool = repo->pool;
+ Repodata *data;
+ int i, j, n;
+
+ switch(key)
+ {
+ case SOLVABLE_NAME:
+ return id2str(pool, s->name);
+ case SOLVABLE_ARCH:
+ return id2str(pool, s->arch);
+ case SOLVABLE_EVR:
+ return id2str(pool, s->evr);
+ case SOLVABLE_VENDOR:
+ return id2str(pool, s->vendor);
+ }
+ n = s - pool->solvables;
+ for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
+ {
+ if (n < data->start || n >= data->end)
+ continue;
+ for (j = 1; j < data->nkeys; j++)
+ {
+ if (data->keys[j].name == key && (data->keys[j].type == TYPE_ID || data->keys[j].type == TYPE_STR))
+ return repodata_lookup_str(data, n - data->start, j);
+ }
+ }
+ return 0;
+}
+
+
+static int
+key_cmp (const void *pa, const void *pb)
+{
+ Repokey *a = (Repokey *)pa;
+ Repokey *b = (Repokey *)pb;
+ return a->name - b->name;
+}
+
+void
+repo_add_attrstore (Repo *repo, Attrstore *s, const char *location)
+{
+ unsigned i;
+ Repodata *data;
+ /* If this is meant to be the embedded attributes, make sure we don't
+ have them already. */
+ if (!location)
+ {
+ for (i = 0; i < repo->nrepodata; i++)
+ if (repo->repodata[i].location == 0)
+ break;
+ if (i != repo->nrepodata)
+ {
+ pool_debug (repo->pool, SAT_FATAL, "embedded attribs added twice\n");
+ exit (1);
+ }
+ }
+ repo->nrepodata++;
+ repo->repodata = xrealloc (repo->repodata, repo->nrepodata * sizeof (*data));
+ data = repo->repodata + repo->nrepodata - 1;
+ memset (data, 0, sizeof (*data));
+ data->s = s;
+ data->nkeys = s->nkeys;
+ if (data->nkeys)
+ {
+ data->keys = xmalloc(data->nkeys * sizeof(data->keys[0]));
+ for (i = 1; i < data->nkeys; i++)
+ {
+ data->keys[i].name = s->keys[i].name;
+ data->keys[i].type = s->keys[i].type;
+ }
+ if (data->nkeys > 2)
+ qsort(data->keys + 1, data->nkeys - 1, sizeof(data->keys[0]), key_cmp);
+ }
+ if (location)
+ data->location = strdup(location);
+}
+
// EOF