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
13 * a repository can contain multiple repodata entries, consisting of
14 * different sets of keys and different sets of solvables
29 #include "poolid_private.h"
37 #define REPODATA_BLOCK 255
39 static unsigned char *data_skip_key(Repodata *data, unsigned char *dp, Repokey *key);
42 repodata_initdata(Repodata *data, Repo *repo, int localpool)
44 memset(data, 0, sizeof (*data));
45 data->repodataid = data - repo->repodata;
47 data->localpool = localpool;
49 stringpool_init_empty(&data->spool);
50 /* dirpool_init(&data->dirpool); just zeros out again */
51 data->keys = solv_calloc(1, sizeof(Repokey));
53 data->schemata = solv_calloc(1, sizeof(Id));
54 data->schemadata = solv_calloc(1, sizeof(Id));
56 data->schemadatalen = 1;
57 repopagestore_init(&data->store);
61 repodata_freedata(Repodata *data)
65 solv_free(data->keys);
67 solv_free(data->schemata);
68 solv_free(data->schemadata);
69 solv_free(data->schematahash);
71 stringpool_free(&data->spool);
72 dirpool_free(&data->dirpool);
74 solv_free(data->mainschemaoffsets);
75 solv_free(data->incoredata);
76 solv_free(data->incoreoffset);
77 solv_free(data->verticaloffset);
79 repopagestore_free(&data->store);
81 solv_free(data->vincore);
84 for (i = 0; i < data->end - data->start; i++)
85 solv_free(data->attrs[i]);
86 solv_free(data->attrs);
88 for (i = 0; i < data->nxattrs; i++)
89 solv_free(data->xattrs[i]);
90 solv_free(data->xattrs);
92 solv_free(data->attrdata);
93 solv_free(data->attriddata);
97 repodata_free(Repodata *data)
99 Repo *repo = data->repo;
100 int i = data - repo->repodata;
103 repodata_freedata(data);
104 if (i < repo->nrepodata - 1)
106 /* whoa! this changes the repodataids! */
107 memmove(repo->repodata + i, repo->repodata + i + 1, (repo->nrepodata - 1 - i) * sizeof(Repodata));
108 for (; i < repo->nrepodata - 1; i++)
109 repo->repodata[i].repodataid = i;
112 if (repo->nrepodata == 1)
114 repo->repodata = solv_free(repo->repodata);
120 repodata_empty(Repodata *data, int localpool)
122 void (*loadcallback)(Repodata *) = data->loadcallback;
123 int state = data->state;
124 repodata_freedata(data);
125 repodata_initdata(data, data->repo, localpool);
127 data->loadcallback = loadcallback;
131 /***************************************************************
132 * key pool management
135 /* this is not so time critical that we need a hash, so we do a simple
138 repodata_key2id(Repodata *data, Repokey *key, int create)
142 for (keyid = 1; keyid < data->nkeys; keyid++)
143 if (data->keys[keyid].name == key->name && data->keys[keyid].type == key->type)
145 if ((key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID) && key->size != data->keys[keyid].size)
149 if (keyid == data->nkeys)
153 /* allocate new key */
154 data->keys = solv_realloc2(data->keys, data->nkeys + 1, sizeof(Repokey));
155 data->keys[data->nkeys++] = *key;
156 if (data->verticaloffset)
158 data->verticaloffset = solv_realloc2(data->verticaloffset, data->nkeys, sizeof(Id));
159 data->verticaloffset[data->nkeys - 1] = 0;
161 data->keybits[(key->name >> 3) & (sizeof(data->keybits) - 1)] |= 1 << (key->name & 7);
167 /***************************************************************
168 * schema pool management
171 #define SCHEMATA_BLOCK 31
172 #define SCHEMATADATA_BLOCK 255
175 repodata_schema2id(Repodata *data, Id *schema, int create)
182 return 0; /* XXX: allow empty schema? */
183 if ((schematahash = data->schematahash) == 0)
185 data->schematahash = schematahash = solv_calloc(256, sizeof(Id));
186 for (i = 1; i < data->nschemata; i++)
188 for (sp = data->schemadata + data->schemata[i], h = 0; *sp; len++)
193 data->schemadata = solv_extend_resize(data->schemadata, data->schemadatalen, sizeof(Id), SCHEMATADATA_BLOCK);
194 data->schemata = solv_extend_resize(data->schemata, data->nschemata, sizeof(Id), SCHEMATA_BLOCK);
197 for (sp = schema, len = 0, h = 0; *sp; len++)
202 cid = schematahash[h];
205 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
207 /* cache conflict, do a slow search */
208 for (cid = 1; cid < data->nschemata; cid++)
209 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
215 data->schemadata = solv_extend(data->schemadata, data->schemadatalen, len, sizeof(Id), SCHEMATADATA_BLOCK);
216 data->schemata = solv_extend(data->schemata, data->nschemata, 1, sizeof(Id), SCHEMATA_BLOCK);
218 memcpy(data->schemadata + data->schemadatalen, schema, len * sizeof(Id));
219 data->schemata[data->nschemata] = data->schemadatalen;
220 data->schemadatalen += len;
221 schematahash[h] = data->nschemata;
223 fprintf(stderr, "schema2id: new schema\n");
225 return data->nschemata++;
229 repodata_free_schemahash(Repodata *data)
231 data->schematahash = solv_free(data->schematahash);
233 data->schemata = solv_realloc2(data->schemata, data->nschemata, sizeof(Id));
234 data->schemadata = solv_realloc2(data->schemadata, data->schemadatalen, sizeof(Id));
238 /***************************************************************
239 * dir pool management
242 #ifndef HAVE_STRCHRNUL
243 static inline const char *strchrnul(const char *str, char x)
245 const char *p = strchr(str, x);
246 return p ? p : str + strlen(str);
251 repodata_str2dir(Repodata *data, const char *dir, int create)
257 while (*dir == '/' && dir[1] == '/')
259 if (*dir == '/' && !dir[1])
261 if (data->dirpool.ndirs)
263 return dirpool_add_dir(&data->dirpool, 0, 1, create);
267 dire = strchrnul(dir, '/');
269 id = stringpool_strn2id(&data->spool, dir, dire - dir, create);
271 id = pool_strn2id(data->repo->pool, dir, dire - dir, create);
274 parent = dirpool_add_dir(&data->dirpool, parent, id, create);
287 repodata_dir2str(Repodata *data, Id did, const char *suf)
289 Pool *pool = data->repo->pool;
296 return suf ? suf : "";
300 comp = dirpool_compid(&data->dirpool, parent);
301 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
303 parent = dirpool_parent(&data->dirpool, parent);
308 l += strlen(suf) + 1;
309 p = pool_alloctmpspace(pool, l + 1) + l;
320 comp = dirpool_compid(&data->dirpool, parent);
321 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
324 strncpy(p, comps, l);
325 parent = dirpool_parent(&data->dirpool, parent);
333 /***************************************************************
337 static inline unsigned char *
338 data_skip_schema(Repodata *data, unsigned char *dp, Id schema)
340 Id *keyp = data->schemadata + data->schemata[schema];
341 for (; *keyp; keyp++)
342 dp = data_skip_key(data, dp, data->keys + *keyp);
346 static unsigned char *
347 data_skip_key(Repodata *data, unsigned char *dp, Repokey *key)
349 int nentries, schema;
352 case REPOKEY_TYPE_FIXARRAY:
353 dp = data_read_id(dp, &nentries);
356 dp = data_read_id(dp, &schema);
358 dp = data_skip_schema(data, dp, schema);
360 case REPOKEY_TYPE_FLEXARRAY:
361 dp = data_read_id(dp, &nentries);
364 dp = data_read_id(dp, &schema);
365 dp = data_skip_schema(data, dp, schema);
369 if (key->storage == KEY_STORAGE_INCORE)
370 dp = data_skip(dp, key->type);
371 else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
373 dp = data_skip(dp, REPOKEY_TYPE_ID);
374 dp = data_skip(dp, REPOKEY_TYPE_ID);
380 static unsigned char *
381 forward_to_key(Repodata *data, Id keyid, Id *keyp, unsigned char *dp)
387 if (data->mainschemaoffsets && dp == data->incoredata + data->mainschemaoffsets[0] && keyp == data->schemadata + data->schemata[data->mainschema])
390 for (i = 0; (k = *keyp++) != 0; i++)
392 return data->incoredata + data->mainschemaoffsets[i];
395 while ((k = *keyp++) != 0)
399 if (data->keys[k].storage == KEY_STORAGE_VERTICAL_OFFSET)
401 dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip offset */
402 dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip length */
405 if (data->keys[k].storage != KEY_STORAGE_INCORE)
407 dp = data_skip_key(data, dp, data->keys + k);
412 static unsigned char *
413 get_vertical_data(Repodata *data, Repokey *key, Id off, Id len)
418 if (off >= data->lastverticaloffset)
420 off -= data->lastverticaloffset;
421 if (off + len > data->vincorelen)
423 return data->vincore + off;
425 if (off + len > key->size)
427 /* we now have the offset, go into vertical */
428 off += data->verticaloffset[key - data->keys];
429 /* fprintf(stderr, "key %d page %d\n", key->name, off / REPOPAGE_BLOBSIZE); */
430 dp = repopagestore_load_page_range(&data->store, off / REPOPAGE_BLOBSIZE, (off + len - 1) / REPOPAGE_BLOBSIZE);
432 dp += off % REPOPAGE_BLOBSIZE;
436 static inline unsigned char *
437 get_data(Repodata *data, Repokey *key, unsigned char **dpp, int advance)
439 unsigned char *dp = *dpp;
443 if (key->storage == KEY_STORAGE_INCORE)
446 *dpp = data_skip_key(data, dp, key);
449 else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
452 dp = data_read_id(dp, &off);
453 dp = data_read_id(dp, &len);
456 return get_vertical_data(data, key, off, len);
462 load_repodata(Repodata *data)
464 if (data->loadcallback)
466 data->loadcallback(data);
467 if (data->state == REPODATA_AVAILABLE)
470 data->state = REPODATA_ERROR;
475 maybe_load_repodata(Repodata *data, Id keyname)
477 if (keyname && !repodata_precheck_keyname(data, keyname))
478 return 0; /* do not bother... */
485 for (i = 1; i < data->nkeys; i++)
486 if (keyname == data->keys[i].name)
488 if (i == data->nkeys)
491 return load_repodata(data);
494 case REPODATA_AVAILABLE:
495 case REPODATA_LOADING:
498 data->state = REPODATA_ERROR;
503 static inline unsigned char *
504 solvid2data(Repodata *data, Id solvid, Id *schemap)
506 unsigned char *dp = data->incoredata;
509 if (solvid == SOLVID_META) /* META */
511 else if (solvid == SOLVID_POS) /* META */
513 Pool *pool = data->repo->pool;
514 if (data->repo != pool->pos.repo)
516 if (data != data->repo->repodata + pool->pos.repodataid)
518 *schemap = pool->pos.schema;
519 return data->incoredata + pool->pos.dp;
523 if (solvid < data->start || solvid >= data->end)
525 dp += data->incoreoffset[solvid - data->start];
527 return data_read_id(dp, schemap);
530 /************************************************************************
534 static inline unsigned char *
535 find_key_data(Repodata *data, Id solvid, Id keyname, Repokey **keypp)
538 Id schema, *keyp, *kp;
541 if (!maybe_load_repodata(data, keyname))
543 dp = solvid2data(data, solvid, &schema);
546 keyp = data->schemadata + data->schemata[schema];
547 for (kp = keyp; *kp; kp++)
548 if (data->keys[*kp].name == keyname)
552 *keypp = key = data->keys + *kp;
553 if (key->type == REPOKEY_TYPE_DELETED)
555 if (key->type == REPOKEY_TYPE_VOID || key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID)
556 return dp; /* no need to forward... */
557 dp = forward_to_key(data, *kp, keyp, dp);
560 return get_data(data, key, &dp, 0);
564 repodata_lookup_type(Repodata *data, Id solvid, Id keyname)
566 Id schema, *keyp, *kp;
567 if (!maybe_load_repodata(data, keyname))
569 if (!solvid2data(data, solvid, &schema))
571 keyp = data->schemadata + data->schemata[schema];
572 for (kp = keyp; *kp; kp++)
573 if (data->keys[*kp].name == keyname)
574 return data->keys[*kp].type;
579 repodata_lookup_id(Repodata *data, Id solvid, Id keyname)
585 dp = find_key_data(data, solvid, keyname, &key);
588 if (key->type == REPOKEY_TYPE_CONSTANTID)
590 if (key->type != REPOKEY_TYPE_ID)
592 dp = data_read_id(dp, &id);
597 repodata_lookup_str(Repodata *data, Id solvid, Id keyname)
603 dp = find_key_data(data, solvid, keyname, &key);
606 if (key->type == REPOKEY_TYPE_STR)
607 return (const char *)dp;
608 if (key->type == REPOKEY_TYPE_CONSTANTID)
610 else if (key->type == REPOKEY_TYPE_ID)
611 dp = data_read_id(dp, &id);
615 return stringpool_id2str(&data->spool, id);
616 return pool_id2str(data->repo->pool, id);
620 repodata_lookup_num(Repodata *data, Id solvid, Id keyname, unsigned int *value)
627 dp = find_key_data(data, solvid, keyname, &key);
630 if (key->type == REPOKEY_TYPE_NUM
631 || key->type == REPOKEY_TYPE_U32
632 || key->type == REPOKEY_TYPE_CONSTANT)
635 dp = data_fetch(dp, &kv, key);
643 repodata_lookup_void(Repodata *data, Id solvid, Id keyname)
649 if (!maybe_load_repodata(data, keyname))
651 dp = solvid2data(data, solvid, &schema);
654 /* can't use find_key_data as we need to test the type */
655 for (keyp = data->schemadata + data->schemata[schema]; *keyp; keyp++)
656 if (data->keys[*keyp].name == keyname && data->keys[*keyp].type == REPOKEY_TYPE_VOID)
661 const unsigned char *
662 repodata_lookup_bin_checksum(Repodata *data, Id solvid, Id keyname, Id *typep)
667 dp = find_key_data(data, solvid, keyname, &key);
675 repodata_lookup_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
683 dp = find_key_data(data, solvid, keyname, &key);
686 if (key->type != REPOKEY_TYPE_IDARRAY && key->type != REPOKEY_TYPE_REL_IDARRAY)
690 dp = data_read_ideof(dp, &id, &eof);
699 repodata_globalize_id(Repodata *data, Id id, int create)
701 if (!id || !data || !data->localpool)
703 return pool_str2id(data->repo->pool, stringpool_id2str(&data->spool, id), create);
707 repodata_localize_id(Repodata *data, Id id, int create)
709 if (!id || !data || !data->localpool)
711 return stringpool_str2id(&data->spool, pool_id2str(data->repo->pool, id), create);
715 repodata_lookup_id_uninternalized(Repodata *data, Id solvid, Id keyname, Id voidid)
720 ap = data->attrs[solvid - data->start];
725 if (data->keys[*ap].name != keyname)
727 if (data->keys[*ap].type == REPOKEY_TYPE_VOID)
729 if (data->keys[*ap].type == REPOKEY_TYPE_ID)
737 /************************************************************************
743 repodata_stringify(Pool *pool, Repodata *data, Repokey *key, KeyValue *kv, int flags)
747 case REPOKEY_TYPE_ID:
748 case REPOKEY_TYPE_CONSTANTID:
749 case REPOKEY_TYPE_IDARRAY:
750 if (data && data->localpool)
751 kv->str = stringpool_id2str(&data->spool, kv->id);
753 kv->str = pool_id2str(pool, kv->id);
754 if ((flags & SEARCH_SKIP_KIND) != 0 && key->storage == KEY_STORAGE_SOLVABLE)
757 for (s = kv->str; *s >= 'a' && *s <= 'z'; s++)
759 if (*s == ':' && s > kv->str)
763 case REPOKEY_TYPE_STR:
765 case REPOKEY_TYPE_DIRSTRARRAY:
766 if (!(flags & SEARCH_FILES))
767 return 1; /* match just the basename */
768 /* Put the full filename into kv->str. */
769 kv->str = repodata_dir2str(data, kv->id, kv->str);
770 /* And to compensate for that put the "empty" directory into
771 kv->id, so that later calls to repodata_dir2str on this data
772 come up with the same filename again. */
775 case REPOKEY_TYPE_MD5:
776 case REPOKEY_TYPE_SHA1:
777 case REPOKEY_TYPE_SHA256:
778 if (!(flags & SEARCH_CHECKSUMS))
779 return 0; /* skip em */
780 kv->str = repodata_chk2str(data, key->type, (const unsigned char *)kv->str);
788 struct subschema_data {
794 /* search a specific repodata */
796 repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata)
800 Id keyid, *kp, *keyp;
801 unsigned char *dp, *ddp;
807 if (!maybe_load_repodata(data, keyname))
809 if (solvid == SOLVID_SUBSCHEMA)
811 struct subschema_data *subd = cbdata;
812 cbdata = subd->cbdata;
814 schema = subd->parent->id;
815 dp = (unsigned char *)subd->parent->str;
816 kv.parent = subd->parent;
821 dp = solvid2data(data, solvid, &schema);
824 s = data->repo->pool->solvables + solvid;
827 keyp = data->schemadata + data->schemata[schema];
830 /* search for a specific key */
831 for (kp = keyp; *kp; kp++)
832 if (data->keys[*kp].name == keyname)
836 dp = forward_to_key(data, *kp, keyp, dp);
842 while ((keyid = *keyp++) != 0)
845 key = data->keys + keyid;
846 ddp = get_data(data, key, &dp, *keyp ? 1 : 0);
848 if (key->type == REPOKEY_TYPE_DELETED)
850 if (key->type == REPOKEY_TYPE_FLEXARRAY || key->type == REPOKEY_TYPE_FIXARRAY)
852 struct subschema_data subd;
856 subd.cbdata = cbdata;
859 ddp = data_read_id(ddp, &nentries);
863 while (ddp && nentries > 0)
867 if (key->type == REPOKEY_TYPE_FLEXARRAY || !kv.entry)
868 ddp = data_read_id(ddp, &schema);
870 kv.str = (char *)ddp;
871 stop = callback(cbdata, s, data, key, &kv);
872 if (stop > SEARCH_NEXT_KEY)
874 if (stop && stop != SEARCH_ENTERSUB)
876 if ((flags & SEARCH_SUB) != 0 || stop == SEARCH_ENTERSUB)
877 repodata_search(data, SOLVID_SUBSCHEMA, 0, flags, callback, &subd);
878 ddp = data_skip_schema(data, ddp, schema);
881 if (!nentries && (flags & SEARCH_ARRAYSENTINEL) != 0)
885 kv.str = (char *)ddp;
886 stop = callback(cbdata, s, data, key, &kv);
887 if (stop > SEARCH_NEXT_KEY)
897 ddp = data_fetch(ddp, &kv, key);
900 stop = callback(cbdata, s, data, key, &kv);
903 while (!kv.eof && !stop);
904 if (onekey || stop > SEARCH_NEXT_KEY)
910 repodata_setpos_kv(Repodata *data, KeyValue *kv)
912 Pool *pool = data->repo->pool;
914 pool_clear_pos(pool);
917 pool->pos.repo = data->repo;
918 pool->pos.repodataid = data - data->repo->repodata;
919 pool->pos.dp = (unsigned char *)kv->str - data->incoredata;
920 pool->pos.schema = kv->id;
924 /************************************************************************
925 * data iterator functions
928 static Repokey solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1] = {
929 { SOLVABLE_NAME, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
930 { SOLVABLE_ARCH, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
931 { SOLVABLE_EVR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
932 { SOLVABLE_VENDOR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
933 { SOLVABLE_PROVIDES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
934 { SOLVABLE_OBSOLETES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
935 { SOLVABLE_CONFLICTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
936 { SOLVABLE_REQUIRES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
937 { SOLVABLE_RECOMMENDS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
938 { SOLVABLE_SUGGESTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
939 { SOLVABLE_SUPPLEMENTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
940 { SOLVABLE_ENHANCES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
941 { RPM_RPMDBID, REPOKEY_TYPE_U32, 0, KEY_STORAGE_SOLVABLE },
945 solvabledata_fetch(Solvable *s, KeyValue *kv, Id keyname)
959 case SOLVABLE_VENDOR:
962 case SOLVABLE_PROVIDES:
964 return s->provides ? s->repo->idarraydata + s->provides : 0;
965 case SOLVABLE_OBSOLETES:
967 return s->obsoletes ? s->repo->idarraydata + s->obsoletes : 0;
968 case SOLVABLE_CONFLICTS:
970 return s->conflicts ? s->repo->idarraydata + s->conflicts : 0;
971 case SOLVABLE_REQUIRES:
973 return s->requires ? s->repo->idarraydata + s->requires : 0;
974 case SOLVABLE_RECOMMENDS:
976 return s->recommends ? s->repo->idarraydata + s->recommends : 0;
977 case SOLVABLE_SUPPLEMENTS:
979 return s->supplements ? s->repo->idarraydata + s->supplements : 0;
980 case SOLVABLE_SUGGESTS:
982 return s->suggests ? s->repo->idarraydata + s->suggests : 0;
983 case SOLVABLE_ENHANCES:
985 return s->enhances ? s->repo->idarraydata + s->enhances : 0;
988 return s->repo->rpmdbid ? s->repo->rpmdbid + (s - s->repo->pool->solvables - s->repo->start) : 0;
995 datamatcher_init(Datamatcher *ma, const char *match, int flags)
1001 if ((flags & SEARCH_STRINGMASK) == SEARCH_REGEX)
1003 ma->matchdata = solv_calloc(1, sizeof(regex_t));
1004 ma->error = regcomp((regex_t *)ma->matchdata, match, REG_EXTENDED | REG_NOSUB | REG_NEWLINE | ((flags & SEARCH_NOCASE) ? REG_ICASE : 0));
1007 solv_free(ma->matchdata);
1008 ma->flags = (flags & ~SEARCH_STRINGMASK) | SEARCH_ERROR;
1015 datamatcher_free(Datamatcher *ma)
1017 if ((ma->flags & SEARCH_STRINGMASK) == SEARCH_REGEX && ma->matchdata)
1019 regfree(ma->matchdata);
1020 ma->matchdata = solv_free(ma->matchdata);
1025 datamatcher_match(Datamatcher *ma, const char *str)
1028 switch ((ma->flags & SEARCH_STRINGMASK))
1030 case SEARCH_SUBSTRING:
1031 if (ma->flags & SEARCH_NOCASE)
1033 if (!strcasestr(str, ma->match))
1038 if (!strstr(str, ma->match))
1043 if (ma->flags & SEARCH_NOCASE)
1045 if (strcasecmp(ma->match, str))
1050 if (strcmp(ma->match, str))
1054 case SEARCH_STRINGSTART:
1055 if (ma->flags & SEARCH_NOCASE)
1057 if (strncasecmp(ma->match, str, strlen(ma->match)))
1062 if (strncmp(ma->match, str, strlen(ma->match)))
1066 case SEARCH_STRINGEND:
1067 l = strlen(str) - strlen(ma->match);
1070 if (ma->flags & SEARCH_NOCASE)
1072 if (strcasecmp(ma->match, str + l))
1077 if (strcmp(ma->match, str + l))
1082 if (fnmatch(ma->match, str, (ma->flags & SEARCH_NOCASE) ? FNM_CASEFOLD : 0))
1086 if (regexec((const regex_t *)ma->matchdata, str, 0, NULL, 0))
1096 repodata_filelistfilter_matches(Repodata *data, const char *str)
1098 /* '.*bin\/.*', '^\/etc\/.*', '^\/usr\/lib\/sendmail$' */
1099 /* for now hardcoded */
1100 if (strstr(str, "bin/"))
1102 if (!strncmp(str, "/etc/", 5))
1104 if (!strcmp(str, "/usr/lib/sendmail"))
1126 di_nextarrayelement,
1131 di_nextsolvableattr,
1136 /* see dataiterator.h for documentation */
1138 dataiterator_init(Dataiterator *di, Pool *pool, Repo *repo, Id p, Id keyname, const char *match, int flags)
1140 memset(di, 0, sizeof(*di));
1142 di->flags = flags & ~SEARCH_THISSOLVID;
1143 if (!pool || (repo && repo->pool != pool))
1151 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1157 di->keyname = keyname;
1158 di->keynames[0] = keyname;
1159 dataiterator_set_search(di, repo, p);
1164 dataiterator_init_clone(Dataiterator *di, Dataiterator *from)
1167 memset(&di->matcher, 0, sizeof(di->matcher));
1168 if (from->matcher.match)
1169 datamatcher_init(&di->matcher, from->matcher.match, from->matcher.flags);
1174 for (i = 1; i < di->nparents; i++)
1175 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1176 di->kv.parent = &di->parents[di->nparents - 1].kv;
1181 dataiterator_set_match(Dataiterator *di, const char *match, int flags)
1183 di->flags = (flags & ~SEARCH_THISSOLVID) | (di->flags & SEARCH_THISSOLVID);
1184 datamatcher_free(&di->matcher);
1185 memset(&di->matcher, 0, sizeof(di->matcher));
1189 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1199 dataiterator_set_search(Dataiterator *di, Repo *repo, Id p)
1203 di->flags &= ~SEARCH_THISSOLVID;
1207 if (!di->pool->urepos)
1215 di->repo = di->pool->repos[di->repoid];
1217 di->state = di_enterrepo;
1219 dataiterator_jump_to_solvid(di, p);
1223 dataiterator_set_keyname(Dataiterator *di, Id keyname)
1226 di->keyname = keyname;
1227 di->keynames[0] = keyname;
1231 dataiterator_prepend_keyname(Dataiterator *di, Id keyname)
1235 if (di->nkeynames >= sizeof(di->keynames)/sizeof(*di->keynames) - 2)
1237 di->state = di_bye; /* sorry */
1240 for (i = di->nkeynames + 1; i > 0; i--)
1241 di->keynames[i] = di->keynames[i - 1];
1242 di->keynames[0] = di->keyname = keyname;
1247 dataiterator_free(Dataiterator *di)
1249 if (di->matcher.match)
1250 datamatcher_free(&di->matcher);
1253 static inline unsigned char *
1254 dataiterator_find_keyname(Dataiterator *di, Id keyname)
1256 Id *keyp = di->keyp;
1257 Repokey *keys = di->data->keys;
1260 for (keyp = di->keyp; *keyp; keyp++)
1261 if (keys[*keyp].name == keyname)
1265 dp = forward_to_key(di->data, *keyp, di->keyp, di->dp);
1273 dataiterator_filelistcheck(Dataiterator *di)
1276 int needcomplete = 0;
1277 Repodata *data = di->data;
1279 if ((di->matcher.flags & SEARCH_COMPLETE_FILELIST) != 0)
1280 if (!di->matcher.match
1281 || ((di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_STRING
1282 && (di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_GLOB)
1283 || !repodata_filelistfilter_matches(di->data, di->matcher.match))
1285 if (data->state != REPODATA_AVAILABLE)
1286 return needcomplete ? 1 : 0;
1287 for (j = 1; j < data->nkeys; j++)
1288 if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
1290 return j == data->nkeys && !needcomplete ? 0 : 1;
1294 dataiterator_step(Dataiterator *di)
1302 case di_enterrepo: di_enterrepo:
1303 if (!di->repo || (di->repo->disabled && !(di->flags & SEARCH_DISABLED_REPOS)))
1305 if (!(di->flags & SEARCH_THISSOLVID))
1307 di->solvid = di->repo->start - 1; /* reset solvid iterator */
1308 goto di_nextsolvable;
1312 case di_entersolvable: di_entersolvable:
1315 di->repodataid = 1; /* reset repodata iterator */
1316 if (di->solvid > 0 && !(di->flags & SEARCH_NO_STORAGE_SOLVABLE) && (!di->keyname || (di->keyname >= SOLVABLE_NAME && di->keyname <= RPM_RPMDBID)) && di->nparents - di->rootlevel == di->nkeynames)
1318 di->key = solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0);
1320 goto di_entersolvablekey;
1325 case di_enterrepodata: di_enterrepodata:
1328 if (di->repodataid >= di->repo->nrepodata)
1329 goto di_nextsolvable;
1330 di->data = di->repo->repodata + di->repodataid;
1332 if (di->repodataid && di->keyname == SOLVABLE_FILELIST && !dataiterator_filelistcheck(di))
1333 goto di_nextrepodata;
1334 if (!maybe_load_repodata(di->data, di->keyname))
1335 goto di_nextrepodata;
1336 di->dp = solvid2data(di->data, di->solvid, &schema);
1338 goto di_nextrepodata;
1339 if (di->solvid == SOLVID_POS)
1340 di->solvid = di->pool->pos.solvid;
1341 /* reset key iterator */
1342 di->keyp = di->data->schemadata + di->data->schemata[schema];
1345 case di_enterschema: di_enterschema:
1347 di->dp = dataiterator_find_keyname(di, di->keyname);
1348 if (!di->dp || !*di->keyp)
1352 goto di_nextrepodata;
1356 case di_enterkey: di_enterkey:
1358 di->key = di->data->keys + *di->keyp;
1359 di->ddp = get_data(di->data, di->key, &di->dp, di->keyp[1] && (!di->keyname || (di->flags & SEARCH_SUB) != 0) ? 1 : 0);
1362 if (di->key->type == REPOKEY_TYPE_DELETED)
1364 if (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY)
1366 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1372 di->ddp = data_fetch(di->ddp, &di->kv, di->key);
1374 di->state = di_nextkey;
1376 di->state = di_nextattr;
1379 case di_nextkey: di_nextkey:
1380 if (!di->keyname && *++di->keyp)
1386 case di_nextrepodata: di_nextrepodata:
1387 if (di->repodataid && ++di->repodataid < di->repo->nrepodata)
1388 goto di_enterrepodata;
1391 case di_nextsolvable: di_nextsolvable:
1392 if (!(di->flags & SEARCH_THISSOLVID))
1395 di->solvid = di->repo->start;
1398 for (; di->solvid < di->repo->end; di->solvid++)
1400 if (di->pool->solvables[di->solvid].repo == di->repo)
1401 goto di_entersolvable;
1406 case di_nextrepo: di_nextrepo:
1411 if (di->repoid < di->pool->nrepos)
1413 di->repo = di->pool->repos[di->repoid];
1419 case di_bye: di_bye:
1423 case di_enterarray: di_enterarray:
1424 if (di->key->name == REPOSITORY_SOLVABLES)
1426 di->ddp = data_read_id(di->ddp, &di->kv.num);
1431 case di_nextarrayelement: di_nextarrayelement:
1434 di->ddp = data_skip_schema(di->data, di->ddp, di->kv.id);
1435 if (di->kv.entry == di->kv.num)
1437 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1439 if (!(di->flags & SEARCH_ARRAYSENTINEL))
1441 di->kv.str = (char *)di->ddp;
1443 di->state = di_nextkey;
1446 if (di->kv.entry == di->kv.num - 1)
1448 if (di->key->type == REPOKEY_TYPE_FLEXARRAY || !di->kv.entry)
1449 di->ddp = data_read_id(di->ddp, &di->kv.id);
1450 di->kv.str = (char *)di->ddp;
1451 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1453 if ((di->flags & SEARCH_SUB) != 0)
1454 di->state = di_entersub;
1456 di->state = di_nextarrayelement;
1459 case di_entersub: di_entersub:
1460 if (di->nparents == sizeof(di->parents)/sizeof(*di->parents) - 1)
1461 goto di_nextarrayelement; /* sorry, full */
1462 di->parents[di->nparents].kv = di->kv;
1463 di->parents[di->nparents].dp = di->dp;
1464 di->parents[di->nparents].keyp = di->keyp;
1465 di->dp = (unsigned char *)di->kv.str;
1466 di->keyp = di->data->schemadata + di->data->schemata[di->kv.id];
1467 memset(&di->kv, 0, sizeof(di->kv));
1468 di->kv.parent = &di->parents[di->nparents].kv;
1470 di->keyname = di->keynames[di->nparents - di->rootlevel];
1471 goto di_enterschema;
1473 case di_leavesub: di_leavesub:
1474 if (di->nparents - 1 < di->rootlevel)
1477 di->dp = di->parents[di->nparents].dp;
1478 di->kv = di->parents[di->nparents].kv;
1479 di->keyp = di->parents[di->nparents].keyp;
1480 di->key = di->data->keys + *di->keyp;
1481 di->ddp = (unsigned char *)di->kv.str;
1482 di->keyname = di->keynames[di->nparents - di->rootlevel];
1483 goto di_nextarrayelement;
1485 /* special solvable attr handling follows */
1487 case di_nextsolvableattr:
1488 di->kv.id = *di->idp++;
1493 di->state = di_nextsolvablekey;
1497 case di_nextsolvablekey: di_nextsolvablekey:
1498 if (di->keyname || di->key->name == RPM_RPMDBID)
1499 goto di_enterrepodata;
1503 case di_entersolvablekey: di_entersolvablekey:
1504 di->idp = solvabledata_fetch(di->pool->solvables + di->solvid, &di->kv, di->key->name);
1505 if (!di->idp || !di->idp[0])
1506 goto di_nextsolvablekey;
1507 di->kv.id = di->idp[0];
1508 di->kv.num = di->idp[0];
1510 if (!di->kv.eof && !di->idp[0])
1514 di->state = di_nextsolvablekey;
1516 di->state = di_nextsolvableattr;
1520 if (di->matcher.match)
1522 /* simple pre-check so that we don't need to stringify */
1523 if (di->keyname == SOLVABLE_FILELIST && di->key->type == REPOKEY_TYPE_DIRSTRARRAY && di->matcher.match && (di->matcher.flags & (SEARCH_FILES|SEARCH_NOCASE|SEARCH_STRINGMASK)) == (SEARCH_FILES|SEARCH_STRING))
1525 int l = strlen(di->matcher.match) - strlen(di->kv.str);
1526 if (l < 0 || strcmp(di->matcher.match + l, di->kv.str))
1529 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1531 if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY))
1535 if (!datamatcher_match(&di->matcher, di->kv.str))
1538 /* found something! */
1544 dataiterator_entersub(Dataiterator *di)
1546 if (di->state == di_nextarrayelement)
1547 di->state = di_entersub;
1551 dataiterator_setpos(Dataiterator *di)
1553 if (di->kv.eof == 2)
1555 pool_clear_pos(di->pool);
1558 di->pool->pos.solvid = di->solvid;
1559 di->pool->pos.repo = di->repo;
1560 di->pool->pos.repodataid = di->data - di->repo->repodata;
1561 di->pool->pos.schema = di->kv.id;
1562 di->pool->pos.dp = (unsigned char *)di->kv.str - di->data->incoredata;
1566 dataiterator_setpos_parent(Dataiterator *di)
1568 if (!di->kv.parent || di->kv.parent->eof == 2)
1570 pool_clear_pos(di->pool);
1573 di->pool->pos.solvid = di->solvid;
1574 di->pool->pos.repo = di->repo;
1575 di->pool->pos.repodataid = di->data - di->repo->repodata;
1576 di->pool->pos.schema = di->kv.parent->id;
1577 di->pool->pos.dp = (unsigned char *)di->kv.parent->str - di->data->incoredata;
1580 /* clones just the position, not the search keys/matcher */
1582 dataiterator_clonepos(Dataiterator *di, Dataiterator *from)
1584 di->state = from->state;
1585 di->flags &= ~SEARCH_THISSOLVID;
1586 di->flags |= (from->flags & SEARCH_THISSOLVID);
1587 di->repo = from->repo;
1588 di->data = from->data;
1590 di->ddp = from->ddp;
1591 di->idp = from->idp;
1592 di->keyp = from->keyp;
1593 di->key = from->key;
1595 di->repodataid = from->repodataid;
1596 di->solvid = from->solvid;
1597 di->repoid = from->repoid;
1598 di->rootlevel = from->rootlevel;
1599 memcpy(di->parents, from->parents, sizeof(from->parents));
1600 di->nparents = from->nparents;
1604 for (i = 1; i < di->nparents; i++)
1605 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1606 di->kv.parent = &di->parents[di->nparents - 1].kv;
1611 dataiterator_seek(Dataiterator *di, int whence)
1613 if ((whence & DI_SEEK_STAY) != 0)
1614 di->rootlevel = di->nparents;
1615 switch (whence & ~DI_SEEK_STAY)
1618 if (di->state != di_nextarrayelement)
1620 if ((whence & DI_SEEK_STAY) != 0)
1621 di->rootlevel = di->nparents + 1; /* XXX: dangerous! */
1622 di->state = di_entersub;
1624 case DI_SEEK_PARENT:
1631 if (di->rootlevel > di->nparents)
1632 di->rootlevel = di->nparents;
1633 di->dp = di->parents[di->nparents].dp;
1634 di->kv = di->parents[di->nparents].kv;
1635 di->keyp = di->parents[di->nparents].keyp;
1636 di->key = di->data->keys + *di->keyp;
1637 di->ddp = (unsigned char *)di->kv.str;
1638 di->keyname = di->keynames[di->nparents - di->rootlevel];
1639 di->state = di_nextarrayelement;
1641 case DI_SEEK_REWIND:
1647 di->dp = (unsigned char *)di->kv.parent->str;
1648 di->keyp = di->data->schemadata + di->data->schemata[di->kv.parent->id];
1649 di->state = di_enterschema;
1657 dataiterator_skip_attribute(Dataiterator *di)
1659 if (di->state == di_nextsolvableattr)
1660 di->state = di_nextsolvablekey;
1662 di->state = di_nextkey;
1666 dataiterator_skip_solvable(Dataiterator *di)
1671 di->keyname = di->keynames[0];
1672 di->state = di_nextsolvable;
1676 dataiterator_skip_repo(Dataiterator *di)
1681 di->keyname = di->keynames[0];
1682 di->state = di_nextrepo;
1686 dataiterator_jump_to_solvid(Dataiterator *di, Id solvid)
1691 di->keyname = di->keynames[0];
1692 if (solvid == SOLVID_POS)
1694 di->repo = di->pool->pos.repo;
1701 di->data = di->repo->repodata + di->pool->pos.repodataid;
1703 di->solvid = solvid;
1704 di->state = di_enterrepo;
1705 di->flags |= SEARCH_THISSOLVID;
1710 di->repo = di->pool->solvables[solvid].repo;
1713 else if (di->repoid > 0)
1715 if (!di->pool->urepos)
1721 di->repo = di->pool->repos[di->repoid];
1724 di->solvid = solvid;
1726 di->flags |= SEARCH_THISSOLVID;
1727 di->state = di_enterrepo;
1731 dataiterator_jump_to_repo(Dataiterator *di, Repo *repo)
1737 di->repoid = 0; /* 0 means stay at repo */
1740 di->flags &= ~SEARCH_THISSOLVID;
1741 di->state = di_enterrepo;
1745 dataiterator_match(Dataiterator *di, Datamatcher *ma)
1747 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1751 return datamatcher_match(ma, di->kv.str);
1754 /************************************************************************
1755 * data modify functions
1758 /* extend repodata so that it includes solvables p */
1760 repodata_extend(Repodata *data, Id p)
1762 if (data->start == data->end)
1763 data->start = data->end = p;
1766 int old = data->end - data->start;
1767 int new = p - data->end + 1;
1770 data->attrs = solv_extend(data->attrs, old, new, sizeof(Id *), REPODATA_BLOCK);
1771 memset(data->attrs + old, 0, new * sizeof(Id *));
1773 data->incoreoffset = solv_extend(data->incoreoffset, old, new, sizeof(Id), REPODATA_BLOCK);
1774 memset(data->incoreoffset + old, 0, new * sizeof(Id));
1777 if (p < data->start)
1779 int old = data->end - data->start;
1780 int new = data->start - p;
1783 data->attrs = solv_extend_resize(data->attrs, old + new, sizeof(Id *), REPODATA_BLOCK);
1784 memmove(data->attrs + new, data->attrs, old * sizeof(Id *));
1785 memset(data->attrs, 0, new * sizeof(Id *));
1787 data->incoreoffset = solv_extend_resize(data->incoreoffset, old + new, sizeof(Id), REPODATA_BLOCK);
1788 memmove(data->incoreoffset + new, data->incoreoffset, old * sizeof(Id));
1789 memset(data->incoreoffset, 0, new * sizeof(Id));
1794 /* shrink end of repodata */
1796 repodata_shrink(Repodata *data, int end)
1800 if (data->end <= end)
1802 if (data->start >= end)
1806 for (i = 0; i < data->end - data->start; i++)
1807 solv_free(data->attrs[i]);
1808 data->attrs = solv_free(data->attrs);
1810 data->incoreoffset = solv_free(data->incoreoffset);
1811 data->start = data->end = 0;
1816 for (i = end; i < data->end; i++)
1817 solv_free(data->attrs[i - data->start]);
1818 data->attrs = solv_extend_resize(data->attrs, end - data->start, sizeof(Id *), REPODATA_BLOCK);
1820 if (data->incoreoffset)
1821 data->incoreoffset = solv_extend_resize(data->incoreoffset, end - data->start, sizeof(Id), REPODATA_BLOCK);
1825 /* extend repodata so that it includes solvables from start to start + num - 1 */
1827 repodata_extend_block(Repodata *data, Id start, Id num)
1831 if (!data->incoreoffset)
1833 data->incoreoffset = solv_calloc_block(num, sizeof(Id), REPODATA_BLOCK);
1834 data->start = start;
1835 data->end = start + num;
1838 repodata_extend(data, start);
1840 repodata_extend(data, start + num - 1);
1843 /**********************************************************************/
1846 #define REPODATA_ATTRS_BLOCK 31
1847 #define REPODATA_ATTRDATA_BLOCK 1023
1848 #define REPODATA_ATTRIDDATA_BLOCK 63
1852 repodata_new_handle(Repodata *data)
1856 data->xattrs = solv_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1857 data->nxattrs = 2; /* -1: SOLVID_META */
1859 data->xattrs = solv_extend(data->xattrs, data->nxattrs, 1, sizeof(Id *), REPODATA_BLOCK);
1860 data->xattrs[data->nxattrs] = 0;
1861 return -(data->nxattrs++);
1865 repodata_get_attrp(Repodata *data, Id handle)
1869 if (handle == SOLVID_META && !data->xattrs)
1871 data->xattrs = solv_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1874 return data->xattrs - handle;
1876 if (handle < data->start || handle >= data->end)
1877 repodata_extend(data, handle);
1879 data->attrs = solv_calloc_block(data->end - data->start, sizeof(Id *), REPODATA_BLOCK);
1880 return data->attrs + (handle - data->start);
1884 repodata_insert_keyid(Repodata *data, Id handle, Id keyid, Id val, int overwrite)
1890 app = repodata_get_attrp(data, handle);
1895 /* Determine equality based on the name only, allows us to change
1896 type (when overwrite is set), and makes TYPE_CONSTANT work. */
1897 for (pp = ap; *pp; pp += 2)
1898 if (data->keys[*pp].name == data->keys[keyid].name)
1902 if (overwrite || data->keys[*pp].type == REPOKEY_TYPE_DELETED)
1911 ap = solv_extend(ap, i, 3, sizeof(Id), REPODATA_ATTRS_BLOCK);
1921 repodata_set(Repodata *data, Id solvid, Repokey *key, Id val)
1925 keyid = repodata_key2id(data, key, 1);
1926 repodata_insert_keyid(data, solvid, keyid, val, 1);
1930 repodata_set_id(Repodata *data, Id solvid, Id keyname, Id id)
1934 key.type = REPOKEY_TYPE_ID;
1936 key.storage = KEY_STORAGE_INCORE;
1937 repodata_set(data, solvid, &key, id);
1941 repodata_set_num(Repodata *data, Id solvid, Id keyname, unsigned int num)
1945 key.type = REPOKEY_TYPE_NUM;
1947 key.storage = KEY_STORAGE_INCORE;
1948 repodata_set(data, solvid, &key, (Id)num);
1952 repodata_set_poolstr(Repodata *data, Id solvid, Id keyname, const char *str)
1956 if (data->localpool)
1957 id = stringpool_str2id(&data->spool, str, 1);
1959 id = pool_str2id(data->repo->pool, str, 1);
1961 key.type = REPOKEY_TYPE_ID;
1963 key.storage = KEY_STORAGE_INCORE;
1964 repodata_set(data, solvid, &key, id);
1968 repodata_set_constant(Repodata *data, Id solvid, Id keyname, unsigned int constant)
1972 key.type = REPOKEY_TYPE_CONSTANT;
1973 key.size = constant;
1974 key.storage = KEY_STORAGE_INCORE;
1975 repodata_set(data, solvid, &key, 0);
1979 repodata_set_constantid(Repodata *data, Id solvid, Id keyname, Id id)
1983 key.type = REPOKEY_TYPE_CONSTANTID;
1985 key.storage = KEY_STORAGE_INCORE;
1986 repodata_set(data, solvid, &key, 0);
1990 repodata_set_void(Repodata *data, Id solvid, Id keyname)
1994 key.type = REPOKEY_TYPE_VOID;
1996 key.storage = KEY_STORAGE_INCORE;
1997 repodata_set(data, solvid, &key, 0);
2001 repodata_set_str(Repodata *data, Id solvid, Id keyname, const char *str)
2006 l = strlen(str) + 1;
2008 key.type = REPOKEY_TYPE_STR;
2010 key.storage = KEY_STORAGE_INCORE;
2011 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2012 memcpy(data->attrdata + data->attrdatalen, str, l);
2013 repodata_set(data, solvid, &key, data->attrdatalen);
2014 data->attrdatalen += l;
2018 repodata_set_binary(Repodata *data, Id solvid, Id keyname, void *buf, int len)
2024 key.type = REPOKEY_TYPE_BINARY;
2026 key.storage = KEY_STORAGE_INCORE;
2027 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, len + 5, 1, REPODATA_ATTRDATA_BLOCK);
2028 dp = data->attrdata + data->attrdatalen;
2029 if (len >= (1 << 14))
2031 if (len >= (1 << 28))
2032 *dp++ = (len >> 28) | 128;
2033 if (len >= (1 << 21))
2034 *dp++ = (len >> 21) | 128;
2035 *dp++ = (len >> 14) | 128;
2037 if (len >= (1 << 7))
2038 *dp++ = (len >> 7) | 128;
2041 memcpy(dp, buf, len);
2042 repodata_set(data, solvid, &key, data->attrdatalen);
2043 data->attrdatalen = dp + len - data->attrdata;
2046 /* add an array element consisting of entrysize Ids to the repodata. modifies attriddata
2047 * so that the caller can append entrysize new elements plus the termination zero there */
2049 repodata_add_array(Repodata *data, Id handle, Id keyname, Id keytype, int entrysize)
2052 Id *ida, *pp, **ppp;
2054 /* check if it is the same as last time, this speeds things up a lot */
2055 if (handle == data->lasthandle && data->keys[data->lastkey].name == keyname && data->keys[data->lastkey].type == keytype && data->attriddatalen == data->lastdatalen)
2057 /* great! just append the new data */
2058 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2059 data->attriddatalen--; /* overwrite terminating 0 */
2060 data->lastdatalen += entrysize;
2064 ppp = repodata_get_attrp(data, handle);
2068 for (; *pp; pp += 2)
2069 if (data->keys[*pp].name == keyname)
2072 if (!pp || !*pp || data->keys[*pp].type != keytype)
2074 /* not found. allocate new key */
2080 key.storage = KEY_STORAGE_INCORE;
2081 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2082 keyid = repodata_key2id(data, &key, 1);
2083 repodata_insert_keyid(data, handle, keyid, data->attriddatalen, 1);
2084 data->lasthandle = handle;
2085 data->lastkey = keyid;
2086 data->lastdatalen = data->attriddatalen + entrysize + 1;
2090 for (ida = data->attriddata + pp[1]; *ida; ida += entrysize)
2091 oldsize += entrysize;
2092 if (ida + 1 == data->attriddata + data->attriddatalen)
2094 /* this was the last entry, just append it */
2095 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2096 data->attriddatalen--; /* overwrite terminating 0 */
2100 /* too bad. move to back. */
2101 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, oldsize + entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2102 memcpy(data->attriddata + data->attriddatalen, data->attriddata + pp[1], oldsize * sizeof(Id));
2103 pp[1] = data->attriddatalen;
2104 data->attriddatalen += oldsize;
2106 data->lasthandle = handle;
2107 data->lastkey = *pp;
2108 data->lastdatalen = data->attriddatalen + entrysize + 1;
2112 repodata_set_bin_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2113 const unsigned char *str)
2118 if (!(l = solv_chksum_len(type)))
2123 key.storage = KEY_STORAGE_INCORE;
2124 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2125 memcpy(data->attrdata + data->attrdatalen, str, l);
2126 repodata_set(data, solvid, &key, data->attrdatalen);
2127 data->attrdatalen += l;
2131 repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2134 unsigned char buf[64];
2137 if (!(l = solv_chksum_len(type)))
2139 if (l > sizeof(buf) || solv_hex2bin(&str, buf, l) != l)
2141 repodata_set_bin_checksum(data, solvid, keyname, type, buf);
2145 repodata_chk2str(Repodata *data, Id type, const unsigned char *buf)
2149 if (!(l = solv_chksum_len(type)))
2151 return pool_bin2hex(data->repo->pool, buf, l);
2154 /* rpm filenames don't contain the epoch, so strip it */
2155 static inline const char *
2156 evrid2vrstr(Pool *pool, Id evrid)
2158 const char *p, *evr = pool_id2str(pool, evrid);
2161 for (p = evr; *p >= '0' && *p <= '9'; p++)
2163 return p != evr && *p == ':' ? p + 1 : evr;
2167 repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, const char *file)
2169 Pool *pool = data->repo->pool;
2171 const char *str, *fp;
2175 repodata_set_constant(data, solvid, SOLVABLE_MEDIANR, medianr);
2178 if ((dir = strrchr(file, '/')) != 0)
2189 if (l >= 2 && dir[0] == '.' && dir[1] == '/' && (l == 2 || dir[2] != '/'))
2194 if (l == 1 && dir[0] == '.')
2196 s = pool->solvables + solvid;
2199 str = pool_id2str(pool, s->arch);
2200 if (!strncmp(dir, str, l) && !str[l])
2201 repodata_set_void(data, solvid, SOLVABLE_MEDIADIR);
2203 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir);
2206 char *dir2 = solv_strdup(dir);
2208 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir2);
2213 str = pool_id2str(pool, s->name);
2215 if ((!l || !strncmp(fp, str, l)) && fp[l] == '-')
2218 str = evrid2vrstr(pool, s->evr);
2220 if ((!l || !strncmp(fp, str, l)) && fp[l] == '.')
2223 str = pool_id2str(pool, s->arch);
2225 if ((!l || !strncmp(fp, str, l)) && !strcmp(fp + l, ".rpm"))
2227 repodata_set_void(data, solvid, SOLVABLE_MEDIAFILE);
2232 repodata_set_str(data, solvid, SOLVABLE_MEDIAFILE, file);
2236 repodata_set_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
2242 key.type = REPOKEY_TYPE_IDARRAY;
2244 key.storage = KEY_STORAGE_INCORE;
2245 repodata_set(data, solvid, &key, data->attriddatalen);
2246 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, q->count + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2247 for (i = 0; i < q->count; i++)
2248 data->attriddata[data->attriddatalen++] = q->elements[i];
2249 data->attriddata[data->attriddatalen++] = 0;
2253 repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2)
2257 fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", solvid, dir, num, num2, data->attriddatalen);
2259 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRNUMNUMARRAY, 3);
2260 data->attriddata[data->attriddatalen++] = dir;
2261 data->attriddata[data->attriddatalen++] = num;
2262 data->attriddata[data->attriddatalen++] = num2;
2263 data->attriddata[data->attriddatalen++] = 0;
2267 repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str)
2273 l = strlen(str) + 1;
2274 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2275 memcpy(data->attrdata + data->attrdatalen, str, l);
2276 stroff = data->attrdatalen;
2277 data->attrdatalen += l;
2280 fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", solvid, dir, str, data->attriddatalen);
2282 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRSTRARRAY, 2);
2283 data->attriddata[data->attriddatalen++] = dir;
2284 data->attriddata[data->attriddatalen++] = stroff;
2285 data->attriddata[data->attriddatalen++] = 0;
2289 repodata_add_idarray(Repodata *data, Id solvid, Id keyname, Id id)
2292 fprintf(stderr, "repodata_add_idarray %d %d (%d)\n", solvid, id, data->attriddatalen);
2294 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_IDARRAY, 1);
2295 data->attriddata[data->attriddatalen++] = id;
2296 data->attriddata[data->attriddatalen++] = 0;
2300 repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname,
2304 if (data->localpool)
2305 id = stringpool_str2id(&data->spool, str, 1);
2307 id = pool_str2id(data->repo->pool, str, 1);
2308 repodata_add_idarray(data, solvid, keyname, id);
2312 repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2314 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FIXARRAY, 1);
2315 data->attriddata[data->attriddatalen++] = ghandle;
2316 data->attriddata[data->attriddatalen++] = 0;
2320 repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2322 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FLEXARRAY, 1);
2323 data->attriddata[data->attriddatalen++] = ghandle;
2324 data->attriddata[data->attriddatalen++] = 0;
2328 repodata_delete_uninternalized(Repodata *data, Id solvid, Id keyname)
2331 app = repodata_get_attrp(data, solvid);
2335 for (; *ap; ap += 2)
2336 if (data->keys[*ap].name == keyname)
2342 for (; *ap; ap += 2)
2344 if (data->keys[*ap].name == keyname)
2352 /* XXX: does not work correctly, needs fix in iterators! */
2354 repodata_delete(Repodata *data, Id solvid, Id keyname)
2358 key.type = REPOKEY_TYPE_DELETED;
2360 key.storage = KEY_STORAGE_INCORE;
2361 repodata_set(data, solvid, &key, 0);
2364 /* add all (uninternalized) attrs from src to dest */
2366 repodata_merge_attrs(Repodata *data, Id dest, Id src)
2369 if (dest == src || data->attrs || !(keyp = data->attrs[src - data->start]))
2371 for (; *keyp; keyp += 2)
2372 repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
2375 /* add some (uninternalized) attrs from src to dest */
2377 repodata_merge_some_attrs(Repodata *data, Id dest, Id src, Map *keyidmap, int overwrite)
2380 if (dest == src || !data->attrs || !(keyp = data->attrs[src - data->start]))
2382 for (; *keyp; keyp += 2)
2383 if (!keyidmap || MAPTST(keyidmap, keyp[0]))
2384 repodata_insert_keyid(data, dest, keyp[0], keyp[1], overwrite);
2387 /* swap (uninternalized) attrs from src and dest */
2389 repodata_swap_attrs(Repodata *data, Id dest, Id src)
2392 if (!data->attrs || dest == src)
2394 tmpattrs = data->attrs[dest - data->start];
2395 data->attrs[dest - data->start] = data->attrs[src - data->start];
2396 data->attrs[src - data->start] = tmpattrs;
2400 /**********************************************************************/
2402 /* TODO: unify with repo_write and repo_solv! */
2404 #define EXTDATA_BLOCK 1023
2412 data_addid(struct extdata *xd, Id x)
2416 xd->buf = solv_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
2417 dp = xd->buf + xd->len;
2422 *dp++ = (x >> 28) | 128;
2424 *dp++ = (x >> 21) | 128;
2425 *dp++ = (x >> 14) | 128;
2428 *dp++ = (x >> 7) | 128;
2430 xd->len = dp - xd->buf;
2434 data_addideof(struct extdata *xd, Id x, int eof)
2437 x = (x & 63) | ((x & ~63) << 1);
2438 data_addid(xd, (eof ? x : x | 64));
2442 data_addblob(struct extdata *xd, unsigned char *blob, int len)
2444 xd->buf = solv_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK);
2445 memcpy(xd->buf + xd->len, blob, len);
2449 /*********************************/
2451 /* internalalize some key into incore/vincore data */
2454 repodata_serialize_key(Repodata *data, struct extdata *newincore,
2455 struct extdata *newvincore,
2457 Repokey *key, Id val)
2461 unsigned int oldvincorelen = 0;
2465 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2468 oldvincorelen = xd->len;
2472 case REPOKEY_TYPE_VOID:
2473 case REPOKEY_TYPE_CONSTANT:
2474 case REPOKEY_TYPE_CONSTANTID:
2476 case REPOKEY_TYPE_STR:
2477 data_addblob(xd, data->attrdata + val, strlen((char *)(data->attrdata + val)) + 1);
2479 case REPOKEY_TYPE_MD5:
2480 data_addblob(xd, data->attrdata + val, SIZEOF_MD5);
2482 case REPOKEY_TYPE_SHA1:
2483 data_addblob(xd, data->attrdata + val, SIZEOF_SHA1);
2485 case REPOKEY_TYPE_SHA256:
2486 data_addblob(xd, data->attrdata + val, SIZEOF_SHA256);
2488 case REPOKEY_TYPE_ID:
2489 case REPOKEY_TYPE_NUM:
2490 case REPOKEY_TYPE_DIR:
2491 data_addid(xd, val);
2493 case REPOKEY_TYPE_BINARY:
2496 unsigned char *dp = data_read_id(data->attrdata + val, &len);
2498 data_addblob(xd, data->attrdata + val, dp - (data->attrdata + val));
2501 case REPOKEY_TYPE_IDARRAY:
2502 for (ida = data->attriddata + val; *ida; ida++)
2503 data_addideof(xd, ida[0], ida[1] ? 0 : 1);
2505 case REPOKEY_TYPE_DIRNUMNUMARRAY:
2506 for (ida = data->attriddata + val; *ida; ida += 3)
2508 data_addid(xd, ida[0]);
2509 data_addid(xd, ida[1]);
2510 data_addideof(xd, ida[2], ida[3] ? 0 : 1);
2513 case REPOKEY_TYPE_DIRSTRARRAY:
2514 for (ida = data->attriddata + val; *ida; ida += 2)
2516 data_addideof(xd, ida[0], ida[2] ? 0 : 1);
2517 data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
2520 case REPOKEY_TYPE_FIXARRAY:
2524 for (ida = data->attriddata + val; *ida; ida++)
2528 kp = data->xattrs[-*ida];
2536 schemaid = repodata_schema2id(data, schema, 1);
2537 else if (schemaid != repodata_schema2id(data, schema, 0))
2539 pool_debug(data->repo->pool, SOLV_FATAL, "fixarray substructs with different schemas\n");
2545 data_addid(xd, num);
2546 data_addid(xd, schemaid);
2547 for (ida = data->attriddata + val; *ida; ida++)
2549 Id *kp = data->xattrs[-*ida];
2553 repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
2557 case REPOKEY_TYPE_FLEXARRAY:
2560 for (ida = data->attriddata + val; *ida; ida++)
2562 data_addid(xd, num);
2563 for (ida = data->attriddata + val; *ida; ida++)
2565 Id *kp = data->xattrs[-*ida];
2568 data_addid(xd, 0); /* XXX */
2575 schemaid = repodata_schema2id(data, schema, 1);
2576 data_addid(xd, schemaid);
2577 kp = data->xattrs[-*ida];
2579 repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
2584 pool_debug(data->repo->pool, SOLV_FATAL, "don't know how to handle type %d\n", key->type);
2587 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2589 /* put offset/len in incore */
2590 data_addid(newincore, data->lastverticaloffset + oldvincorelen);
2591 oldvincorelen = xd->len - oldvincorelen;
2592 data_addid(newincore, oldvincorelen);
2597 repodata_internalize(Repodata *data)
2599 Repokey *key, solvkey;
2601 Id schemaid, *schema, *sp, oldschema, *keyp, *keypstart, *seen;
2602 unsigned char *dp, *ndp;
2603 int newschema, oldcount;
2604 struct extdata newincore;
2605 struct extdata newvincore;
2608 if (!data->attrs && !data->xattrs)
2611 newvincore.buf = data->vincore;
2612 newvincore.len = data->vincorelen;
2614 /* find the solvables key, create if needed */
2615 memset(&solvkey, 0, sizeof(solvkey));
2616 solvkey.name = REPOSITORY_SOLVABLES;
2617 solvkey.type = REPOKEY_TYPE_FLEXARRAY;
2619 solvkey.storage = KEY_STORAGE_INCORE;
2620 solvkeyid = repodata_key2id(data, &solvkey, data->end != data->start ? 1 : 0);
2622 schema = solv_malloc2(data->nkeys, sizeof(Id));
2623 seen = solv_malloc2(data->nkeys, sizeof(Id));
2625 /* Merge the data already existing (in data->schemata, ->incoredata and
2626 friends) with the new attributes in data->attrs[]. */
2627 nentry = data->end - data->start;
2628 memset(&newincore, 0, sizeof(newincore));
2629 data_addid(&newincore, 0); /* start data at offset 1 */
2631 data->mainschema = 0;
2632 data->mainschemaoffsets = solv_free(data->mainschemaoffsets);
2634 /* join entry data */
2635 /* we start with the meta data, entry -1 */
2636 for (entry = -1; entry < nentry; entry++)
2638 memset(seen, 0, data->nkeys * sizeof(Id));
2640 dp = data->incoredata;
2643 dp += entry >= 0 ? data->incoreoffset[entry] : 1;
2644 dp = data_read_id(dp, &oldschema);
2647 fprintf(stderr, "oldschema %d\n", oldschema);
2648 fprintf(stderr, "schemata %d\n", data->schemata[oldschema]);
2649 fprintf(stderr, "schemadata %p\n", data->schemadata);
2651 /* seen: -1: old data 0: skipped >0: id + 1 */
2655 for (keyp = data->schemadata + data->schemata[oldschema]; *keyp; keyp++)
2659 pool_debug(data->repo->pool, SOLV_FATAL, "Inconsistent old data (key occured twice).\n");
2667 keyp = data->attrs ? data->attrs[entry] : 0;
2670 /* strip solvables key */
2672 for (sp = keyp = schema; *sp; sp++)
2673 if (*sp != solvkeyid)
2678 seen[solvkeyid] = 0;
2679 keyp = data->xattrs ? data->xattrs[1] : 0;
2682 for (; *keyp; keyp += 2)
2689 seen[*keyp] = keyp[1] + 1;
2691 if (entry < 0 && data->end != data->start)
2698 /* Ideally we'd like to sort the new schema here, to ensure
2699 schema equality independend of the ordering. We can't do that
2700 yet. For once see below (old ids need to come before new ids).
2701 An additional difficulty is that we also need to move
2702 the values with the keys. */
2703 schemaid = repodata_schema2id(data, schema, 1);
2705 schemaid = oldschema;
2708 /* Now create data blob. We walk through the (possibly new) schema
2709 and either copy over old data, or insert the new. */
2710 /* XXX Here we rely on the fact that the (new) schema has the form
2711 o1 o2 o3 o4 ... | n1 n2 n3 ...
2712 (oX being the old keyids (possibly overwritten), and nX being
2713 the new keyids). This rules out sorting the keyids in order
2714 to ensure a small schema count. */
2716 data->incoreoffset[entry] = newincore.len;
2717 data_addid(&newincore, schemaid);
2720 data->mainschema = schemaid;
2721 data->mainschemaoffsets = solv_calloc(sp - schema, sizeof(Id));
2723 keypstart = data->schemadata + data->schemata[schemaid];
2724 for (keyp = keypstart; *keyp; keyp++)
2727 data->mainschemaoffsets[keyp - keypstart] = newincore.len;
2728 if (*keyp == solvkeyid)
2730 /* add flexarray entry count */
2731 data_addid(&newincore, data->end - data->start);
2734 key = data->keys + *keyp;
2736 fprintf(stderr, "internalize %d(%d):%s:%s\n", entry, entry + data->start, pool_id2str(data->repo->pool, key->name), pool_id2str(data->repo->pool, key->type));
2741 /* Skip the data associated with this old key. */
2742 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2744 ndp = data_skip(dp, REPOKEY_TYPE_ID);
2745 ndp = data_skip(ndp, REPOKEY_TYPE_ID);
2747 else if (key->storage == KEY_STORAGE_INCORE)
2748 ndp = data_skip_key(data, dp, key);
2751 if (seen[*keyp] == -1)
2753 /* If this key was an old one _and_ was not overwritten with
2754 a different value copy over the old value (we skipped it
2757 data_addblob(&newincore, dp, ndp - dp);
2760 else if (seen[*keyp])
2762 /* Otherwise we have a new value. Parse it into the internal
2764 repodata_serialize_key(data, &newincore, &newvincore,
2765 schema, key, seen[*keyp] - 1);
2769 if (entry >= 0 && data->attrs && data->attrs[entry])
2770 data->attrs[entry] = solv_free(data->attrs[entry]);
2772 /* free all xattrs */
2773 for (entry = 0; entry < data->nxattrs; entry++)
2774 if (data->xattrs[entry])
2775 solv_free(data->xattrs[entry]);
2776 data->xattrs = solv_free(data->xattrs);
2779 data->lasthandle = 0;
2781 data->lastdatalen = 0;
2784 repodata_free_schemahash(data);
2786 solv_free(data->incoredata);
2787 data->incoredata = newincore.buf;
2788 data->incoredatalen = newincore.len;
2789 data->incoredatafree = 0;
2791 solv_free(data->vincore);
2792 data->vincore = newvincore.buf;
2793 data->vincorelen = newvincore.len;
2795 data->attrs = solv_free(data->attrs);
2796 data->attrdata = solv_free(data->attrdata);
2797 data->attriddata = solv_free(data->attriddata);
2798 data->attrdatalen = 0;
2799 data->attriddatalen = 0;
2803 repodata_disable_paging(Repodata *data)
2805 if (maybe_load_repodata(data, 0))
2806 repopagestore_disable_paging(&data->store);
2810 repodata_load_stub(Repodata *data)
2812 Repo *repo = data->repo;
2813 Pool *pool = repo->pool;
2815 struct _Pool_tmpspace oldtmpspace;
2817 if (!pool->loadcallback)
2819 data->state = REPODATA_ERROR;
2822 data->state = REPODATA_LOADING;
2824 /* save tmp space */
2825 oldtmpspace = pool->tmpspace;
2826 memset(&pool->tmpspace, 0, sizeof(pool->tmpspace));
2828 r = pool->loadcallback(pool, data, pool->loadcallbackdata);
2830 /* restore tmp space */
2831 for (i = 0; i < POOL_TMPSPACEBUF; i++)
2832 solv_free(pool->tmpspace.buf[i]);
2833 pool->tmpspace = oldtmpspace;
2835 data->state = r ? REPODATA_AVAILABLE : REPODATA_ERROR;
2839 repodata_create_stubs(Repodata *data)
2841 Repo *repo = data->repo;
2842 Pool *pool = repo->pool;
2849 int datastart, dataend;
2851 repodataid = data - repo->repodata;
2852 datastart = data->start;
2853 dataend = data->end;
2854 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2855 while (dataiterator_step(&di))
2857 if (di.data - repo->repodata != repodataid)
2861 dataiterator_free(&di);
2864 stubdataids = solv_calloc(cnt, sizeof(*stubdataids));
2865 for (i = 0; i < cnt; i++)
2867 sdata = repo_add_repodata(repo, 0);
2868 if (dataend > datastart)
2869 repodata_extend_block(sdata, datastart, dataend - datastart);
2870 stubdataids[i] = sdata - repo->repodata;
2871 sdata->state = REPODATA_STUB;
2872 sdata->loadcallback = repodata_load_stub;
2875 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2877 while (dataiterator_step(&di))
2879 if (di.data - repo->repodata != repodataid)
2881 if (di.key->name == REPOSITORY_EXTERNAL && !di.nparents)
2883 dataiterator_entersub(&di);
2884 sdata = repo->repodata + stubdataids[i++];
2888 switch (di.key->type)
2890 case REPOKEY_TYPE_ID:
2891 repodata_set_id(sdata, SOLVID_META, di.key->name, di.kv.id);
2893 case REPOKEY_TYPE_CONSTANTID:
2894 repodata_set_constantid(sdata, SOLVID_META, di.key->name, di.kv.id);
2896 case REPOKEY_TYPE_STR:
2897 repodata_set_str(sdata, SOLVID_META, di.key->name, di.kv.str);
2899 case REPOKEY_TYPE_VOID:
2900 repodata_set_void(sdata, SOLVID_META, di.key->name);
2902 case REPOKEY_TYPE_NUM:
2903 repodata_set_num(sdata, SOLVID_META, di.key->name, di.kv.num);
2905 case REPOKEY_TYPE_MD5:
2906 case REPOKEY_TYPE_SHA1:
2907 case REPOKEY_TYPE_SHA256:
2908 repodata_set_bin_checksum(sdata, SOLVID_META, di.key->name, di.key->type, (const unsigned char *)di.kv.str);
2910 case REPOKEY_TYPE_IDARRAY:
2911 repodata_add_idarray(sdata, SOLVID_META, di.key->name, di.kv.id);
2912 if (di.key->name == REPOSITORY_KEYS)
2919 xkeyname = di.kv.id;
2922 xkey.name = xkeyname;
2923 xkey.type = di.kv.id;
2924 xkey.storage = KEY_STORAGE_INCORE;
2926 repodata_key2id(sdata, &xkey, 1);
2933 dataiterator_free(&di);
2934 for (i = 0; i < cnt; i++)
2935 repodata_internalize(repo->repodata + stubdataids[i]);
2936 solv_free(stubdataids);
2940 repodata_memused(Repodata *data)
2942 return data->incoredatalen + data->vincorelen;
2946 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: