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 int *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)
696 dp = data_fetch(dp, &kv, key);
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
989 static Repokey solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1] = {
990 { SOLVABLE_NAME, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
991 { SOLVABLE_ARCH, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
992 { SOLVABLE_EVR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
993 { SOLVABLE_VENDOR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
994 { SOLVABLE_PROVIDES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
995 { SOLVABLE_OBSOLETES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
996 { SOLVABLE_CONFLICTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
997 { SOLVABLE_REQUIRES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
998 { SOLVABLE_RECOMMENDS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
999 { SOLVABLE_SUGGESTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
1000 { SOLVABLE_SUPPLEMENTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
1001 { SOLVABLE_ENHANCES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
1002 { RPM_RPMDBID, REPOKEY_TYPE_U32, 0, KEY_STORAGE_SOLVABLE },
1006 solvabledata_fetch(Solvable *s, KeyValue *kv, Id keyname)
1020 case SOLVABLE_VENDOR:
1023 case SOLVABLE_PROVIDES:
1025 return s->provides ? s->repo->idarraydata + s->provides : 0;
1026 case SOLVABLE_OBSOLETES:
1028 return s->obsoletes ? s->repo->idarraydata + s->obsoletes : 0;
1029 case SOLVABLE_CONFLICTS:
1031 return s->conflicts ? s->repo->idarraydata + s->conflicts : 0;
1032 case SOLVABLE_REQUIRES:
1034 return s->requires ? s->repo->idarraydata + s->requires : 0;
1035 case SOLVABLE_RECOMMENDS:
1037 return s->recommends ? s->repo->idarraydata + s->recommends : 0;
1038 case SOLVABLE_SUPPLEMENTS:
1040 return s->supplements ? s->repo->idarraydata + s->supplements : 0;
1041 case SOLVABLE_SUGGESTS:
1043 return s->suggests ? s->repo->idarraydata + s->suggests : 0;
1044 case SOLVABLE_ENHANCES:
1046 return s->enhances ? s->repo->idarraydata + s->enhances : 0;
1049 return s->repo->rpmdbid ? s->repo->rpmdbid + (s - s->repo->pool->solvables - s->repo->start) : 0;
1056 datamatcher_init(Datamatcher *ma, const char *match, int flags)
1062 if ((flags & SEARCH_STRINGMASK) == SEARCH_REGEX)
1064 ma->matchdata = solv_calloc(1, sizeof(regex_t));
1065 ma->error = regcomp((regex_t *)ma->matchdata, match, REG_EXTENDED | REG_NOSUB | REG_NEWLINE | ((flags & SEARCH_NOCASE) ? REG_ICASE : 0));
1068 solv_free(ma->matchdata);
1069 ma->flags = (flags & ~SEARCH_STRINGMASK) | SEARCH_ERROR;
1076 datamatcher_free(Datamatcher *ma)
1078 if ((ma->flags & SEARCH_STRINGMASK) == SEARCH_REGEX && ma->matchdata)
1080 regfree(ma->matchdata);
1081 ma->matchdata = solv_free(ma->matchdata);
1086 datamatcher_match(Datamatcher *ma, const char *str)
1089 switch ((ma->flags & SEARCH_STRINGMASK))
1091 case SEARCH_SUBSTRING:
1092 if (ma->flags & SEARCH_NOCASE)
1094 if (!strcasestr(str, ma->match))
1099 if (!strstr(str, ma->match))
1104 if (ma->flags & SEARCH_NOCASE)
1106 if (strcasecmp(ma->match, str))
1111 if (strcmp(ma->match, str))
1115 case SEARCH_STRINGSTART:
1116 if (ma->flags & SEARCH_NOCASE)
1118 if (strncasecmp(ma->match, str, strlen(ma->match)))
1123 if (strncmp(ma->match, str, strlen(ma->match)))
1127 case SEARCH_STRINGEND:
1128 l = strlen(str) - strlen(ma->match);
1131 if (ma->flags & SEARCH_NOCASE)
1133 if (strcasecmp(ma->match, str + l))
1138 if (strcmp(ma->match, str + l))
1143 if (fnmatch(ma->match, str, (ma->flags & SEARCH_NOCASE) ? FNM_CASEFOLD : 0))
1147 if (regexec((const regex_t *)ma->matchdata, str, 0, NULL, 0))
1157 repodata_filelistfilter_matches(Repodata *data, const char *str)
1159 /* '.*bin\/.*', '^\/etc\/.*', '^\/usr\/lib\/sendmail$' */
1160 /* for now hardcoded */
1161 if (strstr(str, "bin/"))
1163 if (!strncmp(str, "/etc/", 5))
1165 if (!strcmp(str, "/usr/lib/sendmail"))
1187 di_nextarrayelement,
1193 di_entersolvablekey,
1197 /* see dataiterator.h for documentation */
1199 dataiterator_init(Dataiterator *di, Pool *pool, Repo *repo, Id p, Id keyname, const char *match, int flags)
1201 memset(di, 0, sizeof(*di));
1203 di->flags = flags & ~SEARCH_THISSOLVID;
1204 if (!pool || (repo && repo->pool != pool))
1212 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1218 di->keyname = keyname;
1219 di->keynames[0] = keyname;
1220 dataiterator_set_search(di, repo, p);
1225 dataiterator_init_clone(Dataiterator *di, Dataiterator *from)
1228 memset(&di->matcher, 0, sizeof(di->matcher));
1229 if (from->matcher.match)
1230 datamatcher_init(&di->matcher, from->matcher.match, from->matcher.flags);
1235 for (i = 1; i < di->nparents; i++)
1236 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1237 di->kv.parent = &di->parents[di->nparents - 1].kv;
1242 dataiterator_set_match(Dataiterator *di, const char *match, int flags)
1244 di->flags = (flags & ~SEARCH_THISSOLVID) | (di->flags & SEARCH_THISSOLVID);
1245 datamatcher_free(&di->matcher);
1246 memset(&di->matcher, 0, sizeof(di->matcher));
1250 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1260 dataiterator_set_search(Dataiterator *di, Repo *repo, Id p)
1264 di->flags &= ~SEARCH_THISSOLVID;
1268 if (!di->pool->urepos)
1276 di->repo = di->pool->repos[di->repoid];
1278 di->state = di_enterrepo;
1280 dataiterator_jump_to_solvid(di, p);
1284 dataiterator_set_keyname(Dataiterator *di, Id keyname)
1287 di->keyname = keyname;
1288 di->keynames[0] = keyname;
1292 dataiterator_prepend_keyname(Dataiterator *di, Id keyname)
1296 if (di->nkeynames >= sizeof(di->keynames)/sizeof(*di->keynames) - 2)
1298 di->state = di_bye; /* sorry */
1301 for (i = di->nkeynames + 1; i > 0; i--)
1302 di->keynames[i] = di->keynames[i - 1];
1303 di->keynames[0] = di->keyname = keyname;
1308 dataiterator_free(Dataiterator *di)
1310 if (di->matcher.match)
1311 datamatcher_free(&di->matcher);
1314 static inline unsigned char *
1315 dataiterator_find_keyname(Dataiterator *di, Id keyname)
1317 Id *keyp = di->keyp;
1318 Repokey *keys = di->data->keys;
1321 for (keyp = di->keyp; *keyp; keyp++)
1322 if (keys[*keyp].name == keyname)
1326 dp = forward_to_key(di->data, *keyp, di->keyp, di->dp);
1334 dataiterator_filelistcheck(Dataiterator *di)
1337 int needcomplete = 0;
1338 Repodata *data = di->data;
1340 if ((di->matcher.flags & SEARCH_COMPLETE_FILELIST) != 0)
1341 if (!di->matcher.match
1342 || ((di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_STRING
1343 && (di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_GLOB)
1344 || !repodata_filelistfilter_matches(di->data, di->matcher.match))
1346 if (data->state != REPODATA_AVAILABLE)
1347 return needcomplete ? 1 : 0;
1348 for (j = 1; j < data->nkeys; j++)
1349 if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
1351 return j == data->nkeys && !needcomplete ? 0 : 1;
1355 dataiterator_step(Dataiterator *di)
1363 case di_enterrepo: di_enterrepo:
1364 if (!di->repo || (di->repo->disabled && !(di->flags & SEARCH_DISABLED_REPOS)))
1366 if (!(di->flags & SEARCH_THISSOLVID))
1368 di->solvid = di->repo->start - 1; /* reset solvid iterator */
1369 goto di_nextsolvable;
1373 case di_entersolvable: di_entersolvable:
1376 di->repodataid = 1; /* reset repodata iterator */
1377 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)
1379 di->key = solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0);
1381 goto di_entersolvablekey;
1386 case di_enterrepodata: di_enterrepodata:
1389 if (di->repodataid >= di->repo->nrepodata)
1390 goto di_nextsolvable;
1391 di->data = di->repo->repodata + di->repodataid;
1393 if (di->repodataid && di->keyname == SOLVABLE_FILELIST && !dataiterator_filelistcheck(di))
1394 goto di_nextrepodata;
1395 if (!maybe_load_repodata(di->data, di->keyname))
1396 goto di_nextrepodata;
1397 di->dp = solvid2data(di->data, di->solvid, &schema);
1399 goto di_nextrepodata;
1400 if (di->solvid == SOLVID_POS)
1401 di->solvid = di->pool->pos.solvid;
1402 /* reset key iterator */
1403 di->keyp = di->data->schemadata + di->data->schemata[schema];
1406 case di_enterschema: di_enterschema:
1408 di->dp = dataiterator_find_keyname(di, di->keyname);
1409 if (!di->dp || !*di->keyp)
1413 goto di_nextrepodata;
1417 case di_enterkey: di_enterkey:
1419 di->key = di->data->keys + *di->keyp;
1420 di->ddp = get_data(di->data, di->key, &di->dp, di->keyp[1] && (!di->keyname || (di->flags & SEARCH_SUB) != 0) ? 1 : 0);
1423 if (di->key->type == REPOKEY_TYPE_DELETED)
1425 if (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY)
1427 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1433 di->ddp = data_fetch(di->ddp, &di->kv, di->key);
1435 di->state = di_nextkey;
1437 di->state = di_nextattr;
1440 case di_nextkey: di_nextkey:
1441 if (!di->keyname && *++di->keyp)
1447 case di_nextrepodata: di_nextrepodata:
1448 if (di->repodataid && ++di->repodataid < di->repo->nrepodata)
1449 goto di_enterrepodata;
1452 case di_nextsolvable: di_nextsolvable:
1453 if (!(di->flags & SEARCH_THISSOLVID))
1456 di->solvid = di->repo->start;
1459 for (; di->solvid < di->repo->end; di->solvid++)
1461 if (di->pool->solvables[di->solvid].repo == di->repo)
1462 goto di_entersolvable;
1467 case di_nextrepo: di_nextrepo:
1472 if (di->repoid < di->pool->nrepos)
1474 di->repo = di->pool->repos[di->repoid];
1480 case di_bye: di_bye:
1484 case di_enterarray: di_enterarray:
1485 if (di->key->name == REPOSITORY_SOLVABLES)
1487 di->ddp = data_read_id(di->ddp, &di->kv.num);
1492 case di_nextarrayelement: di_nextarrayelement:
1495 di->ddp = data_skip_schema(di->data, di->ddp, di->kv.id);
1496 if (di->kv.entry == di->kv.num)
1498 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1500 if (!(di->flags & SEARCH_ARRAYSENTINEL))
1502 di->kv.str = (char *)di->ddp;
1504 di->state = di_nextkey;
1507 if (di->kv.entry == di->kv.num - 1)
1509 if (di->key->type == REPOKEY_TYPE_FLEXARRAY || !di->kv.entry)
1510 di->ddp = data_read_id(di->ddp, &di->kv.id);
1511 di->kv.str = (char *)di->ddp;
1512 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1514 if ((di->flags & SEARCH_SUB) != 0)
1515 di->state = di_entersub;
1517 di->state = di_nextarrayelement;
1520 case di_entersub: di_entersub:
1521 if (di->nparents == sizeof(di->parents)/sizeof(*di->parents) - 1)
1522 goto di_nextarrayelement; /* sorry, full */
1523 di->parents[di->nparents].kv = di->kv;
1524 di->parents[di->nparents].dp = di->dp;
1525 di->parents[di->nparents].keyp = di->keyp;
1526 di->dp = (unsigned char *)di->kv.str;
1527 di->keyp = di->data->schemadata + di->data->schemata[di->kv.id];
1528 memset(&di->kv, 0, sizeof(di->kv));
1529 di->kv.parent = &di->parents[di->nparents].kv;
1531 di->keyname = di->keynames[di->nparents - di->rootlevel];
1532 goto di_enterschema;
1534 case di_leavesub: di_leavesub:
1535 if (di->nparents - 1 < di->rootlevel)
1538 di->dp = di->parents[di->nparents].dp;
1539 di->kv = di->parents[di->nparents].kv;
1540 di->keyp = di->parents[di->nparents].keyp;
1541 di->key = di->data->keys + *di->keyp;
1542 di->ddp = (unsigned char *)di->kv.str;
1543 di->keyname = di->keynames[di->nparents - di->rootlevel];
1544 goto di_nextarrayelement;
1546 /* special solvable attr handling follows */
1548 case di_nextsolvablekey: di_nextsolvablekey:
1549 if (di->keyname || di->key->name == RPM_RPMDBID)
1550 goto di_enterrepodata;
1554 case di_entersolvablekey: di_entersolvablekey:
1555 di->idp = solvabledata_fetch(di->pool->solvables + di->solvid, &di->kv, di->key->name);
1556 if (!di->idp || !*di->idp)
1557 goto di_nextsolvablekey;
1561 di->kv.id = *di->idp;
1562 di->kv.num = *di->idp; /* for rpmdbid */
1564 di->state = di_nextsolvablekey;
1570 case di_nextsolvableattr:
1571 di->state = di_nextsolvableattr;
1572 di->kv.id = *di->idp++;
1577 di->state = di_nextsolvablekey;
1583 if (di->matcher.match)
1585 /* simple pre-check so that we don't need to stringify */
1586 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))
1588 int l = strlen(di->matcher.match) - strlen(di->kv.str);
1589 if (l < 0 || strcmp(di->matcher.match + l, di->kv.str))
1592 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1594 if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY))
1598 if (!datamatcher_match(&di->matcher, di->kv.str))
1601 /* found something! */
1607 dataiterator_entersub(Dataiterator *di)
1609 if (di->state == di_nextarrayelement)
1610 di->state = di_entersub;
1614 dataiterator_setpos(Dataiterator *di)
1616 if (di->kv.eof == 2)
1618 pool_clear_pos(di->pool);
1621 di->pool->pos.solvid = di->solvid;
1622 di->pool->pos.repo = di->repo;
1623 di->pool->pos.repodataid = di->data - di->repo->repodata;
1624 di->pool->pos.schema = di->kv.id;
1625 di->pool->pos.dp = (unsigned char *)di->kv.str - di->data->incoredata;
1629 dataiterator_setpos_parent(Dataiterator *di)
1631 if (!di->kv.parent || di->kv.parent->eof == 2)
1633 pool_clear_pos(di->pool);
1636 di->pool->pos.solvid = di->solvid;
1637 di->pool->pos.repo = di->repo;
1638 di->pool->pos.repodataid = di->data - di->repo->repodata;
1639 di->pool->pos.schema = di->kv.parent->id;
1640 di->pool->pos.dp = (unsigned char *)di->kv.parent->str - di->data->incoredata;
1643 /* clones just the position, not the search keys/matcher */
1645 dataiterator_clonepos(Dataiterator *di, Dataiterator *from)
1647 di->state = from->state;
1648 di->flags &= ~SEARCH_THISSOLVID;
1649 di->flags |= (from->flags & SEARCH_THISSOLVID);
1650 di->repo = from->repo;
1651 di->data = from->data;
1653 di->ddp = from->ddp;
1654 di->idp = from->idp;
1655 di->keyp = from->keyp;
1656 di->key = from->key;
1658 di->repodataid = from->repodataid;
1659 di->solvid = from->solvid;
1660 di->repoid = from->repoid;
1661 di->rootlevel = from->rootlevel;
1662 memcpy(di->parents, from->parents, sizeof(from->parents));
1663 di->nparents = from->nparents;
1667 for (i = 1; i < di->nparents; i++)
1668 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1669 di->kv.parent = &di->parents[di->nparents - 1].kv;
1674 dataiterator_seek(Dataiterator *di, int whence)
1676 if ((whence & DI_SEEK_STAY) != 0)
1677 di->rootlevel = di->nparents;
1678 switch (whence & ~DI_SEEK_STAY)
1681 if (di->state != di_nextarrayelement)
1683 if ((whence & DI_SEEK_STAY) != 0)
1684 di->rootlevel = di->nparents + 1; /* XXX: dangerous! */
1685 di->state = di_entersub;
1687 case DI_SEEK_PARENT:
1694 if (di->rootlevel > di->nparents)
1695 di->rootlevel = di->nparents;
1696 di->dp = di->parents[di->nparents].dp;
1697 di->kv = di->parents[di->nparents].kv;
1698 di->keyp = di->parents[di->nparents].keyp;
1699 di->key = di->data->keys + *di->keyp;
1700 di->ddp = (unsigned char *)di->kv.str;
1701 di->keyname = di->keynames[di->nparents - di->rootlevel];
1702 di->state = di_nextarrayelement;
1704 case DI_SEEK_REWIND:
1710 di->dp = (unsigned char *)di->kv.parent->str;
1711 di->keyp = di->data->schemadata + di->data->schemata[di->kv.parent->id];
1712 di->state = di_enterschema;
1720 dataiterator_skip_attribute(Dataiterator *di)
1722 if (di->state == di_nextsolvableattr)
1723 di->state = di_nextsolvablekey;
1725 di->state = di_nextkey;
1729 dataiterator_skip_solvable(Dataiterator *di)
1734 di->keyname = di->keynames[0];
1735 di->state = di_nextsolvable;
1739 dataiterator_skip_repo(Dataiterator *di)
1744 di->keyname = di->keynames[0];
1745 di->state = di_nextrepo;
1749 dataiterator_jump_to_solvid(Dataiterator *di, Id solvid)
1754 di->keyname = di->keynames[0];
1755 if (solvid == SOLVID_POS)
1757 di->repo = di->pool->pos.repo;
1764 di->data = di->repo->repodata + di->pool->pos.repodataid;
1766 di->solvid = solvid;
1767 di->state = di_enterrepo;
1768 di->flags |= SEARCH_THISSOLVID;
1773 di->repo = di->pool->solvables[solvid].repo;
1776 else if (di->repoid > 0)
1778 if (!di->pool->urepos)
1784 di->repo = di->pool->repos[di->repoid];
1787 di->solvid = solvid;
1789 di->flags |= SEARCH_THISSOLVID;
1790 di->state = di_enterrepo;
1794 dataiterator_jump_to_repo(Dataiterator *di, Repo *repo)
1800 di->repoid = 0; /* 0 means stay at repo */
1803 di->flags &= ~SEARCH_THISSOLVID;
1804 di->state = di_enterrepo;
1808 dataiterator_match(Dataiterator *di, Datamatcher *ma)
1810 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1814 return datamatcher_match(ma, di->kv.str);
1817 /************************************************************************
1818 * data modify functions
1821 /* extend repodata so that it includes solvables p */
1823 repodata_extend(Repodata *data, Id p)
1825 if (data->start == data->end)
1826 data->start = data->end = p;
1829 int old = data->end - data->start;
1830 int new = p - data->end + 1;
1833 data->attrs = solv_extend(data->attrs, old, new, sizeof(Id *), REPODATA_BLOCK);
1834 memset(data->attrs + old, 0, new * sizeof(Id *));
1836 data->incoreoffset = solv_extend(data->incoreoffset, old, new, sizeof(Id), REPODATA_BLOCK);
1837 memset(data->incoreoffset + old, 0, new * sizeof(Id));
1840 if (p < data->start)
1842 int old = data->end - data->start;
1843 int new = data->start - p;
1846 data->attrs = solv_extend_resize(data->attrs, old + new, sizeof(Id *), REPODATA_BLOCK);
1847 memmove(data->attrs + new, data->attrs, old * sizeof(Id *));
1848 memset(data->attrs, 0, new * sizeof(Id *));
1850 data->incoreoffset = solv_extend_resize(data->incoreoffset, old + new, sizeof(Id), REPODATA_BLOCK);
1851 memmove(data->incoreoffset + new, data->incoreoffset, old * sizeof(Id));
1852 memset(data->incoreoffset, 0, new * sizeof(Id));
1857 /* shrink end of repodata */
1859 repodata_shrink(Repodata *data, int end)
1863 if (data->end <= end)
1865 if (data->start >= end)
1869 for (i = 0; i < data->end - data->start; i++)
1870 solv_free(data->attrs[i]);
1871 data->attrs = solv_free(data->attrs);
1873 data->incoreoffset = solv_free(data->incoreoffset);
1874 data->start = data->end = 0;
1879 for (i = end; i < data->end; i++)
1880 solv_free(data->attrs[i - data->start]);
1881 data->attrs = solv_extend_resize(data->attrs, end - data->start, sizeof(Id *), REPODATA_BLOCK);
1883 if (data->incoreoffset)
1884 data->incoreoffset = solv_extend_resize(data->incoreoffset, end - data->start, sizeof(Id), REPODATA_BLOCK);
1888 /* extend repodata so that it includes solvables from start to start + num - 1 */
1890 repodata_extend_block(Repodata *data, Id start, Id num)
1894 if (!data->incoreoffset)
1896 data->incoreoffset = solv_calloc_block(num, sizeof(Id), REPODATA_BLOCK);
1897 data->start = start;
1898 data->end = start + num;
1901 repodata_extend(data, start);
1903 repodata_extend(data, start + num - 1);
1906 /**********************************************************************/
1909 #define REPODATA_ATTRS_BLOCK 31
1910 #define REPODATA_ATTRDATA_BLOCK 1023
1911 #define REPODATA_ATTRIDDATA_BLOCK 63
1912 #define REPODATA_ATTRNUM64DATA_BLOCK 15
1916 repodata_new_handle(Repodata *data)
1920 data->xattrs = solv_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1921 data->nxattrs = 2; /* -1: SOLVID_META */
1923 data->xattrs = solv_extend(data->xattrs, data->nxattrs, 1, sizeof(Id *), REPODATA_BLOCK);
1924 data->xattrs[data->nxattrs] = 0;
1925 return -(data->nxattrs++);
1929 repodata_get_attrp(Repodata *data, Id handle)
1933 if (handle == SOLVID_META && !data->xattrs)
1935 data->xattrs = solv_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1938 return data->xattrs - handle;
1940 if (handle < data->start || handle >= data->end)
1941 repodata_extend(data, handle);
1943 data->attrs = solv_calloc_block(data->end - data->start, sizeof(Id *), REPODATA_BLOCK);
1944 return data->attrs + (handle - data->start);
1948 repodata_insert_keyid(Repodata *data, Id handle, Id keyid, Id val, int overwrite)
1954 app = repodata_get_attrp(data, handle);
1959 /* Determine equality based on the name only, allows us to change
1960 type (when overwrite is set), and makes TYPE_CONSTANT work. */
1961 for (pp = ap; *pp; pp += 2)
1962 if (data->keys[*pp].name == data->keys[keyid].name)
1966 if (overwrite || data->keys[*pp].type == REPOKEY_TYPE_DELETED)
1975 ap = solv_extend(ap, i, 3, sizeof(Id), REPODATA_ATTRS_BLOCK);
1985 repodata_set(Repodata *data, Id solvid, Repokey *key, Id val)
1989 keyid = repodata_key2id(data, key, 1);
1990 repodata_insert_keyid(data, solvid, keyid, val, 1);
1994 repodata_set_id(Repodata *data, Id solvid, Id keyname, Id id)
1998 key.type = REPOKEY_TYPE_ID;
2000 key.storage = KEY_STORAGE_INCORE;
2001 repodata_set(data, solvid, &key, id);
2005 repodata_set_num(Repodata *data, Id solvid, Id keyname, unsigned int num)
2009 key.type = REPOKEY_TYPE_NUM;
2011 key.storage = KEY_STORAGE_INCORE;
2012 if (num >= 0x80000000)
2014 data->attrnum64data = solv_extend(data->attrnum64data, data->attrnum64datalen, 1, sizeof(unsigned long long), REPODATA_ATTRNUM64DATA_BLOCK);
2015 data->attrnum64data[data->attrnum64datalen] = num;
2016 num = 0x80000000 | data->attrnum64datalen++;
2018 repodata_set(data, solvid, &key, (Id)num);
2022 repodata_set_poolstr(Repodata *data, Id solvid, Id keyname, const char *str)
2026 if (data->localpool)
2027 id = stringpool_str2id(&data->spool, str, 1);
2029 id = pool_str2id(data->repo->pool, str, 1);
2031 key.type = REPOKEY_TYPE_ID;
2033 key.storage = KEY_STORAGE_INCORE;
2034 repodata_set(data, solvid, &key, id);
2038 repodata_set_constant(Repodata *data, Id solvid, Id keyname, unsigned int constant)
2042 key.type = REPOKEY_TYPE_CONSTANT;
2043 key.size = constant;
2044 key.storage = KEY_STORAGE_INCORE;
2045 repodata_set(data, solvid, &key, 0);
2049 repodata_set_constantid(Repodata *data, Id solvid, Id keyname, Id id)
2053 key.type = REPOKEY_TYPE_CONSTANTID;
2055 key.storage = KEY_STORAGE_INCORE;
2056 repodata_set(data, solvid, &key, 0);
2060 repodata_set_void(Repodata *data, Id solvid, Id keyname)
2064 key.type = REPOKEY_TYPE_VOID;
2066 key.storage = KEY_STORAGE_INCORE;
2067 repodata_set(data, solvid, &key, 0);
2071 repodata_set_str(Repodata *data, Id solvid, Id keyname, const char *str)
2076 l = strlen(str) + 1;
2078 key.type = REPOKEY_TYPE_STR;
2080 key.storage = KEY_STORAGE_INCORE;
2081 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2082 memcpy(data->attrdata + data->attrdatalen, str, l);
2083 repodata_set(data, solvid, &key, data->attrdatalen);
2084 data->attrdatalen += l;
2088 repodata_set_binary(Repodata *data, Id solvid, Id keyname, void *buf, int len)
2096 key.type = REPOKEY_TYPE_BINARY;
2098 key.storage = KEY_STORAGE_INCORE;
2099 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, len + 5, 1, REPODATA_ATTRDATA_BLOCK);
2100 dp = data->attrdata + data->attrdatalen;
2101 if (len >= (1 << 14))
2103 if (len >= (1 << 28))
2104 *dp++ = (len >> 28) | 128;
2105 if (len >= (1 << 21))
2106 *dp++ = (len >> 21) | 128;
2107 *dp++ = (len >> 14) | 128;
2109 if (len >= (1 << 7))
2110 *dp++ = (len >> 7) | 128;
2113 memcpy(dp, buf, len);
2114 repodata_set(data, solvid, &key, data->attrdatalen);
2115 data->attrdatalen = dp + len - data->attrdata;
2118 /* add an array element consisting of entrysize Ids to the repodata. modifies attriddata
2119 * so that the caller can append entrysize new elements plus the termination zero there */
2121 repodata_add_array(Repodata *data, Id handle, Id keyname, Id keytype, int entrysize)
2124 Id *ida, *pp, **ppp;
2126 /* check if it is the same as last time, this speeds things up a lot */
2127 if (handle == data->lasthandle && data->keys[data->lastkey].name == keyname && data->keys[data->lastkey].type == keytype && data->attriddatalen == data->lastdatalen)
2129 /* great! just append the new data */
2130 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2131 data->attriddatalen--; /* overwrite terminating 0 */
2132 data->lastdatalen += entrysize;
2136 ppp = repodata_get_attrp(data, handle);
2140 for (; *pp; pp += 2)
2141 if (data->keys[*pp].name == keyname)
2144 if (!pp || !*pp || data->keys[*pp].type != keytype)
2146 /* not found. allocate new key */
2152 key.storage = KEY_STORAGE_INCORE;
2153 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2154 keyid = repodata_key2id(data, &key, 1);
2155 repodata_insert_keyid(data, handle, keyid, data->attriddatalen, 1);
2156 data->lasthandle = handle;
2157 data->lastkey = keyid;
2158 data->lastdatalen = data->attriddatalen + entrysize + 1;
2162 for (ida = data->attriddata + pp[1]; *ida; ida += entrysize)
2163 oldsize += entrysize;
2164 if (ida + 1 == data->attriddata + data->attriddatalen)
2166 /* this was the last entry, just append it */
2167 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2168 data->attriddatalen--; /* overwrite terminating 0 */
2172 /* too bad. move to back. */
2173 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, oldsize + entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2174 memcpy(data->attriddata + data->attriddatalen, data->attriddata + pp[1], oldsize * sizeof(Id));
2175 pp[1] = data->attriddatalen;
2176 data->attriddatalen += oldsize;
2178 data->lasthandle = handle;
2179 data->lastkey = *pp;
2180 data->lastdatalen = data->attriddatalen + entrysize + 1;
2184 repodata_set_bin_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2185 const unsigned char *str)
2190 if (!(l = solv_chksum_len(type)))
2195 key.storage = KEY_STORAGE_INCORE;
2196 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2197 memcpy(data->attrdata + data->attrdatalen, str, l);
2198 repodata_set(data, solvid, &key, data->attrdatalen);
2199 data->attrdatalen += l;
2203 repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2206 unsigned char buf[64];
2209 if (!(l = solv_chksum_len(type)))
2211 if (l > sizeof(buf) || solv_hex2bin(&str, buf, l) != l)
2213 repodata_set_bin_checksum(data, solvid, keyname, type, buf);
2217 repodata_chk2str(Repodata *data, Id type, const unsigned char *buf)
2221 if (!(l = solv_chksum_len(type)))
2223 return pool_bin2hex(data->repo->pool, buf, l);
2226 /* rpm filenames don't contain the epoch, so strip it */
2227 static inline const char *
2228 evrid2vrstr(Pool *pool, Id evrid)
2230 const char *p, *evr = pool_id2str(pool, evrid);
2233 for (p = evr; *p >= '0' && *p <= '9'; p++)
2235 return p != evr && *p == ':' ? p + 1 : evr;
2239 repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, const char *file)
2241 Pool *pool = data->repo->pool;
2243 const char *str, *fp;
2247 repodata_set_constant(data, solvid, SOLVABLE_MEDIANR, medianr);
2250 if ((dir = strrchr(file, '/')) != 0)
2261 if (l >= 2 && dir[0] == '.' && dir[1] == '/' && (l == 2 || dir[2] != '/'))
2266 if (l == 1 && dir[0] == '.')
2268 s = pool->solvables + solvid;
2271 str = pool_id2str(pool, s->arch);
2272 if (!strncmp(dir, str, l) && !str[l])
2273 repodata_set_void(data, solvid, SOLVABLE_MEDIADIR);
2275 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir);
2278 char *dir2 = solv_strdup(dir);
2280 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir2);
2285 str = pool_id2str(pool, s->name);
2287 if ((!l || !strncmp(fp, str, l)) && fp[l] == '-')
2290 str = evrid2vrstr(pool, s->evr);
2292 if ((!l || !strncmp(fp, str, l)) && fp[l] == '.')
2295 str = pool_id2str(pool, s->arch);
2297 if ((!l || !strncmp(fp, str, l)) && !strcmp(fp + l, ".rpm"))
2299 repodata_set_void(data, solvid, SOLVABLE_MEDIAFILE);
2304 repodata_set_str(data, solvid, SOLVABLE_MEDIAFILE, file);
2308 repodata_set_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
2314 key.type = REPOKEY_TYPE_IDARRAY;
2316 key.storage = KEY_STORAGE_INCORE;
2317 repodata_set(data, solvid, &key, data->attriddatalen);
2318 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, q->count + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2319 for (i = 0; i < q->count; i++)
2320 data->attriddata[data->attriddatalen++] = q->elements[i];
2321 data->attriddata[data->attriddatalen++] = 0;
2325 repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2)
2329 fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", solvid, dir, num, num2, data->attriddatalen);
2331 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRNUMNUMARRAY, 3);
2332 data->attriddata[data->attriddatalen++] = dir;
2333 data->attriddata[data->attriddatalen++] = num;
2334 data->attriddata[data->attriddatalen++] = num2;
2335 data->attriddata[data->attriddatalen++] = 0;
2339 repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str)
2345 l = strlen(str) + 1;
2346 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2347 memcpy(data->attrdata + data->attrdatalen, str, l);
2348 stroff = data->attrdatalen;
2349 data->attrdatalen += l;
2352 fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", solvid, dir, str, data->attriddatalen);
2354 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRSTRARRAY, 2);
2355 data->attriddata[data->attriddatalen++] = dir;
2356 data->attriddata[data->attriddatalen++] = stroff;
2357 data->attriddata[data->attriddatalen++] = 0;
2361 repodata_add_idarray(Repodata *data, Id solvid, Id keyname, Id id)
2364 fprintf(stderr, "repodata_add_idarray %d %d (%d)\n", solvid, id, data->attriddatalen);
2366 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_IDARRAY, 1);
2367 data->attriddata[data->attriddatalen++] = id;
2368 data->attriddata[data->attriddatalen++] = 0;
2372 repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname,
2376 if (data->localpool)
2377 id = stringpool_str2id(&data->spool, str, 1);
2379 id = pool_str2id(data->repo->pool, str, 1);
2380 repodata_add_idarray(data, solvid, keyname, id);
2384 repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2386 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FIXARRAY, 1);
2387 data->attriddata[data->attriddatalen++] = ghandle;
2388 data->attriddata[data->attriddatalen++] = 0;
2392 repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2394 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FLEXARRAY, 1);
2395 data->attriddata[data->attriddatalen++] = ghandle;
2396 data->attriddata[data->attriddatalen++] = 0;
2400 repodata_delete_uninternalized(Repodata *data, Id solvid, Id keyname)
2403 app = repodata_get_attrp(data, solvid);
2407 for (; *ap; ap += 2)
2408 if (data->keys[*ap].name == keyname)
2414 for (; *ap; ap += 2)
2416 if (data->keys[*ap].name == keyname)
2424 /* XXX: does not work correctly, needs fix in iterators! */
2426 repodata_delete(Repodata *data, Id solvid, Id keyname)
2430 key.type = REPOKEY_TYPE_DELETED;
2432 key.storage = KEY_STORAGE_INCORE;
2433 repodata_set(data, solvid, &key, 0);
2436 /* add all (uninternalized) attrs from src to dest */
2438 repodata_merge_attrs(Repodata *data, Id dest, Id src)
2441 if (dest == src || data->attrs || !(keyp = data->attrs[src - data->start]))
2443 for (; *keyp; keyp += 2)
2444 repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
2447 /* add some (uninternalized) attrs from src to dest */
2449 repodata_merge_some_attrs(Repodata *data, Id dest, Id src, Map *keyidmap, int overwrite)
2452 if (dest == src || !data->attrs || !(keyp = data->attrs[src - data->start]))
2454 for (; *keyp; keyp += 2)
2455 if (!keyidmap || MAPTST(keyidmap, keyp[0]))
2456 repodata_insert_keyid(data, dest, keyp[0], keyp[1], overwrite);
2459 /* swap (uninternalized) attrs from src and dest */
2461 repodata_swap_attrs(Repodata *data, Id dest, Id src)
2464 if (!data->attrs || dest == src)
2466 tmpattrs = data->attrs[dest - data->start];
2467 data->attrs[dest - data->start] = data->attrs[src - data->start];
2468 data->attrs[src - data->start] = tmpattrs;
2472 /**********************************************************************/
2474 /* TODO: unify with repo_write and repo_solv! */
2476 #define EXTDATA_BLOCK 1023
2484 data_addid(struct extdata *xd, Id sx)
2487 unsigned int x = (unsigned int)sx;
2489 xd->buf = solv_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
2490 dp = xd->buf + xd->len;
2495 *dp++ = (x >> 28) | 128;
2497 *dp++ = (x >> 21) | 128;
2498 *dp++ = (x >> 14) | 128;
2501 *dp++ = (x >> 7) | 128;
2503 xd->len = dp - xd->buf;
2507 data_addid64(struct extdata *xd, unsigned long long x)
2509 if (x >= 0x100000000)
2513 data_addid(xd, (Id)(x >> 35));
2514 xd->buf[xd->len - 1] |= 128;
2516 data_addid(xd, (Id)((unsigned int)x | 0x80000000));
2517 xd->buf[xd->len - 5] = (x >> 28) | 128;
2520 data_addid(xd, (Id)x);
2524 data_addideof(struct extdata *xd, Id x, int eof)
2527 abort(); /* XXX: not yet */
2529 x = (x & 63) | ((x & ~63) << 1);
2530 data_addid(xd, (eof ? x : x | 64));
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);
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, di.kv.num);
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: