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);
94 solv_free(data->attrnum64data);
96 solv_free(data->dircache);
100 repodata_free(Repodata *data)
102 Repo *repo = data->repo;
103 int i = data - repo->repodata;
106 repodata_freedata(data);
107 if (i < repo->nrepodata - 1)
109 /* whoa! this changes the repodataids! */
110 memmove(repo->repodata + i, repo->repodata + i + 1, (repo->nrepodata - 1 - i) * sizeof(Repodata));
111 for (; i < repo->nrepodata - 1; i++)
112 repo->repodata[i].repodataid = i;
115 if (repo->nrepodata == 1)
117 repo->repodata = solv_free(repo->repodata);
123 repodata_empty(Repodata *data, int localpool)
125 void (*loadcallback)(Repodata *) = data->loadcallback;
126 int state = data->state;
127 repodata_freedata(data);
128 repodata_initdata(data, data->repo, localpool);
130 data->loadcallback = loadcallback;
134 /***************************************************************
135 * key pool management
138 /* this is not so time critical that we need a hash, so we do a simple
141 repodata_key2id(Repodata *data, Repokey *key, int create)
145 for (keyid = 1; keyid < data->nkeys; keyid++)
146 if (data->keys[keyid].name == key->name && data->keys[keyid].type == key->type)
148 if ((key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID) && key->size != data->keys[keyid].size)
152 if (keyid == data->nkeys)
156 /* allocate new key */
157 data->keys = solv_realloc2(data->keys, data->nkeys + 1, sizeof(Repokey));
158 data->keys[data->nkeys++] = *key;
159 if (data->verticaloffset)
161 data->verticaloffset = solv_realloc2(data->verticaloffset, data->nkeys, sizeof(Id));
162 data->verticaloffset[data->nkeys - 1] = 0;
164 data->keybits[(key->name >> 3) & (sizeof(data->keybits) - 1)] |= 1 << (key->name & 7);
170 /***************************************************************
171 * schema pool management
174 #define SCHEMATA_BLOCK 31
175 #define SCHEMATADATA_BLOCK 255
178 repodata_schema2id(Repodata *data, Id *schema, int create)
185 return 0; /* XXX: allow empty schema? */
186 if ((schematahash = data->schematahash) == 0)
188 data->schematahash = schematahash = solv_calloc(256, sizeof(Id));
189 for (i = 1; i < data->nschemata; i++)
191 for (sp = data->schemadata + data->schemata[i], h = 0; *sp; len++)
196 data->schemadata = solv_extend_resize(data->schemadata, data->schemadatalen, sizeof(Id), SCHEMATADATA_BLOCK);
197 data->schemata = solv_extend_resize(data->schemata, data->nschemata, sizeof(Id), SCHEMATA_BLOCK);
200 for (sp = schema, len = 0, h = 0; *sp; len++)
205 cid = schematahash[h];
208 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
210 /* cache conflict, do a slow search */
211 for (cid = 1; cid < data->nschemata; cid++)
212 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
218 data->schemadata = solv_extend(data->schemadata, data->schemadatalen, len, sizeof(Id), SCHEMATADATA_BLOCK);
219 data->schemata = solv_extend(data->schemata, data->nschemata, 1, sizeof(Id), SCHEMATA_BLOCK);
221 memcpy(data->schemadata + data->schemadatalen, schema, len * sizeof(Id));
222 data->schemata[data->nschemata] = data->schemadatalen;
223 data->schemadatalen += len;
224 schematahash[h] = data->nschemata;
226 fprintf(stderr, "schema2id: new schema\n");
228 return data->nschemata++;
232 repodata_free_schemahash(Repodata *data)
234 data->schematahash = solv_free(data->schematahash);
236 data->schemata = solv_realloc2(data->schemata, data->nschemata, sizeof(Id));
237 data->schemadata = solv_realloc2(data->schemadata, data->schemadatalen, sizeof(Id));
241 /***************************************************************
242 * dir pool management
245 #ifndef HAVE_STRCHRNUL
246 static inline const char *strchrnul(const char *str, char x)
248 const char *p = strchr(str, x);
249 return p ? p : str + strlen(str);
253 #define DIRCACHE_SIZE 41 /* < 1k */
257 Id ids[DIRCACHE_SIZE];
258 char str[(DIRCACHE_SIZE * (DIRCACHE_SIZE - 1)) / 2];
263 repodata_str2dir(Repodata *data, const char *dir, int create)
274 while (*dir == '/' && dir[1] == '/')
276 if (*dir == '/' && !dir[1])
278 if (data->dirpool.ndirs)
280 return dirpool_add_dir(&data->dirpool, 0, 1, create);
287 struct dircache *dircache = data->dircache;
291 if (l < DIRCACHE_SIZE && dircache->ids[l] && !memcmp(dircache->str + l * (l - 1) / 2, dir, l))
293 parent = dircache->ids[l];
309 dire = strchrnul(dir, '/');
311 id = stringpool_strn2id(&data->spool, dir, dire - dir, create);
313 id = pool_strn2id(data->repo->pool, dir, dire - dir, create);
316 parent = dirpool_add_dir(&data->dirpool, parent, id, create);
321 data->dircache = solv_calloc(1, sizeof(struct dircache));
325 if (l < DIRCACHE_SIZE)
327 data->dircache->ids[l] = parent;
328 memcpy(data->dircache->str + l * (l - 1) / 2, dirs, l);
342 repodata_free_dircache(Repodata *data)
344 data->dircache = solv_free(data->dircache);
348 repodata_dir2str(Repodata *data, Id did, const char *suf)
350 Pool *pool = data->repo->pool;
357 return suf ? suf : "";
361 comp = dirpool_compid(&data->dirpool, parent);
362 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
364 parent = dirpool_parent(&data->dirpool, parent);
369 l += strlen(suf) + 1;
370 p = pool_alloctmpspace(pool, l + 1) + l;
381 comp = dirpool_compid(&data->dirpool, parent);
382 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
385 strncpy(p, comps, l);
386 parent = dirpool_parent(&data->dirpool, parent);
394 /***************************************************************
398 static inline unsigned char *
399 data_skip_schema(Repodata *data, unsigned char *dp, Id schema)
401 Id *keyp = data->schemadata + data->schemata[schema];
402 for (; *keyp; keyp++)
403 dp = data_skip_key(data, dp, data->keys + *keyp);
407 static unsigned char *
408 data_skip_key(Repodata *data, unsigned char *dp, Repokey *key)
410 int nentries, schema;
413 case REPOKEY_TYPE_FIXARRAY:
414 dp = data_read_id(dp, &nentries);
417 dp = data_read_id(dp, &schema);
419 dp = data_skip_schema(data, dp, schema);
421 case REPOKEY_TYPE_FLEXARRAY:
422 dp = data_read_id(dp, &nentries);
425 dp = data_read_id(dp, &schema);
426 dp = data_skip_schema(data, dp, schema);
430 if (key->storage == KEY_STORAGE_INCORE)
431 dp = data_skip(dp, key->type);
432 else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
434 dp = data_skip(dp, REPOKEY_TYPE_ID);
435 dp = data_skip(dp, REPOKEY_TYPE_ID);
441 static unsigned char *
442 forward_to_key(Repodata *data, Id keyid, Id *keyp, unsigned char *dp)
448 if (data->mainschemaoffsets && dp == data->incoredata + data->mainschemaoffsets[0] && keyp == data->schemadata + data->schemata[data->mainschema])
451 for (i = 0; (k = *keyp++) != 0; i++)
453 return data->incoredata + data->mainschemaoffsets[i];
456 while ((k = *keyp++) != 0)
460 if (data->keys[k].storage == KEY_STORAGE_VERTICAL_OFFSET)
462 dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip offset */
463 dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip length */
466 if (data->keys[k].storage != KEY_STORAGE_INCORE)
468 dp = data_skip_key(data, dp, data->keys + k);
473 static unsigned char *
474 get_vertical_data(Repodata *data, Repokey *key, Id off, Id len)
479 if (off >= data->lastverticaloffset)
481 off -= data->lastverticaloffset;
482 if (off + len > data->vincorelen)
484 return data->vincore + off;
486 if (off + len > key->size)
488 /* we now have the offset, go into vertical */
489 off += data->verticaloffset[key - data->keys];
490 /* fprintf(stderr, "key %d page %d\n", key->name, off / REPOPAGE_BLOBSIZE); */
491 dp = repopagestore_load_page_range(&data->store, off / REPOPAGE_BLOBSIZE, (off + len - 1) / REPOPAGE_BLOBSIZE);
493 dp += off % REPOPAGE_BLOBSIZE;
497 static inline unsigned char *
498 get_data(Repodata *data, Repokey *key, unsigned char **dpp, int advance)
500 unsigned char *dp = *dpp;
504 if (key->storage == KEY_STORAGE_INCORE)
507 *dpp = data_skip_key(data, dp, key);
510 else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
513 dp = data_read_id(dp, &off);
514 dp = data_read_id(dp, &len);
517 return get_vertical_data(data, key, off, len);
523 load_repodata(Repodata *data)
525 if (data->loadcallback)
527 data->loadcallback(data);
528 if (data->state == REPODATA_AVAILABLE)
531 data->state = REPODATA_ERROR;
536 maybe_load_repodata(Repodata *data, Id keyname)
538 if (keyname && !repodata_precheck_keyname(data, keyname))
539 return 0; /* do not bother... */
546 for (i = 1; i < data->nkeys; i++)
547 if (keyname == data->keys[i].name)
549 if (i == data->nkeys)
552 return load_repodata(data);
555 case REPODATA_AVAILABLE:
556 case REPODATA_LOADING:
559 data->state = REPODATA_ERROR;
564 static inline unsigned char *
565 solvid2data(Repodata *data, Id solvid, Id *schemap)
567 unsigned char *dp = data->incoredata;
570 if (solvid == SOLVID_META) /* META */
572 else if (solvid == SOLVID_POS) /* META */
574 Pool *pool = data->repo->pool;
575 if (data->repo != pool->pos.repo)
577 if (data != data->repo->repodata + pool->pos.repodataid)
579 *schemap = pool->pos.schema;
580 return data->incoredata + pool->pos.dp;
584 if (solvid < data->start || solvid >= data->end)
586 dp += data->incoreoffset[solvid - data->start];
588 return data_read_id(dp, schemap);
591 /************************************************************************
595 static inline unsigned char *
596 find_key_data(Repodata *data, Id solvid, Id keyname, Repokey **keypp)
599 Id schema, *keyp, *kp;
602 if (!maybe_load_repodata(data, keyname))
604 dp = solvid2data(data, solvid, &schema);
607 keyp = data->schemadata + data->schemata[schema];
608 for (kp = keyp; *kp; kp++)
609 if (data->keys[*kp].name == keyname)
613 *keypp = key = data->keys + *kp;
614 if (key->type == REPOKEY_TYPE_DELETED)
616 if (key->type == REPOKEY_TYPE_VOID || key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID)
617 return dp; /* no need to forward... */
618 dp = forward_to_key(data, *kp, keyp, dp);
621 return get_data(data, key, &dp, 0);
625 repodata_lookup_type(Repodata *data, Id solvid, Id keyname)
627 Id schema, *keyp, *kp;
628 if (!maybe_load_repodata(data, keyname))
630 if (!solvid2data(data, solvid, &schema))
632 keyp = data->schemadata + data->schemata[schema];
633 for (kp = keyp; *kp; kp++)
634 if (data->keys[*kp].name == keyname)
635 return data->keys[*kp].type;
640 repodata_lookup_id(Repodata *data, Id solvid, Id keyname)
646 dp = find_key_data(data, solvid, keyname, &key);
649 if (key->type == REPOKEY_TYPE_CONSTANTID)
651 if (key->type != REPOKEY_TYPE_ID)
653 dp = data_read_id(dp, &id);
658 repodata_lookup_str(Repodata *data, Id solvid, Id keyname)
664 dp = find_key_data(data, solvid, keyname, &key);
667 if (key->type == REPOKEY_TYPE_STR)
668 return (const char *)dp;
669 if (key->type == REPOKEY_TYPE_CONSTANTID)
671 else if (key->type == REPOKEY_TYPE_ID)
672 dp = data_read_id(dp, &id);
676 return stringpool_id2str(&data->spool, id);
677 return pool_id2str(data->repo->pool, id);
681 repodata_lookup_num(Repodata *data, Id solvid, Id keyname, unsigned long long *value)
688 dp = find_key_data(data, solvid, keyname, &key);
691 if (key->type == REPOKEY_TYPE_NUM
692 || key->type == REPOKEY_TYPE_U32
693 || key->type == REPOKEY_TYPE_CONSTANT)
695 kv.num = kv.num2 = 0;
696 dp = data_fetch(dp, &kv, key);
697 *value = SOLV_KV_NUM64(&kv);
704 repodata_lookup_void(Repodata *data, Id solvid, Id keyname)
710 if (!maybe_load_repodata(data, keyname))
712 dp = solvid2data(data, solvid, &schema);
715 /* can't use find_key_data as we need to test the type */
716 for (keyp = data->schemadata + data->schemata[schema]; *keyp; keyp++)
717 if (data->keys[*keyp].name == keyname && data->keys[*keyp].type == REPOKEY_TYPE_VOID)
722 const unsigned char *
723 repodata_lookup_bin_checksum(Repodata *data, Id solvid, Id keyname, Id *typep)
728 dp = find_key_data(data, solvid, keyname, &key);
736 repodata_lookup_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
744 dp = find_key_data(data, solvid, keyname, &key);
747 if (key->type != REPOKEY_TYPE_IDARRAY && key->type != REPOKEY_TYPE_REL_IDARRAY)
751 dp = data_read_ideof(dp, &id, &eof);
760 repodata_globalize_id(Repodata *data, Id id, int create)
762 if (!id || !data || !data->localpool)
764 return pool_str2id(data->repo->pool, stringpool_id2str(&data->spool, id), create);
768 repodata_localize_id(Repodata *data, Id id, int create)
770 if (!id || !data || !data->localpool)
772 return stringpool_str2id(&data->spool, pool_id2str(data->repo->pool, id), create);
776 repodata_lookup_id_uninternalized(Repodata *data, Id solvid, Id keyname, Id voidid)
781 ap = data->attrs[solvid - data->start];
786 if (data->keys[*ap].name != keyname)
788 if (data->keys[*ap].type == REPOKEY_TYPE_VOID)
790 if (data->keys[*ap].type == REPOKEY_TYPE_ID)
798 /************************************************************************
804 repodata_stringify(Pool *pool, Repodata *data, Repokey *key, KeyValue *kv, int flags)
808 case REPOKEY_TYPE_ID:
809 case REPOKEY_TYPE_CONSTANTID:
810 case REPOKEY_TYPE_IDARRAY:
811 if (data && data->localpool)
812 kv->str = stringpool_id2str(&data->spool, kv->id);
814 kv->str = pool_id2str(pool, kv->id);
815 if ((flags & SEARCH_SKIP_KIND) != 0 && key->storage == KEY_STORAGE_SOLVABLE)
818 for (s = kv->str; *s >= 'a' && *s <= 'z'; s++)
820 if (*s == ':' && s > kv->str)
824 case REPOKEY_TYPE_STR:
826 case REPOKEY_TYPE_DIRSTRARRAY:
827 if (!(flags & SEARCH_FILES))
828 return 1; /* match just the basename */
829 /* Put the full filename into kv->str. */
830 kv->str = repodata_dir2str(data, kv->id, kv->str);
831 /* And to compensate for that put the "empty" directory into
832 kv->id, so that later calls to repodata_dir2str on this data
833 come up with the same filename again. */
836 case REPOKEY_TYPE_MD5:
837 case REPOKEY_TYPE_SHA1:
838 case REPOKEY_TYPE_SHA256:
839 if (!(flags & SEARCH_CHECKSUMS))
840 return 0; /* skip em */
841 kv->str = repodata_chk2str(data, key->type, (const unsigned char *)kv->str);
849 struct subschema_data {
855 /* search a specific repodata */
857 repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata)
861 Id keyid, *kp, *keyp;
862 unsigned char *dp, *ddp;
868 if (!maybe_load_repodata(data, keyname))
870 if (solvid == SOLVID_SUBSCHEMA)
872 struct subschema_data *subd = cbdata;
873 cbdata = subd->cbdata;
875 schema = subd->parent->id;
876 dp = (unsigned char *)subd->parent->str;
877 kv.parent = subd->parent;
882 dp = solvid2data(data, solvid, &schema);
885 s = data->repo->pool->solvables + solvid;
888 keyp = data->schemadata + data->schemata[schema];
891 /* search for a specific key */
892 for (kp = keyp; *kp; kp++)
893 if (data->keys[*kp].name == keyname)
897 dp = forward_to_key(data, *kp, keyp, dp);
903 while ((keyid = *keyp++) != 0)
906 key = data->keys + keyid;
907 ddp = get_data(data, key, &dp, *keyp ? 1 : 0);
909 if (key->type == REPOKEY_TYPE_DELETED)
911 if (key->type == REPOKEY_TYPE_FLEXARRAY || key->type == REPOKEY_TYPE_FIXARRAY)
913 struct subschema_data subd;
917 subd.cbdata = cbdata;
920 ddp = data_read_id(ddp, &nentries);
924 while (ddp && nentries > 0)
928 if (key->type == REPOKEY_TYPE_FLEXARRAY || !kv.entry)
929 ddp = data_read_id(ddp, &schema);
931 kv.str = (char *)ddp;
932 stop = callback(cbdata, s, data, key, &kv);
933 if (stop > SEARCH_NEXT_KEY)
935 if (stop && stop != SEARCH_ENTERSUB)
937 if ((flags & SEARCH_SUB) != 0 || stop == SEARCH_ENTERSUB)
938 repodata_search(data, SOLVID_SUBSCHEMA, 0, flags, callback, &subd);
939 ddp = data_skip_schema(data, ddp, schema);
942 if (!nentries && (flags & SEARCH_ARRAYSENTINEL) != 0)
946 kv.str = (char *)ddp;
947 stop = callback(cbdata, s, data, key, &kv);
948 if (stop > SEARCH_NEXT_KEY)
958 ddp = data_fetch(ddp, &kv, key);
961 stop = callback(cbdata, s, data, key, &kv);
964 while (!kv.eof && !stop);
965 if (onekey || stop > SEARCH_NEXT_KEY)
971 repodata_setpos_kv(Repodata *data, KeyValue *kv)
973 Pool *pool = data->repo->pool;
975 pool_clear_pos(pool);
978 pool->pos.repo = data->repo;
979 pool->pos.repodataid = data - data->repo->repodata;
980 pool->pos.dp = (unsigned char *)kv->str - data->incoredata;
981 pool->pos.schema = kv->id;
985 /************************************************************************
986 * data iterator functions
990 solvabledata_fetch(Solvable *s, KeyValue *kv, Id keyname)
1004 case SOLVABLE_VENDOR:
1007 case SOLVABLE_PROVIDES:
1009 return s->provides ? s->repo->idarraydata + s->provides : 0;
1010 case SOLVABLE_OBSOLETES:
1012 return s->obsoletes ? s->repo->idarraydata + s->obsoletes : 0;
1013 case SOLVABLE_CONFLICTS:
1015 return s->conflicts ? s->repo->idarraydata + s->conflicts : 0;
1016 case SOLVABLE_REQUIRES:
1018 return s->requires ? s->repo->idarraydata + s->requires : 0;
1019 case SOLVABLE_RECOMMENDS:
1021 return s->recommends ? s->repo->idarraydata + s->recommends : 0;
1022 case SOLVABLE_SUPPLEMENTS:
1024 return s->supplements ? s->repo->idarraydata + s->supplements : 0;
1025 case SOLVABLE_SUGGESTS:
1027 return s->suggests ? s->repo->idarraydata + s->suggests : 0;
1028 case SOLVABLE_ENHANCES:
1030 return s->enhances ? s->repo->idarraydata + s->enhances : 0;
1033 return s->repo->rpmdbid ? s->repo->rpmdbid + (s - s->repo->pool->solvables - s->repo->start) : 0;
1040 datamatcher_init(Datamatcher *ma, const char *match, int flags)
1046 if ((flags & SEARCH_STRINGMASK) == SEARCH_REGEX)
1048 ma->matchdata = solv_calloc(1, sizeof(regex_t));
1049 ma->error = regcomp((regex_t *)ma->matchdata, match, REG_EXTENDED | REG_NOSUB | REG_NEWLINE | ((flags & SEARCH_NOCASE) ? REG_ICASE : 0));
1052 solv_free(ma->matchdata);
1053 ma->flags = (flags & ~SEARCH_STRINGMASK) | SEARCH_ERROR;
1060 datamatcher_free(Datamatcher *ma)
1062 if ((ma->flags & SEARCH_STRINGMASK) == SEARCH_REGEX && ma->matchdata)
1064 regfree(ma->matchdata);
1065 ma->matchdata = solv_free(ma->matchdata);
1070 datamatcher_match(Datamatcher *ma, const char *str)
1073 switch ((ma->flags & SEARCH_STRINGMASK))
1075 case SEARCH_SUBSTRING:
1076 if (ma->flags & SEARCH_NOCASE)
1078 if (!strcasestr(str, ma->match))
1083 if (!strstr(str, ma->match))
1088 if (ma->flags & SEARCH_NOCASE)
1090 if (strcasecmp(ma->match, str))
1095 if (strcmp(ma->match, str))
1099 case SEARCH_STRINGSTART:
1100 if (ma->flags & SEARCH_NOCASE)
1102 if (strncasecmp(ma->match, str, strlen(ma->match)))
1107 if (strncmp(ma->match, str, strlen(ma->match)))
1111 case SEARCH_STRINGEND:
1112 l = strlen(str) - strlen(ma->match);
1115 if (ma->flags & SEARCH_NOCASE)
1117 if (strcasecmp(ma->match, str + l))
1122 if (strcmp(ma->match, str + l))
1127 if (fnmatch(ma->match, str, (ma->flags & SEARCH_NOCASE) ? FNM_CASEFOLD : 0))
1131 if (regexec((const regex_t *)ma->matchdata, str, 0, NULL, 0))
1141 repodata_filelistfilter_matches(Repodata *data, const char *str)
1143 /* '.*bin\/.*', '^\/etc\/.*', '^\/usr\/lib\/sendmail$' */
1144 /* for now hardcoded */
1145 if (strstr(str, "bin/"))
1147 if (!strncmp(str, "/etc/", 5))
1149 if (!strcmp(str, "/usr/lib/sendmail"))
1171 di_nextarrayelement,
1177 di_entersolvablekey,
1181 /* see dataiterator.h for documentation */
1183 dataiterator_init(Dataiterator *di, Pool *pool, Repo *repo, Id p, Id keyname, const char *match, int flags)
1185 memset(di, 0, sizeof(*di));
1187 di->flags = flags & ~SEARCH_THISSOLVID;
1188 if (!pool || (repo && repo->pool != pool))
1196 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1202 di->keyname = keyname;
1203 di->keynames[0] = keyname;
1204 dataiterator_set_search(di, repo, p);
1209 dataiterator_init_clone(Dataiterator *di, Dataiterator *from)
1212 memset(&di->matcher, 0, sizeof(di->matcher));
1213 if (from->matcher.match)
1214 datamatcher_init(&di->matcher, from->matcher.match, from->matcher.flags);
1219 for (i = 1; i < di->nparents; i++)
1220 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1221 di->kv.parent = &di->parents[di->nparents - 1].kv;
1226 dataiterator_set_match(Dataiterator *di, const char *match, int flags)
1228 di->flags = (flags & ~SEARCH_THISSOLVID) | (di->flags & SEARCH_THISSOLVID);
1229 datamatcher_free(&di->matcher);
1230 memset(&di->matcher, 0, sizeof(di->matcher));
1234 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1244 dataiterator_set_search(Dataiterator *di, Repo *repo, Id p)
1248 di->flags &= ~SEARCH_THISSOLVID;
1252 if (!di->pool->urepos)
1260 di->repo = di->pool->repos[di->repoid];
1262 di->state = di_enterrepo;
1264 dataiterator_jump_to_solvid(di, p);
1268 dataiterator_set_keyname(Dataiterator *di, Id keyname)
1271 di->keyname = keyname;
1272 di->keynames[0] = keyname;
1276 dataiterator_prepend_keyname(Dataiterator *di, Id keyname)
1280 if (di->nkeynames >= sizeof(di->keynames)/sizeof(*di->keynames) - 2)
1282 di->state = di_bye; /* sorry */
1285 for (i = di->nkeynames + 1; i > 0; i--)
1286 di->keynames[i] = di->keynames[i - 1];
1287 di->keynames[0] = di->keyname = keyname;
1292 dataiterator_free(Dataiterator *di)
1294 if (di->matcher.match)
1295 datamatcher_free(&di->matcher);
1298 static inline unsigned char *
1299 dataiterator_find_keyname(Dataiterator *di, Id keyname)
1301 Id *keyp = di->keyp;
1302 Repokey *keys = di->data->keys;
1305 for (keyp = di->keyp; *keyp; keyp++)
1306 if (keys[*keyp].name == keyname)
1310 dp = forward_to_key(di->data, *keyp, di->keyp, di->dp);
1318 dataiterator_filelistcheck(Dataiterator *di)
1321 int needcomplete = 0;
1322 Repodata *data = di->data;
1324 if ((di->matcher.flags & SEARCH_COMPLETE_FILELIST) != 0)
1325 if (!di->matcher.match
1326 || ((di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_STRING
1327 && (di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_GLOB)
1328 || !repodata_filelistfilter_matches(di->data, di->matcher.match))
1330 if (data->state != REPODATA_AVAILABLE)
1331 return needcomplete ? 1 : 0;
1332 for (j = 1; j < data->nkeys; j++)
1333 if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
1335 return j == data->nkeys && !needcomplete ? 0 : 1;
1339 dataiterator_step(Dataiterator *di)
1347 case di_enterrepo: di_enterrepo:
1348 if (!di->repo || (di->repo->disabled && !(di->flags & SEARCH_DISABLED_REPOS)))
1350 if (!(di->flags & SEARCH_THISSOLVID))
1352 di->solvid = di->repo->start - 1; /* reset solvid iterator */
1353 goto di_nextsolvable;
1357 case di_entersolvable: di_entersolvable:
1360 di->repodataid = 1; /* reset repodata iterator */
1361 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)
1363 extern Repokey repo_solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1];
1365 di->key = repo_solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0);
1367 goto di_entersolvablekey;
1372 case di_enterrepodata: di_enterrepodata:
1375 if (di->repodataid >= di->repo->nrepodata)
1376 goto di_nextsolvable;
1377 di->data = di->repo->repodata + di->repodataid;
1379 if (di->repodataid && di->keyname == SOLVABLE_FILELIST && !dataiterator_filelistcheck(di))
1380 goto di_nextrepodata;
1381 if (!maybe_load_repodata(di->data, di->keyname))
1382 goto di_nextrepodata;
1383 di->dp = solvid2data(di->data, di->solvid, &schema);
1385 goto di_nextrepodata;
1386 if (di->solvid == SOLVID_POS)
1387 di->solvid = di->pool->pos.solvid;
1388 /* reset key iterator */
1389 di->keyp = di->data->schemadata + di->data->schemata[schema];
1392 case di_enterschema: di_enterschema:
1394 di->dp = dataiterator_find_keyname(di, di->keyname);
1395 if (!di->dp || !*di->keyp)
1399 goto di_nextrepodata;
1403 case di_enterkey: di_enterkey:
1405 di->key = di->data->keys + *di->keyp;
1406 di->ddp = get_data(di->data, di->key, &di->dp, di->keyp[1] && (!di->keyname || (di->flags & SEARCH_SUB) != 0) ? 1 : 0);
1409 if (di->key->type == REPOKEY_TYPE_DELETED)
1411 if (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY)
1413 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1419 di->ddp = data_fetch(di->ddp, &di->kv, di->key);
1421 di->state = di_nextkey;
1423 di->state = di_nextattr;
1426 case di_nextkey: di_nextkey:
1427 if (!di->keyname && *++di->keyp)
1433 case di_nextrepodata: di_nextrepodata:
1434 if (di->repodataid && ++di->repodataid < di->repo->nrepodata)
1435 goto di_enterrepodata;
1438 case di_nextsolvable: di_nextsolvable:
1439 if (!(di->flags & SEARCH_THISSOLVID))
1442 di->solvid = di->repo->start;
1445 for (; di->solvid < di->repo->end; di->solvid++)
1447 if (di->pool->solvables[di->solvid].repo == di->repo)
1448 goto di_entersolvable;
1453 case di_nextrepo: di_nextrepo:
1458 if (di->repoid < di->pool->nrepos)
1460 di->repo = di->pool->repos[di->repoid];
1466 case di_bye: di_bye:
1470 case di_enterarray: di_enterarray:
1471 if (di->key->name == REPOSITORY_SOLVABLES)
1473 di->ddp = data_read_id(di->ddp, (Id *)&di->kv.num);
1478 case di_nextarrayelement: di_nextarrayelement:
1481 di->ddp = data_skip_schema(di->data, di->ddp, di->kv.id);
1482 if (di->kv.entry == di->kv.num)
1484 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1486 if (!(di->flags & SEARCH_ARRAYSENTINEL))
1488 di->kv.str = (char *)di->ddp;
1490 di->state = di_nextkey;
1493 if (di->kv.entry == di->kv.num - 1)
1495 if (di->key->type == REPOKEY_TYPE_FLEXARRAY || !di->kv.entry)
1496 di->ddp = data_read_id(di->ddp, &di->kv.id);
1497 di->kv.str = (char *)di->ddp;
1498 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1500 if ((di->flags & SEARCH_SUB) != 0)
1501 di->state = di_entersub;
1503 di->state = di_nextarrayelement;
1506 case di_entersub: di_entersub:
1507 if (di->nparents == sizeof(di->parents)/sizeof(*di->parents) - 1)
1508 goto di_nextarrayelement; /* sorry, full */
1509 di->parents[di->nparents].kv = di->kv;
1510 di->parents[di->nparents].dp = di->dp;
1511 di->parents[di->nparents].keyp = di->keyp;
1512 di->dp = (unsigned char *)di->kv.str;
1513 di->keyp = di->data->schemadata + di->data->schemata[di->kv.id];
1514 memset(&di->kv, 0, sizeof(di->kv));
1515 di->kv.parent = &di->parents[di->nparents].kv;
1517 di->keyname = di->keynames[di->nparents - di->rootlevel];
1518 goto di_enterschema;
1520 case di_leavesub: di_leavesub:
1521 if (di->nparents - 1 < di->rootlevel)
1524 di->dp = di->parents[di->nparents].dp;
1525 di->kv = di->parents[di->nparents].kv;
1526 di->keyp = di->parents[di->nparents].keyp;
1527 di->key = di->data->keys + *di->keyp;
1528 di->ddp = (unsigned char *)di->kv.str;
1529 di->keyname = di->keynames[di->nparents - di->rootlevel];
1530 goto di_nextarrayelement;
1532 /* special solvable attr handling follows */
1534 case di_nextsolvablekey: di_nextsolvablekey:
1535 if (di->keyname || di->key->name == RPM_RPMDBID)
1536 goto di_enterrepodata;
1540 case di_entersolvablekey: di_entersolvablekey:
1541 di->idp = solvabledata_fetch(di->pool->solvables + di->solvid, &di->kv, di->key->name);
1542 if (!di->idp || !*di->idp)
1543 goto di_nextsolvablekey;
1547 di->kv.id = *di->idp;
1548 di->kv.num = *di->idp; /* for rpmdbid */
1549 di->kv.num2 = 0; /* for rpmdbid */
1551 di->state = di_nextsolvablekey;
1557 case di_nextsolvableattr:
1558 di->state = di_nextsolvableattr;
1559 di->kv.id = *di->idp++;
1564 di->state = di_nextsolvablekey;
1570 if (di->matcher.match)
1572 /* simple pre-check so that we don't need to stringify */
1573 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))
1575 int l = strlen(di->matcher.match) - strlen(di->kv.str);
1576 if (l < 0 || strcmp(di->matcher.match + l, di->kv.str))
1579 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1581 if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY))
1585 if (!datamatcher_match(&di->matcher, di->kv.str))
1588 /* found something! */
1594 dataiterator_entersub(Dataiterator *di)
1596 if (di->state == di_nextarrayelement)
1597 di->state = di_entersub;
1601 dataiterator_setpos(Dataiterator *di)
1603 if (di->kv.eof == 2)
1605 pool_clear_pos(di->pool);
1608 di->pool->pos.solvid = di->solvid;
1609 di->pool->pos.repo = di->repo;
1610 di->pool->pos.repodataid = di->data - di->repo->repodata;
1611 di->pool->pos.schema = di->kv.id;
1612 di->pool->pos.dp = (unsigned char *)di->kv.str - di->data->incoredata;
1616 dataiterator_setpos_parent(Dataiterator *di)
1618 if (!di->kv.parent || di->kv.parent->eof == 2)
1620 pool_clear_pos(di->pool);
1623 di->pool->pos.solvid = di->solvid;
1624 di->pool->pos.repo = di->repo;
1625 di->pool->pos.repodataid = di->data - di->repo->repodata;
1626 di->pool->pos.schema = di->kv.parent->id;
1627 di->pool->pos.dp = (unsigned char *)di->kv.parent->str - di->data->incoredata;
1630 /* clones just the position, not the search keys/matcher */
1632 dataiterator_clonepos(Dataiterator *di, Dataiterator *from)
1634 di->state = from->state;
1635 di->flags &= ~SEARCH_THISSOLVID;
1636 di->flags |= (from->flags & SEARCH_THISSOLVID);
1637 di->repo = from->repo;
1638 di->data = from->data;
1640 di->ddp = from->ddp;
1641 di->idp = from->idp;
1642 di->keyp = from->keyp;
1643 di->key = from->key;
1645 di->repodataid = from->repodataid;
1646 di->solvid = from->solvid;
1647 di->repoid = from->repoid;
1648 di->rootlevel = from->rootlevel;
1649 memcpy(di->parents, from->parents, sizeof(from->parents));
1650 di->nparents = from->nparents;
1654 for (i = 1; i < di->nparents; i++)
1655 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1656 di->kv.parent = &di->parents[di->nparents - 1].kv;
1661 dataiterator_seek(Dataiterator *di, int whence)
1663 if ((whence & DI_SEEK_STAY) != 0)
1664 di->rootlevel = di->nparents;
1665 switch (whence & ~DI_SEEK_STAY)
1668 if (di->state != di_nextarrayelement)
1670 if ((whence & DI_SEEK_STAY) != 0)
1671 di->rootlevel = di->nparents + 1; /* XXX: dangerous! */
1672 di->state = di_entersub;
1674 case DI_SEEK_PARENT:
1681 if (di->rootlevel > di->nparents)
1682 di->rootlevel = di->nparents;
1683 di->dp = di->parents[di->nparents].dp;
1684 di->kv = di->parents[di->nparents].kv;
1685 di->keyp = di->parents[di->nparents].keyp;
1686 di->key = di->data->keys + *di->keyp;
1687 di->ddp = (unsigned char *)di->kv.str;
1688 di->keyname = di->keynames[di->nparents - di->rootlevel];
1689 di->state = di_nextarrayelement;
1691 case DI_SEEK_REWIND:
1697 di->dp = (unsigned char *)di->kv.parent->str;
1698 di->keyp = di->data->schemadata + di->data->schemata[di->kv.parent->id];
1699 di->state = di_enterschema;
1707 dataiterator_skip_attribute(Dataiterator *di)
1709 if (di->state == di_nextsolvableattr)
1710 di->state = di_nextsolvablekey;
1712 di->state = di_nextkey;
1716 dataiterator_skip_solvable(Dataiterator *di)
1721 di->keyname = di->keynames[0];
1722 di->state = di_nextsolvable;
1726 dataiterator_skip_repo(Dataiterator *di)
1731 di->keyname = di->keynames[0];
1732 di->state = di_nextrepo;
1736 dataiterator_jump_to_solvid(Dataiterator *di, Id solvid)
1741 di->keyname = di->keynames[0];
1742 if (solvid == SOLVID_POS)
1744 di->repo = di->pool->pos.repo;
1751 di->data = di->repo->repodata + di->pool->pos.repodataid;
1753 di->solvid = solvid;
1754 di->state = di_enterrepo;
1755 di->flags |= SEARCH_THISSOLVID;
1760 di->repo = di->pool->solvables[solvid].repo;
1763 else if (di->repoid > 0)
1765 if (!di->pool->urepos)
1771 di->repo = di->pool->repos[di->repoid];
1774 di->solvid = solvid;
1776 di->flags |= SEARCH_THISSOLVID;
1777 di->state = di_enterrepo;
1781 dataiterator_jump_to_repo(Dataiterator *di, Repo *repo)
1787 di->repoid = 0; /* 0 means stay at repo */
1790 di->flags &= ~SEARCH_THISSOLVID;
1791 di->state = di_enterrepo;
1795 dataiterator_match(Dataiterator *di, Datamatcher *ma)
1797 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1801 return datamatcher_match(ma, di->kv.str);
1804 /************************************************************************
1805 * data modify functions
1808 /* extend repodata so that it includes solvables p */
1810 repodata_extend(Repodata *data, Id p)
1812 if (data->start == data->end)
1813 data->start = data->end = p;
1816 int old = data->end - data->start;
1817 int new = p - data->end + 1;
1820 data->attrs = solv_extend(data->attrs, old, new, sizeof(Id *), REPODATA_BLOCK);
1821 memset(data->attrs + old, 0, new * sizeof(Id *));
1823 data->incoreoffset = solv_extend(data->incoreoffset, old, new, sizeof(Id), REPODATA_BLOCK);
1824 memset(data->incoreoffset + old, 0, new * sizeof(Id));
1827 if (p < data->start)
1829 int old = data->end - data->start;
1830 int new = data->start - p;
1833 data->attrs = solv_extend_resize(data->attrs, old + new, sizeof(Id *), REPODATA_BLOCK);
1834 memmove(data->attrs + new, data->attrs, old * sizeof(Id *));
1835 memset(data->attrs, 0, new * sizeof(Id *));
1837 data->incoreoffset = solv_extend_resize(data->incoreoffset, old + new, sizeof(Id), REPODATA_BLOCK);
1838 memmove(data->incoreoffset + new, data->incoreoffset, old * sizeof(Id));
1839 memset(data->incoreoffset, 0, new * sizeof(Id));
1844 /* shrink end of repodata */
1846 repodata_shrink(Repodata *data, int end)
1850 if (data->end <= end)
1852 if (data->start >= end)
1856 for (i = 0; i < data->end - data->start; i++)
1857 solv_free(data->attrs[i]);
1858 data->attrs = solv_free(data->attrs);
1860 data->incoreoffset = solv_free(data->incoreoffset);
1861 data->start = data->end = 0;
1866 for (i = end; i < data->end; i++)
1867 solv_free(data->attrs[i - data->start]);
1868 data->attrs = solv_extend_resize(data->attrs, end - data->start, sizeof(Id *), REPODATA_BLOCK);
1870 if (data->incoreoffset)
1871 data->incoreoffset = solv_extend_resize(data->incoreoffset, end - data->start, sizeof(Id), REPODATA_BLOCK);
1875 /* extend repodata so that it includes solvables from start to start + num - 1 */
1877 repodata_extend_block(Repodata *data, Id start, Id num)
1881 if (!data->incoreoffset)
1883 data->incoreoffset = solv_calloc_block(num, sizeof(Id), REPODATA_BLOCK);
1884 data->start = start;
1885 data->end = start + num;
1888 repodata_extend(data, start);
1890 repodata_extend(data, start + num - 1);
1893 /**********************************************************************/
1896 #define REPODATA_ATTRS_BLOCK 31
1897 #define REPODATA_ATTRDATA_BLOCK 1023
1898 #define REPODATA_ATTRIDDATA_BLOCK 63
1899 #define REPODATA_ATTRNUM64DATA_BLOCK 15
1903 repodata_new_handle(Repodata *data)
1907 data->xattrs = solv_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1908 data->nxattrs = 2; /* -1: SOLVID_META */
1910 data->xattrs = solv_extend(data->xattrs, data->nxattrs, 1, sizeof(Id *), REPODATA_BLOCK);
1911 data->xattrs[data->nxattrs] = 0;
1912 return -(data->nxattrs++);
1916 repodata_get_attrp(Repodata *data, Id handle)
1920 if (handle == SOLVID_META && !data->xattrs)
1922 data->xattrs = solv_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1925 return data->xattrs - handle;
1927 if (handle < data->start || handle >= data->end)
1928 repodata_extend(data, handle);
1930 data->attrs = solv_calloc_block(data->end - data->start, sizeof(Id *), REPODATA_BLOCK);
1931 return data->attrs + (handle - data->start);
1935 repodata_insert_keyid(Repodata *data, Id handle, Id keyid, Id val, int overwrite)
1941 app = repodata_get_attrp(data, handle);
1946 /* Determine equality based on the name only, allows us to change
1947 type (when overwrite is set), and makes TYPE_CONSTANT work. */
1948 for (pp = ap; *pp; pp += 2)
1949 if (data->keys[*pp].name == data->keys[keyid].name)
1953 if (overwrite || data->keys[*pp].type == REPOKEY_TYPE_DELETED)
1962 ap = solv_extend(ap, i, 3, sizeof(Id), REPODATA_ATTRS_BLOCK);
1972 repodata_set(Repodata *data, Id solvid, Repokey *key, Id val)
1976 keyid = repodata_key2id(data, key, 1);
1977 repodata_insert_keyid(data, solvid, keyid, val, 1);
1981 repodata_set_id(Repodata *data, Id solvid, Id keyname, Id id)
1985 key.type = REPOKEY_TYPE_ID;
1987 key.storage = KEY_STORAGE_INCORE;
1988 repodata_set(data, solvid, &key, id);
1992 repodata_set_num(Repodata *data, Id solvid, Id keyname, unsigned long long num)
1996 key.type = REPOKEY_TYPE_NUM;
1998 key.storage = KEY_STORAGE_INCORE;
1999 if (num >= 0x80000000)
2001 data->attrnum64data = solv_extend(data->attrnum64data, data->attrnum64datalen, 1, sizeof(unsigned long long), REPODATA_ATTRNUM64DATA_BLOCK);
2002 data->attrnum64data[data->attrnum64datalen] = num;
2003 num = 0x80000000 | data->attrnum64datalen++;
2005 repodata_set(data, solvid, &key, (Id)num);
2009 repodata_set_poolstr(Repodata *data, Id solvid, Id keyname, const char *str)
2013 if (data->localpool)
2014 id = stringpool_str2id(&data->spool, str, 1);
2016 id = pool_str2id(data->repo->pool, str, 1);
2018 key.type = REPOKEY_TYPE_ID;
2020 key.storage = KEY_STORAGE_INCORE;
2021 repodata_set(data, solvid, &key, id);
2025 repodata_set_constant(Repodata *data, Id solvid, Id keyname, unsigned int constant)
2029 key.type = REPOKEY_TYPE_CONSTANT;
2030 key.size = constant;
2031 key.storage = KEY_STORAGE_INCORE;
2032 repodata_set(data, solvid, &key, 0);
2036 repodata_set_constantid(Repodata *data, Id solvid, Id keyname, Id id)
2040 key.type = REPOKEY_TYPE_CONSTANTID;
2042 key.storage = KEY_STORAGE_INCORE;
2043 repodata_set(data, solvid, &key, 0);
2047 repodata_set_void(Repodata *data, Id solvid, Id keyname)
2051 key.type = REPOKEY_TYPE_VOID;
2053 key.storage = KEY_STORAGE_INCORE;
2054 repodata_set(data, solvid, &key, 0);
2058 repodata_set_str(Repodata *data, Id solvid, Id keyname, const char *str)
2063 l = strlen(str) + 1;
2065 key.type = REPOKEY_TYPE_STR;
2067 key.storage = KEY_STORAGE_INCORE;
2068 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2069 memcpy(data->attrdata + data->attrdatalen, str, l);
2070 repodata_set(data, solvid, &key, data->attrdatalen);
2071 data->attrdatalen += l;
2075 repodata_set_binary(Repodata *data, Id solvid, Id keyname, void *buf, int len)
2083 key.type = REPOKEY_TYPE_BINARY;
2085 key.storage = KEY_STORAGE_INCORE;
2086 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, len + 5, 1, REPODATA_ATTRDATA_BLOCK);
2087 dp = data->attrdata + data->attrdatalen;
2088 if (len >= (1 << 14))
2090 if (len >= (1 << 28))
2091 *dp++ = (len >> 28) | 128;
2092 if (len >= (1 << 21))
2093 *dp++ = (len >> 21) | 128;
2094 *dp++ = (len >> 14) | 128;
2096 if (len >= (1 << 7))
2097 *dp++ = (len >> 7) | 128;
2100 memcpy(dp, buf, len);
2101 repodata_set(data, solvid, &key, data->attrdatalen);
2102 data->attrdatalen = dp + len - data->attrdata;
2105 /* add an array element consisting of entrysize Ids to the repodata. modifies attriddata
2106 * so that the caller can append entrysize new elements plus the termination zero there */
2108 repodata_add_array(Repodata *data, Id handle, Id keyname, Id keytype, int entrysize)
2111 Id *ida, *pp, **ppp;
2113 /* check if it is the same as last time, this speeds things up a lot */
2114 if (handle == data->lasthandle && data->keys[data->lastkey].name == keyname && data->keys[data->lastkey].type == keytype && data->attriddatalen == data->lastdatalen)
2116 /* great! just append the new data */
2117 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2118 data->attriddatalen--; /* overwrite terminating 0 */
2119 data->lastdatalen += entrysize;
2123 ppp = repodata_get_attrp(data, handle);
2127 for (; *pp; pp += 2)
2128 if (data->keys[*pp].name == keyname)
2131 if (!pp || !*pp || data->keys[*pp].type != keytype)
2133 /* not found. allocate new key */
2139 key.storage = KEY_STORAGE_INCORE;
2140 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2141 keyid = repodata_key2id(data, &key, 1);
2142 repodata_insert_keyid(data, handle, keyid, data->attriddatalen, 1);
2143 data->lasthandle = handle;
2144 data->lastkey = keyid;
2145 data->lastdatalen = data->attriddatalen + entrysize + 1;
2149 for (ida = data->attriddata + pp[1]; *ida; ida += entrysize)
2150 oldsize += entrysize;
2151 if (ida + 1 == data->attriddata + data->attriddatalen)
2153 /* this was the last entry, just append it */
2154 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2155 data->attriddatalen--; /* overwrite terminating 0 */
2159 /* too bad. move to back. */
2160 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, oldsize + entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2161 memcpy(data->attriddata + data->attriddatalen, data->attriddata + pp[1], oldsize * sizeof(Id));
2162 pp[1] = data->attriddatalen;
2163 data->attriddatalen += oldsize;
2165 data->lasthandle = handle;
2166 data->lastkey = *pp;
2167 data->lastdatalen = data->attriddatalen + entrysize + 1;
2171 repodata_set_bin_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2172 const unsigned char *str)
2177 if (!(l = solv_chksum_len(type)))
2182 key.storage = KEY_STORAGE_INCORE;
2183 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2184 memcpy(data->attrdata + data->attrdatalen, str, l);
2185 repodata_set(data, solvid, &key, data->attrdatalen);
2186 data->attrdatalen += l;
2190 repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2193 unsigned char buf[64];
2196 if (!(l = solv_chksum_len(type)))
2198 if (l > sizeof(buf) || solv_hex2bin(&str, buf, l) != l)
2200 repodata_set_bin_checksum(data, solvid, keyname, type, buf);
2204 repodata_chk2str(Repodata *data, Id type, const unsigned char *buf)
2208 if (!(l = solv_chksum_len(type)))
2210 return pool_bin2hex(data->repo->pool, buf, l);
2213 /* rpm filenames don't contain the epoch, so strip it */
2214 static inline const char *
2215 evrid2vrstr(Pool *pool, Id evrid)
2217 const char *p, *evr = pool_id2str(pool, evrid);
2220 for (p = evr; *p >= '0' && *p <= '9'; p++)
2222 return p != evr && *p == ':' ? p + 1 : evr;
2226 repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, const char *file)
2228 Pool *pool = data->repo->pool;
2230 const char *str, *fp;
2234 repodata_set_constant(data, solvid, SOLVABLE_MEDIANR, medianr);
2237 if ((dir = strrchr(file, '/')) != 0)
2248 if (l >= 2 && dir[0] == '.' && dir[1] == '/' && (l == 2 || dir[2] != '/'))
2253 if (l == 1 && dir[0] == '.')
2255 s = pool->solvables + solvid;
2258 str = pool_id2str(pool, s->arch);
2259 if (!strncmp(dir, str, l) && !str[l])
2260 repodata_set_void(data, solvid, SOLVABLE_MEDIADIR);
2262 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir);
2265 char *dir2 = solv_strdup(dir);
2267 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir2);
2272 str = pool_id2str(pool, s->name);
2274 if ((!l || !strncmp(fp, str, l)) && fp[l] == '-')
2277 str = evrid2vrstr(pool, s->evr);
2279 if ((!l || !strncmp(fp, str, l)) && fp[l] == '.')
2282 str = pool_id2str(pool, s->arch);
2284 if ((!l || !strncmp(fp, str, l)) && !strcmp(fp + l, ".rpm"))
2286 repodata_set_void(data, solvid, SOLVABLE_MEDIAFILE);
2291 repodata_set_str(data, solvid, SOLVABLE_MEDIAFILE, file);
2295 repodata_set_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
2301 key.type = REPOKEY_TYPE_IDARRAY;
2303 key.storage = KEY_STORAGE_INCORE;
2304 repodata_set(data, solvid, &key, data->attriddatalen);
2305 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, q->count + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2306 for (i = 0; i < q->count; i++)
2307 data->attriddata[data->attriddatalen++] = q->elements[i];
2308 data->attriddata[data->attriddatalen++] = 0;
2312 repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2)
2316 fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", solvid, dir, num, num2, data->attriddatalen);
2318 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRNUMNUMARRAY, 3);
2319 data->attriddata[data->attriddatalen++] = dir;
2320 data->attriddata[data->attriddatalen++] = num;
2321 data->attriddata[data->attriddatalen++] = num2;
2322 data->attriddata[data->attriddatalen++] = 0;
2326 repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str)
2332 l = strlen(str) + 1;
2333 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2334 memcpy(data->attrdata + data->attrdatalen, str, l);
2335 stroff = data->attrdatalen;
2336 data->attrdatalen += l;
2339 fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", solvid, dir, str, data->attriddatalen);
2341 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRSTRARRAY, 2);
2342 data->attriddata[data->attriddatalen++] = dir;
2343 data->attriddata[data->attriddatalen++] = stroff;
2344 data->attriddata[data->attriddatalen++] = 0;
2348 repodata_add_idarray(Repodata *data, Id solvid, Id keyname, Id id)
2351 fprintf(stderr, "repodata_add_idarray %d %d (%d)\n", solvid, id, data->attriddatalen);
2353 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_IDARRAY, 1);
2354 data->attriddata[data->attriddatalen++] = id;
2355 data->attriddata[data->attriddatalen++] = 0;
2359 repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname,
2363 if (data->localpool)
2364 id = stringpool_str2id(&data->spool, str, 1);
2366 id = pool_str2id(data->repo->pool, str, 1);
2367 repodata_add_idarray(data, solvid, keyname, id);
2371 repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2373 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FIXARRAY, 1);
2374 data->attriddata[data->attriddatalen++] = ghandle;
2375 data->attriddata[data->attriddatalen++] = 0;
2379 repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2381 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FLEXARRAY, 1);
2382 data->attriddata[data->attriddatalen++] = ghandle;
2383 data->attriddata[data->attriddatalen++] = 0;
2387 repodata_delete_uninternalized(Repodata *data, Id solvid, Id keyname)
2390 app = repodata_get_attrp(data, solvid);
2394 for (; *ap; ap += 2)
2395 if (data->keys[*ap].name == keyname)
2401 for (; *ap; ap += 2)
2403 if (data->keys[*ap].name == keyname)
2411 /* XXX: does not work correctly, needs fix in iterators! */
2413 repodata_delete(Repodata *data, Id solvid, Id keyname)
2417 key.type = REPOKEY_TYPE_DELETED;
2419 key.storage = KEY_STORAGE_INCORE;
2420 repodata_set(data, solvid, &key, 0);
2423 /* add all (uninternalized) attrs from src to dest */
2425 repodata_merge_attrs(Repodata *data, Id dest, Id src)
2428 if (dest == src || !data->attrs || !(keyp = data->attrs[src - data->start]))
2430 for (; *keyp; keyp += 2)
2431 repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
2434 /* add some (uninternalized) attrs from src to dest */
2436 repodata_merge_some_attrs(Repodata *data, Id dest, Id src, Map *keyidmap, int overwrite)
2439 if (dest == src || !data->attrs || !(keyp = data->attrs[src - data->start]))
2441 for (; *keyp; keyp += 2)
2442 if (!keyidmap || MAPTST(keyidmap, keyp[0]))
2443 repodata_insert_keyid(data, dest, keyp[0], keyp[1], overwrite);
2446 /* swap (uninternalized) attrs from src and dest */
2448 repodata_swap_attrs(Repodata *data, Id dest, Id src)
2451 if (!data->attrs || dest == src)
2453 tmpattrs = data->attrs[dest - data->start];
2454 data->attrs[dest - data->start] = data->attrs[src - data->start];
2455 data->attrs[src - data->start] = tmpattrs;
2459 /**********************************************************************/
2461 /* TODO: unify with repo_write and repo_solv! */
2463 #define EXTDATA_BLOCK 1023
2471 data_addid(struct extdata *xd, Id sx)
2473 unsigned int x = (unsigned int)sx;
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_addid64(struct extdata *xd, unsigned long long x)
2496 if (x >= 0x100000000)
2500 data_addid(xd, (Id)(x >> 35));
2501 xd->buf[xd->len - 1] |= 128;
2503 data_addid(xd, (Id)((unsigned int)x | 0x80000000));
2504 xd->buf[xd->len - 5] = (x >> 28) | 128;
2507 data_addid(xd, (Id)x);
2511 data_addideof(struct extdata *xd, Id sx, int eof)
2513 unsigned int x = (unsigned int)sx;
2516 xd->buf = solv_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
2517 dp = xd->buf + xd->len;
2522 *dp++ = (x >> 27) | 128;
2524 *dp++ = (x >> 20) | 128;
2525 *dp++ = (x >> 13) | 128;
2528 *dp++ = (x >> 6) | 128;
2529 *dp++ = eof ? (x & 63) : (x & 63) | 64;
2530 xd->len = dp - xd->buf;
2534 data_addblob(struct extdata *xd, unsigned char *blob, int len)
2536 xd->buf = solv_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK);
2537 memcpy(xd->buf + xd->len, blob, len);
2541 /*********************************/
2543 /* internalalize some key into incore/vincore data */
2546 repodata_serialize_key(Repodata *data, struct extdata *newincore,
2547 struct extdata *newvincore,
2549 Repokey *key, Id val)
2553 unsigned int oldvincorelen = 0;
2557 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2560 oldvincorelen = xd->len;
2564 case REPOKEY_TYPE_VOID:
2565 case REPOKEY_TYPE_CONSTANT:
2566 case REPOKEY_TYPE_CONSTANTID:
2568 case REPOKEY_TYPE_STR:
2569 data_addblob(xd, data->attrdata + val, strlen((char *)(data->attrdata + val)) + 1);
2571 case REPOKEY_TYPE_MD5:
2572 data_addblob(xd, data->attrdata + val, SIZEOF_MD5);
2574 case REPOKEY_TYPE_SHA1:
2575 data_addblob(xd, data->attrdata + val, SIZEOF_SHA1);
2577 case REPOKEY_TYPE_SHA256:
2578 data_addblob(xd, data->attrdata + val, SIZEOF_SHA256);
2580 case REPOKEY_TYPE_NUM:
2581 if (val & 0x80000000)
2583 data_addid64(xd, data->attrnum64data[val ^ 0x80000000]);
2587 case REPOKEY_TYPE_ID:
2588 case REPOKEY_TYPE_DIR:
2589 data_addid(xd, val);
2591 case REPOKEY_TYPE_BINARY:
2594 unsigned char *dp = data_read_id(data->attrdata + val, &len);
2595 dp += (unsigned int)len;
2596 data_addblob(xd, data->attrdata + val, dp - (data->attrdata + val));
2599 case REPOKEY_TYPE_IDARRAY:
2600 for (ida = data->attriddata + val; *ida; ida++)
2601 data_addideof(xd, ida[0], ida[1] ? 0 : 1);
2603 case REPOKEY_TYPE_DIRNUMNUMARRAY:
2604 for (ida = data->attriddata + val; *ida; ida += 3)
2606 data_addid(xd, ida[0]);
2607 data_addid(xd, ida[1]);
2608 data_addideof(xd, ida[2], ida[3] ? 0 : 1);
2611 case REPOKEY_TYPE_DIRSTRARRAY:
2612 for (ida = data->attriddata + val; *ida; ida += 2)
2614 data_addideof(xd, ida[0], ida[2] ? 0 : 1);
2615 data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
2618 case REPOKEY_TYPE_FIXARRAY:
2622 for (ida = data->attriddata + val; *ida; ida++)
2626 kp = data->xattrs[-*ida];
2634 schemaid = repodata_schema2id(data, schema, 1);
2635 else if (schemaid != repodata_schema2id(data, schema, 0))
2637 pool_debug(data->repo->pool, SOLV_FATAL, "fixarray substructs with different schemas\n");
2643 data_addid(xd, num);
2644 data_addid(xd, schemaid);
2645 for (ida = data->attriddata + val; *ida; ida++)
2647 Id *kp = data->xattrs[-*ida];
2651 repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
2655 case REPOKEY_TYPE_FLEXARRAY:
2658 for (ida = data->attriddata + val; *ida; ida++)
2660 data_addid(xd, num);
2661 for (ida = data->attriddata + val; *ida; ida++)
2663 Id *kp = data->xattrs[-*ida];
2666 data_addid(xd, 0); /* XXX */
2673 schemaid = repodata_schema2id(data, schema, 1);
2674 data_addid(xd, schemaid);
2675 kp = data->xattrs[-*ida];
2677 repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
2682 pool_debug(data->repo->pool, SOLV_FATAL, "don't know how to handle type %d\n", key->type);
2685 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2687 /* put offset/len in incore */
2688 data_addid(newincore, data->lastverticaloffset + oldvincorelen);
2689 oldvincorelen = xd->len - oldvincorelen;
2690 data_addid(newincore, oldvincorelen);
2695 repodata_internalize(Repodata *data)
2697 Repokey *key, solvkey;
2699 Id schemaid, *schema, *sp, oldschema, *keyp, *keypstart, *seen;
2700 unsigned char *dp, *ndp;
2701 int newschema, oldcount;
2702 struct extdata newincore;
2703 struct extdata newvincore;
2706 if (!data->attrs && !data->xattrs)
2709 newvincore.buf = data->vincore;
2710 newvincore.len = data->vincorelen;
2712 /* find the solvables key, create if needed */
2713 memset(&solvkey, 0, sizeof(solvkey));
2714 solvkey.name = REPOSITORY_SOLVABLES;
2715 solvkey.type = REPOKEY_TYPE_FLEXARRAY;
2717 solvkey.storage = KEY_STORAGE_INCORE;
2718 solvkeyid = repodata_key2id(data, &solvkey, data->end != data->start ? 1 : 0);
2720 schema = solv_malloc2(data->nkeys, sizeof(Id));
2721 seen = solv_malloc2(data->nkeys, sizeof(Id));
2723 /* Merge the data already existing (in data->schemata, ->incoredata and
2724 friends) with the new attributes in data->attrs[]. */
2725 nentry = data->end - data->start;
2726 memset(&newincore, 0, sizeof(newincore));
2727 data_addid(&newincore, 0); /* start data at offset 1 */
2729 data->mainschema = 0;
2730 data->mainschemaoffsets = solv_free(data->mainschemaoffsets);
2732 /* join entry data */
2733 /* we start with the meta data, entry -1 */
2734 for (entry = -1; entry < nentry; entry++)
2736 memset(seen, 0, data->nkeys * sizeof(Id));
2738 dp = data->incoredata;
2741 dp += entry >= 0 ? data->incoreoffset[entry] : 1;
2742 dp = data_read_id(dp, &oldschema);
2745 fprintf(stderr, "oldschema %d\n", oldschema);
2746 fprintf(stderr, "schemata %d\n", data->schemata[oldschema]);
2747 fprintf(stderr, "schemadata %p\n", data->schemadata);
2749 /* seen: -1: old data 0: skipped >0: id + 1 */
2753 for (keyp = data->schemadata + data->schemata[oldschema]; *keyp; keyp++)
2757 pool_debug(data->repo->pool, SOLV_FATAL, "Inconsistent old data (key occured twice).\n");
2765 keyp = data->attrs ? data->attrs[entry] : 0;
2768 /* strip solvables key */
2770 for (sp = keyp = schema; *sp; sp++)
2771 if (*sp != solvkeyid)
2776 seen[solvkeyid] = 0;
2777 keyp = data->xattrs ? data->xattrs[1] : 0;
2780 for (; *keyp; keyp += 2)
2787 seen[*keyp] = keyp[1] + 1;
2789 if (entry < 0 && data->end != data->start)
2796 /* Ideally we'd like to sort the new schema here, to ensure
2797 schema equality independend of the ordering. We can't do that
2798 yet. For once see below (old ids need to come before new ids).
2799 An additional difficulty is that we also need to move
2800 the values with the keys. */
2801 schemaid = repodata_schema2id(data, schema, 1);
2803 schemaid = oldschema;
2806 /* Now create data blob. We walk through the (possibly new) schema
2807 and either copy over old data, or insert the new. */
2808 /* XXX Here we rely on the fact that the (new) schema has the form
2809 o1 o2 o3 o4 ... | n1 n2 n3 ...
2810 (oX being the old keyids (possibly overwritten), and nX being
2811 the new keyids). This rules out sorting the keyids in order
2812 to ensure a small schema count. */
2814 data->incoreoffset[entry] = newincore.len;
2815 data_addid(&newincore, schemaid);
2818 data->mainschema = schemaid;
2819 data->mainschemaoffsets = solv_calloc(sp - schema, sizeof(Id));
2821 keypstart = data->schemadata + data->schemata[schemaid];
2822 for (keyp = keypstart; *keyp; keyp++)
2825 data->mainschemaoffsets[keyp - keypstart] = newincore.len;
2826 if (*keyp == solvkeyid)
2828 /* add flexarray entry count */
2829 data_addid(&newincore, data->end - data->start);
2832 key = data->keys + *keyp;
2834 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));
2839 /* Skip the data associated with this old key. */
2840 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2842 ndp = data_skip(dp, REPOKEY_TYPE_ID);
2843 ndp = data_skip(ndp, REPOKEY_TYPE_ID);
2845 else if (key->storage == KEY_STORAGE_INCORE)
2846 ndp = data_skip_key(data, dp, key);
2849 if (seen[*keyp] == -1)
2851 /* If this key was an old one _and_ was not overwritten with
2852 a different value copy over the old value (we skipped it
2855 data_addblob(&newincore, dp, ndp - dp);
2858 else if (seen[*keyp])
2860 /* Otherwise we have a new value. Parse it into the internal
2862 repodata_serialize_key(data, &newincore, &newvincore,
2863 schema, key, seen[*keyp] - 1);
2867 if (entry >= 0 && data->attrs && data->attrs[entry])
2868 data->attrs[entry] = solv_free(data->attrs[entry]);
2870 /* free all xattrs */
2871 for (entry = 0; entry < data->nxattrs; entry++)
2872 if (data->xattrs[entry])
2873 solv_free(data->xattrs[entry]);
2874 data->xattrs = solv_free(data->xattrs);
2877 data->lasthandle = 0;
2879 data->lastdatalen = 0;
2882 repodata_free_schemahash(data);
2884 solv_free(data->incoredata);
2885 data->incoredata = newincore.buf;
2886 data->incoredatalen = newincore.len;
2887 data->incoredatafree = 0;
2889 solv_free(data->vincore);
2890 data->vincore = newvincore.buf;
2891 data->vincorelen = newvincore.len;
2893 data->attrs = solv_free(data->attrs);
2894 data->attrdata = solv_free(data->attrdata);
2895 data->attriddata = solv_free(data->attriddata);
2896 data->attrnum64data = solv_free(data->attrnum64data);
2897 data->attrdatalen = 0;
2898 data->attriddatalen = 0;
2899 data->attrnum64datalen = 0;
2903 repodata_disable_paging(Repodata *data)
2905 if (maybe_load_repodata(data, 0))
2906 repopagestore_disable_paging(&data->store);
2910 repodata_load_stub(Repodata *data)
2912 Repo *repo = data->repo;
2913 Pool *pool = repo->pool;
2915 struct _Pool_tmpspace oldtmpspace;
2917 if (!pool->loadcallback)
2919 data->state = REPODATA_ERROR;
2922 data->state = REPODATA_LOADING;
2924 /* save tmp space */
2925 oldtmpspace = pool->tmpspace;
2926 memset(&pool->tmpspace, 0, sizeof(pool->tmpspace));
2928 r = pool->loadcallback(pool, data, pool->loadcallbackdata);
2930 /* restore tmp space */
2931 for (i = 0; i < POOL_TMPSPACEBUF; i++)
2932 solv_free(pool->tmpspace.buf[i]);
2933 pool->tmpspace = oldtmpspace;
2935 data->state = r ? REPODATA_AVAILABLE : REPODATA_ERROR;
2939 repodata_create_stubs(Repodata *data)
2941 Repo *repo = data->repo;
2942 Pool *pool = repo->pool;
2949 int datastart, dataend;
2951 repodataid = data - repo->repodata;
2952 datastart = data->start;
2953 dataend = data->end;
2954 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2955 while (dataiterator_step(&di))
2957 if (di.data - repo->repodata != repodataid)
2961 dataiterator_free(&di);
2964 stubdataids = solv_calloc(cnt, sizeof(*stubdataids));
2965 for (i = 0; i < cnt; i++)
2967 sdata = repo_add_repodata(repo, 0);
2968 if (dataend > datastart)
2969 repodata_extend_block(sdata, datastart, dataend - datastart);
2970 stubdataids[i] = sdata - repo->repodata;
2971 sdata->state = REPODATA_STUB;
2972 sdata->loadcallback = repodata_load_stub;
2975 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2977 while (dataiterator_step(&di))
2979 if (di.data - repo->repodata != repodataid)
2981 if (di.key->name == REPOSITORY_EXTERNAL && !di.nparents)
2983 dataiterator_entersub(&di);
2984 sdata = repo->repodata + stubdataids[i++];
2988 switch (di.key->type)
2990 case REPOKEY_TYPE_ID:
2991 repodata_set_id(sdata, SOLVID_META, di.key->name, di.kv.id);
2993 case REPOKEY_TYPE_CONSTANTID:
2994 repodata_set_constantid(sdata, SOLVID_META, di.key->name, di.kv.id);
2996 case REPOKEY_TYPE_STR:
2997 repodata_set_str(sdata, SOLVID_META, di.key->name, di.kv.str);
2999 case REPOKEY_TYPE_VOID:
3000 repodata_set_void(sdata, SOLVID_META, di.key->name);
3002 case REPOKEY_TYPE_NUM:
3003 repodata_set_num(sdata, SOLVID_META, di.key->name, SOLV_KV_NUM64(&di.kv));
3005 case REPOKEY_TYPE_MD5:
3006 case REPOKEY_TYPE_SHA1:
3007 case REPOKEY_TYPE_SHA256:
3008 repodata_set_bin_checksum(sdata, SOLVID_META, di.key->name, di.key->type, (const unsigned char *)di.kv.str);
3010 case REPOKEY_TYPE_IDARRAY:
3011 repodata_add_idarray(sdata, SOLVID_META, di.key->name, di.kv.id);
3012 if (di.key->name == REPOSITORY_KEYS)
3019 xkeyname = di.kv.id;
3022 xkey.name = xkeyname;
3023 xkey.type = di.kv.id;
3024 xkey.storage = KEY_STORAGE_INCORE;
3026 repodata_key2id(sdata, &xkey, 1);
3033 dataiterator_free(&di);
3034 for (i = 0; i < cnt; i++)
3035 repodata_internalize(repo->repodata + stubdataids[i]);
3036 solv_free(stubdataids);
3040 repodata_memused(Repodata *data)
3042 return data->incoredatalen + data->vincorelen;
3046 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: