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);
95 solv_free(data->dircache);
99 repodata_free(Repodata *data)
101 Repo *repo = data->repo;
102 int i = data - repo->repodata;
105 repodata_freedata(data);
106 if (i < repo->nrepodata - 1)
108 /* whoa! this changes the repodataids! */
109 memmove(repo->repodata + i, repo->repodata + i + 1, (repo->nrepodata - 1 - i) * sizeof(Repodata));
110 for (; i < repo->nrepodata - 1; i++)
111 repo->repodata[i].repodataid = i;
114 if (repo->nrepodata == 1)
116 repo->repodata = solv_free(repo->repodata);
122 repodata_empty(Repodata *data, int localpool)
124 void (*loadcallback)(Repodata *) = data->loadcallback;
125 int state = data->state;
126 repodata_freedata(data);
127 repodata_initdata(data, data->repo, localpool);
129 data->loadcallback = loadcallback;
133 /***************************************************************
134 * key pool management
137 /* this is not so time critical that we need a hash, so we do a simple
140 repodata_key2id(Repodata *data, Repokey *key, int create)
144 for (keyid = 1; keyid < data->nkeys; keyid++)
145 if (data->keys[keyid].name == key->name && data->keys[keyid].type == key->type)
147 if ((key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID) && key->size != data->keys[keyid].size)
151 if (keyid == data->nkeys)
155 /* allocate new key */
156 data->keys = solv_realloc2(data->keys, data->nkeys + 1, sizeof(Repokey));
157 data->keys[data->nkeys++] = *key;
158 if (data->verticaloffset)
160 data->verticaloffset = solv_realloc2(data->verticaloffset, data->nkeys, sizeof(Id));
161 data->verticaloffset[data->nkeys - 1] = 0;
163 data->keybits[(key->name >> 3) & (sizeof(data->keybits) - 1)] |= 1 << (key->name & 7);
169 /***************************************************************
170 * schema pool management
173 #define SCHEMATA_BLOCK 31
174 #define SCHEMATADATA_BLOCK 255
177 repodata_schema2id(Repodata *data, Id *schema, int create)
184 return 0; /* XXX: allow empty schema? */
185 if ((schematahash = data->schematahash) == 0)
187 data->schematahash = schematahash = solv_calloc(256, sizeof(Id));
188 for (i = 1; i < data->nschemata; i++)
190 for (sp = data->schemadata + data->schemata[i], h = 0; *sp; len++)
195 data->schemadata = solv_extend_resize(data->schemadata, data->schemadatalen, sizeof(Id), SCHEMATADATA_BLOCK);
196 data->schemata = solv_extend_resize(data->schemata, data->nschemata, sizeof(Id), SCHEMATA_BLOCK);
199 for (sp = schema, len = 0, h = 0; *sp; len++)
204 cid = schematahash[h];
207 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
209 /* cache conflict, do a slow search */
210 for (cid = 1; cid < data->nschemata; cid++)
211 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
217 data->schemadata = solv_extend(data->schemadata, data->schemadatalen, len, sizeof(Id), SCHEMATADATA_BLOCK);
218 data->schemata = solv_extend(data->schemata, data->nschemata, 1, sizeof(Id), SCHEMATA_BLOCK);
220 memcpy(data->schemadata + data->schemadatalen, schema, len * sizeof(Id));
221 data->schemata[data->nschemata] = data->schemadatalen;
222 data->schemadatalen += len;
223 schematahash[h] = data->nschemata;
225 fprintf(stderr, "schema2id: new schema\n");
227 return data->nschemata++;
231 repodata_free_schemahash(Repodata *data)
233 data->schematahash = solv_free(data->schematahash);
235 data->schemata = solv_realloc2(data->schemata, data->nschemata, sizeof(Id));
236 data->schemadata = solv_realloc2(data->schemadata, data->schemadatalen, sizeof(Id));
240 /***************************************************************
241 * dir pool management
244 #ifndef HAVE_STRCHRNUL
245 static inline const char *strchrnul(const char *str, char x)
247 const char *p = strchr(str, x);
248 return p ? p : str + strlen(str);
252 #define DIRCACHE_SIZE 41 /* < 1k */
256 Id ids[DIRCACHE_SIZE];
257 char str[(DIRCACHE_SIZE * (DIRCACHE_SIZE - 1)) / 2];
262 repodata_str2dir(Repodata *data, const char *dir, int create)
273 while (*dir == '/' && dir[1] == '/')
275 if (*dir == '/' && !dir[1])
277 if (data->dirpool.ndirs)
279 return dirpool_add_dir(&data->dirpool, 0, 1, create);
286 struct dircache *dircache = data->dircache;
290 if (l < DIRCACHE_SIZE && dircache->ids[l] && !memcmp(dircache->str + l * (l - 1) / 2, dir, l))
292 parent = dircache->ids[l];
308 dire = strchrnul(dir, '/');
310 id = stringpool_strn2id(&data->spool, dir, dire - dir, create);
312 id = pool_strn2id(data->repo->pool, dir, dire - dir, create);
315 parent = dirpool_add_dir(&data->dirpool, parent, id, create);
320 data->dircache = solv_calloc(1, sizeof(struct dircache));
324 if (l < DIRCACHE_SIZE)
326 data->dircache->ids[l] = parent;
327 memcpy(data->dircache->str + l * (l - 1) / 2, dirs, l);
341 repodata_free_dircache(Repodata *data)
343 data->dircache = solv_free(data->dircache);
347 repodata_dir2str(Repodata *data, Id did, const char *suf)
349 Pool *pool = data->repo->pool;
356 return suf ? suf : "";
360 comp = dirpool_compid(&data->dirpool, parent);
361 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
363 parent = dirpool_parent(&data->dirpool, parent);
368 l += strlen(suf) + 1;
369 p = pool_alloctmpspace(pool, l + 1) + l;
380 comp = dirpool_compid(&data->dirpool, parent);
381 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
384 strncpy(p, comps, l);
385 parent = dirpool_parent(&data->dirpool, parent);
393 /***************************************************************
397 static inline unsigned char *
398 data_skip_schema(Repodata *data, unsigned char *dp, Id schema)
400 Id *keyp = data->schemadata + data->schemata[schema];
401 for (; *keyp; keyp++)
402 dp = data_skip_key(data, dp, data->keys + *keyp);
406 static unsigned char *
407 data_skip_key(Repodata *data, unsigned char *dp, Repokey *key)
409 int nentries, schema;
412 case REPOKEY_TYPE_FIXARRAY:
413 dp = data_read_id(dp, &nentries);
416 dp = data_read_id(dp, &schema);
418 dp = data_skip_schema(data, dp, schema);
420 case REPOKEY_TYPE_FLEXARRAY:
421 dp = data_read_id(dp, &nentries);
424 dp = data_read_id(dp, &schema);
425 dp = data_skip_schema(data, dp, schema);
429 if (key->storage == KEY_STORAGE_INCORE)
430 dp = data_skip(dp, key->type);
431 else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
433 dp = data_skip(dp, REPOKEY_TYPE_ID);
434 dp = data_skip(dp, REPOKEY_TYPE_ID);
440 static unsigned char *
441 forward_to_key(Repodata *data, Id keyid, Id *keyp, unsigned char *dp)
447 if (data->mainschemaoffsets && dp == data->incoredata + data->mainschemaoffsets[0] && keyp == data->schemadata + data->schemata[data->mainschema])
450 for (i = 0; (k = *keyp++) != 0; i++)
452 return data->incoredata + data->mainschemaoffsets[i];
455 while ((k = *keyp++) != 0)
459 if (data->keys[k].storage == KEY_STORAGE_VERTICAL_OFFSET)
461 dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip offset */
462 dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip length */
465 if (data->keys[k].storage != KEY_STORAGE_INCORE)
467 dp = data_skip_key(data, dp, data->keys + k);
472 static unsigned char *
473 get_vertical_data(Repodata *data, Repokey *key, Id off, Id len)
478 if (off >= data->lastverticaloffset)
480 off -= data->lastverticaloffset;
481 if (off + len > data->vincorelen)
483 return data->vincore + off;
485 if (off + len > key->size)
487 /* we now have the offset, go into vertical */
488 off += data->verticaloffset[key - data->keys];
489 /* fprintf(stderr, "key %d page %d\n", key->name, off / REPOPAGE_BLOBSIZE); */
490 dp = repopagestore_load_page_range(&data->store, off / REPOPAGE_BLOBSIZE, (off + len - 1) / REPOPAGE_BLOBSIZE);
492 dp += off % REPOPAGE_BLOBSIZE;
496 static inline unsigned char *
497 get_data(Repodata *data, Repokey *key, unsigned char **dpp, int advance)
499 unsigned char *dp = *dpp;
503 if (key->storage == KEY_STORAGE_INCORE)
506 *dpp = data_skip_key(data, dp, key);
509 else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
512 dp = data_read_id(dp, &off);
513 dp = data_read_id(dp, &len);
516 return get_vertical_data(data, key, off, len);
522 load_repodata(Repodata *data)
524 if (data->loadcallback)
526 data->loadcallback(data);
527 if (data->state == REPODATA_AVAILABLE)
530 data->state = REPODATA_ERROR;
535 maybe_load_repodata(Repodata *data, Id keyname)
537 if (keyname && !repodata_precheck_keyname(data, keyname))
538 return 0; /* do not bother... */
545 for (i = 1; i < data->nkeys; i++)
546 if (keyname == data->keys[i].name)
548 if (i == data->nkeys)
551 return load_repodata(data);
554 case REPODATA_AVAILABLE:
555 case REPODATA_LOADING:
558 data->state = REPODATA_ERROR;
563 static inline unsigned char *
564 solvid2data(Repodata *data, Id solvid, Id *schemap)
566 unsigned char *dp = data->incoredata;
569 if (solvid == SOLVID_META) /* META */
571 else if (solvid == SOLVID_POS) /* META */
573 Pool *pool = data->repo->pool;
574 if (data->repo != pool->pos.repo)
576 if (data != data->repo->repodata + pool->pos.repodataid)
578 *schemap = pool->pos.schema;
579 return data->incoredata + pool->pos.dp;
583 if (solvid < data->start || solvid >= data->end)
585 dp += data->incoreoffset[solvid - data->start];
587 return data_read_id(dp, schemap);
590 /************************************************************************
594 static inline unsigned char *
595 find_key_data(Repodata *data, Id solvid, Id keyname, Repokey **keypp)
598 Id schema, *keyp, *kp;
601 if (!maybe_load_repodata(data, keyname))
603 dp = solvid2data(data, solvid, &schema);
606 keyp = data->schemadata + data->schemata[schema];
607 for (kp = keyp; *kp; kp++)
608 if (data->keys[*kp].name == keyname)
612 *keypp = key = data->keys + *kp;
613 if (key->type == REPOKEY_TYPE_DELETED)
615 if (key->type == REPOKEY_TYPE_VOID || key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID)
616 return dp; /* no need to forward... */
617 dp = forward_to_key(data, *kp, keyp, dp);
620 return get_data(data, key, &dp, 0);
624 repodata_lookup_type(Repodata *data, Id solvid, Id keyname)
626 Id schema, *keyp, *kp;
627 if (!maybe_load_repodata(data, keyname))
629 if (!solvid2data(data, solvid, &schema))
631 keyp = data->schemadata + data->schemata[schema];
632 for (kp = keyp; *kp; kp++)
633 if (data->keys[*kp].name == keyname)
634 return data->keys[*kp].type;
639 repodata_lookup_id(Repodata *data, Id solvid, Id keyname)
645 dp = find_key_data(data, solvid, keyname, &key);
648 if (key->type == REPOKEY_TYPE_CONSTANTID)
650 if (key->type != REPOKEY_TYPE_ID)
652 dp = data_read_id(dp, &id);
657 repodata_lookup_str(Repodata *data, Id solvid, Id keyname)
663 dp = find_key_data(data, solvid, keyname, &key);
666 if (key->type == REPOKEY_TYPE_STR)
667 return (const char *)dp;
668 if (key->type == REPOKEY_TYPE_CONSTANTID)
670 else if (key->type == REPOKEY_TYPE_ID)
671 dp = data_read_id(dp, &id);
675 return stringpool_id2str(&data->spool, id);
676 return pool_id2str(data->repo->pool, id);
680 repodata_lookup_num(Repodata *data, Id solvid, Id keyname, unsigned int *value)
687 dp = find_key_data(data, solvid, keyname, &key);
690 if (key->type == REPOKEY_TYPE_NUM
691 || key->type == REPOKEY_TYPE_U32
692 || key->type == REPOKEY_TYPE_CONSTANT)
695 dp = data_fetch(dp, &kv, key);
703 repodata_lookup_void(Repodata *data, Id solvid, Id keyname)
709 if (!maybe_load_repodata(data, keyname))
711 dp = solvid2data(data, solvid, &schema);
714 /* can't use find_key_data as we need to test the type */
715 for (keyp = data->schemadata + data->schemata[schema]; *keyp; keyp++)
716 if (data->keys[*keyp].name == keyname && data->keys[*keyp].type == REPOKEY_TYPE_VOID)
721 const unsigned char *
722 repodata_lookup_bin_checksum(Repodata *data, Id solvid, Id keyname, Id *typep)
727 dp = find_key_data(data, solvid, keyname, &key);
735 repodata_lookup_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
743 dp = find_key_data(data, solvid, keyname, &key);
746 if (key->type != REPOKEY_TYPE_IDARRAY && key->type != REPOKEY_TYPE_REL_IDARRAY)
750 dp = data_read_ideof(dp, &id, &eof);
759 repodata_globalize_id(Repodata *data, Id id, int create)
761 if (!id || !data || !data->localpool)
763 return pool_str2id(data->repo->pool, stringpool_id2str(&data->spool, id), create);
767 repodata_localize_id(Repodata *data, Id id, int create)
769 if (!id || !data || !data->localpool)
771 return stringpool_str2id(&data->spool, pool_id2str(data->repo->pool, id), create);
775 repodata_lookup_id_uninternalized(Repodata *data, Id solvid, Id keyname, Id voidid)
780 ap = data->attrs[solvid - data->start];
785 if (data->keys[*ap].name != keyname)
787 if (data->keys[*ap].type == REPOKEY_TYPE_VOID)
789 if (data->keys[*ap].type == REPOKEY_TYPE_ID)
797 /************************************************************************
803 repodata_stringify(Pool *pool, Repodata *data, Repokey *key, KeyValue *kv, int flags)
807 case REPOKEY_TYPE_ID:
808 case REPOKEY_TYPE_CONSTANTID:
809 case REPOKEY_TYPE_IDARRAY:
810 if (data && data->localpool)
811 kv->str = stringpool_id2str(&data->spool, kv->id);
813 kv->str = pool_id2str(pool, kv->id);
814 if ((flags & SEARCH_SKIP_KIND) != 0 && key->storage == KEY_STORAGE_SOLVABLE)
817 for (s = kv->str; *s >= 'a' && *s <= 'z'; s++)
819 if (*s == ':' && s > kv->str)
823 case REPOKEY_TYPE_STR:
825 case REPOKEY_TYPE_DIRSTRARRAY:
826 if (!(flags & SEARCH_FILES))
827 return 1; /* match just the basename */
828 /* Put the full filename into kv->str. */
829 kv->str = repodata_dir2str(data, kv->id, kv->str);
830 /* And to compensate for that put the "empty" directory into
831 kv->id, so that later calls to repodata_dir2str on this data
832 come up with the same filename again. */
835 case REPOKEY_TYPE_MD5:
836 case REPOKEY_TYPE_SHA1:
837 case REPOKEY_TYPE_SHA256:
838 if (!(flags & SEARCH_CHECKSUMS))
839 return 0; /* skip em */
840 kv->str = repodata_chk2str(data, key->type, (const unsigned char *)kv->str);
848 struct subschema_data {
854 /* search a specific repodata */
856 repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata)
860 Id keyid, *kp, *keyp;
861 unsigned char *dp, *ddp;
867 if (!maybe_load_repodata(data, keyname))
869 if (solvid == SOLVID_SUBSCHEMA)
871 struct subschema_data *subd = cbdata;
872 cbdata = subd->cbdata;
874 schema = subd->parent->id;
875 dp = (unsigned char *)subd->parent->str;
876 kv.parent = subd->parent;
881 dp = solvid2data(data, solvid, &schema);
884 s = data->repo->pool->solvables + solvid;
887 keyp = data->schemadata + data->schemata[schema];
890 /* search for a specific key */
891 for (kp = keyp; *kp; kp++)
892 if (data->keys[*kp].name == keyname)
896 dp = forward_to_key(data, *kp, keyp, dp);
902 while ((keyid = *keyp++) != 0)
905 key = data->keys + keyid;
906 ddp = get_data(data, key, &dp, *keyp ? 1 : 0);
908 if (key->type == REPOKEY_TYPE_DELETED)
910 if (key->type == REPOKEY_TYPE_FLEXARRAY || key->type == REPOKEY_TYPE_FIXARRAY)
912 struct subschema_data subd;
916 subd.cbdata = cbdata;
919 ddp = data_read_id(ddp, &nentries);
923 while (ddp && nentries > 0)
927 if (key->type == REPOKEY_TYPE_FLEXARRAY || !kv.entry)
928 ddp = data_read_id(ddp, &schema);
930 kv.str = (char *)ddp;
931 stop = callback(cbdata, s, data, key, &kv);
932 if (stop > SEARCH_NEXT_KEY)
934 if (stop && stop != SEARCH_ENTERSUB)
936 if ((flags & SEARCH_SUB) != 0 || stop == SEARCH_ENTERSUB)
937 repodata_search(data, SOLVID_SUBSCHEMA, 0, flags, callback, &subd);
938 ddp = data_skip_schema(data, ddp, schema);
941 if (!nentries && (flags & SEARCH_ARRAYSENTINEL) != 0)
945 kv.str = (char *)ddp;
946 stop = callback(cbdata, s, data, key, &kv);
947 if (stop > SEARCH_NEXT_KEY)
957 ddp = data_fetch(ddp, &kv, key);
960 stop = callback(cbdata, s, data, key, &kv);
963 while (!kv.eof && !stop);
964 if (onekey || stop > SEARCH_NEXT_KEY)
970 repodata_setpos_kv(Repodata *data, KeyValue *kv)
972 Pool *pool = data->repo->pool;
974 pool_clear_pos(pool);
977 pool->pos.repo = data->repo;
978 pool->pos.repodataid = data - data->repo->repodata;
979 pool->pos.dp = (unsigned char *)kv->str - data->incoredata;
980 pool->pos.schema = kv->id;
984 /************************************************************************
985 * data iterator functions
988 static Repokey solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1] = {
989 { SOLVABLE_NAME, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
990 { SOLVABLE_ARCH, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
991 { SOLVABLE_EVR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
992 { SOLVABLE_VENDOR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
993 { SOLVABLE_PROVIDES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
994 { SOLVABLE_OBSOLETES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
995 { SOLVABLE_CONFLICTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
996 { SOLVABLE_REQUIRES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
997 { SOLVABLE_RECOMMENDS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
998 { SOLVABLE_SUGGESTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
999 { SOLVABLE_SUPPLEMENTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
1000 { SOLVABLE_ENHANCES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
1001 { RPM_RPMDBID, REPOKEY_TYPE_U32, 0, KEY_STORAGE_SOLVABLE },
1005 solvabledata_fetch(Solvable *s, KeyValue *kv, Id keyname)
1019 case SOLVABLE_VENDOR:
1022 case SOLVABLE_PROVIDES:
1024 return s->provides ? s->repo->idarraydata + s->provides : 0;
1025 case SOLVABLE_OBSOLETES:
1027 return s->obsoletes ? s->repo->idarraydata + s->obsoletes : 0;
1028 case SOLVABLE_CONFLICTS:
1030 return s->conflicts ? s->repo->idarraydata + s->conflicts : 0;
1031 case SOLVABLE_REQUIRES:
1033 return s->requires ? s->repo->idarraydata + s->requires : 0;
1034 case SOLVABLE_RECOMMENDS:
1036 return s->recommends ? s->repo->idarraydata + s->recommends : 0;
1037 case SOLVABLE_SUPPLEMENTS:
1039 return s->supplements ? s->repo->idarraydata + s->supplements : 0;
1040 case SOLVABLE_SUGGESTS:
1042 return s->suggests ? s->repo->idarraydata + s->suggests : 0;
1043 case SOLVABLE_ENHANCES:
1045 return s->enhances ? s->repo->idarraydata + s->enhances : 0;
1048 return s->repo->rpmdbid ? s->repo->rpmdbid + (s - s->repo->pool->solvables - s->repo->start) : 0;
1055 datamatcher_init(Datamatcher *ma, const char *match, int flags)
1061 if ((flags & SEARCH_STRINGMASK) == SEARCH_REGEX)
1063 ma->matchdata = solv_calloc(1, sizeof(regex_t));
1064 ma->error = regcomp((regex_t *)ma->matchdata, match, REG_EXTENDED | REG_NOSUB | REG_NEWLINE | ((flags & SEARCH_NOCASE) ? REG_ICASE : 0));
1067 solv_free(ma->matchdata);
1068 ma->flags = (flags & ~SEARCH_STRINGMASK) | SEARCH_ERROR;
1075 datamatcher_free(Datamatcher *ma)
1077 if ((ma->flags & SEARCH_STRINGMASK) == SEARCH_REGEX && ma->matchdata)
1079 regfree(ma->matchdata);
1080 ma->matchdata = solv_free(ma->matchdata);
1085 datamatcher_match(Datamatcher *ma, const char *str)
1088 switch ((ma->flags & SEARCH_STRINGMASK))
1090 case SEARCH_SUBSTRING:
1091 if (ma->flags & SEARCH_NOCASE)
1093 if (!strcasestr(str, ma->match))
1098 if (!strstr(str, ma->match))
1103 if (ma->flags & SEARCH_NOCASE)
1105 if (strcasecmp(ma->match, str))
1110 if (strcmp(ma->match, str))
1114 case SEARCH_STRINGSTART:
1115 if (ma->flags & SEARCH_NOCASE)
1117 if (strncasecmp(ma->match, str, strlen(ma->match)))
1122 if (strncmp(ma->match, str, strlen(ma->match)))
1126 case SEARCH_STRINGEND:
1127 l = strlen(str) - strlen(ma->match);
1130 if (ma->flags & SEARCH_NOCASE)
1132 if (strcasecmp(ma->match, str + l))
1137 if (strcmp(ma->match, str + l))
1142 if (fnmatch(ma->match, str, (ma->flags & SEARCH_NOCASE) ? FNM_CASEFOLD : 0))
1146 if (regexec((const regex_t *)ma->matchdata, str, 0, NULL, 0))
1156 repodata_filelistfilter_matches(Repodata *data, const char *str)
1158 /* '.*bin\/.*', '^\/etc\/.*', '^\/usr\/lib\/sendmail$' */
1159 /* for now hardcoded */
1160 if (strstr(str, "bin/"))
1162 if (!strncmp(str, "/etc/", 5))
1164 if (!strcmp(str, "/usr/lib/sendmail"))
1186 di_nextarrayelement,
1191 di_nextsolvableattr,
1196 /* see dataiterator.h for documentation */
1198 dataiterator_init(Dataiterator *di, Pool *pool, Repo *repo, Id p, Id keyname, const char *match, int flags)
1200 memset(di, 0, sizeof(*di));
1202 di->flags = flags & ~SEARCH_THISSOLVID;
1203 if (!pool || (repo && repo->pool != pool))
1211 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1217 di->keyname = keyname;
1218 di->keynames[0] = keyname;
1219 dataiterator_set_search(di, repo, p);
1224 dataiterator_init_clone(Dataiterator *di, Dataiterator *from)
1227 memset(&di->matcher, 0, sizeof(di->matcher));
1228 if (from->matcher.match)
1229 datamatcher_init(&di->matcher, from->matcher.match, from->matcher.flags);
1234 for (i = 1; i < di->nparents; i++)
1235 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1236 di->kv.parent = &di->parents[di->nparents - 1].kv;
1241 dataiterator_set_match(Dataiterator *di, const char *match, int flags)
1243 di->flags = (flags & ~SEARCH_THISSOLVID) | (di->flags & SEARCH_THISSOLVID);
1244 datamatcher_free(&di->matcher);
1245 memset(&di->matcher, 0, sizeof(di->matcher));
1249 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1259 dataiterator_set_search(Dataiterator *di, Repo *repo, Id p)
1263 di->flags &= ~SEARCH_THISSOLVID;
1267 if (!di->pool->urepos)
1275 di->repo = di->pool->repos[di->repoid];
1277 di->state = di_enterrepo;
1279 dataiterator_jump_to_solvid(di, p);
1283 dataiterator_set_keyname(Dataiterator *di, Id keyname)
1286 di->keyname = keyname;
1287 di->keynames[0] = keyname;
1291 dataiterator_prepend_keyname(Dataiterator *di, Id keyname)
1295 if (di->nkeynames >= sizeof(di->keynames)/sizeof(*di->keynames) - 2)
1297 di->state = di_bye; /* sorry */
1300 for (i = di->nkeynames + 1; i > 0; i--)
1301 di->keynames[i] = di->keynames[i - 1];
1302 di->keynames[0] = di->keyname = keyname;
1307 dataiterator_free(Dataiterator *di)
1309 if (di->matcher.match)
1310 datamatcher_free(&di->matcher);
1313 static inline unsigned char *
1314 dataiterator_find_keyname(Dataiterator *di, Id keyname)
1316 Id *keyp = di->keyp;
1317 Repokey *keys = di->data->keys;
1320 for (keyp = di->keyp; *keyp; keyp++)
1321 if (keys[*keyp].name == keyname)
1325 dp = forward_to_key(di->data, *keyp, di->keyp, di->dp);
1333 dataiterator_filelistcheck(Dataiterator *di)
1336 int needcomplete = 0;
1337 Repodata *data = di->data;
1339 if ((di->matcher.flags & SEARCH_COMPLETE_FILELIST) != 0)
1340 if (!di->matcher.match
1341 || ((di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_STRING
1342 && (di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_GLOB)
1343 || !repodata_filelistfilter_matches(di->data, di->matcher.match))
1345 if (data->state != REPODATA_AVAILABLE)
1346 return needcomplete ? 1 : 0;
1347 for (j = 1; j < data->nkeys; j++)
1348 if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
1350 return j == data->nkeys && !needcomplete ? 0 : 1;
1354 dataiterator_step(Dataiterator *di)
1362 case di_enterrepo: di_enterrepo:
1363 if (!di->repo || (di->repo->disabled && !(di->flags & SEARCH_DISABLED_REPOS)))
1365 if (!(di->flags & SEARCH_THISSOLVID))
1367 di->solvid = di->repo->start - 1; /* reset solvid iterator */
1368 goto di_nextsolvable;
1372 case di_entersolvable: di_entersolvable:
1375 di->repodataid = 1; /* reset repodata iterator */
1376 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)
1378 di->key = solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0);
1380 goto di_entersolvablekey;
1385 case di_enterrepodata: di_enterrepodata:
1388 if (di->repodataid >= di->repo->nrepodata)
1389 goto di_nextsolvable;
1390 di->data = di->repo->repodata + di->repodataid;
1392 if (di->repodataid && di->keyname == SOLVABLE_FILELIST && !dataiterator_filelistcheck(di))
1393 goto di_nextrepodata;
1394 if (!maybe_load_repodata(di->data, di->keyname))
1395 goto di_nextrepodata;
1396 di->dp = solvid2data(di->data, di->solvid, &schema);
1398 goto di_nextrepodata;
1399 if (di->solvid == SOLVID_POS)
1400 di->solvid = di->pool->pos.solvid;
1401 /* reset key iterator */
1402 di->keyp = di->data->schemadata + di->data->schemata[schema];
1405 case di_enterschema: di_enterschema:
1407 di->dp = dataiterator_find_keyname(di, di->keyname);
1408 if (!di->dp || !*di->keyp)
1412 goto di_nextrepodata;
1416 case di_enterkey: di_enterkey:
1418 di->key = di->data->keys + *di->keyp;
1419 di->ddp = get_data(di->data, di->key, &di->dp, di->keyp[1] && (!di->keyname || (di->flags & SEARCH_SUB) != 0) ? 1 : 0);
1422 if (di->key->type == REPOKEY_TYPE_DELETED)
1424 if (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY)
1426 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1432 di->ddp = data_fetch(di->ddp, &di->kv, di->key);
1434 di->state = di_nextkey;
1436 di->state = di_nextattr;
1439 case di_nextkey: di_nextkey:
1440 if (!di->keyname && *++di->keyp)
1446 case di_nextrepodata: di_nextrepodata:
1447 if (di->repodataid && ++di->repodataid < di->repo->nrepodata)
1448 goto di_enterrepodata;
1451 case di_nextsolvable: di_nextsolvable:
1452 if (!(di->flags & SEARCH_THISSOLVID))
1455 di->solvid = di->repo->start;
1458 for (; di->solvid < di->repo->end; di->solvid++)
1460 if (di->pool->solvables[di->solvid].repo == di->repo)
1461 goto di_entersolvable;
1466 case di_nextrepo: di_nextrepo:
1471 if (di->repoid < di->pool->nrepos)
1473 di->repo = di->pool->repos[di->repoid];
1479 case di_bye: di_bye:
1483 case di_enterarray: di_enterarray:
1484 if (di->key->name == REPOSITORY_SOLVABLES)
1486 di->ddp = data_read_id(di->ddp, &di->kv.num);
1491 case di_nextarrayelement: di_nextarrayelement:
1494 di->ddp = data_skip_schema(di->data, di->ddp, di->kv.id);
1495 if (di->kv.entry == di->kv.num)
1497 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1499 if (!(di->flags & SEARCH_ARRAYSENTINEL))
1501 di->kv.str = (char *)di->ddp;
1503 di->state = di_nextkey;
1506 if (di->kv.entry == di->kv.num - 1)
1508 if (di->key->type == REPOKEY_TYPE_FLEXARRAY || !di->kv.entry)
1509 di->ddp = data_read_id(di->ddp, &di->kv.id);
1510 di->kv.str = (char *)di->ddp;
1511 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1513 if ((di->flags & SEARCH_SUB) != 0)
1514 di->state = di_entersub;
1516 di->state = di_nextarrayelement;
1519 case di_entersub: di_entersub:
1520 if (di->nparents == sizeof(di->parents)/sizeof(*di->parents) - 1)
1521 goto di_nextarrayelement; /* sorry, full */
1522 di->parents[di->nparents].kv = di->kv;
1523 di->parents[di->nparents].dp = di->dp;
1524 di->parents[di->nparents].keyp = di->keyp;
1525 di->dp = (unsigned char *)di->kv.str;
1526 di->keyp = di->data->schemadata + di->data->schemata[di->kv.id];
1527 memset(&di->kv, 0, sizeof(di->kv));
1528 di->kv.parent = &di->parents[di->nparents].kv;
1530 di->keyname = di->keynames[di->nparents - di->rootlevel];
1531 goto di_enterschema;
1533 case di_leavesub: di_leavesub:
1534 if (di->nparents - 1 < di->rootlevel)
1537 di->dp = di->parents[di->nparents].dp;
1538 di->kv = di->parents[di->nparents].kv;
1539 di->keyp = di->parents[di->nparents].keyp;
1540 di->key = di->data->keys + *di->keyp;
1541 di->ddp = (unsigned char *)di->kv.str;
1542 di->keyname = di->keynames[di->nparents - di->rootlevel];
1543 goto di_nextarrayelement;
1545 /* special solvable attr handling follows */
1547 case di_nextsolvableattr:
1548 di->kv.id = *di->idp++;
1553 di->state = di_nextsolvablekey;
1557 case di_nextsolvablekey: di_nextsolvablekey:
1558 if (di->keyname || di->key->name == RPM_RPMDBID)
1559 goto di_enterrepodata;
1563 case di_entersolvablekey: di_entersolvablekey:
1564 di->idp = solvabledata_fetch(di->pool->solvables + di->solvid, &di->kv, di->key->name);
1565 if (!di->idp || !di->idp[0])
1566 goto di_nextsolvablekey;
1567 di->kv.id = di->idp[0];
1568 di->kv.num = di->idp[0];
1570 if (!di->kv.eof && !di->idp[0])
1574 di->state = di_nextsolvablekey;
1576 di->state = di_nextsolvableattr;
1580 if (di->matcher.match)
1582 /* simple pre-check so that we don't need to stringify */
1583 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))
1585 int l = strlen(di->matcher.match) - strlen(di->kv.str);
1586 if (l < 0 || strcmp(di->matcher.match + l, di->kv.str))
1589 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1591 if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY))
1595 if (!datamatcher_match(&di->matcher, di->kv.str))
1598 /* found something! */
1604 dataiterator_entersub(Dataiterator *di)
1606 if (di->state == di_nextarrayelement)
1607 di->state = di_entersub;
1611 dataiterator_setpos(Dataiterator *di)
1613 if (di->kv.eof == 2)
1615 pool_clear_pos(di->pool);
1618 di->pool->pos.solvid = di->solvid;
1619 di->pool->pos.repo = di->repo;
1620 di->pool->pos.repodataid = di->data - di->repo->repodata;
1621 di->pool->pos.schema = di->kv.id;
1622 di->pool->pos.dp = (unsigned char *)di->kv.str - di->data->incoredata;
1626 dataiterator_setpos_parent(Dataiterator *di)
1628 if (!di->kv.parent || di->kv.parent->eof == 2)
1630 pool_clear_pos(di->pool);
1633 di->pool->pos.solvid = di->solvid;
1634 di->pool->pos.repo = di->repo;
1635 di->pool->pos.repodataid = di->data - di->repo->repodata;
1636 di->pool->pos.schema = di->kv.parent->id;
1637 di->pool->pos.dp = (unsigned char *)di->kv.parent->str - di->data->incoredata;
1640 /* clones just the position, not the search keys/matcher */
1642 dataiterator_clonepos(Dataiterator *di, Dataiterator *from)
1644 di->state = from->state;
1645 di->flags &= ~SEARCH_THISSOLVID;
1646 di->flags |= (from->flags & SEARCH_THISSOLVID);
1647 di->repo = from->repo;
1648 di->data = from->data;
1650 di->ddp = from->ddp;
1651 di->idp = from->idp;
1652 di->keyp = from->keyp;
1653 di->key = from->key;
1655 di->repodataid = from->repodataid;
1656 di->solvid = from->solvid;
1657 di->repoid = from->repoid;
1658 di->rootlevel = from->rootlevel;
1659 memcpy(di->parents, from->parents, sizeof(from->parents));
1660 di->nparents = from->nparents;
1664 for (i = 1; i < di->nparents; i++)
1665 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1666 di->kv.parent = &di->parents[di->nparents - 1].kv;
1671 dataiterator_seek(Dataiterator *di, int whence)
1673 if ((whence & DI_SEEK_STAY) != 0)
1674 di->rootlevel = di->nparents;
1675 switch (whence & ~DI_SEEK_STAY)
1678 if (di->state != di_nextarrayelement)
1680 if ((whence & DI_SEEK_STAY) != 0)
1681 di->rootlevel = di->nparents + 1; /* XXX: dangerous! */
1682 di->state = di_entersub;
1684 case DI_SEEK_PARENT:
1691 if (di->rootlevel > di->nparents)
1692 di->rootlevel = di->nparents;
1693 di->dp = di->parents[di->nparents].dp;
1694 di->kv = di->parents[di->nparents].kv;
1695 di->keyp = di->parents[di->nparents].keyp;
1696 di->key = di->data->keys + *di->keyp;
1697 di->ddp = (unsigned char *)di->kv.str;
1698 di->keyname = di->keynames[di->nparents - di->rootlevel];
1699 di->state = di_nextarrayelement;
1701 case DI_SEEK_REWIND:
1707 di->dp = (unsigned char *)di->kv.parent->str;
1708 di->keyp = di->data->schemadata + di->data->schemata[di->kv.parent->id];
1709 di->state = di_enterschema;
1717 dataiterator_skip_attribute(Dataiterator *di)
1719 if (di->state == di_nextsolvableattr)
1720 di->state = di_nextsolvablekey;
1722 di->state = di_nextkey;
1726 dataiterator_skip_solvable(Dataiterator *di)
1731 di->keyname = di->keynames[0];
1732 di->state = di_nextsolvable;
1736 dataiterator_skip_repo(Dataiterator *di)
1741 di->keyname = di->keynames[0];
1742 di->state = di_nextrepo;
1746 dataiterator_jump_to_solvid(Dataiterator *di, Id solvid)
1751 di->keyname = di->keynames[0];
1752 if (solvid == SOLVID_POS)
1754 di->repo = di->pool->pos.repo;
1761 di->data = di->repo->repodata + di->pool->pos.repodataid;
1763 di->solvid = solvid;
1764 di->state = di_enterrepo;
1765 di->flags |= SEARCH_THISSOLVID;
1770 di->repo = di->pool->solvables[solvid].repo;
1773 else if (di->repoid > 0)
1775 if (!di->pool->urepos)
1781 di->repo = di->pool->repos[di->repoid];
1784 di->solvid = solvid;
1786 di->flags |= SEARCH_THISSOLVID;
1787 di->state = di_enterrepo;
1791 dataiterator_jump_to_repo(Dataiterator *di, Repo *repo)
1797 di->repoid = 0; /* 0 means stay at repo */
1800 di->flags &= ~SEARCH_THISSOLVID;
1801 di->state = di_enterrepo;
1805 dataiterator_match(Dataiterator *di, Datamatcher *ma)
1807 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1811 return datamatcher_match(ma, di->kv.str);
1814 /************************************************************************
1815 * data modify functions
1818 /* extend repodata so that it includes solvables p */
1820 repodata_extend(Repodata *data, Id p)
1822 if (data->start == data->end)
1823 data->start = data->end = p;
1826 int old = data->end - data->start;
1827 int new = p - data->end + 1;
1830 data->attrs = solv_extend(data->attrs, old, new, sizeof(Id *), REPODATA_BLOCK);
1831 memset(data->attrs + old, 0, new * sizeof(Id *));
1833 data->incoreoffset = solv_extend(data->incoreoffset, old, new, sizeof(Id), REPODATA_BLOCK);
1834 memset(data->incoreoffset + old, 0, new * sizeof(Id));
1837 if (p < data->start)
1839 int old = data->end - data->start;
1840 int new = data->start - p;
1843 data->attrs = solv_extend_resize(data->attrs, old + new, sizeof(Id *), REPODATA_BLOCK);
1844 memmove(data->attrs + new, data->attrs, old * sizeof(Id *));
1845 memset(data->attrs, 0, new * sizeof(Id *));
1847 data->incoreoffset = solv_extend_resize(data->incoreoffset, old + new, sizeof(Id), REPODATA_BLOCK);
1848 memmove(data->incoreoffset + new, data->incoreoffset, old * sizeof(Id));
1849 memset(data->incoreoffset, 0, new * sizeof(Id));
1854 /* shrink end of repodata */
1856 repodata_shrink(Repodata *data, int end)
1860 if (data->end <= end)
1862 if (data->start >= end)
1866 for (i = 0; i < data->end - data->start; i++)
1867 solv_free(data->attrs[i]);
1868 data->attrs = solv_free(data->attrs);
1870 data->incoreoffset = solv_free(data->incoreoffset);
1871 data->start = data->end = 0;
1876 for (i = end; i < data->end; i++)
1877 solv_free(data->attrs[i - data->start]);
1878 data->attrs = solv_extend_resize(data->attrs, end - data->start, sizeof(Id *), REPODATA_BLOCK);
1880 if (data->incoreoffset)
1881 data->incoreoffset = solv_extend_resize(data->incoreoffset, end - data->start, sizeof(Id), REPODATA_BLOCK);
1885 /* extend repodata so that it includes solvables from start to start + num - 1 */
1887 repodata_extend_block(Repodata *data, Id start, Id num)
1891 if (!data->incoreoffset)
1893 data->incoreoffset = solv_calloc_block(num, sizeof(Id), REPODATA_BLOCK);
1894 data->start = start;
1895 data->end = start + num;
1898 repodata_extend(data, start);
1900 repodata_extend(data, start + num - 1);
1903 /**********************************************************************/
1906 #define REPODATA_ATTRS_BLOCK 31
1907 #define REPODATA_ATTRDATA_BLOCK 1023
1908 #define REPODATA_ATTRIDDATA_BLOCK 63
1912 repodata_new_handle(Repodata *data)
1916 data->xattrs = solv_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1917 data->nxattrs = 2; /* -1: SOLVID_META */
1919 data->xattrs = solv_extend(data->xattrs, data->nxattrs, 1, sizeof(Id *), REPODATA_BLOCK);
1920 data->xattrs[data->nxattrs] = 0;
1921 return -(data->nxattrs++);
1925 repodata_get_attrp(Repodata *data, Id handle)
1929 if (handle == SOLVID_META && !data->xattrs)
1931 data->xattrs = solv_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1934 return data->xattrs - handle;
1936 if (handle < data->start || handle >= data->end)
1937 repodata_extend(data, handle);
1939 data->attrs = solv_calloc_block(data->end - data->start, sizeof(Id *), REPODATA_BLOCK);
1940 return data->attrs + (handle - data->start);
1944 repodata_insert_keyid(Repodata *data, Id handle, Id keyid, Id val, int overwrite)
1950 app = repodata_get_attrp(data, handle);
1955 /* Determine equality based on the name only, allows us to change
1956 type (when overwrite is set), and makes TYPE_CONSTANT work. */
1957 for (pp = ap; *pp; pp += 2)
1958 if (data->keys[*pp].name == data->keys[keyid].name)
1962 if (overwrite || data->keys[*pp].type == REPOKEY_TYPE_DELETED)
1971 ap = solv_extend(ap, i, 3, sizeof(Id), REPODATA_ATTRS_BLOCK);
1981 repodata_set(Repodata *data, Id solvid, Repokey *key, Id val)
1985 keyid = repodata_key2id(data, key, 1);
1986 repodata_insert_keyid(data, solvid, keyid, val, 1);
1990 repodata_set_id(Repodata *data, Id solvid, Id keyname, Id id)
1994 key.type = REPOKEY_TYPE_ID;
1996 key.storage = KEY_STORAGE_INCORE;
1997 repodata_set(data, solvid, &key, id);
2001 repodata_set_num(Repodata *data, Id solvid, Id keyname, unsigned int num)
2005 key.type = REPOKEY_TYPE_NUM;
2007 key.storage = KEY_STORAGE_INCORE;
2008 repodata_set(data, solvid, &key, (Id)num);
2012 repodata_set_poolstr(Repodata *data, Id solvid, Id keyname, const char *str)
2016 if (data->localpool)
2017 id = stringpool_str2id(&data->spool, str, 1);
2019 id = pool_str2id(data->repo->pool, str, 1);
2021 key.type = REPOKEY_TYPE_ID;
2023 key.storage = KEY_STORAGE_INCORE;
2024 repodata_set(data, solvid, &key, id);
2028 repodata_set_constant(Repodata *data, Id solvid, Id keyname, unsigned int constant)
2032 key.type = REPOKEY_TYPE_CONSTANT;
2033 key.size = constant;
2034 key.storage = KEY_STORAGE_INCORE;
2035 repodata_set(data, solvid, &key, 0);
2039 repodata_set_constantid(Repodata *data, Id solvid, Id keyname, Id id)
2043 key.type = REPOKEY_TYPE_CONSTANTID;
2045 key.storage = KEY_STORAGE_INCORE;
2046 repodata_set(data, solvid, &key, 0);
2050 repodata_set_void(Repodata *data, Id solvid, Id keyname)
2054 key.type = REPOKEY_TYPE_VOID;
2056 key.storage = KEY_STORAGE_INCORE;
2057 repodata_set(data, solvid, &key, 0);
2061 repodata_set_str(Repodata *data, Id solvid, Id keyname, const char *str)
2066 l = strlen(str) + 1;
2068 key.type = REPOKEY_TYPE_STR;
2070 key.storage = KEY_STORAGE_INCORE;
2071 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2072 memcpy(data->attrdata + data->attrdatalen, str, l);
2073 repodata_set(data, solvid, &key, data->attrdatalen);
2074 data->attrdatalen += l;
2078 repodata_set_binary(Repodata *data, Id solvid, Id keyname, void *buf, int len)
2084 key.type = REPOKEY_TYPE_BINARY;
2086 key.storage = KEY_STORAGE_INCORE;
2087 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, len + 5, 1, REPODATA_ATTRDATA_BLOCK);
2088 dp = data->attrdata + data->attrdatalen;
2089 if (len >= (1 << 14))
2091 if (len >= (1 << 28))
2092 *dp++ = (len >> 28) | 128;
2093 if (len >= (1 << 21))
2094 *dp++ = (len >> 21) | 128;
2095 *dp++ = (len >> 14) | 128;
2097 if (len >= (1 << 7))
2098 *dp++ = (len >> 7) | 128;
2101 memcpy(dp, buf, len);
2102 repodata_set(data, solvid, &key, data->attrdatalen);
2103 data->attrdatalen = dp + len - data->attrdata;
2106 /* add an array element consisting of entrysize Ids to the repodata. modifies attriddata
2107 * so that the caller can append entrysize new elements plus the termination zero there */
2109 repodata_add_array(Repodata *data, Id handle, Id keyname, Id keytype, int entrysize)
2112 Id *ida, *pp, **ppp;
2114 /* check if it is the same as last time, this speeds things up a lot */
2115 if (handle == data->lasthandle && data->keys[data->lastkey].name == keyname && data->keys[data->lastkey].type == keytype && data->attriddatalen == data->lastdatalen)
2117 /* great! just append the new data */
2118 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2119 data->attriddatalen--; /* overwrite terminating 0 */
2120 data->lastdatalen += entrysize;
2124 ppp = repodata_get_attrp(data, handle);
2128 for (; *pp; pp += 2)
2129 if (data->keys[*pp].name == keyname)
2132 if (!pp || !*pp || data->keys[*pp].type != keytype)
2134 /* not found. allocate new key */
2140 key.storage = KEY_STORAGE_INCORE;
2141 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2142 keyid = repodata_key2id(data, &key, 1);
2143 repodata_insert_keyid(data, handle, keyid, data->attriddatalen, 1);
2144 data->lasthandle = handle;
2145 data->lastkey = keyid;
2146 data->lastdatalen = data->attriddatalen + entrysize + 1;
2150 for (ida = data->attriddata + pp[1]; *ida; ida += entrysize)
2151 oldsize += entrysize;
2152 if (ida + 1 == data->attriddata + data->attriddatalen)
2154 /* this was the last entry, just append it */
2155 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2156 data->attriddatalen--; /* overwrite terminating 0 */
2160 /* too bad. move to back. */
2161 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, oldsize + entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2162 memcpy(data->attriddata + data->attriddatalen, data->attriddata + pp[1], oldsize * sizeof(Id));
2163 pp[1] = data->attriddatalen;
2164 data->attriddatalen += oldsize;
2166 data->lasthandle = handle;
2167 data->lastkey = *pp;
2168 data->lastdatalen = data->attriddatalen + entrysize + 1;
2172 repodata_set_bin_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2173 const unsigned char *str)
2178 if (!(l = solv_chksum_len(type)))
2183 key.storage = KEY_STORAGE_INCORE;
2184 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2185 memcpy(data->attrdata + data->attrdatalen, str, l);
2186 repodata_set(data, solvid, &key, data->attrdatalen);
2187 data->attrdatalen += l;
2191 repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2194 unsigned char buf[64];
2197 if (!(l = solv_chksum_len(type)))
2199 if (l > sizeof(buf) || solv_hex2bin(&str, buf, l) != l)
2201 repodata_set_bin_checksum(data, solvid, keyname, type, buf);
2205 repodata_chk2str(Repodata *data, Id type, const unsigned char *buf)
2209 if (!(l = solv_chksum_len(type)))
2211 return pool_bin2hex(data->repo->pool, buf, l);
2214 /* rpm filenames don't contain the epoch, so strip it */
2215 static inline const char *
2216 evrid2vrstr(Pool *pool, Id evrid)
2218 const char *p, *evr = pool_id2str(pool, evrid);
2221 for (p = evr; *p >= '0' && *p <= '9'; p++)
2223 return p != evr && *p == ':' ? p + 1 : evr;
2227 repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, const char *file)
2229 Pool *pool = data->repo->pool;
2231 const char *str, *fp;
2235 repodata_set_constant(data, solvid, SOLVABLE_MEDIANR, medianr);
2238 if ((dir = strrchr(file, '/')) != 0)
2249 if (l >= 2 && dir[0] == '.' && dir[1] == '/' && (l == 2 || dir[2] != '/'))
2254 if (l == 1 && dir[0] == '.')
2256 s = pool->solvables + solvid;
2259 str = pool_id2str(pool, s->arch);
2260 if (!strncmp(dir, str, l) && !str[l])
2261 repodata_set_void(data, solvid, SOLVABLE_MEDIADIR);
2263 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir);
2266 char *dir2 = solv_strdup(dir);
2268 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir2);
2273 str = pool_id2str(pool, s->name);
2275 if ((!l || !strncmp(fp, str, l)) && fp[l] == '-')
2278 str = evrid2vrstr(pool, s->evr);
2280 if ((!l || !strncmp(fp, str, l)) && fp[l] == '.')
2283 str = pool_id2str(pool, s->arch);
2285 if ((!l || !strncmp(fp, str, l)) && !strcmp(fp + l, ".rpm"))
2287 repodata_set_void(data, solvid, SOLVABLE_MEDIAFILE);
2292 repodata_set_str(data, solvid, SOLVABLE_MEDIAFILE, file);
2296 repodata_set_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
2302 key.type = REPOKEY_TYPE_IDARRAY;
2304 key.storage = KEY_STORAGE_INCORE;
2305 repodata_set(data, solvid, &key, data->attriddatalen);
2306 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, q->count + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2307 for (i = 0; i < q->count; i++)
2308 data->attriddata[data->attriddatalen++] = q->elements[i];
2309 data->attriddata[data->attriddatalen++] = 0;
2313 repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2)
2317 fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", solvid, dir, num, num2, data->attriddatalen);
2319 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRNUMNUMARRAY, 3);
2320 data->attriddata[data->attriddatalen++] = dir;
2321 data->attriddata[data->attriddatalen++] = num;
2322 data->attriddata[data->attriddatalen++] = num2;
2323 data->attriddata[data->attriddatalen++] = 0;
2327 repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str)
2333 l = strlen(str) + 1;
2334 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2335 memcpy(data->attrdata + data->attrdatalen, str, l);
2336 stroff = data->attrdatalen;
2337 data->attrdatalen += l;
2340 fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", solvid, dir, str, data->attriddatalen);
2342 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRSTRARRAY, 2);
2343 data->attriddata[data->attriddatalen++] = dir;
2344 data->attriddata[data->attriddatalen++] = stroff;
2345 data->attriddata[data->attriddatalen++] = 0;
2349 repodata_add_idarray(Repodata *data, Id solvid, Id keyname, Id id)
2352 fprintf(stderr, "repodata_add_idarray %d %d (%d)\n", solvid, id, data->attriddatalen);
2354 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_IDARRAY, 1);
2355 data->attriddata[data->attriddatalen++] = id;
2356 data->attriddata[data->attriddatalen++] = 0;
2360 repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname,
2364 if (data->localpool)
2365 id = stringpool_str2id(&data->spool, str, 1);
2367 id = pool_str2id(data->repo->pool, str, 1);
2368 repodata_add_idarray(data, solvid, keyname, id);
2372 repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2374 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FIXARRAY, 1);
2375 data->attriddata[data->attriddatalen++] = ghandle;
2376 data->attriddata[data->attriddatalen++] = 0;
2380 repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2382 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FLEXARRAY, 1);
2383 data->attriddata[data->attriddatalen++] = ghandle;
2384 data->attriddata[data->attriddatalen++] = 0;
2388 repodata_delete_uninternalized(Repodata *data, Id solvid, Id keyname)
2391 app = repodata_get_attrp(data, solvid);
2395 for (; *ap; ap += 2)
2396 if (data->keys[*ap].name == keyname)
2402 for (; *ap; ap += 2)
2404 if (data->keys[*ap].name == keyname)
2412 /* XXX: does not work correctly, needs fix in iterators! */
2414 repodata_delete(Repodata *data, Id solvid, Id keyname)
2418 key.type = REPOKEY_TYPE_DELETED;
2420 key.storage = KEY_STORAGE_INCORE;
2421 repodata_set(data, solvid, &key, 0);
2424 /* add all (uninternalized) attrs from src to dest */
2426 repodata_merge_attrs(Repodata *data, Id dest, Id src)
2429 if (dest == src || data->attrs || !(keyp = data->attrs[src - data->start]))
2431 for (; *keyp; keyp += 2)
2432 repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
2435 /* add some (uninternalized) attrs from src to dest */
2437 repodata_merge_some_attrs(Repodata *data, Id dest, Id src, Map *keyidmap, int overwrite)
2440 if (dest == src || !data->attrs || !(keyp = data->attrs[src - data->start]))
2442 for (; *keyp; keyp += 2)
2443 if (!keyidmap || MAPTST(keyidmap, keyp[0]))
2444 repodata_insert_keyid(data, dest, keyp[0], keyp[1], overwrite);
2447 /* swap (uninternalized) attrs from src and dest */
2449 repodata_swap_attrs(Repodata *data, Id dest, Id src)
2452 if (!data->attrs || dest == src)
2454 tmpattrs = data->attrs[dest - data->start];
2455 data->attrs[dest - data->start] = data->attrs[src - data->start];
2456 data->attrs[src - data->start] = tmpattrs;
2460 /**********************************************************************/
2462 /* TODO: unify with repo_write and repo_solv! */
2464 #define EXTDATA_BLOCK 1023
2472 data_addid(struct extdata *xd, Id x)
2476 xd->buf = solv_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
2477 dp = xd->buf + xd->len;
2482 *dp++ = (x >> 28) | 128;
2484 *dp++ = (x >> 21) | 128;
2485 *dp++ = (x >> 14) | 128;
2488 *dp++ = (x >> 7) | 128;
2490 xd->len = dp - xd->buf;
2494 data_addideof(struct extdata *xd, Id x, int eof)
2497 x = (x & 63) | ((x & ~63) << 1);
2498 data_addid(xd, (eof ? x : x | 64));
2502 data_addblob(struct extdata *xd, unsigned char *blob, int len)
2504 xd->buf = solv_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK);
2505 memcpy(xd->buf + xd->len, blob, len);
2509 /*********************************/
2511 /* internalalize some key into incore/vincore data */
2514 repodata_serialize_key(Repodata *data, struct extdata *newincore,
2515 struct extdata *newvincore,
2517 Repokey *key, Id val)
2521 unsigned int oldvincorelen = 0;
2525 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2528 oldvincorelen = xd->len;
2532 case REPOKEY_TYPE_VOID:
2533 case REPOKEY_TYPE_CONSTANT:
2534 case REPOKEY_TYPE_CONSTANTID:
2536 case REPOKEY_TYPE_STR:
2537 data_addblob(xd, data->attrdata + val, strlen((char *)(data->attrdata + val)) + 1);
2539 case REPOKEY_TYPE_MD5:
2540 data_addblob(xd, data->attrdata + val, SIZEOF_MD5);
2542 case REPOKEY_TYPE_SHA1:
2543 data_addblob(xd, data->attrdata + val, SIZEOF_SHA1);
2545 case REPOKEY_TYPE_SHA256:
2546 data_addblob(xd, data->attrdata + val, SIZEOF_SHA256);
2548 case REPOKEY_TYPE_ID:
2549 case REPOKEY_TYPE_NUM:
2550 case REPOKEY_TYPE_DIR:
2551 data_addid(xd, val);
2553 case REPOKEY_TYPE_BINARY:
2556 unsigned char *dp = data_read_id(data->attrdata + val, &len);
2558 data_addblob(xd, data->attrdata + val, dp - (data->attrdata + val));
2561 case REPOKEY_TYPE_IDARRAY:
2562 for (ida = data->attriddata + val; *ida; ida++)
2563 data_addideof(xd, ida[0], ida[1] ? 0 : 1);
2565 case REPOKEY_TYPE_DIRNUMNUMARRAY:
2566 for (ida = data->attriddata + val; *ida; ida += 3)
2568 data_addid(xd, ida[0]);
2569 data_addid(xd, ida[1]);
2570 data_addideof(xd, ida[2], ida[3] ? 0 : 1);
2573 case REPOKEY_TYPE_DIRSTRARRAY:
2574 for (ida = data->attriddata + val; *ida; ida += 2)
2576 data_addideof(xd, ida[0], ida[2] ? 0 : 1);
2577 data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
2580 case REPOKEY_TYPE_FIXARRAY:
2584 for (ida = data->attriddata + val; *ida; ida++)
2588 kp = data->xattrs[-*ida];
2596 schemaid = repodata_schema2id(data, schema, 1);
2597 else if (schemaid != repodata_schema2id(data, schema, 0))
2599 pool_debug(data->repo->pool, SOLV_FATAL, "fixarray substructs with different schemas\n");
2605 data_addid(xd, num);
2606 data_addid(xd, schemaid);
2607 for (ida = data->attriddata + val; *ida; ida++)
2609 Id *kp = data->xattrs[-*ida];
2613 repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
2617 case REPOKEY_TYPE_FLEXARRAY:
2620 for (ida = data->attriddata + val; *ida; ida++)
2622 data_addid(xd, num);
2623 for (ida = data->attriddata + val; *ida; ida++)
2625 Id *kp = data->xattrs[-*ida];
2628 data_addid(xd, 0); /* XXX */
2635 schemaid = repodata_schema2id(data, schema, 1);
2636 data_addid(xd, schemaid);
2637 kp = data->xattrs[-*ida];
2639 repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
2644 pool_debug(data->repo->pool, SOLV_FATAL, "don't know how to handle type %d\n", key->type);
2647 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2649 /* put offset/len in incore */
2650 data_addid(newincore, data->lastverticaloffset + oldvincorelen);
2651 oldvincorelen = xd->len - oldvincorelen;
2652 data_addid(newincore, oldvincorelen);
2657 repodata_internalize(Repodata *data)
2659 Repokey *key, solvkey;
2661 Id schemaid, *schema, *sp, oldschema, *keyp, *keypstart, *seen;
2662 unsigned char *dp, *ndp;
2663 int newschema, oldcount;
2664 struct extdata newincore;
2665 struct extdata newvincore;
2668 if (!data->attrs && !data->xattrs)
2671 newvincore.buf = data->vincore;
2672 newvincore.len = data->vincorelen;
2674 /* find the solvables key, create if needed */
2675 memset(&solvkey, 0, sizeof(solvkey));
2676 solvkey.name = REPOSITORY_SOLVABLES;
2677 solvkey.type = REPOKEY_TYPE_FLEXARRAY;
2679 solvkey.storage = KEY_STORAGE_INCORE;
2680 solvkeyid = repodata_key2id(data, &solvkey, data->end != data->start ? 1 : 0);
2682 schema = solv_malloc2(data->nkeys, sizeof(Id));
2683 seen = solv_malloc2(data->nkeys, sizeof(Id));
2685 /* Merge the data already existing (in data->schemata, ->incoredata and
2686 friends) with the new attributes in data->attrs[]. */
2687 nentry = data->end - data->start;
2688 memset(&newincore, 0, sizeof(newincore));
2689 data_addid(&newincore, 0); /* start data at offset 1 */
2691 data->mainschema = 0;
2692 data->mainschemaoffsets = solv_free(data->mainschemaoffsets);
2694 /* join entry data */
2695 /* we start with the meta data, entry -1 */
2696 for (entry = -1; entry < nentry; entry++)
2698 memset(seen, 0, data->nkeys * sizeof(Id));
2700 dp = data->incoredata;
2703 dp += entry >= 0 ? data->incoreoffset[entry] : 1;
2704 dp = data_read_id(dp, &oldschema);
2707 fprintf(stderr, "oldschema %d\n", oldschema);
2708 fprintf(stderr, "schemata %d\n", data->schemata[oldschema]);
2709 fprintf(stderr, "schemadata %p\n", data->schemadata);
2711 /* seen: -1: old data 0: skipped >0: id + 1 */
2715 for (keyp = data->schemadata + data->schemata[oldschema]; *keyp; keyp++)
2719 pool_debug(data->repo->pool, SOLV_FATAL, "Inconsistent old data (key occured twice).\n");
2727 keyp = data->attrs ? data->attrs[entry] : 0;
2730 /* strip solvables key */
2732 for (sp = keyp = schema; *sp; sp++)
2733 if (*sp != solvkeyid)
2738 seen[solvkeyid] = 0;
2739 keyp = data->xattrs ? data->xattrs[1] : 0;
2742 for (; *keyp; keyp += 2)
2749 seen[*keyp] = keyp[1] + 1;
2751 if (entry < 0 && data->end != data->start)
2758 /* Ideally we'd like to sort the new schema here, to ensure
2759 schema equality independend of the ordering. We can't do that
2760 yet. For once see below (old ids need to come before new ids).
2761 An additional difficulty is that we also need to move
2762 the values with the keys. */
2763 schemaid = repodata_schema2id(data, schema, 1);
2765 schemaid = oldschema;
2768 /* Now create data blob. We walk through the (possibly new) schema
2769 and either copy over old data, or insert the new. */
2770 /* XXX Here we rely on the fact that the (new) schema has the form
2771 o1 o2 o3 o4 ... | n1 n2 n3 ...
2772 (oX being the old keyids (possibly overwritten), and nX being
2773 the new keyids). This rules out sorting the keyids in order
2774 to ensure a small schema count. */
2776 data->incoreoffset[entry] = newincore.len;
2777 data_addid(&newincore, schemaid);
2780 data->mainschema = schemaid;
2781 data->mainschemaoffsets = solv_calloc(sp - schema, sizeof(Id));
2783 keypstart = data->schemadata + data->schemata[schemaid];
2784 for (keyp = keypstart; *keyp; keyp++)
2787 data->mainschemaoffsets[keyp - keypstart] = newincore.len;
2788 if (*keyp == solvkeyid)
2790 /* add flexarray entry count */
2791 data_addid(&newincore, data->end - data->start);
2794 key = data->keys + *keyp;
2796 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));
2801 /* Skip the data associated with this old key. */
2802 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2804 ndp = data_skip(dp, REPOKEY_TYPE_ID);
2805 ndp = data_skip(ndp, REPOKEY_TYPE_ID);
2807 else if (key->storage == KEY_STORAGE_INCORE)
2808 ndp = data_skip_key(data, dp, key);
2811 if (seen[*keyp] == -1)
2813 /* If this key was an old one _and_ was not overwritten with
2814 a different value copy over the old value (we skipped it
2817 data_addblob(&newincore, dp, ndp - dp);
2820 else if (seen[*keyp])
2822 /* Otherwise we have a new value. Parse it into the internal
2824 repodata_serialize_key(data, &newincore, &newvincore,
2825 schema, key, seen[*keyp] - 1);
2829 if (entry >= 0 && data->attrs && data->attrs[entry])
2830 data->attrs[entry] = solv_free(data->attrs[entry]);
2832 /* free all xattrs */
2833 for (entry = 0; entry < data->nxattrs; entry++)
2834 if (data->xattrs[entry])
2835 solv_free(data->xattrs[entry]);
2836 data->xattrs = solv_free(data->xattrs);
2839 data->lasthandle = 0;
2841 data->lastdatalen = 0;
2844 repodata_free_schemahash(data);
2846 solv_free(data->incoredata);
2847 data->incoredata = newincore.buf;
2848 data->incoredatalen = newincore.len;
2849 data->incoredatafree = 0;
2851 solv_free(data->vincore);
2852 data->vincore = newvincore.buf;
2853 data->vincorelen = newvincore.len;
2855 data->attrs = solv_free(data->attrs);
2856 data->attrdata = solv_free(data->attrdata);
2857 data->attriddata = solv_free(data->attriddata);
2858 data->attrdatalen = 0;
2859 data->attriddatalen = 0;
2863 repodata_disable_paging(Repodata *data)
2865 if (maybe_load_repodata(data, 0))
2866 repopagestore_disable_paging(&data->store);
2870 repodata_load_stub(Repodata *data)
2872 Repo *repo = data->repo;
2873 Pool *pool = repo->pool;
2875 struct _Pool_tmpspace oldtmpspace;
2877 if (!pool->loadcallback)
2879 data->state = REPODATA_ERROR;
2882 data->state = REPODATA_LOADING;
2884 /* save tmp space */
2885 oldtmpspace = pool->tmpspace;
2886 memset(&pool->tmpspace, 0, sizeof(pool->tmpspace));
2888 r = pool->loadcallback(pool, data, pool->loadcallbackdata);
2890 /* restore tmp space */
2891 for (i = 0; i < POOL_TMPSPACEBUF; i++)
2892 solv_free(pool->tmpspace.buf[i]);
2893 pool->tmpspace = oldtmpspace;
2895 data->state = r ? REPODATA_AVAILABLE : REPODATA_ERROR;
2899 repodata_create_stubs(Repodata *data)
2901 Repo *repo = data->repo;
2902 Pool *pool = repo->pool;
2909 int datastart, dataend;
2911 repodataid = data - repo->repodata;
2912 datastart = data->start;
2913 dataend = data->end;
2914 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2915 while (dataiterator_step(&di))
2917 if (di.data - repo->repodata != repodataid)
2921 dataiterator_free(&di);
2924 stubdataids = solv_calloc(cnt, sizeof(*stubdataids));
2925 for (i = 0; i < cnt; i++)
2927 sdata = repo_add_repodata(repo, 0);
2928 if (dataend > datastart)
2929 repodata_extend_block(sdata, datastart, dataend - datastart);
2930 stubdataids[i] = sdata - repo->repodata;
2931 sdata->state = REPODATA_STUB;
2932 sdata->loadcallback = repodata_load_stub;
2935 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2937 while (dataiterator_step(&di))
2939 if (di.data - repo->repodata != repodataid)
2941 if (di.key->name == REPOSITORY_EXTERNAL && !di.nparents)
2943 dataiterator_entersub(&di);
2944 sdata = repo->repodata + stubdataids[i++];
2948 switch (di.key->type)
2950 case REPOKEY_TYPE_ID:
2951 repodata_set_id(sdata, SOLVID_META, di.key->name, di.kv.id);
2953 case REPOKEY_TYPE_CONSTANTID:
2954 repodata_set_constantid(sdata, SOLVID_META, di.key->name, di.kv.id);
2956 case REPOKEY_TYPE_STR:
2957 repodata_set_str(sdata, SOLVID_META, di.key->name, di.kv.str);
2959 case REPOKEY_TYPE_VOID:
2960 repodata_set_void(sdata, SOLVID_META, di.key->name);
2962 case REPOKEY_TYPE_NUM:
2963 repodata_set_num(sdata, SOLVID_META, di.key->name, di.kv.num);
2965 case REPOKEY_TYPE_MD5:
2966 case REPOKEY_TYPE_SHA1:
2967 case REPOKEY_TYPE_SHA256:
2968 repodata_set_bin_checksum(sdata, SOLVID_META, di.key->name, di.key->type, (const unsigned char *)di.kv.str);
2970 case REPOKEY_TYPE_IDARRAY:
2971 repodata_add_idarray(sdata, SOLVID_META, di.key->name, di.kv.id);
2972 if (di.key->name == REPOSITORY_KEYS)
2979 xkeyname = di.kv.id;
2982 xkey.name = xkeyname;
2983 xkey.type = di.kv.id;
2984 xkey.storage = KEY_STORAGE_INCORE;
2986 repodata_key2id(sdata, &xkey, 1);
2993 dataiterator_free(&di);
2994 for (i = 0; i < cnt; i++)
2995 repodata_internalize(repo->repodata + stubdataids[i]);
2996 solv_free(stubdataids);
3000 repodata_memused(Repodata *data)
3002 return data->incoredatalen + data->vincorelen;
3006 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: