RPM Community Forums

Mailing List Message of <rpm-devel>

Re: Conflicts on files not symmetric

From: Jeff Johnson <n3npq@mac.com>
Date: Wed 24 Sep 2008 - 01:40:24 CEST
Message-id: <F2A8032E-B7A7-49DA-9C88-CCDE22CBF1F0@mac.com>

On Sep 19, 2008, at 5:07 AM, Michael Schroeder wrote:

>
> If this needs fixing, here's an idea: As it probably costs too
> much time to test each file in the file list for conflicts, how
> about creating a index of the conflicts first and only test
> the files that match the index?
>
> I.e. add a function
>
> char *rpmdbKeyIterator(rpmdbMatchIterator mi) {
>     int rc, xx;
>     dbiIndex dbi;
>
>     dbi = dbiOpen(mi->mi_db, mi->mi_rpmtag, 0);
>     if (mi->mi_dbc == NULL)
>         xx = dbiCopen(dbi, dbi->dbi_txnid, &mi->mi_dbc, mi- 
> >mi_cflags);
>     rc = dbiGet(dbi, mi->mi_dbc, &mi->mi_key, &mi->mi_data, DB_NEXT);
>     if (rc)
>         return 0;
>     if (mi->mi_keyp)
>         free((char *)mi->mi_keyp);
>     mi->mi_keyp = (void *)xmalloc(mi->mi_key.size + 1);
>     memcpy((char *)mi->mi_keyp, mi->mi_key.data, mi->mi_key.size);
>     ((char *)mi->mi_keyp)[mi->mi_key.size] = 0;
>     mi->mi_keylen = mi->mi_key.size;
>     return (char *)mi->mi_keyp;
> }
>
> to rpmdb.c, then use
>
>     mi = rpmtsInitIterator(ts, RPMTAG_CONFLICTNAME, 0, 0);
>     while ((key = rpmdbKeyIterator(mi)) != 0)
>       ...
>
> to create an array of basenames, sort it and then go through the
> filelist and match only if bsearch for the basename returns true.
>
> Thoughts?
>

This is basically the right approach, a lightweight, i.e. no
headerLoad(), just a search through the keys in an index.

For various reasons, I want to get a pattern filter into the db  
traversal too.

So here's the (preliminary) prototype whose innards will be much as  
you have
suggested:

/** \ingroup rpmdb
  * Return array of keys matching a pattern.
  * @param db            rpm database
  * @param tag           rpm tag
  * @param mode          type of pattern match
  * @param pat           pattern to match
  * @retval *argvp       array of keys that match
  * @return              0 on success
  */
int rpmdbMireApply(rpmdb db, rpmTag tag, rpmMireMode mode, const char  
* pat,
                 const char *** argvp)
         /*@modifies db, *argvp */;

to return the array of keys in the index that match the pattern.

Looping over the tuple of keys known to be in the index seems slightly
better than having a bsearch'able array of all keys in index  
externally imho.

The extra extraction and loop over the tuple of keys can likely be  
buried in
the existing match iterator when, say Glob_pattern_p() identifies the
retrieval key as a pattern. It would just be a retrieve on a tuple of  
keys
instead of a single key.

Using DB_PARTIAL for the key DBT, using the stem of the pattern,
with post retrieve pattern application, starts to get patterns into the
existing rpmdb iterator efficiently too.

Dunno fer sure yet, but that seems like the right approach.

No clue what to do about sqlite3 which doesn't have DB_PARTIAL, but
likely has Something Else Instead.

73 de Jeff
Received on Wed Sep 24 01:41:20 2008
Driven by Jeff Johnson and the RPM project team.
Hosted by OpenPKG and Ralf S. Engelschall.
Powered by FreeBSD and OpenPKG.