return supplements;
}
-#if 0
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_id(Repodata *data, Id num, Id key)
+repodata_lookup_str(Repodata *data, Id entry, Id key)
{
+ Id schema;
Id id, k, *kp, *keyp;
+ unsigned char *dp;
- fseek(data->fp, data->itemoffsets[num] , SEEK_SET);
- Id *keyp = data->schemadata + data->schemata[read_id(data->fp, data->numschemata)];
- /* make sure our schema contains the key */
- for (kp = keyp; (k = *kp++) != 0)
+ 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;
- /* get it */
- while ((k = *keyp++) != 0)
+ switch (data->keys[key].storage)
{
- if (k == key)
- break;
- switch (keys[key].type)
+ case KEY_STORAGE_VERTICAL_OFFSET:
+ case KEY_STORAGE_INCORE:
+ dp = data->incoredata + data->incoreoffset[entry];
+ while ((k = *keyp++) != 0)
{
- case TYPE_ID:
- while ((read_u8(data->fp) & 0x80) != 0)
- ;
- break;
- case TYPE_U32:
- read_u32(data->fp);
- break;
- case TYPE_STR:
- while(read_u8(data->fp) != 0)
- ;
- break;
- case TYPE_IDARRAY:
- while ((read_u8(data->fp) & 0xc0) != 0)
- ;
- break;
+ 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
}
- id = read_id(data->fp, 0);
- return data->ss.stringspace + data->ss.strings[id];
+ return 0;
}
-Id
-repo_lookup_id(Solvable *s, Id key)
+const char *
+repo_lookup_str(Solvable *s, Id key)
{
- Solvable *rs;
Repo *repo = s->repo;
+ Pool *pool = repo->pool;
Repodata *data;
int i, j, n;
switch(key)
{
case SOLVABLE_NAME:
- return s->name;
+ return id2str(pool, s->name);
case SOLVABLE_ARCH:
- return s->arch;
+ return id2str(pool, s->arch);
case SOLVABLE_EVR:
- return s->evr;
+ return id2str(pool, s->evr);
case SOLVABLE_VENDOR:
- return s->vendor;
- }
- /* convert solvable id into repo item count */
- if (repo->end - repo->start + 1 == repo->nsolvables)
- {
- n = (s - pool->solvables);
- if (n < repo->start || n > repo->end)
- return 0;
- n -= repo->start;
- }
- else
- {
- for (i = repo->start, rs = pool->solvables + i, n = 0; i < repo->end; i++, rs++)
- {
- if (rs->repo != repo)
- continue;
- if (rs == s)
- break;
- n++;
- }
- if (i == repo->end)
- return 0;
+ return id2str(pool, s->vendor);
}
+ n = s - pool->solvables;
for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
{
- for (j = 0; j < data->nkeys; j++)
+ 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)
- return repodata_lookup_id(data, n, 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;
}
-#endif
+
static int
key_cmp (const void *pa, const void *pb)
{
- struct key { Id name; unsigned type; };
- struct key *a = (struct key*)pa;
- struct key *b = (struct key*)pb;
+ Repokey *a = (Repokey *)pa;
+ Repokey *b = (Repokey *)pb;
return a->name - b->name;
}
memset (data, 0, sizeof (*data));
data->s = s;
data->nkeys = s->nkeys;
- /* Don't store the first key, it's {0,0,0}. */
- data->nkeys--;
if (data->nkeys)
{
- data->keys = xmalloc (data->nkeys * sizeof (data->keys[0]));
- for (i = 0; i < data->nkeys; i++)
+ data->keys = xmalloc(data->nkeys * sizeof(data->keys[0]));
+ for (i = 1; i < data->nkeys; i++)
{
- data->keys[i].name = s->keys[i + 1].name;
- data->keys[i].type = s->keys[i + 1].type;
+ data->keys[i].name = s->keys[i].name;
+ data->keys[i].type = s->keys[i].type;
}
- qsort (data->keys, data->nkeys, sizeof (data->keys[0]), key_cmp);
+ if (data->nkeys > 2)
+ qsort(data->keys + 1, data->nkeys - 1, sizeof(data->keys[0]), key_cmp);
}
if (location)
data->location = strdup(location);
static int
key_cmp (const void *pa, const void *pb)
{
- struct key { Id name; unsigned type; };
- struct key *a = (struct key*)pa;
- struct key *b = (struct key*)pb;
+ Repokey *a = (Repokey *)pa;
+ Repokey *b = (Repokey *)pb;
return a->name - b->name;
}
-struct key {
- Id name;
- Id type;
- Id size;
-};
-
static void
-parse_repodata (FILE *fp, Id *keyp, struct key *keys, Id *idmap, unsigned numid, unsigned numrel, Repo *repo)
+parse_repodata (FILE *fp, Id *keyp, Repokey *keys, Id *idmap, unsigned numid, unsigned numrel, Repo *repo)
{
Id key, id;
Id *ida, *ide;
repo->repodata = xrealloc(repo->repodata, (repo->nrepodata + 1) * sizeof (*data));
data = repo->repodata + repo->nrepodata++;
+ data->repo = repo;
memset(data, 0, sizeof(*data));
while ((key = *keyp++) != 0)
pool_debug (mypool, SAT_FATAL, "invalid attribute data\n");
exit (1);
}
- data->nkeys = n >> 1;
+ data->nkeys = 1 + (n >> 1);
data->keys = xmalloc2(data->nkeys, sizeof(data->keys[0]));
- for (i = 0, ide = ida; i < data->nkeys; i++)
+ memset(data->keys, 0, sizeof(Repokey));
+ for (i = 1, ide = ida; i < data->nkeys; i++)
{
if (*ide >= numid)
{
}
data->keys[i].name = idmap[*ide++];
data->keys[i].type = *ide++;
+ data->keys[i].size = 0;
+ data->keys[i].storage = 0;
}
xfree(ida);
- qsort(data->keys, data->nkeys, sizeof(data->keys[0]), key_cmp);
+ if (data->nkeys > 2)
+ qsort(data->keys + 1, data->nkeys - 1, sizeof(data->keys[0]), key_cmp);
break;
case TYPE_STR:
if (id != REPODATA_LOCATION)
/*-----------------------------------------------------------------*/
-void
-skip_schema(FILE *fp, Id *keyp, struct key *keys, unsigned int numid, unsigned int numrel)
+static void
+skip_schema(FILE *fp, Id *keyp, Repokey *keys, unsigned int numid, unsigned int numrel)
{
Id key;
while ((key = *keyp++) != 0)
skip_item(fp, keys[key].type, numid, numrel);
}
+/*-----------------------------------------------------------------*/
+
+static void
+incore_add_id(Repodata *data, Id x)
+{
+ unsigned char *dp;
+ /* make sure we have at least 5 bytes free */
+ if (data->incoredatafree < 5)
+ {
+ data->incoredata = xrealloc(data->incoredata, data->incoredatalen + 1024);
+ data->incoredatafree = 1024;
+ }
+ dp = data->incoredata + data->incoredatalen;
+ if (x < 0)
+ abort();
+ if (x >= (1 << 14))
+ {
+ if (x >= (1 << 28))
+ *dp++ = (x >> 28) | 128;
+ if (x >= (1 << 21))
+ *dp++ = (x >> 21) | 128;
+ *dp++ = (x >> 14) | 128;
+ }
+ if (x >= (1 << 7))
+ *dp++ = (x >> 7) | 128;
+ *dp++ = x & 127;
+ data->incoredatafree -= dp - (data->incoredata + data->incoredatalen);
+ data->incoredatalen = dp - data->incoredata;
+}
+
+static void
+incore_add_u32(Repodata *data, unsigned int x)
+{
+ unsigned char *dp;
+ /* make sure we have at least 4 bytes free */
+ if (data->incoredatafree < 4)
+ {
+ data->incoredata = xrealloc(data->incoredata, data->incoredatalen + 1024);
+ data->incoredatafree = 1024;
+ }
+ dp = data->incoredata + data->incoredatalen;
+ *dp++ = x >> 24;
+ *dp++ = x >> 16;
+ *dp++ = x >> 8;
+ *dp++ = x;
+ data->incoredatafree -= 4;
+ data->incoredatalen += 4;
+}
+
+static void
+incore_add_u8(Repodata *data, unsigned int x)
+{
+ unsigned char *dp;
+ /* make sure we have at least 1 byte free */
+ if (data->incoredatafree < 1)
+ {
+ data->incoredata = xrealloc(data->incoredata, data->incoredatalen + 1024);
+ data->incoredatafree = 1024;
+ }
+ dp = data->incoredata + data->incoredatalen;
+ *dp++ = x;
+ data->incoredatafree--;
+ data->incoredatalen++;
+}
+
// ----------------------------------------------
/*
int i, l;
unsigned int numid, numrel, numsolv;
unsigned int numkeys, numschemata, numinfo;
+#if 0
Attrstore *embedded_store = 0;
+#endif
Offset sizeid;
Offset *str; /* map Id -> Offset into string space */
Solvable *s;
unsigned int solvflags;
unsigned int solvversion;
- struct key *keys;
+ Repokey *keys;
Id *schemadata, *schemadatap, *schemadataend;
Id *schemata, key;
+ Repodata data;
+
mypool = pool;
if (read_u32(fp) != ('S' << 24 | 'O' << 16 | 'L' << 8 | 'V'))
numinfo = read_u32(fp);
solvflags = read_u32(fp);
+ memset(&data, 0, sizeof(data));
+ data.repo = repo;
+
if (solvversion < SOLV_VERSION_3
&& numinfo)
{
/* keys start at 1 */
for (i = 1; i < numkeys; i++)
{
- keys[i].name = idmap[read_id(fp, numid)];
+ keys[i].name = id = idmap[read_id(fp, numid)];
keys[i].type = read_id(fp, 0);
keys[i].size = read_id(fp, 0);
+ keys[i].storage = KEY_STORAGE_DROPPED;
+ switch (keys[i].type)
+ {
+ case TYPE_ID:
+ switch(id)
+ {
+ case SOLVABLE_NAME:
+ case SOLVABLE_ARCH:
+ case SOLVABLE_EVR:
+ case SOLVABLE_VENDOR:
+ keys[i].storage = KEY_STORAGE_SOLVABLE;
+ break;
+ default:
+ keys[i].storage = KEY_STORAGE_INCORE;
+ break;
+ }
+ break;
+ case TYPE_IDARRAY:
+ case TYPE_REL_IDARRAY:
+ if (id >= INTERESTED_START && id <= INTERESTED_END)
+ keys[i].storage = KEY_STORAGE_SOLVABLE;
+ else
+ keys[i].storage = KEY_STORAGE_INCORE;
+ break;
+ case TYPE_STR:
+ keys[i].storage = KEY_STORAGE_INCORE;
+ break;
+ case TYPE_U32:
+ if (id == RPM_RPMDBID)
+ keys[i].storage = KEY_STORAGE_SOLVABLE;
+ else
+ keys[i].storage = KEY_STORAGE_INCORE;
+ break;
+ default:
+ break;
+ }
}
+ data.keys = keys;
+ data.nkeys = numkeys;
+
/******* Part 4: Schemata ********************************************/
id = read_id(fp, 0);
schemata[i] = schemadatap - schemadata;
schemadatap = read_idarray(fp, numid, 0, schemadatap, schemadataend, 0);
}
+ data.schemata = schemata;
+ data.nschemata = numschemata;
+ data.schemadata = schemadata;
/******* Part 5: Info ***********************************************/
for (i = 0; i < numinfo; i++)
Solvable *sstart = s;
Id type;
+/* XXX BROKEN CODE */
+
for (i = 0; i < numsolv; i++)
solvschema[i] = read_id(fp, numschemata);
for (key = 1; key < numkeys; key++)
s->evr = did;
else if (id == SOLVABLE_VENDOR)
s->vendor = did;
+ else
+ incore_add_id(&data, did);
break;
case TYPE_U32:
h = read_u32(fp);
repo->rpmdbid = (Id *)xcalloc(numsolv, sizeof(Id));
repo->rpmdbid[i] = h;
}
+ else
+ {
+ incore_add_u32(&data, h);
+ }
break;
case TYPE_STR:
while(read_u8(fp) != 0)
s->freshens = ido;
break;
case TYPE_VOID:
+ break;
+#if 0
case TYPE_ATTR_INT:
case TYPE_ATTR_CHUNK:
case TYPE_ATTR_STRING:
embedded_store = new_store (pool);
add_attr_from_file (embedded_store, i, id, type, idmap, numid, fp);
break;
+#endif
+ default:
+ abort();
}
}
}
mypool = 0;
return;
}
+
for (i = 0; i < numsolv; i++, s++)
{
if (exists && !exists[i])
s->evr = did;
else if (id == SOLVABLE_VENDOR)
s->vendor = did;
+ else if (keys[key].storage == KEY_STORAGE_INCORE)
+ incore_add_id(&data, did);
#if 0
POOL_DEBUG(SAT_DEBUG_STATS, "%s -> %s\n", id2str(pool, id), id2str(pool, did));
#endif
repo->rpmdbid = (Id *)xcalloc(numsolv, sizeof(Id));
repo->rpmdbid[i] = h;
}
+ else if (keys[key].storage == KEY_STORAGE_INCORE)
+ incore_add_u32(&data, h);
break;
case TYPE_STR:
- while(read_u8(fp) != 0)
- ;
+ if (keys[key].storage == KEY_STORAGE_INCORE)
+ {
+ while ((h = read_u8(fp)) != 0)
+ incore_add_u8(&data, h);
+ incore_add_u8(&data, 0);
+ }
+ else
+ {
+ while (read_u8(fp) != 0)
+ ;
+ }
break;
case TYPE_IDARRAY:
case TYPE_REL_IDARRAY:
if (id < INTERESTED_START || id > INTERESTED_END)
{
- /* not interested in array */
- while ((read_u8(fp) & 0xc0) != 0)
- ;
- break;
+ if (keys[key].storage == KEY_STORAGE_INCORE)
+ {
+ Id old = 0, rel = keys[key].type == TYPE_REL_IDARRAY ? SOLVABLE_PREREQMARKER : 0;
+ do
+ {
+ did = read_id(fp, 0);
+ h = did & 0x40;
+ did = (did & 0x3f) | ((did >> 1) & ~0x3f);
+ if (rel)
+ {
+ if (did == 0)
+ {
+ did = rel;
+ old = 0;
+ }
+ else
+ {
+ did += old;
+ old = did;
+ }
+ }
+ if (did >= numid + numrel)
+ abort();
+ did = idmap[did];
+ did = ((did & ~0x3f) << 1) | h;
+ incore_add_id(&data, did);
+ }
+ while (h);
+ }
+ else
+ {
+ while ((read_u8(fp) & 0xc0) != 0)
+ ;
+ break;
+ }
}
ido = idarraydatap - repo->idarraydata;
idarraydatap = read_idarray(fp, numid + numrel, idmap, idarraydatap, idarraydataend, keys[key].type == TYPE_REL_IDARRAY);
POOL_DEBUG(SAT_DEBUG_STATS," %s\n", dep2str(pool, repo->idarraydata[ido]));
#endif
break;
+#if 0
case TYPE_VOID:
+
case TYPE_ATTR_INT:
case TYPE_ATTR_CHUNK:
case TYPE_ATTR_STRING:
embedded_store = new_store (pool);
add_attr_from_file (embedded_store, i, id, keys[key].type, idmap, numid, fp);
break;
+#endif
default:
skip_item(fp, keys[key].type, numid, numrel);
}
}
}
+
+ if (data.incoredatafree)
+ {
+ /* shrink excess size */
+ data.incoredata = xrealloc(data.incoredata, data.incoredatalen);
+ data.incoredatafree = 0;
+ }
+
+ for (i = 1; i < numkeys; i++)
+ if (keys[i].storage == KEY_STORAGE_VERTICAL_OFFSET)
+ break;
+ if (i < numkeys)
+ {
+ /* we have vertical data, make it available */
+ data.fp = fp;
+ data.verticaloffset = ftell(fp);
+ }
+
+ if (data.incoredatalen || data.fp)
+ {
+ /* we got some data, make it available */
+ repo->repodata = xrealloc(repo->repodata, (repo->nrepodata + 1) * sizeof(data));
+ repo->repodata[repo->nrepodata++] = data;
+ }
+ else
+ {
+ xfree(schemata);
+ xfree(schemadata);
+ xfree(keys);
+ }
+
xfree(exists);
+#if 0
if (embedded_store)
{
attr_store_pack (embedded_store);
/* The NULL name here means embedded attributes. */
repo_add_attrstore (repo, embedded_store, NULL);
}
+#endif
xfree(idmap);
- xfree(schemata);
- xfree(schemadata);
- xfree(keys);
mypool = 0;
}