From: Michael Schroeder Date: Fri, 14 Dec 2007 20:08:42 +0000 (+0000) Subject: - some pieces of code for the unified lookup/search interface X-Git-Tag: BASE-SuSE-Code-12_1-Branch~1056 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a70ae66d2187f0e64121983edae034fbbb742cf8;p=platform%2Fupstream%2Flibsolv.git - some pieces of code for the unified lookup/search interface --- diff --git a/src/evr.c b/src/evr.c index 857b92e..9ea0398 100644 --- a/src/evr.c +++ b/src/evr.c @@ -98,6 +98,16 @@ evrcmp(Pool *pool, Id evr1id, Id evr2id, int mode) ; for (s2 = evr2; *s2 >= '0' && *s2 <= '9'; s2++) ; + if (mode == EVRCMP_MATCH && (*evr1 == ':' || *evr2 == ':')) + { + /* empty epoch, skip epoch check */ + if (*s1 == ':') + evr1 = s1 + 1; + if (*s2 == ':') + evr2 = s2 + 1; + s1 = evr1; + s2 = evr2; + } if (s1 == evr1 || *s1 != ':') s1 = 0; if (s2 == evr2 || *s2 != ':') diff --git a/src/repo.c b/src/repo.c index 90deae5..0a18895 100644 --- a/src/repo.c +++ b/src/repo.c @@ -445,111 +445,175 @@ repo_fix_legacy(Repo *repo, Offset provides, Offset supplements) return supplements; } -#if 0 void repodata_search(Repodata *data, Id key) { } +unsigned char * +data_read_id(unsigned char *dp, Id *idp) +{ + Id x = 0; + unsigned char c; + for (;;) + { + c = *dp++; + if (!(c & 0x80)) + { + *idp = (x << 7) ^ c; + return dp; + } + x = (x << 7) ^ c ^ 128; + } +} + +unsigned char * +data_skip(unsigned char *dp, int type) +{ + switch (type) + { + case TYPE_VOID: + return dp; + case TYPE_ID: + while ((*dp & 0x80) != 0) + dp++; + return dp; + case TYPE_IDARRAY: + case TYPE_REL_IDARRAY: + case TYPE_IDVALUEARRAY: + case TYPE_IDVALUEVALUEARRAY: + while ((*dp & 0xc0) != 0) + dp++; + return dp; + default: + fprintf(stderr, "unknown type in data_skip\n"); + exit(1); + } +} + const char * -repodata_lookup_id(Repodata *data, Id num, Id key) +repodata_lookup_str(Repodata *data, Id entry, Id key) { + Id schema; Id id, k, *kp, *keyp; + unsigned char *dp; - fseek(data->fp, data->itemoffsets[num] , SEEK_SET); - Id *keyp = data->schemadata + data->schemata[read_id(data->fp, data->numschemata)]; - /* make sure our schema contains the key */ - for (kp = keyp; (k = *kp++) != 0) + if (data->entryschemau8) + schema = data->entryschemau8[entry]; + else + schema = data->entryschema[entry]; + keyp = data->schemadata + schema; + /* make sure the schema of this solvable contains the key */ + for (kp = keyp; (k = *kp++) != 0; ) if (k == key) break; if (k == 0) return 0; - /* get it */ - while ((k = *keyp++) != 0) + switch (data->keys[key].storage) { - if (k == key) - break; - switch (keys[key].type) + case KEY_STORAGE_VERTICAL_OFFSET: + case KEY_STORAGE_INCORE: + dp = data->incoredata + data->incoreoffset[entry]; + while ((k = *keyp++) != 0) { - case TYPE_ID: - while ((read_u8(data->fp) & 0x80) != 0) - ; - break; - case TYPE_U32: - read_u32(data->fp); - break; - case TYPE_STR: - while(read_u8(data->fp) != 0) - ; - break; - case TYPE_IDARRAY: - while ((read_u8(data->fp) & 0xc0) != 0) - ; - break; + if (k == key) + break; + if (data->keys[k].storage == KEY_STORAGE_VERTICAL_OFFSET) + { + /* skip that offset */ + dp = data_skip(dp, TYPE_ID); + continue; + } + if (data->keys[k].storage != KEY_STORAGE_INCORE) + continue; + dp = data_skip(dp, data->keys[k].type); } + if (data->keys[key].storage == KEY_STORAGE_VERTICAL_OFFSET) + { + int i, oi, max; + if (!data->fp) + return 0; + dp = data_read_id(dp, &id); + max = data->keys[key].size - id; + if (max <= 0) + return 0; + /* we now have the offset, go into vertical */ + for (i = 1; i < key; i++) + if (data->keys[i].storage == KEY_STORAGE_VERTICAL_OFFSET) + id += data->keys[i].size; + if (fseek(data->fp, data->verticaloffset + id, SEEK_SET)) + return 0; + i = max > 256 ? 256 : max; + for (oi = 0;; oi = i, i += 256) + { + if (i > max) + i = max; + if (i == oi) + return 0; + if (i > data->strbuflen) + { + data->strbuf = xrealloc(data->strbuf, i); + data->strbuflen = i; + } + if (fread(data->strbuf + oi, i - oi, 1, data->fp) != 1) + return 0; + if (memchr(data->strbuf + oi, 0, i - oi)) + return data->strbuf; + } + } + if (data->keys[key].type == TYPE_STR) + return (const char *)dp; + /* id type, must either use global or local string strore*/ + dp = data_read_id(dp, &id); +#if 0 + /* not yet working */ + return data->ss.stringspace + data->ss.strings[id]; +#else + return id2str(data->repo->pool, id); +#endif } - id = read_id(data->fp, 0); - return data->ss.stringspace + data->ss.strings[id]; + return 0; } -Id -repo_lookup_id(Solvable *s, Id key) +const char * +repo_lookup_str(Solvable *s, Id key) { - Solvable *rs; Repo *repo = s->repo; + Pool *pool = repo->pool; Repodata *data; int i, j, n; switch(key) { case SOLVABLE_NAME: - return s->name; + return id2str(pool, s->name); case SOLVABLE_ARCH: - return s->arch; + return id2str(pool, s->arch); case SOLVABLE_EVR: - return s->evr; + return id2str(pool, s->evr); case SOLVABLE_VENDOR: - return s->vendor; - } - /* convert solvable id into repo item count */ - if (repo->end - repo->start + 1 == repo->nsolvables) - { - n = (s - pool->solvables); - if (n < repo->start || n > repo->end) - return 0; - n -= repo->start; - } - else - { - for (i = repo->start, rs = pool->solvables + i, n = 0; i < repo->end; i++, rs++) - { - if (rs->repo != repo) - continue; - if (rs == s) - break; - n++; - } - if (i == repo->end) - return 0; + return id2str(pool, s->vendor); } + n = s - pool->solvables; for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++) { - for (j = 0; j < data->nkeys; j++) + if (n < data->start || n >= data->end) + continue; + for (j = 1; j < data->nkeys; j++) { - if (data->keys[j].name == key && data->keys[j].type == TYPE_ID) - return repodata_lookup_id(data, n, j); + if (data->keys[j].name == key && (data->keys[j].type == TYPE_ID || data->keys[j].type == TYPE_STR)) + return repodata_lookup_str(data, n - data->start, j); } } return 0; } -#endif + static int key_cmp (const void *pa, const void *pb) { - struct key { Id name; unsigned type; }; - struct key *a = (struct key*)pa; - struct key *b = (struct key*)pb; + Repokey *a = (Repokey *)pa; + Repokey *b = (Repokey *)pb; return a->name - b->name; } @@ -577,17 +641,16 @@ repo_add_attrstore (Repo *repo, Attrstore *s, const char *location) memset (data, 0, sizeof (*data)); data->s = s; data->nkeys = s->nkeys; - /* Don't store the first key, it's {0,0,0}. */ - data->nkeys--; if (data->nkeys) { - data->keys = xmalloc (data->nkeys * sizeof (data->keys[0])); - for (i = 0; i < data->nkeys; i++) + data->keys = xmalloc(data->nkeys * sizeof(data->keys[0])); + for (i = 1; i < data->nkeys; i++) { - data->keys[i].name = s->keys[i + 1].name; - data->keys[i].type = s->keys[i + 1].type; + data->keys[i].name = s->keys[i].name; + data->keys[i].type = s->keys[i].type; } - qsort (data->keys, data->nkeys, sizeof (data->keys[0]), key_cmp); + if (data->nkeys > 2) + qsort(data->keys + 1, data->nkeys - 1, sizeof(data->keys[0]), key_cmp); } if (location) data->location = strdup(location); diff --git a/src/repo.h b/src/repo.h index eda14d2..a27b9ba 100644 --- a/src/repo.h +++ b/src/repo.h @@ -17,18 +17,55 @@ #include "pool.h" #include "attr_store.h" +typedef struct _Repokey { + Id name; + Id type; + Id size; + Id storage; +} Repokey; + +#define KEY_STORAGE_DROPPED 0 +#define KEY_STORAGE_SOLVABLE 1 +#define KEY_STORAGE_INCORE 2 +#define KEY_STORAGE_VERTICAL_OFFSET 3 + +struct _Repo; + typedef struct _Repodata { + struct _Repo *repo; /* back pointer to repo */ + + int start; /* start of solvables this repodata is valid for */ + int end; /* last solvable + 1 of this repodata */ + /* Keys provided by this attribute store, sorted by name value. The same keys may be provided by multiple attribute stores, but then only for different solvables. I.e. the relation (solvable,name) -> store has to be injective. */ - struct { - Id name; - unsigned type; - } *keys; - /* Length of keys array */ - unsigned nkeys; + + Repokey *keys; /* keys, first entry is always zero */ + unsigned int nkeys; /* length of keys array */ + + Id *schemata; /* schema -> offset into schemadata */ + unsigned int nschemata; /* number of schemata */ + + Id *schemadata; /* schema storage */ + + unsigned char *entryschemau8; /* schema for entry */ + Id *entryschema; /* schema for entry */ + + unsigned char *incoredata; /* in-core data */ + unsigned int incoredatalen; /* data len */ + unsigned int incoredatafree; /* data len */ + + Id *incoreoffset; /* offset for all entries */ + + FILE *fp; /* for paged access */ + Id verticaloffset; /* offset of verticals */ + + char *strbuf; + int strbuflen; + /* The attribute store itself. */ Attrstore *s; @@ -42,9 +79,11 @@ typedef struct _Repodata { unsigned char checksum[20]; } Repodata; + typedef struct _Repo { const char *name; struct _Pool *pool; /* pool containing repo data */ + int start; /* start of this repo solvables within pool->solvables */ int end; /* last solvable + 1 of this repo */ int nsolvables; /* number of solvables repo is contributing to pool */ diff --git a/src/repo_solv.c b/src/repo_solv.c index a01f719..8c690af 100644 --- a/src/repo_solv.c +++ b/src/repo_solv.c @@ -284,20 +284,13 @@ skip_item (FILE *fp, unsigned type, unsigned numid, unsigned numrel) static int key_cmp (const void *pa, const void *pb) { - struct key { Id name; unsigned type; }; - struct key *a = (struct key*)pa; - struct key *b = (struct key*)pb; + Repokey *a = (Repokey *)pa; + Repokey *b = (Repokey *)pb; return a->name - b->name; } -struct key { - Id name; - Id type; - Id size; -}; - static void -parse_repodata (FILE *fp, Id *keyp, struct key *keys, Id *idmap, unsigned numid, unsigned numrel, Repo *repo) +parse_repodata (FILE *fp, Id *keyp, Repokey *keys, Id *idmap, unsigned numid, unsigned numrel, Repo *repo) { Id key, id; Id *ida, *ide; @@ -306,6 +299,7 @@ parse_repodata (FILE *fp, Id *keyp, struct key *keys, Id *idmap, unsigned numid, repo->repodata = xrealloc(repo->repodata, (repo->nrepodata + 1) * sizeof (*data)); data = repo->repodata + repo->nrepodata++; + data->repo = repo; memset(data, 0, sizeof(*data)); while ((key = *keyp++) != 0) @@ -327,9 +321,10 @@ parse_repodata (FILE *fp, Id *keyp, struct key *keys, Id *idmap, unsigned numid, pool_debug (mypool, SAT_FATAL, "invalid attribute data\n"); exit (1); } - data->nkeys = n >> 1; + data->nkeys = 1 + (n >> 1); data->keys = xmalloc2(data->nkeys, sizeof(data->keys[0])); - for (i = 0, ide = ida; i < data->nkeys; i++) + memset(data->keys, 0, sizeof(Repokey)); + for (i = 1, ide = ida; i < data->nkeys; i++) { if (*ide >= numid) { @@ -338,9 +333,12 @@ parse_repodata (FILE *fp, Id *keyp, struct key *keys, Id *idmap, unsigned numid, } data->keys[i].name = idmap[*ide++]; data->keys[i].type = *ide++; + data->keys[i].size = 0; + data->keys[i].storage = 0; } xfree(ida); - qsort(data->keys, data->nkeys, sizeof(data->keys[0]), key_cmp); + if (data->nkeys > 2) + qsort(data->keys + 1, data->nkeys - 1, sizeof(data->keys[0]), key_cmp); break; case TYPE_STR: if (id != REPODATA_LOCATION) @@ -366,14 +364,79 @@ parse_repodata (FILE *fp, Id *keyp, struct key *keys, Id *idmap, unsigned numid, /*-----------------------------------------------------------------*/ -void -skip_schema(FILE *fp, Id *keyp, struct key *keys, unsigned int numid, unsigned int numrel) +static void +skip_schema(FILE *fp, Id *keyp, Repokey *keys, unsigned int numid, unsigned int numrel) { Id key; while ((key = *keyp++) != 0) skip_item(fp, keys[key].type, numid, numrel); } +/*-----------------------------------------------------------------*/ + +static void +incore_add_id(Repodata *data, Id x) +{ + unsigned char *dp; + /* make sure we have at least 5 bytes free */ + if (data->incoredatafree < 5) + { + data->incoredata = xrealloc(data->incoredata, data->incoredatalen + 1024); + data->incoredatafree = 1024; + } + dp = data->incoredata + data->incoredatalen; + if (x < 0) + abort(); + if (x >= (1 << 14)) + { + if (x >= (1 << 28)) + *dp++ = (x >> 28) | 128; + if (x >= (1 << 21)) + *dp++ = (x >> 21) | 128; + *dp++ = (x >> 14) | 128; + } + if (x >= (1 << 7)) + *dp++ = (x >> 7) | 128; + *dp++ = x & 127; + data->incoredatafree -= dp - (data->incoredata + data->incoredatalen); + data->incoredatalen = dp - data->incoredata; +} + +static void +incore_add_u32(Repodata *data, unsigned int x) +{ + unsigned char *dp; + /* make sure we have at least 4 bytes free */ + if (data->incoredatafree < 4) + { + data->incoredata = xrealloc(data->incoredata, data->incoredatalen + 1024); + data->incoredatafree = 1024; + } + dp = data->incoredata + data->incoredatalen; + *dp++ = x >> 24; + *dp++ = x >> 16; + *dp++ = x >> 8; + *dp++ = x; + data->incoredatafree -= 4; + data->incoredatalen += 4; +} + +static void +incore_add_u8(Repodata *data, unsigned int x) +{ + unsigned char *dp; + /* make sure we have at least 1 byte free */ + if (data->incoredatafree < 1) + { + data->incoredata = xrealloc(data->incoredata, data->incoredatalen + 1024); + data->incoredatafree = 1024; + } + dp = data->incoredata + data->incoredatalen; + *dp++ = x; + data->incoredatafree--; + data->incoredatalen++; +} + // ---------------------------------------------- /* @@ -388,7 +451,9 @@ repo_add_solv(Repo *repo, FILE *fp) int i, l; unsigned int numid, numrel, numsolv; unsigned int numkeys, numschemata, numinfo; +#if 0 Attrstore *embedded_store = 0; +#endif Offset sizeid; Offset *str; /* map Id -> Offset into string space */ @@ -408,10 +473,12 @@ repo_add_solv(Repo *repo, FILE *fp) Solvable *s; unsigned int solvflags; unsigned int solvversion; - struct key *keys; + Repokey *keys; Id *schemadata, *schemadatap, *schemadataend; Id *schemata, key; + Repodata data; + mypool = pool; if (read_u32(fp) != ('S' << 24 | 'O' << 16 | 'L' << 8 | 'V')) @@ -441,6 +508,9 @@ repo_add_solv(Repo *repo, FILE *fp) numinfo = read_u32(fp); solvflags = read_u32(fp); + memset(&data, 0, sizeof(data)); + data.repo = repo; + if (solvversion < SOLV_VERSION_3 && numinfo) { @@ -679,11 +749,50 @@ repo_add_solv(Repo *repo, FILE *fp) /* keys start at 1 */ for (i = 1; i < numkeys; i++) { - keys[i].name = idmap[read_id(fp, numid)]; + keys[i].name = id = idmap[read_id(fp, numid)]; keys[i].type = read_id(fp, 0); keys[i].size = read_id(fp, 0); + keys[i].storage = KEY_STORAGE_DROPPED; + switch (keys[i].type) + { + case TYPE_ID: + switch(id) + { + case SOLVABLE_NAME: + case SOLVABLE_ARCH: + case SOLVABLE_EVR: + case SOLVABLE_VENDOR: + keys[i].storage = KEY_STORAGE_SOLVABLE; + break; + default: + keys[i].storage = KEY_STORAGE_INCORE; + break; + } + break; + case TYPE_IDARRAY: + case TYPE_REL_IDARRAY: + if (id >= INTERESTED_START && id <= INTERESTED_END) + keys[i].storage = KEY_STORAGE_SOLVABLE; + else + keys[i].storage = KEY_STORAGE_INCORE; + break; + case TYPE_STR: + keys[i].storage = KEY_STORAGE_INCORE; + break; + case TYPE_U32: + if (id == RPM_RPMDBID) + keys[i].storage = KEY_STORAGE_SOLVABLE; + else + keys[i].storage = KEY_STORAGE_INCORE; + break; + default: + break; + } } + data.keys = keys; + data.nkeys = numkeys; + /******* Part 4: Schemata ********************************************/ id = read_id(fp, 0); @@ -696,6 +805,9 @@ repo_add_solv(Repo *repo, FILE *fp) schemata[i] = schemadatap - schemadata; schemadatap = read_idarray(fp, numid, 0, schemadatap, schemadataend, 0); } + data.schemata = schemata; + data.nschemata = numschemata; + data.schemadata = schemadata; /******* Part 5: Info ***********************************************/ for (i = 0; i < numinfo; i++) @@ -760,6 +872,8 @@ repo_add_solv(Repo *repo, FILE *fp) Solvable *sstart = s; Id type; +/* XXX BROKEN CODE */ + for (i = 0; i < numsolv; i++) solvschema[i] = read_id(fp, numschemata); for (key = 1; key < numkeys; key++) @@ -793,6 +907,8 @@ repo_add_solv(Repo *repo, FILE *fp) s->evr = did; else if (id == SOLVABLE_VENDOR) s->vendor = did; + else + incore_add_id(&data, did); break; case TYPE_U32: h = read_u32(fp); @@ -802,6 +918,10 @@ repo_add_solv(Repo *repo, FILE *fp) repo->rpmdbid = (Id *)xcalloc(numsolv, sizeof(Id)); repo->rpmdbid[i] = h; } + else + { + incore_add_u32(&data, h); + } break; case TYPE_STR: while(read_u8(fp) != 0) @@ -838,6 +958,8 @@ repo_add_solv(Repo *repo, FILE *fp) s->freshens = ido; break; case TYPE_VOID: + break; +#if 0 case TYPE_ATTR_INT: case TYPE_ATTR_CHUNK: case TYPE_ATTR_STRING: @@ -847,6 +969,9 @@ repo_add_solv(Repo *repo, FILE *fp) embedded_store = new_store (pool); add_attr_from_file (embedded_store, i, id, type, idmap, numid, fp); break; +#endif + default: + abort(); } } } @@ -859,6 +984,7 @@ repo_add_solv(Repo *repo, FILE *fp) mypool = 0; return; } + for (i = 0; i < numsolv; i++, s++) { if (exists && !exists[i]) @@ -879,6 +1005,8 @@ repo_add_solv(Repo *repo, FILE *fp) s->evr = did; else if (id == SOLVABLE_VENDOR) s->vendor = did; + else if (keys[key].storage == KEY_STORAGE_INCORE) + incore_add_id(&data, did); #if 0 POOL_DEBUG(SAT_DEBUG_STATS, "%s -> %s\n", id2str(pool, id), id2str(pool, did)); #endif @@ -894,19 +1022,61 @@ repo_add_solv(Repo *repo, FILE *fp) repo->rpmdbid = (Id *)xcalloc(numsolv, sizeof(Id)); repo->rpmdbid[i] = h; } + else if (keys[key].storage == KEY_STORAGE_INCORE) + incore_add_u32(&data, h); break; case TYPE_STR: - while(read_u8(fp) != 0) - ; + if (keys[key].storage == KEY_STORAGE_INCORE) + { + while ((h = read_u8(fp)) != 0) + incore_add_u8(&data, h); + incore_add_u8(&data, 0); + } + else + { + while (read_u8(fp) != 0) + ; + } break; case TYPE_IDARRAY: case TYPE_REL_IDARRAY: if (id < INTERESTED_START || id > INTERESTED_END) { - /* not interested in array */ - while ((read_u8(fp) & 0xc0) != 0) - ; - break; + if (keys[key].storage == KEY_STORAGE_INCORE) + { + Id old = 0, rel = keys[key].type == TYPE_REL_IDARRAY ? SOLVABLE_PREREQMARKER : 0; + do + { + did = read_id(fp, 0); + h = did & 0x40; + did = (did & 0x3f) | ((did >> 1) & ~0x3f); + if (rel) + { + if (did == 0) + { + did = rel; + old = 0; + } + else + { + did += old; + old = did; + } + } + if (did >= numid + numrel) + abort(); + did = idmap[did]; + did = ((did & ~0x3f) << 1) | h; + incore_add_id(&data, did); + } + while (h); + } + else + { + while ((read_u8(fp) & 0xc0) != 0) + ; + break; + } } ido = idarraydatap - repo->idarraydata; idarraydatap = read_idarray(fp, numid + numrel, idmap, idarraydatap, idarraydataend, keys[key].type == TYPE_REL_IDARRAY); @@ -934,7 +1104,9 @@ repo_add_solv(Repo *repo, FILE *fp) POOL_DEBUG(SAT_DEBUG_STATS," %s\n", dep2str(pool, repo->idarraydata[ido])); #endif break; +#if 0 case TYPE_VOID: + case TYPE_ATTR_INT: case TYPE_ATTR_CHUNK: case TYPE_ATTR_STRING: @@ -944,12 +1116,45 @@ repo_add_solv(Repo *repo, FILE *fp) embedded_store = new_store (pool); add_attr_from_file (embedded_store, i, id, keys[key].type, idmap, numid, fp); break; +#endif default: skip_item(fp, keys[key].type, numid, numrel); } } } + + if (data.incoredatafree) + { + /* shrink excess size */ + data.incoredata = xrealloc(data.incoredata, data.incoredatalen); + data.incoredatafree = 0; + } + + for (i = 1; i < numkeys; i++) + if (keys[i].storage == KEY_STORAGE_VERTICAL_OFFSET) + break; + if (i < numkeys) + { + /* we have vertical data, make it available */ + data.fp = fp; + data.verticaloffset = ftell(fp); + } + + if (data.incoredatalen || data.fp) + { + /* we got some data, make it available */ + repo->repodata = xrealloc(repo->repodata, (repo->nrepodata + 1) * sizeof(data)); + repo->repodata[repo->nrepodata++] = data; + } + else + { + xfree(schemata); + xfree(schemadata); + xfree(keys); + } + xfree(exists); +#if 0 if (embedded_store) { attr_store_pack (embedded_store); @@ -958,10 +1163,8 @@ repo_add_solv(Repo *repo, FILE *fp) /* The NULL name here means embedded attributes. */ repo_add_attrstore (repo, embedded_store, NULL); } +#endif xfree(idmap); - xfree(schemata); - xfree(schemadata); - xfree(keys); mypool = 0; }