Hashval *dirmap;
Hashmask dirmapn;
unsigned int dirmapused;
+ int dirconflicts;
+
+ Map idxmap;
Hashval idx;
unsigned int hx;
}
static void
-finddirs_cb(void *cbdatav, char *fn, int fmode, char *md5)
+finddirs_cb(void *cbdatav, const char *fn, int fmode, const char *md5)
{
struct cbdata *cbdata = cbdatav;
Hashmask h, hh, hx, qx;
if (cbdata->dirmap[2 * h + 1] == idx)
return;
/* found a conflict, this dir is used in multiple packages */
- cbdata->dirmap[2 * h + 1] = -1;
+ if (cbdata->dirmap[2 * h + 1] != -1)
+ {
+ cbdata->dirmap[2 * h + 1] = -1;
+ cbdata->dirconflicts++;
+ }
+ MAPSET(&cbdata->idxmap, idx);
}
static inline int
}
static void
-findfileconflicts_cb(void *cbdatav, char *fn, int fmode, char *md5)
+findfileconflicts_cb(void *cbdatav, const char *fn, int fmode, const char *md5)
{
struct cbdata *cbdata = cbdatav;
int isdir = S_ISDIR(fmode);
}
static void
-findfileconflicts2_cb(void *cbdatav, char *fn, int fmode, char *md5)
+findfileconflicts2_cb(void *cbdatav, const char *fn, int fmode, const char *md5)
{
struct cbdata *cbdata = cbdatav;
unsigned int hx = strhash(fn);
int
pool_findfileconflicts(Pool *pool, Queue *pkgs, int cutoff, Queue *conflicts, void *(*handle_cb)(Pool *, Id, void *) , void *handle_cbdata)
{
- int i, j, cflmapn;
+ int i, j, cflmapn, idxmapset;
unsigned int hx;
struct cbdata cbdata;
unsigned int now, start;
void *handle;
+ Id p;
queue_empty(conflicts);
if (!pkgs->count)
queue_init(&cbdata.lookat);
queue_init(&cbdata.lookat_dir);
queue_init(&cbdata.files);
+ map_init(&cbdata.idxmap, pkgs->count);
+
if (cutoff <= 0)
cutoff = pkgs->count;
cbdata.dirmap = sat_calloc(cflmapn, 2 * sizeof(Id));
cbdata.dirmapn = cflmapn - 1; /* make it a mask */
cbdata.create = 1;
+ idxmapset = 0;
for (i = 0; i < pkgs->count; i++)
{
- Id p = pkgs->elements[i];
+ p = pkgs->elements[i];
cbdata.idx = i;
if (i == cutoff)
cbdata.create = 0;
handle = (*handle_cb)(pool, p, handle_cbdata);
if (handle)
rpm_iterate_filelist(handle, RPM_ITERATE_FILELIST_ONLYDIRS, finddirs_cb, &cbdata);
+ if (MAPTST(&cbdata.idxmap, i))
+ idxmapset++;
}
POOL_DEBUG(SAT_DEBUG_STATS, "dirmap size: %d used %d\n", cbdata.dirmapn + 1, cbdata.dirmapused);
POOL_DEBUG(SAT_DEBUG_STATS, "dirmap memory usage: %d K\n", (cbdata.dirmapn + 1) * 2 * (int)sizeof(Id) / 1024);
POOL_DEBUG(SAT_DEBUG_STATS, "dirmap creation took %d ms\n", sat_timems(now));
+ POOL_DEBUG(SAT_DEBUG_STATS, "dir conflicts found: %d, idxmap %d of %d\n", cbdata.dirconflicts, idxmapset, pkgs->count);
/* second pass: scan files */
now = sat_timems(0);
cbdata.create = 1;
for (i = 0; i < pkgs->count; i++)
{
- Id p = pkgs->elements[i];
+ if (!MAPTST(&cbdata.idxmap, i))
+ continue;
+ p = pkgs->elements[i];
cbdata.idx = i;
if (i == cutoff)
cbdata.create = 0;
cbdata.cflmap = sat_free(cbdata.cflmap);
cbdata.cflmapn = 0;
cbdata.cflmapused = 0;
+ map_free(&cbdata.idxmap);
now = sat_timems(0);
POOL_DEBUG(SAT_DEBUG_STATS, "lookat_dir size: %d\n", cbdata.lookat_dir.count);
{
int pend, ii, jj;
int pidx = cbdata.lookat.elements[i + 1];
- Id p = pkgs->elements[pidx];
-
+ p = pkgs->elements[pidx];
hx = cbdata.lookat.elements[i];
if (cbdata.lookat.elements[i + 2] != hx)
continue; /* no package left */
}
cbdata.filesspace = sat_free(cbdata.filesspace);
cbdata.filesspacen = 0;
+ queue_free(&cbdata.lookat);
+ queue_free(&cbdata.files);
POOL_DEBUG(SAT_DEBUG_STATS, "candidate check took %d ms\n", sat_timems(now));
if (conflicts->count > 5)
sat_sort(conflicts->elements, conflicts->count / 5, 5 * sizeof(Id), conflicts_cmp, pool);
#include "repo.h"
#include "hash.h"
#include "util.h"
+#include "queue.h"
#include "repo_rpmdb.h"
#define RPMDB_COOKIE_VERSION 2
return ido;
}
+#define COPYDIR_DIRCACHE_SIZE 512
+
static Id copydir_complex(Pool *pool, Repodata *data, Stringpool *fromspool, Repodata *fromdata, Id did, Id *cache);
static inline Id
}
if (db->open(db, 0, "Name", 0, DB_UNKNOWN, DB_RDONLY, 0664))
{
- perror("db->open var/lib/rpm/Name");
+ perror("db->open Name index");
exit(1);
}
if (db->get_byteswapped(db, &byteswapped))
perror("dbenv open");
exit(1);
}
- if (db_create(&db, dbenv, 0))
- {
- perror("db_create");
- exit(1);
- }
/* XXX: should get ro lock of Packages database! */
snprintf(dbpath, PATH_MAX, "%s/var/lib/rpm/Packages", rootdir);
if ((flags & RPMDB_REPORT_PROGRESS) != 0)
count = count_headers(rootdir, dbenv);
+ if (db_create(&db, dbenv, 0))
+ {
+ perror("db_create");
+ exit(1);
+ }
if (db->open(db, 0, "Packages", 0, DB_UNKNOWN, DB_RDONLY, 0664))
{
- perror("db->open var/lib/rpm/Packages");
+ perror("db->open Packages index");
exit(1);
}
if (db->get_byteswapped(db, &byteswapped))
}
else
{
- Id dircache[512];
+ Id dircache[COPYDIR_DIRCACHE_SIZE]; /* see copydir */
memset(dircache, 0, sizeof(dircache));
+ if (db_create(&db, dbenv, 0))
+ {
+ perror("db_create");
+ exit(1);
+ }
if (db->open(db, 0, "Name", 0, DB_UNKNOWN, DB_RDONLY, 0664))
{
- perror("db->open var/lib/rpm/Name");
+ perror("db->open Name index");
exit(1);
}
if (db->get_byteswapped(db, &byteswapped))
}
void
-rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, char *, int, char *), void *cbdata)
+rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, const char *, int, const char *), void *cbdata)
{
RpmHead *rpmhead = rpmhandle;
char **bn;
char **dn;
char **md = 0;
char **lt = 0;
- unsigned int *di;
+ unsigned int *di, diidx;
+ unsigned int lastdir;
+ int lastdirl;
unsigned int *fm;
int cnt, dcnt, cnt2;
int i, l1, l;
return;
}
}
+ lastdir = dcnt;
+ lastdirl = 0;
for (i = 0; i < cnt; i++)
{
- if (di[i] >= dcnt)
+ diidx = di[i];
+ if (diidx >= dcnt)
continue;
- l1 = strlen(dn[di[i]]);
+ l1 = lastdir == diidx ? lastdirl : strlen(dn[diidx]);
if (l1 == 0)
continue;
l = l1 + strlen(bn[i]) + 1;
spacen = l + 16;
space = sat_realloc(space, spacen);
}
- strcpy(space, dn[di[i]]);
+ if (lastdir != diidx)
+ {
+ strcpy(space, dn[diidx]);
+ lastdir = diidx;
+ lastdirl = l1;
+ }
strcpy(space + l1, bn[i]);
if (md)
{
}
(*cb)(cbdata, space, fm[i], md5p);
}
+ sat_free(space);
sat_free(lt);
sat_free(md);
sat_free(fm);
int byteswapped;
};
+int
+rpm_installedrpmdbids(const char *rootdir, Queue *rpmdbidq)
+{
+ char dbpath[PATH_MAX];
+ DB_ENV *dbenv = 0;
+ DB *db = 0;
+ DBC *dbc = 0;
+ int byteswapped;
+ DBT dbkey;
+ DBT dbdata;
+ Id rpmdbid;
+ unsigned char *dp;
+ int dl, cnt;
+
+ if (rpmdbidq)
+ queue_empty(rpmdbidq);
+ cnt = 0;
+
+ if (db_env_create(&dbenv, 0))
+ {
+ perror("db_env_create");
+ return 0;
+ }
+ snprintf(dbpath, PATH_MAX, "%s/var/lib/rpm", rootdir ? rootdir : "");
+#ifdef FEDORA
+ if (dbenv->open(dbenv, dbpath, DB_CREATE|DB_INIT_CDB|DB_INIT_MPOOL, 0))
+#else
+ if (dbenv->open(dbenv, dbpath, DB_CREATE|DB_PRIVATE|DB_INIT_MPOOL, 0))
+#endif
+ {
+ perror("dbenv open");
+ dbenv->close(dbenv, 0);
+ return 0;
+ }
+ if (db_create(&db, dbenv, 0))
+ {
+ perror("db_create");
+ dbenv->close(dbenv, 0);
+ return 0;
+ }
+ if (db->open(db, 0, "Name", 0, DB_UNKNOWN, DB_RDONLY, 0664))
+ {
+ perror("db->open Name index");
+ db->close(db, 0);
+ dbenv->close(dbenv, 0);
+ return 0;
+ }
+ if (db->get_byteswapped(db, &byteswapped))
+ {
+ perror("db->get_byteswapped");
+ db->close(db, 0);
+ dbenv->close(dbenv, 0);
+ return 0;
+ }
+ if (db->cursor(db, NULL, &dbc, 0))
+ {
+ perror("db->cursor");
+ db->close(db, 0);
+ dbenv->close(dbenv, 0);
+ return 0;
+ }
+ memset(&dbkey, 0, sizeof(dbkey));
+ memset(&dbdata, 0, sizeof(dbdata));
+ while (dbc->c_get(dbc, &dbkey, &dbdata, DB_NEXT) == 0)
+ {
+ if (dbkey.size == 10 && !memcmp(dbkey.data, "gpg-pubkey", 10))
+ continue;
+ dl = dbdata.size;
+ dp = dbdata.data;
+ while(dl >= 8)
+ {
+ if (byteswapped)
+ {
+ ((char *)&rpmdbid)[0] = dp[3];
+ ((char *)&rpmdbid)[1] = dp[2];
+ ((char *)&rpmdbid)[2] = dp[1];
+ ((char *)&rpmdbid)[3] = dp[0];
+ }
+ else
+ memcpy((char *)&rpmdbid, dp, 4);
+ if (rpmdbidq)
+ queue_push(rpmdbidq, rpmdbid);
+ cnt++;
+ dp += 8;
+ dl -= 8;
+ }
+ }
+ dbc->c_close(dbc);
+ db->close(db, 0);
+ dbenv->close(dbenv, 0);
+ return cnt;
+}
+
void *
rpm_byrpmdbid(Id rpmdbid, const char *rootdir, void **statep)
{