repodata_initdata(Repodata *data, Repo *repo, int localpool)
{
memset(data, 0, sizeof (*data));
+ data->repodataid = data - repo->repodata;
data->repo = repo;
data->localpool = localpool;
if (localpool)
solv_free(data->attrdata);
solv_free(data->attriddata);
-}
-
-Repodata *
-repodata_create(Repo *repo, int localpool)
-{
- Repodata *data;
+ solv_free(data->attrnum64data);
- if (!repo->nrepodata)
- {
- repo->nrepodata = 2; /* start with id 1 */
- repo->repodata = solv_calloc(repo->nrepodata, sizeof(*data));
- }
- else
- {
- repo->nrepodata++;
- repo->repodata = solv_realloc2(repo->repodata, repo->nrepodata, sizeof(*data));
- }
- data = repo->repodata + repo->nrepodata - 1;
- repodata_initdata(data, repo, localpool);
- return data;
+ solv_free(data->dircache);
}
void
{
Repo *repo = data->repo;
int i = data - repo->repodata;
+ if (i == 0)
+ return;
repodata_freedata(data);
if (i < repo->nrepodata - 1)
- memmove(repo->repodata + i, repo->repodata + i + 1, (repo->nrepodata - 1 - i) * sizeof(Repodata));
+ {
+ /* whoa! this changes the repodataids! */
+ memmove(repo->repodata + i, repo->repodata + i + 1, (repo->nrepodata - 1 - i) * sizeof(Repodata));
+ for (; i < repo->nrepodata - 1; i++)
+ repo->repodata[i].repodataid = i;
+ }
repo->nrepodata--;
if (repo->nrepodata == 1)
{
}
#endif
+#define DIRCACHE_SIZE 41 /* < 1k */
+
+#ifdef DIRCACHE_SIZE
+struct dircache {
+ Id ids[DIRCACHE_SIZE];
+ char str[(DIRCACHE_SIZE * (DIRCACHE_SIZE - 1)) / 2];
+};
+#endif
+
Id
repodata_str2dir(Repodata *data, const char *dir, int create)
{
Id id, parent;
+#ifdef DIRCACHE_SIZE
+ const char *dirs;
+#endif
const char *dire;
parent = 0;
+ if (!*dir)
+ return 0;
while (*dir == '/' && dir[1] == '/')
dir++;
if (*dir == '/' && !dir[1])
return 1;
return dirpool_add_dir(&data->dirpool, 0, 1, create);
}
+#ifdef DIRCACHE_SIZE
+ dirs = dir;
+ if (data->dircache)
+ {
+ int l;
+ struct dircache *dircache = data->dircache;
+ l = strlen(dir);
+ while (l > 0)
+ {
+ if (l < DIRCACHE_SIZE && dircache->ids[l] && !memcmp(dircache->str + l * (l - 1) / 2, dir, l))
+ {
+ parent = dircache->ids[l];
+ dir += l;
+ if (!*dir)
+ return parent;
+ while (*dir == '/')
+ dir++;
+ break;
+ }
+ while (--l)
+ if (dir[l] == '/')
+ break;
+ }
+ }
+#endif
while (*dir)
{
dire = strchrnul(dir, '/');
parent = dirpool_add_dir(&data->dirpool, parent, id, create);
if (!parent)
return 0;
+#ifdef DIRCACHE_SIZE
+ if (!data->dircache)
+ data->dircache = solv_calloc(1, sizeof(struct dircache));
+ if (data->dircache)
+ {
+ int l = dire - dirs;
+ if (l < DIRCACHE_SIZE)
+ {
+ data->dircache->ids[l] = parent;
+ memcpy(data->dircache->str + l * (l - 1) / 2, dirs, l);
+ }
+ }
+#endif
if (!*dire)
break;
dir = dire + 1;
return parent;
}
+void
+repodata_free_dircache(Repodata *data)
+{
+ data->dircache = solv_free(data->dircache);
+}
+
const char *
repodata_dir2str(Repodata *data, Id did, const char *suf)
{
}
int
-repodata_lookup_num(Repodata *data, Id solvid, Id keyname, unsigned int *value)
+repodata_lookup_num(Repodata *data, Id solvid, Id keyname, unsigned long long *value)
{
unsigned char *dp;
Repokey *key;
- KeyValue kv;
+ unsigned int high, low;
*value = 0;
dp = find_key_data(data, solvid, keyname, &key);
if (!dp)
return 0;
- if (key->type == REPOKEY_TYPE_NUM
- || key->type == REPOKEY_TYPE_U32
- || key->type == REPOKEY_TYPE_CONSTANT)
+ switch (key->type)
{
- kv.num = 0;
- dp = data_fetch(dp, &kv, key);
- *value = kv.num;
+ case REPOKEY_TYPE_NUM:
+ data_read_num64(dp, &low, &high);
+ *value = (unsigned long long)high << 32 | low;
+ return 1;
+ case REPOKEY_TYPE_U32:
+ data_read_u32(dp, &low);
+ *value = low;
+ return 1;
+ case REPOKEY_TYPE_CONSTANT:
+ *value = key->size;
return 1;
+ default:
+ return 0;
}
- return 0;
}
int
dp = find_key_data(data, solvid, keyname, &key);
if (!dp)
return 0;
+ if (!(key->type == REPOKEY_TYPE_MD5 || key->type == REPOKEY_TYPE_SHA1 || key->type == REPOKEY_TYPE_SHA256))
+ return 0;
*typep = key->type;
return dp;
}
return stringpool_str2id(&data->spool, pool_id2str(data->repo->pool, id), create);
}
+Id
+repodata_lookup_id_uninternalized(Repodata *data, Id solvid, Id keyname, Id voidid)
+{
+ Id *ap;
+ if (!data->attrs)
+ return 0;
+ ap = data->attrs[solvid - data->start];
+ if (!ap)
+ return 0;
+ for (; *ap; ap += 2)
+ {
+ if (data->keys[*ap].name != keyname)
+ continue;
+ if (data->keys[*ap].type == REPOKEY_TYPE_VOID)
+ return voidid;
+ if (data->keys[*ap].type == REPOKEY_TYPE_ID)
+ return ap[1];
+ return 0;
+ }
+ return 0;
+}
+
/************************************************************************
* data search
* data iterator functions
*/
-static Repokey solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1] = {
- { SOLVABLE_NAME, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
- { SOLVABLE_ARCH, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
- { SOLVABLE_EVR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
- { SOLVABLE_VENDOR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
- { SOLVABLE_PROVIDES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
- { SOLVABLE_OBSOLETES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
- { SOLVABLE_CONFLICTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
- { SOLVABLE_REQUIRES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
- { SOLVABLE_RECOMMENDS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
- { SOLVABLE_SUGGESTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
- { SOLVABLE_SUPPLEMENTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
- { SOLVABLE_ENHANCES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
- { RPM_RPMDBID, REPOKEY_TYPE_U32, 0, KEY_STORAGE_SOLVABLE },
-};
-
static inline Id *
solvabledata_fetch(Solvable *s, KeyValue *kv, Id keyname)
{
di_entersub,
di_leavesub,
- di_nextsolvableattr,
di_nextsolvablekey,
- di_entersolvablekey
+ di_entersolvablekey,
+ di_nextsolvableattr
};
/* see dataiterator.h for documentation */
di->repodataid = 1; /* reset repodata iterator */
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)
{
- di->key = solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0);
+ extern Repokey repo_solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1];
+
+ di->key = repo_solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0);
di->data = 0;
goto di_entersolvablekey;
}
case di_enterarray: di_enterarray:
if (di->key->name == REPOSITORY_SOLVABLES)
goto di_nextkey;
- di->ddp = data_read_id(di->ddp, &di->kv.num);
+ di->ddp = data_read_id(di->ddp, (Id *)&di->kv.num);
di->kv.eof = 0;
di->kv.entry = -1;
/* FALLTHROUGH */
/* special solvable attr handling follows */
- case di_nextsolvableattr:
- di->kv.id = *di->idp++;
- di->kv.entry++;
- if (!*di->idp)
- {
- di->kv.eof = 1;
- di->state = di_nextsolvablekey;
- }
- break;
-
case di_nextsolvablekey: di_nextsolvablekey:
if (di->keyname || di->key->name == RPM_RPMDBID)
goto di_enterrepodata;
case di_entersolvablekey: di_entersolvablekey:
di->idp = solvabledata_fetch(di->pool->solvables + di->solvid, &di->kv, di->key->name);
- if (!di->idp || !di->idp[0])
+ if (!di->idp || !*di->idp)
goto di_nextsolvablekey;
- di->kv.id = di->idp[0];
- di->kv.num = di->idp[0];
- di->idp++;
- if (!di->kv.eof && !di->idp[0])
- di->kv.eof = 1;
- di->kv.entry = 0;
if (di->kv.eof)
- di->state = di_nextsolvablekey;
- else
- di->state = di_nextsolvableattr;
+ {
+ /* not an array */
+ di->kv.id = *di->idp;
+ di->kv.num = *di->idp; /* for rpmdbid */
+ di->kv.num2 = 0; /* for rpmdbid */
+ di->kv.entry = 0;
+ di->state = di_nextsolvablekey;
+ break;
+ }
+ di->kv.entry = -1;
+ /* FALLTHROUGH */
+
+ case di_nextsolvableattr:
+ di->state = di_nextsolvableattr;
+ di->kv.id = *di->idp++;
+ di->kv.entry++;
+ if (!*di->idp)
+ {
+ di->kv.eof = 1;
+ di->state = di_nextsolvablekey;
+ }
break;
+
}
if (di->matcher.match)
if (!datamatcher_match(&di->matcher, di->kv.str))
continue;
}
+ else
+ {
+ if (di->keyname == SOLVABLE_FILELIST && di->key->type == REPOKEY_TYPE_DIRSTRARRAY && (di->flags & SEARCH_FILES) != 0)
+ repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags);
+ }
/* found something! */
return 1;
}
#define REPODATA_ATTRS_BLOCK 31
#define REPODATA_ATTRDATA_BLOCK 1023
#define REPODATA_ATTRIDDATA_BLOCK 63
+#define REPODATA_ATTRNUM64DATA_BLOCK 15
Id
}
void
-repodata_set_num(Repodata *data, Id solvid, Id keyname, unsigned int num)
+repodata_set_num(Repodata *data, Id solvid, Id keyname, unsigned long long num)
{
Repokey key;
key.name = keyname;
key.type = REPOKEY_TYPE_NUM;
key.size = 0;
key.storage = KEY_STORAGE_INCORE;
+ if (num >= 0x80000000)
+ {
+ data->attrnum64data = solv_extend(data->attrnum64data, data->attrnum64datalen, 1, sizeof(unsigned long long), REPODATA_ATTRNUM64DATA_BLOCK);
+ data->attrnum64data[data->attrnum64datalen] = num;
+ num = 0x80000000 | data->attrnum64datalen++;
+ }
repodata_set(data, solvid, &key, (Id)num);
}
Repokey key;
unsigned char *dp;
+ if (len < 0)
+ return;
key.name = keyname;
key.type = REPOKEY_TYPE_BINARY;
key.size = 0;
return evr;
for (p = evr; *p >= '0' && *p <= '9'; p++)
;
- return p != evr && *p == ':' ? p + 1 : evr;
+ return p != evr && *p == ':' && p[1] ? p + 1 : evr;
}
void
repodata_set_str(data, solvid, SOLVABLE_MEDIAFILE, file);
}
+static inline void repodata_set_poolstrn(Repodata *data, Id solvid, Id keyname, const char *str, int l)
+{
+ Id id;
+ if (data->localpool)
+ id = stringpool_strn2id(&data->spool, str, l, 1);
+ else
+ id = pool_strn2id(data->repo->pool, str, l, 1);
+ repodata_set_id(data, solvid, keyname, id);
+}
+
+/* XXX: medianr is currently not stored */
+void
+repodata_set_deltalocation(Repodata *data, Id handle, int medianr, const char *dir, const char *file)
+{
+ int l = 0;
+ const char *evr, *suf, *s;
+
+ if (!dir)
+ {
+ if ((dir = strrchr(file, '/')) != 0)
+ {
+ l = dir - file;
+ dir = file;
+ file = dir + l + 1;
+ if (!l)
+ l++;
+ }
+ }
+ else
+ l = strlen(dir);
+ if (l >= 2 && dir[0] == '.' && dir[1] == '/' && (l == 2 || dir[2] != '/'))
+ {
+ dir += 2;
+ l -= 2;
+ }
+ if (l == 1 && dir[0] == '.')
+ l = 0;
+ if (dir && l)
+ repodata_set_poolstrn(data, handle, DELTA_LOCATION_DIR, dir, l);
+ evr = strchr(file, '-');
+ if (evr)
+ {
+ for (s = evr - 1; s > file; s--)
+ if (*s == '-')
+ {
+ evr = s;
+ break;
+ }
+ }
+ suf = strrchr(file, '.');
+ if (suf)
+ {
+ for (s = suf - 1; s > file; s--)
+ if (*s == '.')
+ {
+ suf = s;
+ break;
+ }
+ if (!strcmp(suf, ".delta.rpm") || !strcmp(suf, ".patch.rpm"))
+ {
+ /* We accept one more item as suffix. */
+ for (s = suf - 1; s > file; s--)
+ if (*s == '.')
+ {
+ suf = s;
+ break;
+ }
+ }
+ }
+ if (!evr)
+ suf = 0;
+ if (suf && evr && suf < evr)
+ suf = 0;
+ repodata_set_poolstrn(data, handle, DELTA_LOCATION_NAME, file, evr ? evr - file : strlen(file));
+ if (evr)
+ repodata_set_poolstrn(data, handle, DELTA_LOCATION_EVR, evr + 1, suf ? suf - evr - 1: strlen(evr + 1));
+ if (suf)
+ repodata_set_poolstr(data, handle, DELTA_LOCATION_SUFFIX, suf + 1);
+}
+
+void
+repodata_set_sourcepkg(Repodata *data, Id solvid, const char *sourcepkg)
+{
+ Pool *pool = data->repo->pool;
+ Solvable *s = pool->solvables + solvid;
+ const char *p, *sevr, *sarch, *name, *evr;
+
+ p = strrchr(sourcepkg, '.');
+ if (!p || strcmp(p, ".rpm") != 0)
+ {
+ if (*sourcepkg)
+ repodata_set_str(data, solvid, SOLVABLE_SOURCENAME, sourcepkg);
+ return;
+ }
+ p--;
+ while (p > sourcepkg && *p != '.')
+ p--;
+ if (*p != '.' || p == sourcepkg)
+ return;
+ sarch = p-- + 1;
+ while (p > sourcepkg && *p != '-')
+ p--;
+ if (*p != '-' || p == sourcepkg)
+ return;
+ p--;
+ while (p > sourcepkg && *p != '-')
+ p--;
+ if (*p != '-' || p == sourcepkg)
+ return;
+ sevr = p + 1;
+ pool = s->repo->pool;
+
+ name = pool_id2str(pool, s->name);
+ if (name && !strncmp(sourcepkg, name, sevr - sourcepkg - 1) && name[sevr - sourcepkg - 1] == 0)
+ repodata_set_void(data, solvid, SOLVABLE_SOURCENAME);
+ else
+ repodata_set_id(data, solvid, SOLVABLE_SOURCENAME, pool_strn2id(pool, sourcepkg, sevr - sourcepkg - 1, 1));
+
+ evr = evrid2vrstr(pool, s->evr);
+ if (evr && !strncmp(sevr, evr, sarch - sevr - 1) && evr[sarch - sevr - 1] == 0)
+ repodata_set_void(data, solvid, SOLVABLE_SOURCEEVR);
+ else
+ repodata_set_id(data, solvid, SOLVABLE_SOURCEEVR, pool_strn2id(pool, sevr, sarch - sevr - 1, 1));
+
+ if (!strcmp(sarch, "src.rpm"))
+ repodata_set_constantid(data, solvid, SOLVABLE_SOURCEARCH, ARCH_SRC);
+ else if (!strcmp(sarch, "nosrc.rpm"))
+ repodata_set_constantid(data, solvid, SOLVABLE_SOURCEARCH, ARCH_NOSRC);
+ else
+ repodata_set_constantid(data, solvid, SOLVABLE_SOURCEARCH, pool_strn2id(pool, sarch, strlen(sarch) - 4, 1));
+}
+
void
repodata_set_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
{
}
void
-repodata_delete_uninternalized(Repodata *data, Id solvid, Id keyname)
+repodata_set_deleted_uninternalized(Repodata *data, Id solvid, Id keyname)
{
Id *pp, *ap, **app;
app = repodata_get_attrp(data, solvid);
/* XXX: does not work correctly, needs fix in iterators! */
void
-repodata_delete(Repodata *data, Id solvid, Id keyname)
+repodata_set_deleted(Repodata *data, Id solvid, Id keyname)
{
Repokey key;
key.name = keyname;
repodata_merge_attrs(Repodata *data, Id dest, Id src)
{
Id *keyp;
- if (dest == src || !(keyp = data->attrs[src - data->start]))
+ if (dest == src || !data->attrs || !(keyp = data->attrs[src - data->start]))
return;
for (; *keyp; keyp += 2)
repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
repodata_merge_some_attrs(Repodata *data, Id dest, Id src, Map *keyidmap, int overwrite)
{
Id *keyp;
- if (dest == src || !(keyp = data->attrs[src - data->start]))
+ if (dest == src || !data->attrs || !(keyp = data->attrs[src - data->start]))
return;
for (; *keyp; keyp += 2)
if (!keyidmap || MAPTST(keyidmap, keyp[0]))
repodata_insert_keyid(data, dest, keyp[0], keyp[1], overwrite);
}
+/* swap (uninternalized) attrs from src and dest */
+void
+repodata_swap_attrs(Repodata *data, Id dest, Id src)
+{
+ Id *tmpattrs;
+ if (!data->attrs || dest == src)
+ return;
+ tmpattrs = data->attrs[dest - data->start];
+ data->attrs[dest - data->start] = data->attrs[src - data->start];
+ data->attrs[src - data->start] = tmpattrs;
+}
/**********************************************************************/
};
static void
-data_addid(struct extdata *xd, Id x)
+data_addid(struct extdata *xd, Id sx)
{
+ unsigned int x = (unsigned int)sx;
unsigned char *dp;
xd->buf = solv_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
}
static void
-data_addideof(struct extdata *xd, Id x, int eof)
+data_addid64(struct extdata *xd, unsigned long long x)
+{
+ if (x >= 0x100000000)
+ {
+ if ((x >> 35) != 0)
+ {
+ data_addid(xd, (Id)(x >> 35));
+ xd->buf[xd->len - 1] |= 128;
+ }
+ data_addid(xd, (Id)((unsigned int)x | 0x80000000));
+ xd->buf[xd->len - 5] = (x >> 28) | 128;
+ }
+ else
+ data_addid(xd, (Id)x);
+}
+
+static void
+data_addideof(struct extdata *xd, Id sx, int eof)
{
- if (x >= 64)
- x = (x & 63) | ((x & ~63) << 1);
- data_addid(xd, (eof ? x : x | 64));
+ unsigned int x = (unsigned int)sx;
+ unsigned char *dp;
+
+ xd->buf = solv_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
+ dp = xd->buf + xd->len;
+
+ if (x >= (1 << 13))
+ {
+ if (x >= (1 << 27))
+ *dp++ = (x >> 27) | 128;
+ if (x >= (1 << 20))
+ *dp++ = (x >> 20) | 128;
+ *dp++ = (x >> 13) | 128;
+ }
+ if (x >= (1 << 6))
+ *dp++ = (x >> 6) | 128;
+ *dp++ = eof ? (x & 63) : (x & 63) | 64;
+ xd->len = dp - xd->buf;
}
static void
case REPOKEY_TYPE_SHA256:
data_addblob(xd, data->attrdata + val, SIZEOF_SHA256);
break;
- case REPOKEY_TYPE_ID:
case REPOKEY_TYPE_NUM:
+ if (val & 0x80000000)
+ {
+ data_addid64(xd, data->attrnum64data[val ^ 0x80000000]);
+ break;
+ }
+ /* FALLTHROUGH */
+ case REPOKEY_TYPE_ID:
case REPOKEY_TYPE_DIR:
data_addid(xd, val);
break;
{
Id len;
unsigned char *dp = data_read_id(data->attrdata + val, &len);
- dp += len;
+ dp += (unsigned int)len;
data_addblob(xd, data->attrdata + val, dp - (data->attrdata + val));
}
break;
data->attrs = solv_free(data->attrs);
data->attrdata = solv_free(data->attrdata);
data->attriddata = solv_free(data->attriddata);
+ data->attrnum64data = solv_free(data->attrnum64data);
data->attrdatalen = 0;
data->attriddatalen = 0;
+ data->attrnum64datalen = 0;
}
void
repodata_set_void(sdata, SOLVID_META, di.key->name);
break;
case REPOKEY_TYPE_NUM:
- repodata_set_num(sdata, SOLVID_META, di.key->name, di.kv.num);
+ repodata_set_num(sdata, SOLVID_META, di.key->name, SOLV_KV_NUM64(&di.kv));
break;
case REPOKEY_TYPE_MD5:
case REPOKEY_TYPE_SHA1:
xkey.name = xkeyname;
xkey.type = di.kv.id;
xkey.storage = KEY_STORAGE_INCORE;
- xkey.size = 0;
+ xkey.size = 0;
repodata_key2id(sdata, &xkey, 1);
xkeyname = 0;
}
solv_free(stubdataids);
}
+unsigned int
+repodata_memused(Repodata *data)
+{
+ return data->incoredatalen + data->vincorelen;
+}
+
/*
vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4:
*/