close(data->pagefd);
}
+unsigned char *
+data_skip_recursive(Repodata *data, unsigned char *dp, Repokey *key)
+{
+ KeyValue kv;
+ if (key->type != REPOKEY_TYPE_COUNTED)
+ return data_skip(dp, key->type);
+ dp = data_fetch(dp, &kv, key);
+ int num = kv.num;
+ int schema = kv.id;
+ while (num--)
+ {
+ Id *keyp = data->schemadata + data->schemata[schema];
+ for (; *keyp; keyp++)
+ dp = data_skip_recursive(data, dp, data->keys + *keyp);
+ }
+ return dp;
+}
+
static unsigned char *
forward_to_key(Repodata *data, Id keyid, Id schemaid, unsigned char *dp)
{
}
if (data->keys[k].storage != KEY_STORAGE_INCORE)
continue;
- dp = data_skip(dp, data->keys[k].type);
+ dp = data_skip_recursive(data, dp, data->keys + k);
}
return 0;
}
if (key->storage == KEY_STORAGE_INCORE)
{
/* hmm, this is a bit expensive */
- *dpp = data_skip(dp, key->type);
+ *dpp = data_skip_recursive(data, dp, key);
return dp;
}
else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
ddp = data_fetch(ddp, &kv, key);
if (!ddp)
break;
- stop = callback(cbdata, data->repo->pool->solvables + data->start + entry, data, key, &kv);
+ if (key->type == REPOKEY_TYPE_COUNTED)
+ {
+ int num = kv.num;
+ int subschema = kv.id;
+ Repokey *countkey = key;
+ kv.eof = 0;
+ callback(cbdata, data->repo->pool->solvables + data->start + entry, data, countkey, &kv);
+ while (num--)
+ {
+ Id *kp = data->schemadata + data->schemata[subschema];
+ for (; *kp; kp++)
+ {
+ key = data->keys + *kp;
+ ddp = data_fetch(ddp, &kv, key);
+ if (!ddp)
+ exit(1);
+ callback(cbdata, data->repo->pool->solvables + data->start + entry, data, key, &kv);
+ }
+ kv.eof = 1;
+ callback(cbdata, data->repo->pool->solvables + data->start + entry, data, countkey, &kv);
+ }
+ kv.eof = 2;
+ stop = callback(cbdata, data->repo->pool->solvables + data->start + entry, data, countkey, &kv);
+ }
+ else
+ stop = callback(cbdata, data->repo->pool->solvables + data->start + entry, data, key, &kv);
}
while (!kv.eof && !stop);
if (onekey || stop > SEARCH_NEXT_KEY)
di->kv.eof = 1;
di->repo = repo;
di->idp = 0;
+ di->subkeyp = 0;
}
/* FIXME factor and merge with repo_matchvalue */
continue;
}
}
+ else if (di->subkeyp)
+ {
+ Id keyid;
+ if (!di->subnum)
+ {
+ /* Send end-of-substruct. We are here only when we saw a
+ _COUNTED key one level up. Since then we didn't increment
+ ->keyp, so it still can be found at keyp[-1]. */
+ di->kv.eof = 2;
+ di->key = di->data->keys + di->keyp[-1];
+ di->subkeyp = 0;
+ }
+ else if (!(keyid = *di->subkeyp++))
+ {
+ /* Send end-of-element. See above for keyp[-1]. */
+ di->kv.eof = 1;
+ di->key = di->data->keys + di->keyp[-1];
+ di->subkeyp = di->data->schemadata + di->data->schemata[di->subschema];
+ di->subnum--;
+ }
+ else
+ {
+ di->key = di->data->keys + keyid;
+ di->dp = data_fetch(di->dp, &di->kv, di->key);
+ if (!di->dp)
+ exit(1);
+ }
+ }
else
{
if (di->kv.eof)
}
di->dp = data_fetch(di->dp, &di->kv, di->key);
}
+ if (di->key->type == REPOKEY_TYPE_COUNTED)
+ {
+ di->subnum = di->kv.num;
+ di->subschema = di->kv.id;
+ di->kv.eof = 0;
+ di->subkeyp = di->data->schemadata + di->data->schemata[di->subschema];
+ }
}
weg2:
if (!di->match
repodata_create_struct(Repodata *data, Id handle, Id keyname)
{
Id newhandle = get_new_struct(data);
- repodata_add_idarray(data, handle, keyname, newhandle);
+ repodata_add_array(data, handle, keyname, REPOKEY_TYPE_COUNTED, 1);
+ data->attriddata[data->attriddatalen++] = newhandle;
+ data->attriddata[data->attriddatalen++] = 0;
return newhandle;
}
return data->nschemata++;
}
+static void
+repodata_serialize_key(Repodata *data, struct extdata *newincore,
+ struct extdata *newvincore,
+ Id *schema, Id *schematacache,
+ Repokey *key, Id val)
+{
+ /* Otherwise we have a new value. Parse it into the internal
+ form. */
+ Id *ida;
+ struct extdata *xd;
+ unsigned int oldvincorelen = 0;
+ Id schemaid, *sp;
+
+ xd = newincore;
+ if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
+ {
+ xd = newvincore;
+ oldvincorelen = xd->len;
+ }
+ switch (key->type)
+ {
+ case REPOKEY_TYPE_VOID:
+ case REPOKEY_TYPE_CONSTANT:
+ case REPOKEY_TYPE_CONSTANTID:
+ break;
+ case REPOKEY_TYPE_STR:
+ data_addblob(xd, data->attrdata + val, strlen((char *)(data->attrdata + val)) + 1);
+ break;
+ case REPOKEY_TYPE_MD5:
+ data_addblob(xd, data->attrdata + val, SIZEOF_MD5);
+ break;
+ case REPOKEY_TYPE_SHA1:
+ data_addblob(xd, data->attrdata + val, SIZEOF_SHA1);
+ break;
+ case REPOKEY_TYPE_ID:
+ case REPOKEY_TYPE_NUM:
+ case REPOKEY_TYPE_DIR:
+ data_addid(xd, val);
+ break;
+ case REPOKEY_TYPE_IDARRAY:
+ for (ida = data->attriddata + val; *ida; ida++)
+ data_addideof(xd, ida[0], ida[1] ? 0 : 1);
+ break;
+ case REPOKEY_TYPE_DIRNUMNUMARRAY:
+ for (ida = data->attriddata + val; *ida; ida += 3)
+ {
+ data_addid(xd, ida[0]);
+ data_addid(xd, ida[1]);
+ data_addideof(xd, ida[2], ida[3] ? 0 : 1);
+ }
+ break;
+ case REPOKEY_TYPE_DIRSTRARRAY:
+ for (ida = data->attriddata + val; *ida; ida += 2)
+ {
+ data_addideof(xd, ida[0], ida[2] ? 0 : 1);
+ data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
+ }
+ break;
+ case REPOKEY_TYPE_COUNTED:
+ {
+ int num = 0;
+ schemaid = 0;
+ for (ida = data->attriddata + val; *ida; ida++)
+ {
+#if 0
+ fprintf(stderr, "serialize struct %d\n", *ida);
+#endif
+ sp = schema;
+ Id *kp = data->structs[*ida];
+ if (!kp)
+ continue;
+ num++;
+ for (;*kp; kp += 2)
+ {
+#if 0
+ fprintf(stderr, " %s:%d\n", id2str(data->repo->pool, data->keys[*kp].name), kp[1]);
+#endif
+ *sp++ = *kp;
+ }
+ *sp = 0;
+ if (!schemaid)
+ schemaid = addschema(data, schema, schematacache);
+ else if (schemaid != addschema(data, schema, schematacache))
+ {
+ fprintf(stderr, " not yet implemented: substructs with different schemas\n");
+ exit(1);
+ }
+#if 0
+ fprintf(stderr, " schema %d\n", schemaid);
+#endif
+ }
+ if (!num)
+ break;
+ data_addid(xd, num);
+ data_addid(xd, schemaid);
+ for (ida = data->attriddata + val; *ida; ida++)
+ {
+ Id *kp = data->structs[*ida];
+ if (!kp)
+ continue;
+ for (;*kp; kp += 2)
+ {
+ repodata_serialize_key(data, newincore, newvincore,
+ schema, schematacache,
+ data->keys + *kp, kp[1]);
+ }
+ }
+ break;
+ }
+ default:
+ fprintf(stderr, "don't know how to handle type %d\n", key->type);
+ exit(1);
+ }
+ if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
+ {
+ /* put offset/len in incore */
+ data_addid(newincore, data->lastverticaloffset + oldvincorelen);
+ oldvincorelen = xd->len - oldvincorelen;
+ data_addid(newincore, oldvincorelen);
+ }
+}
void
repodata_internalize(Repodata *data)
{
Repokey *key;
- Id id, entry, nentry, *ida;
+ Id entry, nentry;
Id schematacache[256];
Id schemaid, *schema, *sp, oldschema, *keyp, *seen;
unsigned char *dp, *ndp;
for (keyp = data->schemadata + data->schemata[schemaid]; *keyp; keyp++)
{
key = data->keys + *keyp;
+#if 0
+ fprintf(stderr, "internalize %d:%s:%s\n", entry, id2str(data->repo->pool, key->name), id2str(data->repo->pool, key->type));
+#endif
ndp = dp;
if (oldcount)
{
ndp = data_skip(ndp, REPOKEY_TYPE_ID);
}
else if (key->storage == KEY_STORAGE_INCORE)
- ndp = data_skip(dp, key->type);
+ ndp = data_skip_recursive(data, dp, key);
oldcount--;
}
if (seen[*keyp] == -1)
{
/* Otherwise we have a new value. Parse it into the internal
form. */
- struct extdata *xd;
- unsigned int oldvincorelen = 0;
-
- xd = &newincore;
- if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
- {
- xd = &newvincore;
- oldvincorelen = xd->len;
- }
- id = seen[*keyp] - 1;
- switch (key->type)
- {
- case REPOKEY_TYPE_VOID:
- case REPOKEY_TYPE_CONSTANT:
- case REPOKEY_TYPE_CONSTANTID:
- break;
- case REPOKEY_TYPE_STR:
- data_addblob(xd, data->attrdata + id, strlen((char *)(data->attrdata + id)) + 1);
- break;
- case REPOKEY_TYPE_MD5:
- data_addblob(xd, data->attrdata + id, SIZEOF_MD5);
- break;
- case REPOKEY_TYPE_SHA1:
- data_addblob(xd, data->attrdata + id, SIZEOF_SHA1);
- break;
- case REPOKEY_TYPE_ID:
- case REPOKEY_TYPE_NUM:
- case REPOKEY_TYPE_DIR:
- data_addid(xd, id);
- break;
- case REPOKEY_TYPE_IDARRAY:
- for (ida = data->attriddata + id; *ida; ida++)
- data_addideof(xd, ida[0], ida[1] ? 0 : 1);
- break;
- case REPOKEY_TYPE_DIRNUMNUMARRAY:
- for (ida = data->attriddata + id; *ida; ida += 3)
- {
- data_addid(xd, ida[0]);
- data_addid(xd, ida[1]);
- data_addideof(xd, ida[2], ida[3] ? 0 : 1);
- }
- break;
- case REPOKEY_TYPE_DIRSTRARRAY:
- for (ida = data->attriddata + id; *ida; ida += 2)
- {
- data_addideof(xd, ida[0], ida[2] ? 0 : 1);
- data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
- }
- break;
- default:
- fprintf(stderr, "don't know how to handle type %d\n", key->type);
- exit(1);
- }
- if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
- {
- /* put offset/len in incore */
- data_addid(&newincore, data->lastverticaloffset + oldvincorelen);
- oldvincorelen = xd->len - oldvincorelen;
- data_addid(&newincore, oldvincorelen);
- }
+ repodata_serialize_key(data, &newincore, &newvincore,
+ schema, schematacache,
+ key, seen[*keyp] - 1);
}
dp = ndp;
}
Id *schema; /* schema construction space */
Id *sp; /* pointer in above */
+ Id *oldschema, *oldsp;
Id *myschemata;
int nmyschemata;
Id *solvschemata;
Id *extraschemata;
+ Id *subschemata;
+ int nsubschemata;
+ int current_sub;
struct extdata *extdata;
if (!rm)
return SEARCH_NEXT_KEY; /* we do not want this one */
/* record key in schema */
- if (cbdata->sp == cbdata->schema || cbdata->sp[-1] != rm)
+ if ((key->type != REPOKEY_TYPE_COUNTED || kv->eof == 0)
+ && (cbdata->sp == cbdata->schema || cbdata->sp[-1] != rm))
*cbdata->sp++ = rm;
switch(key->type)
{
else
setdirused(cbdata, &data->dirpool, id);
break;
+ case REPOKEY_TYPE_COUNTED:
+ if (kv->eof == 0)
+ {
+ if (cbdata->oldschema)
+ {
+ fprintf(stderr, "nested structs not yet implemented\n");
+ exit(1);
+ }
+ cbdata->oldschema = cbdata->schema;
+ cbdata->oldsp = cbdata->sp;
+ cbdata->schema = sat_calloc(cbdata->nmykeys, sizeof(Id));
+ cbdata->sp = cbdata->schema;
+ }
+ else if (kv->eof == 1)
+ {
+ cbdata->current_sub++;
+ *cbdata->sp = 0;
+ cbdata->subschemata = sat_extend(cbdata->subschemata, cbdata->nsubschemata, 1, sizeof(Id), SCHEMATA_BLOCK);
+ cbdata->subschemata[cbdata->nsubschemata++] = addschema(cbdata, cbdata->schema);
+#if 0
+ fprintf(stderr, "Have schema %d\n", cbdata->subschemata[cbdata->nsubschemata-1]);
+#endif
+ cbdata->sp = cbdata->schema;
+ }
+ else
+ {
+ sat_free(cbdata->schema);
+ cbdata->schema = cbdata->oldschema;
+ cbdata->sp = cbdata->oldsp;
+ cbdata->oldsp = cbdata->oldschema = 0;
+ }
+ break;
default:
break;
}
data_addideof(xd, id, kv->eof);
data_addblob(xd, (unsigned char *)kv->str, strlen(kv->str) + 1);
break;
+ case REPOKEY_TYPE_COUNTED:
+ if (kv->eof == 0)
+ {
+ if (kv->num)
+ {
+ data_addid(xd, kv->num);
+ data_addid(xd, cbdata->subschemata[cbdata->current_sub]);
+#if 0
+ fprintf(stderr, "writing %d %d\n", kv->num, cbdata->subschemata[cbdata->current_sub]);
+#endif
+ }
+ }
+ else if (kv->eof == 1)
+ {
+ cbdata->current_sub++;
+ }
+ else
+ {
+ }
+ break;
default:
fprintf(stderr, "unknown type for %d: %d\n", key->name, key->type);
exit(1);
/********************************************************************/
cbdata.extdata = sat_calloc(cbdata.nmykeys, sizeof(struct extdata));
+ cbdata.current_sub = 0;
xd = cbdata.extdata;
maxentrysize = 0;
for (i = repo->start, s = pool->solvables + i, n = 0; i < repo->end; i++, s++)