2 * Copyright (c) 2007, Novell Inc.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
11 * Manage data coming from one repository
27 #include "poolid_private.h"
33 extern unsigned int compress_buf (const unsigned char *in, unsigned int in_len,
34 unsigned char *out, unsigned int out_len);
35 extern unsigned int unchecked_decompress_buf (const unsigned char *in,
38 unsigned int out_len);
40 #define REPODATA_BLOCK 255
44 repodata_init(Repodata *data, Repo *repo, int localpool)
46 memset(data, 0, sizeof (*data));
48 data->localpool = localpool;
50 stringpool_init_empty(&data->spool);
51 data->keys = sat_calloc(1, sizeof(Repokey));
53 data->schemata = sat_calloc(1, sizeof(Id));
54 data->schemadata = sat_calloc(1, sizeof(Id));
56 data->schemadatalen = 1;
57 repopagestore_init(&data->store);
61 repodata_free(Repodata *data)
67 sat_free(data->schemata);
68 sat_free(data->schemadata);
69 sat_free(data->schematahash);
71 stringpool_free(&data->spool);
72 dirpool_free(&data->dirpool);
74 sat_free(data->mainschemaoffsets);
75 sat_free(data->incoredata);
76 sat_free(data->incoreoffset);
77 sat_free(data->verticaloffset);
79 repopagestore_free(&data->store);
81 sat_free(data->vincore);
84 for (i = 0; i < data->end - data->start; i++)
85 sat_free(data->attrs[i]);
86 sat_free(data->attrs);
88 for (i = 0; i < data->nxattrs; i++)
89 sat_free(data->xattrs[i]);
90 sat_free(data->xattrs);
92 sat_free(data->attrdata);
93 sat_free(data->attriddata);
97 /***************************************************************
101 /* this is not so time critical that we need a hash, so we do a simple
104 repodata_key2id(Repodata *data, Repokey *key, int create)
108 for (keyid = 1; keyid < data->nkeys; keyid++)
109 if (data->keys[keyid].name == key->name && data->keys[keyid].type == key->type)
111 if ((key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID) && key->size != data->keys[keyid].size)
115 if (keyid == data->nkeys)
119 /* allocate new key */
120 data->keys = sat_realloc2(data->keys, data->nkeys + 1, sizeof(Repokey));
121 data->keys[data->nkeys++] = *key;
122 if (data->verticaloffset)
124 data->verticaloffset = sat_realloc2(data->verticaloffset, data->nkeys, sizeof(Id));
125 data->verticaloffset[data->nkeys - 1] = 0;
127 data->keybits[(key->name >> 3) & (sizeof(data->keybits) - 1)] |= 1 << (key->name & 7);
133 /***************************************************************
134 * schema pool management
137 #define SCHEMATA_BLOCK 31
138 #define SCHEMATADATA_BLOCK 255
141 repodata_schema2id(Repodata *data, Id *schema, int create)
147 if ((schematahash = data->schematahash) == 0)
149 data->schematahash = schematahash = sat_calloc(256, sizeof(Id));
150 for (i = 0; i < data->nschemata; i++)
152 for (sp = data->schemadata + data->schemata[i], h = 0; *sp; len++)
155 schematahash[h] = i + 1;
157 data->schemadata = sat_extend_resize(data->schemadata, data->schemadatalen, sizeof(Id), SCHEMATADATA_BLOCK);
158 data->schemata = sat_extend_resize(data->schemata, data->nschemata, sizeof(Id), SCHEMATA_BLOCK);
161 for (sp = schema, len = 0, h = 0; *sp; len++)
166 cid = schematahash[h];
170 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
173 for (cid = 0; cid < data->nschemata; cid++)
174 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
180 data->schemadata = sat_extend(data->schemadata, data->schemadatalen, len, sizeof(Id), SCHEMATADATA_BLOCK);
181 data->schemata = sat_extend(data->schemata, data->nschemata, 1, sizeof(Id), SCHEMATA_BLOCK);
183 memcpy(data->schemadata + data->schemadatalen, schema, len * sizeof(Id));
184 data->schemata[data->nschemata] = data->schemadatalen;
185 data->schemadatalen += len;
186 schematahash[h] = data->nschemata + 1;
188 fprintf(stderr, "schema2id: new schema\n");
190 return data->nschemata++;
194 repodata_free_schemahash(Repodata *data)
196 data->schematahash = sat_free(data->schematahash);
198 data->schemata = sat_realloc2(data->schemata, data->nschemata, sizeof(Id));
199 data->schemadata = sat_realloc2(data->schemadata, data->schemadatalen, sizeof(Id));
203 /***************************************************************
204 * dir pool management
208 repodata_str2dir(Repodata *data, const char *dir, int create)
214 while (*dir == '/' && dir[1] == '/')
216 if (*dir == '/' && !dir[1])
220 dire = strchrnul(dir, '/');
222 id = stringpool_strn2id(&data->spool, dir, dire - dir, create);
224 id = strn2id(data->repo->pool, dir, dire - dir, create);
227 parent = dirpool_add_dir(&data->dirpool, parent, id, create);
240 repodata_dir2str(Repodata *data, Id did, const char *suf)
242 Pool *pool = data->repo->pool;
249 return suf ? suf : "";
253 comp = dirpool_compid(&data->dirpool, parent);
254 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
256 parent = dirpool_parent(&data->dirpool, parent);
261 l += strlen(suf) + 1;
262 p = pool_alloctmpspace(pool, l + 1) + l;
273 comp = dirpool_compid(&data->dirpool, parent);
274 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
277 strncpy(p, comps, l);
278 parent = dirpool_parent(&data->dirpool, parent);
286 /***************************************************************
290 static inline unsigned char *
291 data_skip_schema(Repodata *data, unsigned char *dp, Id schema)
293 Id *keyp = data->schemadata + data->schemata[schema];
294 for (; *keyp; keyp++)
295 dp = data_skip_key(data, dp, data->keys + *keyp);
300 data_skip_key(Repodata *data, unsigned char *dp, Repokey *key)
302 int nentries, schema;
305 case REPOKEY_TYPE_FIXARRAY:
306 dp = data_read_id(dp, &nentries);
309 dp = data_read_id(dp, &schema);
311 dp = data_skip_schema(data, dp, schema);
313 case REPOKEY_TYPE_FLEXARRAY:
314 dp = data_read_id(dp, &nentries);
317 dp = data_read_id(dp, &schema);
318 dp = data_skip_schema(data, dp, schema);
322 if (key->storage == KEY_STORAGE_INCORE)
323 dp = data_skip(dp, key->type);
324 else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
326 dp = data_skip(dp, REPOKEY_TYPE_ID);
327 dp = data_skip(dp, REPOKEY_TYPE_ID);
333 static unsigned char *
334 forward_to_key(Repodata *data, Id keyid, Id *keyp, unsigned char *dp)
340 if (data->mainschemaoffsets && dp == data->incoredata + data->mainschemaoffsets[0] && keyp == data->schemadata + data->schemata[data->mainschema])
343 for (i = 0; (k = *keyp++) != 0; i++)
345 return data->incoredata + data->mainschemaoffsets[i];
348 while ((k = *keyp++) != 0)
352 if (data->keys[k].storage == KEY_STORAGE_VERTICAL_OFFSET)
354 dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip offset */
355 dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip length */
358 if (data->keys[k].storage != KEY_STORAGE_INCORE)
360 dp = data_skip_key(data, dp, data->keys + k);
365 static unsigned char *
366 get_vertical_data(Repodata *data, Repokey *key, Id off, Id len)
371 if (off >= data->lastverticaloffset)
373 off -= data->lastverticaloffset;
374 if (off + len > data->vincorelen)
376 return data->vincore + off;
378 if (off + len > key->size)
380 /* we now have the offset, go into vertical */
381 off += data->verticaloffset[key - data->keys];
382 /* fprintf(stderr, "key %d page %d\n", key->name, off / BLOB_PAGESIZE); */
383 dp = repopagestore_load_page_range(&data->store, off / BLOB_PAGESIZE, (off + len - 1) / BLOB_PAGESIZE);
385 dp += off % BLOB_PAGESIZE;
389 static inline unsigned char *
390 get_data(Repodata *data, Repokey *key, unsigned char **dpp, int advance)
392 unsigned char *dp = *dpp;
396 if (key->storage == KEY_STORAGE_INCORE)
399 *dpp = data_skip_key(data, dp, key);
402 else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
405 dp = data_read_id(dp, &off);
406 dp = data_read_id(dp, &len);
409 return get_vertical_data(data, key, off, len);
415 load_repodata(Repodata *data)
417 if (data->loadcallback)
419 data->loadcallback(data);
420 if (data->state == REPODATA_AVAILABLE)
423 data->state = REPODATA_ERROR;
428 maybe_load_repodata(Repodata *data, Id keyname)
430 if (keyname && !repodata_precheck_keyname(data, keyname))
431 return 0; /* do not bother... */
438 for (i = 0; i < data->nkeys; i++)
439 if (keyname == data->keys[i].name)
441 if (i == data->nkeys)
444 return load_repodata(data);
447 case REPODATA_AVAILABLE:
450 data->state = REPODATA_ERROR;
455 static inline unsigned char*
456 solvid2data(Repodata *data, Id solvid, Id *schemap)
458 unsigned char *dp = data->incoredata;
461 if (solvid == SOLVID_META) /* META */
463 else if (solvid == SOLVID_POS) /* META */
465 Pool *pool = data->repo->pool;
466 if (data->repo != pool->pos.repo)
468 if (data != data->repo->repodata + pool->pos.repodataid)
470 *schemap = pool->pos.schema;
471 return data->incoredata + pool->pos.dp;
475 if (solvid < data->start || solvid >= data->end)
477 dp += data->incoreoffset[solvid - data->start];
479 return data_read_id(dp, schemap);
482 /************************************************************************
486 static inline unsigned char *
487 find_key_data(Repodata *data, Id solvid, Id keyname, Repokey **keypp)
490 Id schema, *keyp, *kp;
493 if (!maybe_load_repodata(data, keyname))
495 dp = solvid2data(data, solvid, &schema);
498 keyp = data->schemadata + data->schemata[schema];
499 for (kp = keyp; *kp; kp++)
500 if (data->keys[*kp].name == keyname)
504 *keypp = key = data->keys + *kp;
505 if (key->type == REPOKEY_TYPE_VOID || key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID)
506 return dp; /* no need to forward... */
507 dp = forward_to_key(data, *kp, keyp, dp);
510 return get_data(data, key, &dp, 0);
515 repodata_lookup_id(Repodata *data, Id solvid, Id keyname)
521 dp = find_key_data(data, solvid, keyname, &key);
524 if (key->type == REPOKEY_TYPE_CONSTANTID)
526 if (key->type != REPOKEY_TYPE_ID)
528 dp = data_read_id(dp, &id);
533 repodata_lookup_str(Repodata *data, Id solvid, Id keyname)
539 dp = find_key_data(data, solvid, keyname, &key);
542 if (key->type == REPOKEY_TYPE_STR)
543 return (const char *)dp;
544 if (key->type == REPOKEY_TYPE_CONSTANTID)
545 return id2str(data->repo->pool, key->size);
546 if (key->type == REPOKEY_TYPE_ID)
547 dp = data_read_id(dp, &id);
551 return data->spool.stringspace + data->spool.strings[id];
552 return id2str(data->repo->pool, id);
556 repodata_lookup_num(Repodata *data, Id solvid, Id keyname, unsigned int *value)
563 dp = find_key_data(data, solvid, keyname, &key);
566 if (key->type == REPOKEY_TYPE_NUM
567 || key->type == REPOKEY_TYPE_U32
568 || key->type == REPOKEY_TYPE_CONSTANT)
570 dp = data_fetch(dp, &kv, key);
578 repodata_lookup_void(Repodata *data, Id solvid, Id keyname)
584 if (!maybe_load_repodata(data, keyname))
586 dp = solvid2data(data, solvid, &schema);
589 /* can't use find_key_data as we need to test the type */
590 for (keyp = data->schemadata + data->schemata[schema]; *keyp; keyp++)
591 if (data->keys[*keyp].name == keyname && data->keys[*keyp].type == REPOKEY_TYPE_VOID)
596 const unsigned char *
597 repodata_lookup_bin_checksum(Repodata *data, Id solvid, Id keyname, Id *typep)
602 dp = find_key_data(data, solvid, keyname, &key);
610 /************************************************************************
616 repodata_stringify(Pool *pool, Repodata *data, Repokey *key, KeyValue *kv, int flags)
620 case REPOKEY_TYPE_ID:
621 case REPOKEY_TYPE_CONSTANTID:
622 case REPOKEY_TYPE_IDARRAY:
623 if (data && data->localpool)
624 kv->str = stringpool_id2str(&data->spool, kv->id);
626 kv->str = id2str(pool, kv->id);
627 if ((flags & SEARCH_SKIP_KIND) != 0 && key->storage == KEY_STORAGE_SOLVABLE)
629 const char *s = strchr(kv->str, ':');
634 case REPOKEY_TYPE_STR:
636 case REPOKEY_TYPE_DIRSTRARRAY:
637 if (!(flags & SEARCH_FILES))
638 return 1; /* match just the basename */
639 /* Put the full filename into kv->str. */
640 kv->str = repodata_dir2str(data, kv->id, kv->str);
641 /* And to compensate for that put the "empty" directory into
642 kv->id, so that later calls to repodata_dir2str on this data
643 come up with the same filename again. */
652 struct subschema_data {
658 /* search a specific repodata */
660 repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata)
664 Id keyid, *kp, *keyp;
665 unsigned char *dp, *ddp;
671 if (!maybe_load_repodata(data, keyname))
673 if (solvid == SOLVID_SUBSCHEMA)
675 struct subschema_data *subd = cbdata;
676 cbdata = subd->cbdata;
678 schema = subd->parent->id;
679 dp = (unsigned char *)subd->parent->str;
680 kv.parent = subd->parent;
685 dp = solvid2data(data, solvid, &schema);
688 s = data->repo->pool->solvables + solvid;
691 keyp = data->schemadata + data->schemata[schema];
694 /* search for a specific key */
695 for (kp = keyp; *kp; kp++)
696 if (data->keys[*kp].name == keyname)
700 dp = forward_to_key(data, *kp, keyp, dp);
706 while ((keyid = *keyp++) != 0)
709 key = data->keys + keyid;
710 ddp = get_data(data, key, &dp, *keyp ? 1 : 0);
712 if (key->type == REPOKEY_TYPE_FLEXARRAY || key->type == REPOKEY_TYPE_FIXARRAY)
714 struct subschema_data subd;
718 subd.cbdata = cbdata;
721 ddp = data_read_id(ddp, &nentries);
725 while (ddp && nentries > 0)
729 if (key->type == REPOKEY_TYPE_FLEXARRAY || !kv.entry)
730 ddp = data_read_id(ddp, &schema);
732 kv.str = (char *)ddp;
733 stop = callback(cbdata, s, data, key, &kv);
734 if (stop > SEARCH_NEXT_KEY)
736 if (stop && stop != SEARCH_ENTERSUB)
738 if ((flags & SEARCH_SUB) != 0 || stop == SEARCH_ENTERSUB)
739 repodata_search(data, SOLVID_SUBSCHEMA, 0, flags, callback, &subd);
740 ddp = data_skip_schema(data, ddp, schema);
743 if (!nentries && (flags & SEARCH_ARRAYSENTINEL) != 0)
747 kv.str = (char *)ddp;
748 stop = callback(cbdata, s, data, key, &kv);
749 if (stop > SEARCH_NEXT_KEY)
759 ddp = data_fetch(ddp, &kv, key);
762 stop = callback(cbdata, s, data, key, &kv);
765 while (!kv.eof && !stop);
766 if (onekey || stop > SEARCH_NEXT_KEY)
772 repodata_setpos_kv(Repodata *data, KeyValue *kv)
774 Pool *pool = data->repo->pool;
776 pool_clear_pos(pool);
779 pool->pos.repo = data->repo;
780 pool->pos.repodataid = data - data->repo->repodata;
781 pool->pos.dp = (unsigned char *)kv->str - data->incoredata;
782 pool->pos.schema = kv->id;
786 /************************************************************************
787 * data iterator functions
790 static Repokey solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1] = {
791 { SOLVABLE_NAME, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
792 { SOLVABLE_ARCH, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
793 { SOLVABLE_EVR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
794 { SOLVABLE_VENDOR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
795 { SOLVABLE_PROVIDES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
796 { SOLVABLE_OBSOLETES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
797 { SOLVABLE_CONFLICTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
798 { SOLVABLE_REQUIRES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
799 { SOLVABLE_RECOMMENDS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
800 { SOLVABLE_SUGGESTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
801 { SOLVABLE_SUPPLEMENTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
802 { SOLVABLE_ENHANCES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
803 { RPM_RPMDBID, REPOKEY_TYPE_U32, 0, KEY_STORAGE_SOLVABLE },
807 solvabledata_fetch(Solvable *s, KeyValue *kv, Id keyname)
821 case SOLVABLE_VENDOR:
824 case SOLVABLE_PROVIDES:
826 return s->provides ? s->repo->idarraydata + s->provides : 0;
827 case SOLVABLE_OBSOLETES:
829 return s->obsoletes ? s->repo->idarraydata + s->obsoletes : 0;
830 case SOLVABLE_CONFLICTS:
832 return s->conflicts ? s->repo->idarraydata + s->conflicts : 0;
833 case SOLVABLE_REQUIRES:
835 return s->requires ? s->repo->idarraydata + s->requires : 0;
836 case SOLVABLE_RECOMMENDS:
838 return s->recommends ? s->repo->idarraydata + s->recommends : 0;
839 case SOLVABLE_SUPPLEMENTS:
841 return s->supplements ? s->repo->idarraydata + s->supplements : 0;
842 case SOLVABLE_SUGGESTS:
844 return s->suggests ? s->repo->idarraydata + s->suggests : 0;
845 case SOLVABLE_ENHANCES:
847 return s->enhances ? s->repo->idarraydata + s->enhances : 0;
850 return s->repo->rpmdbid ? s->repo->rpmdbid + (s - s->repo->pool->solvables - s->repo->start) : 0;
857 datamatcher_init(Datamatcher *ma, const char *match, int flags)
859 ma->match = (void *)match;
862 if ((flags & SEARCH_STRINGMASK) == SEARCH_REGEX)
864 ma->match = sat_calloc(1, sizeof(regex_t));
865 ma->error = regcomp((regex_t *)ma->match, match, REG_EXTENDED | REG_NOSUB | REG_NEWLINE | ((flags & SEARCH_NOCASE) ? REG_ICASE : 0));
869 ma->match = (void *)match;
870 ma->flags = (flags & ~SEARCH_STRINGMASK) | SEARCH_ERROR;
877 datamatcher_free(Datamatcher *ma)
879 if ((ma->flags & SEARCH_STRINGMASK) == SEARCH_REGEX && ma->match)
882 ma->match = sat_free(ma->match);
887 datamatcher_match(Datamatcher *ma, const char *str)
889 switch ((ma->flags & SEARCH_STRINGMASK))
891 case SEARCH_SUBSTRING:
892 if (ma->flags & SEARCH_NOCASE)
894 if (!strcasestr(str, (const char *)ma->match))
899 if (!strstr(str, (const char *)ma->match))
904 if (ma->flags & SEARCH_NOCASE)
906 if (strcasecmp((const char *)ma->match, str))
911 if (strcmp((const char *)ma->match, str))
916 if (fnmatch((const char *)ma->match, str, (ma->flags & SEARCH_NOCASE) ? FNM_CASEFOLD : 0))
920 if (regexec((const regex_t *)ma->match, str, 0, NULL, 0))
955 /* see repo.h for documentation */
957 dataiterator_init(Dataiterator *di, Pool *pool, Repo *repo, Id p, Id keyname, const char *match, int flags)
959 memset(di, 0, sizeof(*di));
961 if (!pool || (repo && repo->pool != pool))
969 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
976 di->keyname = keyname;
977 di->keynames[0] = keyname;
978 di->flags = flags & ~SEARCH_THISSOLVID;
987 dataiterator_jump_to_solvid(di, p);
991 di->repo = pool->repos[0];
992 di->state = di_enterrepo;
998 dataiterator_prepend_keyname(Dataiterator *di, Id keyname)
1002 if (di->nkeynames >= sizeof(di->keynames)/sizeof(*di->keynames) - 2)
1004 di->state = di_bye; /* sorry */
1007 for (i = di->nkeynames + 1; i > 0; i--)
1008 di->keynames[i] = di->keynames[i - 1];
1009 di->keynames[0] = di->keyname = keyname;
1014 dataiterator_free(Dataiterator *di)
1016 if (di->matcher.match)
1017 datamatcher_free(&di->matcher);
1020 static inline unsigned char *
1021 dataiterator_find_keyname(Dataiterator *di, Id keyname)
1023 Id *keyp = di->keyp;
1024 Repokey *keys = di->data->keys;
1027 for (keyp = di->keyp; *keyp; keyp++)
1028 if (keys[*keyp].name == keyname)
1032 dp = forward_to_key(di->data, *keyp, di->keyp, di->dp);
1040 dataiterator_step(Dataiterator *di)
1048 case di_enterrepo: di_enterrepo:
1051 if (!(di->flags & SEARCH_THISSOLVID))
1053 di->solvid = di->repo->start - 1; /* reset solvid iterator */
1054 goto di_nextsolvable;
1058 case di_entersolvable: di_entersolvable:
1059 if (di->repodataid >= 0)
1061 di->repodataid = 0; /* reset repodata iterator */
1062 if (di->solvid > 0 && !(di->flags & SEARCH_NO_STORAGE_SOLVABLE) && (!di->keyname || (di->keyname >= SOLVABLE_NAME && di->keyname <= RPM_RPMDBID)))
1064 di->key = solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0);
1066 goto di_entersolvablekey;
1071 case di_enterrepodata: di_enterrepodata:
1072 if (di->repodataid >= 0)
1074 if (di->repodataid >= di->repo->nrepodata)
1075 goto di_nextsolvable;
1076 di->data = di->repo->repodata + di->repodataid;
1078 if (!maybe_load_repodata(di->data, di->keyname))
1079 goto di_nextrepodata;
1080 di->dp = solvid2data(di->data, di->solvid, &schema);
1082 goto di_nextrepodata;
1083 if (di->solvid == SOLVID_POS)
1084 di->solvid = di->pool->pos.solvid;
1085 /* reset key iterator */
1086 di->keyp = di->data->schemadata + di->data->schemata[schema];
1089 case di_enterschema: di_enterschema:
1091 di->dp = dataiterator_find_keyname(di, di->keyname);
1092 if (!di->dp || !*di->keyp)
1096 goto di_nextrepodata;
1100 case di_enterkey: di_enterkey:
1102 di->key = di->data->keys + *di->keyp;
1103 di->ddp = get_data(di->data, di->key, &di->dp, di->keyp[1] && (!di->keyname || (di->flags & SEARCH_SUB) != 0) ? 1 : 0);
1106 if (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY)
1108 if (di->nparents < di->nkeynames)
1114 di->ddp = data_fetch(di->ddp, &di->kv, di->key);
1116 di->state = di_nextkey;
1118 di->state = di_nextattr;
1121 case di_nextkey: di_nextkey:
1122 if (!di->keyname && *++di->keyp)
1128 case di_nextrepodata: di_nextrepodata:
1129 if (di->repodataid >= 0 && ++di->repodataid < di->repo->nrepodata)
1130 goto di_enterrepodata;
1133 case di_nextsolvable: di_nextsolvable:
1134 if (!(di->flags & SEARCH_THISSOLVID))
1137 di->solvid = di->repo->start;
1140 for (; di->solvid < di->repo->end; di->solvid++)
1142 if (di->pool->solvables[di->solvid].repo == di->repo)
1143 goto di_entersolvable;
1149 if (di->repoid >= 0)
1152 if (di->repoid < di->pool->nrepos)
1154 di->repo = di->pool->repos[di->repoid];
1160 case di_bye: di_bye:
1164 case di_enterarray: di_enterarray:
1165 if (di->key->name == REPOSITORY_SOLVABLES)
1167 di->ddp = data_read_id(di->ddp, &di->kv.num);
1172 case di_nextarrayelement: di_nextarrayelement:
1175 di->ddp = data_skip_schema(di->data, di->ddp, di->kv.id);
1176 if (di->kv.entry == di->kv.num)
1178 if (di->nparents < di->nkeynames)
1180 if (!(di->flags & SEARCH_ARRAYSENTINEL))
1182 di->kv.str = (char *)di->ddp;
1184 di->state = di_nextkey;
1187 if (di->kv.entry == di->kv.num - 1)
1189 if (di->key->type == REPOKEY_TYPE_FLEXARRAY || !di->kv.entry)
1190 di->ddp = data_read_id(di->ddp, &di->kv.id);
1191 di->kv.str = (char *)di->ddp;
1192 if (di->nparents < di->nkeynames)
1194 if ((di->flags & SEARCH_SUB) != 0)
1195 di->state = di_entersub;
1197 di->state = di_nextarrayelement;
1200 case di_entersub: di_entersub:
1201 if (di->nparents == sizeof(di->parents)/sizeof(*di->parents) - 1)
1202 goto di_nextarrayelement; /* sorry, full */
1203 di->parents[di->nparents].kv = di->kv;
1204 di->parents[di->nparents].dp = di->dp;
1205 di->parents[di->nparents].keyp = di->keyp;
1206 di->dp = (unsigned char *)di->kv.str;
1207 di->keyp = di->data->schemadata + di->data->schemata[di->kv.id];
1208 memset(&di->kv, 0, sizeof(di->kv));
1209 di->kv.parent = &di->parents[di->nparents].kv;
1211 di->keyname = di->keynames[di->nparents];
1212 goto di_enterschema;
1214 case di_leavesub: di_leavesub:
1216 di->dp = di->parents[di->nparents].dp;
1217 di->kv = di->parents[di->nparents].kv;
1218 di->keyp = di->parents[di->nparents].keyp;
1219 di->key = di->data->keys + *di->keyp;
1220 di->ddp = (unsigned char *)di->kv.str;
1221 di->keyname = di->keynames[di->nparents];
1222 goto di_nextarrayelement;
1224 /* special solvable attr handling follows */
1226 case di_nextsolvableattr:
1227 di->kv.id = *di->idp++;
1232 di->state = di_nextsolvablekey;
1236 case di_nextsolvablekey: di_nextsolvablekey:
1237 if (di->keyname || di->key->name == RPM_RPMDBID)
1238 goto di_enterrepodata;
1242 case di_entersolvablekey: di_entersolvablekey:
1243 di->idp = solvabledata_fetch(di->pool->solvables + di->solvid, &di->kv, di->key->name);
1244 if (!di->idp || !di->idp[0])
1245 goto di_nextsolvablekey;
1246 di->kv.id = di->idp[0];
1247 di->kv.num = di->idp[0];
1249 if (!di->kv.eof && !di->idp[0])
1253 di->state = di_nextsolvablekey;
1255 di->state = di_nextsolvableattr;
1259 if (di->matcher.match)
1261 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1263 if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY))
1267 if (!datamatcher_match(&di->matcher, di->kv.str))
1270 /* found something! */
1276 dataiterator_entersub(Dataiterator *di)
1278 if (di->state == di_nextarrayelement)
1279 di->state = di_entersub;
1283 dataiterator_setpos(Dataiterator *di)
1285 if (di->kv.eof == 2)
1287 pool_clear_pos(di->pool);
1290 di->pool->pos.solvid = di->solvid;
1291 di->pool->pos.repo = di->repo;
1292 di->pool->pos.repodataid = di->data - di->repo->repodata;
1293 di->pool->pos.schema = di->kv.id;
1294 di->pool->pos.dp = (unsigned char *)di->kv.str - di->data->incoredata;
1298 dataiterator_setpos_parent(Dataiterator *di)
1300 if (!di->kv.parent || di->kv.parent->eof == 2)
1302 pool_clear_pos(di->pool);
1305 di->pool->pos.solvid = di->solvid;
1306 di->pool->pos.repo = di->repo;
1307 di->pool->pos.repodataid = di->data - di->repo->repodata;
1308 di->pool->pos.schema = di->kv.parent->id;
1309 di->pool->pos.dp = (unsigned char *)di->kv.parent->str - di->data->incoredata;
1313 dataiterator_skip_attribute(Dataiterator *di)
1315 if (di->state == di_nextsolvableattr)
1316 di->state = di_nextsolvablekey;
1318 di->state = di_nextkey;
1322 dataiterator_skip_solvable(Dataiterator *di)
1324 di->state = di_nextsolvable;
1328 dataiterator_skip_repo(Dataiterator *di)
1330 di->state = di_nextrepo;
1334 dataiterator_jump_to_solvid(Dataiterator *di, Id solvid)
1337 if (solvid == SOLVID_POS)
1339 di->repo = di->pool->pos.repo;
1346 di->data = di->repo->repodata + di->pool->pos.repodataid;
1347 di->repodataid = -1;
1348 di->solvid = solvid;
1349 di->state = di_enterrepo;
1350 di->flags |= SEARCH_THISSOLVID;
1355 di->repo = di->pool->solvables[solvid].repo;
1358 else if (di->repoid >= 0)
1360 if (!di->pool->nrepos)
1365 di->repo = di->pool->repos[0];
1369 di->solvid = solvid;
1371 di->flags |= SEARCH_THISSOLVID;
1372 di->state = di_enterrepo;
1376 dataiterator_jump_to_repo(Dataiterator *di, Repo *repo)
1383 di->flags &= ~SEARCH_THISSOLVID;
1384 di->state = di_enterrepo;
1388 dataiterator_match(Dataiterator *di, Datamatcher *ma)
1390 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1392 return datamatcher_match(ma, di->kv.str);
1396 dataiterator_match_obsolete(Dataiterator *di, int flags, const void *vmatch)
1398 Datamatcher matcher;
1400 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, flags))
1402 matcher = di->matcher;
1403 matcher.flags = flags;
1404 matcher.match = (void *)vmatch;
1405 return datamatcher_match(&matcher, di->kv.str);
1409 /************************************************************************
1410 * data modify functions
1413 /* extend repodata so that it includes solvables p */
1415 repodata_extend(Repodata *data, Id p)
1417 if (data->start == data->end)
1418 data->start = data->end = p;
1421 int old = data->end - data->start;
1422 int new = p - data->end + 1;
1425 data->attrs = sat_extend(data->attrs, old, new, sizeof(Id *), REPODATA_BLOCK);
1426 memset(data->attrs + old, 0, new * sizeof(Id *));
1428 data->incoreoffset = sat_extend(data->incoreoffset, old, new, sizeof(Id), REPODATA_BLOCK);
1429 memset(data->incoreoffset + old, 0, new * sizeof(Id));
1432 if (p < data->start)
1434 int old = data->end - data->start;
1435 int new = data->start - p;
1438 data->attrs = sat_extend_resize(data->attrs, old + new, sizeof(Id *), REPODATA_BLOCK);
1439 memmove(data->attrs + new, data->attrs, old * sizeof(Id *));
1440 memset(data->attrs, 0, new * sizeof(Id *));
1442 data->incoreoffset = sat_extend_resize(data->incoreoffset, old + new, sizeof(Id), REPODATA_BLOCK);
1443 memmove(data->incoreoffset + new, data->incoreoffset, old * sizeof(Id));
1444 memset(data->incoreoffset, 0, new * sizeof(Id));
1450 repodata_extend_block(Repodata *data, Id start, Id num)
1454 if (!data->incoreoffset)
1456 data->incoreoffset = sat_calloc_block(num, sizeof(Id), REPODATA_BLOCK);
1457 data->start = start;
1458 data->end = start + num;
1461 repodata_extend(data, start);
1463 repodata_extend(data, start + num - 1);
1466 /**********************************************************************/
1468 #define REPODATA_ATTRS_BLOCK 63
1469 #define REPODATA_ATTRDATA_BLOCK 1023
1470 #define REPODATA_ATTRIDDATA_BLOCK 63
1474 repodata_new_handle(Repodata *data)
1478 data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1481 data->xattrs = sat_extend(data->xattrs, data->nxattrs, 1, sizeof(Id *), REPODATA_BLOCK);
1482 data->xattrs[data->nxattrs] = 0;
1483 return -(data->nxattrs++);
1487 repodata_get_attrp(Repodata *data, Id handle)
1489 if (handle == SOLVID_META)
1493 data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1498 return data->xattrs - handle;
1499 if (handle < data->start || handle >= data->end)
1500 repodata_extend(data, handle);
1502 data->attrs = sat_calloc_block(data->end - data->start, sizeof(Id *), REPODATA_BLOCK);
1503 return data->attrs + (handle - data->start);
1507 repodata_insert_keyid(Repodata *data, Id handle, Id keyid, Id val, int overwrite)
1513 app = repodata_get_attrp(data, handle);
1518 for (pp = ap; *pp; pp += 2)
1519 /* Determine equality based on the name only, allows us to change
1520 type (when overwrite is set), and makes TYPE_CONSTANT work. */
1521 if (data->keys[*pp].name == data->keys[keyid].name)
1534 ap = sat_extend(ap, i, 3, sizeof(Id), REPODATA_ATTRS_BLOCK);
1544 repodata_set(Repodata *data, Id solvid, Repokey *key, Id val)
1548 keyid = repodata_key2id(data, key, 1);
1549 repodata_insert_keyid(data, solvid, keyid, val, 1);
1553 repodata_set_id(Repodata *data, Id solvid, Id keyname, Id id)
1557 key.type = REPOKEY_TYPE_ID;
1559 key.storage = KEY_STORAGE_INCORE;
1560 repodata_set(data, solvid, &key, id);
1564 repodata_set_num(Repodata *data, Id solvid, Id keyname, unsigned int num)
1568 key.type = REPOKEY_TYPE_NUM;
1570 key.storage = KEY_STORAGE_INCORE;
1571 repodata_set(data, solvid, &key, (Id)num);
1575 repodata_set_poolstr(Repodata *data, Id solvid, Id keyname, const char *str)
1579 if (data->localpool)
1580 id = stringpool_str2id(&data->spool, str, 1);
1582 id = str2id(data->repo->pool, str, 1);
1584 key.type = REPOKEY_TYPE_ID;
1586 key.storage = KEY_STORAGE_INCORE;
1587 repodata_set(data, solvid, &key, id);
1591 repodata_set_constant(Repodata *data, Id solvid, Id keyname, unsigned int constant)
1595 key.type = REPOKEY_TYPE_CONSTANT;
1596 key.size = constant;
1597 key.storage = KEY_STORAGE_INCORE;
1598 repodata_set(data, solvid, &key, 0);
1602 repodata_set_constantid(Repodata *data, Id solvid, Id keyname, Id id)
1606 key.type = REPOKEY_TYPE_CONSTANTID;
1608 key.storage = KEY_STORAGE_INCORE;
1609 repodata_set(data, solvid, &key, 0);
1613 repodata_set_void(Repodata *data, Id solvid, Id keyname)
1617 key.type = REPOKEY_TYPE_VOID;
1619 key.storage = KEY_STORAGE_INCORE;
1620 repodata_set(data, solvid, &key, 0);
1624 repodata_set_str(Repodata *data, Id solvid, Id keyname, const char *str)
1629 l = strlen(str) + 1;
1631 key.type = REPOKEY_TYPE_STR;
1633 key.storage = KEY_STORAGE_INCORE;
1634 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1635 memcpy(data->attrdata + data->attrdatalen, str, l);
1636 repodata_set(data, solvid, &key, data->attrdatalen);
1637 data->attrdatalen += l;
1641 repodata_add_array(Repodata *data, Id handle, Id keyname, Id keytype, int entrysize)
1644 Id *ida, *pp, **ppp;
1646 if (handle == data->lasthandle && data->keys[data->lastkey].name == keyname && data->keys[data->lastkey].type == keytype && data->attriddatalen == data->lastdatalen)
1648 /* great! just append the new data */
1649 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
1650 data->attriddatalen--; /* overwrite terminating 0 */
1651 data->lastdatalen += entrysize;
1654 ppp = repodata_get_attrp(data, handle);
1657 for (; *pp; pp += 2)
1658 if (data->keys[*pp].name == keyname && data->keys[*pp].type == keytype)
1662 /* not found. allocate new key */
1667 key.storage = KEY_STORAGE_INCORE;
1668 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
1669 repodata_set(data, handle, &key, data->attriddatalen);
1670 data->lasthandle = 0; /* next time... */
1674 for (ida = data->attriddata + pp[1]; *ida; ida += entrysize)
1675 oldsize += entrysize;
1676 if (ida + 1 == data->attriddata + data->attriddatalen)
1678 /* this was the last entry, just append it */
1679 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
1680 data->attriddatalen--; /* overwrite terminating 0 */
1684 /* too bad. move to back. */
1685 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, oldsize + entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
1686 memcpy(data->attriddata + data->attriddatalen, data->attriddata + pp[1], oldsize * sizeof(Id));
1687 pp[1] = data->attriddatalen;
1688 data->attriddatalen += oldsize;
1690 data->lasthandle = handle;
1691 data->lastkey = *pp;
1692 data->lastdatalen = data->attriddatalen + entrysize + 1;
1696 checksumtype2len(Id type)
1700 case REPOKEY_TYPE_MD5:
1702 case REPOKEY_TYPE_SHA1:
1704 case REPOKEY_TYPE_SHA256:
1705 return SIZEOF_SHA256;
1712 repodata_set_bin_checksum(Repodata *data, Id solvid, Id keyname, Id type,
1713 const unsigned char *str)
1716 int l = checksumtype2len(type);
1723 key.storage = KEY_STORAGE_INCORE;
1724 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1725 memcpy(data->attrdata + data->attrdatalen, str, l);
1726 repodata_set(data, solvid, &key, data->attrdatalen);
1727 data->attrdatalen += l;
1731 hexstr2bytes(unsigned char *buf, const char *str, int buflen)
1734 for (i = 0; i < buflen; i++)
1736 #define c2h(c) (((c)>='0' && (c)<='9') ? ((c)-'0') \
1737 : ((c)>='a' && (c)<='f') ? ((c)-'a'+10) \
1738 : ((c)>='A' && (c)<='F') ? ((c)-'A'+10) \
1749 buf[i] = (buf[i] << 4) | v;
1756 repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type,
1759 unsigned char buf[64];
1760 int l = checksumtype2len(type);
1764 if (hexstr2bytes(buf, str, l) != l)
1766 repodata_set_bin_checksum(data, solvid, keyname, type, buf);
1770 repodata_chk2str(Repodata *data, Id type, const unsigned char *buf)
1775 l = checksumtype2len(type);
1778 s = str = pool_alloctmpspace(data->repo->pool, 2 * l + 1);
1779 for (i = 0; i < l; i++)
1781 unsigned char v = buf[i];
1782 unsigned char w = v >> 4;
1783 *s++ = w >= 10 ? w + ('a' - 10) : w + '0';
1785 *s++ = w >= 10 ? w + ('a' - 10) : w + '0';
1791 static inline const char *
1792 evrid2vrstr(Pool *pool, Id evrid)
1794 const char *p, *evr = id2str(pool, evrid);
1797 for (p = evr; *p >= '0' && *p <= '9'; p++)
1799 return p != evr && *p == ':' ? p + 1 : evr;
1803 repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, const char *file)
1805 Pool *pool = data->repo->pool;
1807 const char *str, *fp;
1811 repodata_set_constant(data, solvid, SOLVABLE_MEDIANR, medianr);
1814 if ((dir = strrchr(file, '/')) != 0)
1825 if (l >= 2 && dir[0] == '.' && dir[1] == '/' && (l == 2 || dir[2] != '/'))
1830 if (l == 1 && dir[0] == '.')
1832 s = pool->solvables + solvid;
1835 str = id2str(pool, s->arch);
1836 if (!strncmp(dir, str, l) && !str[l])
1837 repodata_set_void(data, solvid, SOLVABLE_MEDIADIR);
1839 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir);
1842 char *dir2 = strdup(dir);
1844 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir2);
1849 str = id2str(pool, s->name);
1851 if ((!l || !strncmp(fp, str, l)) && fp[l] == '-')
1854 str = evrid2vrstr(pool, s->evr);
1856 if ((!l || !strncmp(fp, str, l)) && fp[l] == '.')
1859 str = id2str(pool, s->arch);
1861 if ((!l || !strncmp(fp, str, l)) && !strcmp(fp + l, ".rpm"))
1863 repodata_set_void(data, solvid, SOLVABLE_MEDIAFILE);
1868 repodata_set_str(data, solvid, SOLVABLE_MEDIAFILE, file);
1872 repodata_globalize_id(Repodata *data, Id id)
1874 if (!data || !data->localpool)
1876 return str2id(data->repo->pool, stringpool_id2str(&data->spool, id), 1);
1880 repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2)
1884 fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", solvid, dir, num, num2, data->attriddatalen);
1886 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRNUMNUMARRAY, 3);
1887 data->attriddata[data->attriddatalen++] = dir;
1888 data->attriddata[data->attriddatalen++] = num;
1889 data->attriddata[data->attriddatalen++] = num2;
1890 data->attriddata[data->attriddatalen++] = 0;
1894 repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str)
1900 l = strlen(str) + 1;
1901 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1902 memcpy(data->attrdata + data->attrdatalen, str, l);
1903 stroff = data->attrdatalen;
1904 data->attrdatalen += l;
1907 fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", solvid, dir, str, data->attriddatalen);
1909 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRSTRARRAY, 2);
1910 data->attriddata[data->attriddatalen++] = dir;
1911 data->attriddata[data->attriddatalen++] = stroff;
1912 data->attriddata[data->attriddatalen++] = 0;
1916 repodata_add_idarray(Repodata *data, Id solvid, Id keyname, Id id)
1919 fprintf(stderr, "repodata_add_idarray %d %d (%d)\n", solvid, id, data->attriddatalen);
1921 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_IDARRAY, 1);
1922 data->attriddata[data->attriddatalen++] = id;
1923 data->attriddata[data->attriddatalen++] = 0;
1927 repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname,
1931 if (data->localpool)
1932 id = stringpool_str2id(&data->spool, str, 1);
1934 id = str2id(data->repo->pool, str, 1);
1935 repodata_add_idarray(data, solvid, keyname, id);
1939 repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
1941 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FIXARRAY, 1);
1942 data->attriddata[data->attriddatalen++] = ghandle;
1943 data->attriddata[data->attriddatalen++] = 0;
1947 repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
1949 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FLEXARRAY, 1);
1950 data->attriddata[data->attriddatalen++] = ghandle;
1951 data->attriddata[data->attriddatalen++] = 0;
1955 repodata_merge_attrs(Repodata *data, Id dest, Id src)
1958 if (dest == src || !(keyp = data->attrs[src - data->start]))
1960 for (; *keyp; keyp += 2)
1961 repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
1967 /**********************************************************************/
1969 /* unify with repo_write! */
1971 #define EXTDATA_BLOCK 1023
1979 data_addid(struct extdata *xd, Id x)
1982 xd->buf = sat_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
1983 dp = xd->buf + xd->len;
1988 *dp++ = (x >> 28) | 128;
1990 *dp++ = (x >> 21) | 128;
1991 *dp++ = (x >> 14) | 128;
1994 *dp++ = (x >> 7) | 128;
1996 xd->len = dp - xd->buf;
2000 data_addideof(struct extdata *xd, Id x, int eof)
2003 x = (x & 63) | ((x & ~63) << 1);
2004 data_addid(xd, (eof ? x: x | 64));
2008 data_addblob(struct extdata *xd, unsigned char *blob, int len)
2010 xd->buf = sat_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK);
2011 memcpy(xd->buf + xd->len, blob, len);
2015 /*********************************/
2018 repodata_serialize_key(Repodata *data, struct extdata *newincore,
2019 struct extdata *newvincore,
2021 Repokey *key, Id val)
2023 /* Otherwise we have a new value. Parse it into the internal
2027 unsigned int oldvincorelen = 0;
2031 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2034 oldvincorelen = xd->len;
2038 case REPOKEY_TYPE_VOID:
2039 case REPOKEY_TYPE_CONSTANT:
2040 case REPOKEY_TYPE_CONSTANTID:
2042 case REPOKEY_TYPE_STR:
2043 data_addblob(xd, data->attrdata + val, strlen((char *)(data->attrdata + val)) + 1);
2045 case REPOKEY_TYPE_MD5:
2046 data_addblob(xd, data->attrdata + val, SIZEOF_MD5);
2048 case REPOKEY_TYPE_SHA1:
2049 data_addblob(xd, data->attrdata + val, SIZEOF_SHA1);
2051 case REPOKEY_TYPE_SHA256:
2052 data_addblob(xd, data->attrdata + val, SIZEOF_SHA256);
2054 case REPOKEY_TYPE_ID:
2055 case REPOKEY_TYPE_NUM:
2056 case REPOKEY_TYPE_DIR:
2057 data_addid(xd, val);
2059 case REPOKEY_TYPE_IDARRAY:
2060 for (ida = data->attriddata + val; *ida; ida++)
2061 data_addideof(xd, ida[0], ida[1] ? 0 : 1);
2063 case REPOKEY_TYPE_DIRNUMNUMARRAY:
2064 for (ida = data->attriddata + val; *ida; ida += 3)
2066 data_addid(xd, ida[0]);
2067 data_addid(xd, ida[1]);
2068 data_addideof(xd, ida[2], ida[3] ? 0 : 1);
2071 case REPOKEY_TYPE_DIRSTRARRAY:
2072 for (ida = data->attriddata + val; *ida; ida += 2)
2074 data_addideof(xd, ida[0], ida[2] ? 0 : 1);
2075 data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
2078 case REPOKEY_TYPE_FIXARRAY:
2082 for (ida = data->attriddata + val; *ida; ida++)
2085 fprintf(stderr, "serialize struct %d\n", *ida);
2088 Id *kp = data->xattrs[-*ida];
2095 fprintf(stderr, " %s:%d\n", id2str(data->repo->pool, data->keys[*kp].name), kp[1]);
2101 schemaid = repodata_schema2id(data, schema, 1);
2102 else if (schemaid != repodata_schema2id(data, schema, 0))
2104 pool_debug(data->repo->pool, SAT_FATAL, "substructs with different schemas\n");
2108 fprintf(stderr, " schema %d\n", schemaid);
2113 data_addid(xd, num);
2114 data_addid(xd, schemaid);
2115 for (ida = data->attriddata + val; *ida; ida++)
2117 Id *kp = data->xattrs[-*ida];
2122 repodata_serialize_key(data, newincore, newvincore,
2123 schema, data->keys + *kp, kp[1]);
2128 case REPOKEY_TYPE_FLEXARRAY:
2131 for (ida = data->attriddata + val; *ida; ida++)
2133 data_addid(xd, num);
2134 for (ida = data->attriddata + val; *ida; ida++)
2136 Id *kp = data->xattrs[-*ida];
2139 data_addid(xd, 0); /* XXX */
2146 schemaid = repodata_schema2id(data, schema, 1);
2147 data_addid(xd, schemaid);
2148 kp = data->xattrs[-*ida];
2151 repodata_serialize_key(data, newincore, newvincore,
2152 schema, data->keys + *kp, kp[1]);
2158 pool_debug(data->repo->pool, SAT_FATAL, "don't know how to handle type %d\n", key->type);
2161 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2163 /* put offset/len in incore */
2164 data_addid(newincore, data->lastverticaloffset + oldvincorelen);
2165 oldvincorelen = xd->len - oldvincorelen;
2166 data_addid(newincore, oldvincorelen);
2171 repodata_internalize(Repodata *data)
2173 Repokey *key, solvkey;
2175 Id schemaid, *schema, *sp, oldschema, *keyp, *keypstart, *seen;
2176 unsigned char *dp, *ndp;
2177 int newschema, oldcount;
2178 struct extdata newincore;
2179 struct extdata newvincore;
2182 if (!data->attrs && !data->xattrs)
2185 newvincore.buf = data->vincore;
2186 newvincore.len = data->vincorelen;
2188 /* find the solvables key, create if needed */
2189 memset(&solvkey, 0, sizeof(solvkey));
2190 solvkey.name = REPOSITORY_SOLVABLES;
2191 solvkey.type = REPOKEY_TYPE_FLEXARRAY;
2193 solvkey.storage = KEY_STORAGE_INCORE;
2194 solvkeyid = repodata_key2id(data, &solvkey, data->end != data->start ? 1 : 0);
2196 schema = sat_malloc2(data->nkeys, sizeof(Id));
2197 seen = sat_malloc2(data->nkeys, sizeof(Id));
2199 /* Merge the data already existing (in data->schemata, ->incoredata and
2200 friends) with the new attributes in data->attrs[]. */
2201 nentry = data->end - data->start;
2202 memset(&newincore, 0, sizeof(newincore));
2203 data_addid(&newincore, 0); /* start data at offset 1 */
2205 data->mainschema = 0;
2206 data->mainschemaoffsets = sat_free(data->mainschemaoffsets);
2208 /* join entry data */
2209 /* we start with the meta data, entry -1 */
2210 for (entry = -1; entry < nentry; entry++)
2212 memset(seen, 0, data->nkeys * sizeof(Id));
2214 dp = data->incoredata;
2217 dp += entry >= 0 ? data->incoreoffset[entry] : 1;
2218 dp = data_read_id(dp, &oldschema);
2221 fprintf(stderr, "oldschema %d\n", oldschema);
2222 fprintf(stderr, "schemata %d\n", data->schemata[oldschema]);
2223 fprintf(stderr, "schemadata %p\n", data->schemadata);
2225 /* seen: -1: old data 0: skipped >0: id + 1 */
2229 for (keyp = data->schemadata + data->schemata[oldschema]; *keyp; keyp++)
2233 pool_debug(data->repo->pool, SAT_FATAL, "Inconsistent old data (key occured twice).\n");
2241 keyp = data->attrs ? data->attrs[entry] : 0;
2244 /* strip solvables key */
2246 for (sp = keyp = schema; *sp; sp++)
2247 if (*sp != solvkeyid)
2252 seen[solvkeyid] = 0;
2253 keyp = data->xattrs ? data->xattrs[1] : 0;
2256 for (; *keyp; keyp += 2)
2263 seen[*keyp] = keyp[1] + 1;
2265 if (entry < 0 && data->end != data->start)
2272 /* Ideally we'd like to sort the new schema here, to ensure
2273 schema equality independend of the ordering. We can't do that
2274 yet. For once see below (old ids need to come before new ids).
2275 An additional difficulty is that we also need to move
2276 the values with the keys. */
2277 schemaid = repodata_schema2id(data, schema, 1);
2279 schemaid = oldschema;
2282 /* Now create data blob. We walk through the (possibly new) schema
2283 and either copy over old data, or insert the new. */
2284 /* XXX Here we rely on the fact that the (new) schema has the form
2285 o1 o2 o3 o4 ... | n1 n2 n3 ...
2286 (oX being the old keyids (possibly overwritten), and nX being
2287 the new keyids). This rules out sorting the keyids in order
2288 to ensure a small schema count. */
2290 data->incoreoffset[entry] = newincore.len;
2291 data_addid(&newincore, schemaid);
2294 data->mainschema = schemaid;
2295 data->mainschemaoffsets = sat_calloc(sp - schema, sizeof(Id));
2297 keypstart = data->schemadata + data->schemata[schemaid];
2298 for (keyp = keypstart; *keyp; keyp++)
2301 data->mainschemaoffsets[keyp - keypstart] = newincore.len;
2302 if (*keyp == solvkeyid)
2304 /* add flexarray entry count */
2305 data_addid(&newincore, data->end - data->start);
2308 key = data->keys + *keyp;
2310 fprintf(stderr, "internalize %d:%s:%s\n", entry, id2str(data->repo->pool, key->name), id2str(data->repo->pool, key->type));
2315 /* Skip the data associated with this old key. */
2316 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2318 ndp = data_skip(dp, REPOKEY_TYPE_ID);
2319 ndp = data_skip(ndp, REPOKEY_TYPE_ID);
2321 else if (key->storage == KEY_STORAGE_INCORE)
2322 ndp = data_skip_key(data, dp, key);
2325 if (seen[*keyp] == -1)
2327 /* If this key was an old one _and_ was not overwritten with
2328 a different value copy over the old value (we skipped it
2331 data_addblob(&newincore, dp, ndp - dp);
2334 else if (seen[*keyp])
2336 /* Otherwise we have a new value. Parse it into the internal
2338 repodata_serialize_key(data, &newincore, &newvincore,
2339 schema, key, seen[*keyp] - 1);
2343 if (entry >= 0 && data->attrs && data->attrs[entry])
2344 data->attrs[entry] = sat_free(data->attrs[entry]);
2346 /* free all xattrs */
2347 for (entry = 0; entry < data->nxattrs; entry++)
2348 if (data->xattrs[entry])
2349 sat_free(data->xattrs[entry]);
2350 data->xattrs = sat_free(data->xattrs);
2353 data->lasthandle = 0;
2355 data->lastdatalen = 0;
2358 repodata_free_schemahash(data);
2360 sat_free(data->incoredata);
2361 data->incoredata = newincore.buf;
2362 data->incoredatalen = newincore.len;
2363 data->incoredatafree = 0;
2365 sat_free(data->vincore);
2366 data->vincore = newvincore.buf;
2367 data->vincorelen = newvincore.len;
2369 data->attrs = sat_free(data->attrs);
2370 data->attrdata = sat_free(data->attrdata);
2371 data->attriddata = sat_free(data->attriddata);
2372 data->attrdatalen = 0;
2373 data->attriddatalen = 0;
2377 repodata_disable_paging(Repodata *data)
2379 if (maybe_load_repodata(data, 0))
2380 repopagestore_disable_paging(&data->store);
2384 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: