Skip to content

Commit

Permalink
Replace by-fingerprint rpmFpHash with STL unordered_map
Browse files Browse the repository at this point in the history
This is a bit trickier than the average hash because it uses pointers
to structs as keys, but we need to hash and compare the actual structs
and not the pointers.

This is was also the last user of rpmhash in the codebase.
  • Loading branch information
pmatilai authored and ffesti committed Jun 26, 2024
1 parent 12fb827 commit 08a6a5e
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 77 deletions.
114 changes: 47 additions & 67 deletions lib/fprint.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,6 @@
#include "debug.h"
#include <libgen.h>

/* Create by-fingerprint hash table */
#define HASHTYPE rpmFpHash
#define HTKEYTYPE const fingerPrint *
#define HTDATATYPE struct rpmffi_s
#include "rpmhash.H"
#include "rpmhash.C"
#undef HASHTYPE
#undef HTKEYTYPE
#undef HTDATATYPE

static unsigned int sidHash(rpmsid sid)
{
Expand Down Expand Up @@ -67,7 +58,41 @@ struct fingerPrint {
((a).subDirId == (b).subDirId) \
)

using rpmFpEntryHash = std::unordered_multimap<rpmsid,fprintCacheEntry_s>
/* Hash value for a finger print pointer, based on dev and inode only! */
struct fpHash
{
size_t operator() (const fingerPrint *fp) const
{
unsigned int hash = 0;
int j;

hash = sidHash(fp->baseNameId);
if (fp->subDirId) hash ^= sidHash(fp->subDirId);

hash ^= ((unsigned)fp->entry->dev);
for (j=0; j<4; j++) hash ^= ((fp->entry->ino >> (8*j)) & 0xFF) << ((3-j)*8);

return hash;
}
};

struct fpEqual
{
bool operator()(const fingerPrint * k1, const fingerPrint * k2) const
{
/* If the addresses are the same, so are the values. */
if (k1 == k2)
return true;

/* Otherwise, compare fingerprints by value. */
if (FP_EQUAL(*k1, *k2))
return true;
return false;
}
};

using rpmFpEntryHash = std::unordered_multimap<rpmsid,fprintCacheEntry_s>;
using rpmFpHash = std::unordered_map<fingerPrint *,rpmffi_s,fpHash,fpEqual>;

/**
* Finger print cache.
Expand All @@ -88,7 +113,6 @@ fingerPrintCache fpCacheCreate(int sizeHint, rpmstrPool pool)
fingerPrintCache fpCacheFree(fingerPrintCache cache)
{
if (cache) {
cache->fp = rpmFpHashFree(cache->fp);
cache->pool = rpmstrPoolFree(cache->pool);
delete cache;
}
Expand Down Expand Up @@ -227,39 +251,6 @@ int fpLookupId(fingerPrintCache cache,
return doLookupId(cache, dirNameId, baseNameId, *fp);
}

/**
* Return hash value for a finger print.
* Hash based on dev and inode only!
* @param fp pointer to finger print entry
* @return hash value
*/
static unsigned int fpHashFunction(const fingerPrint * fp)
{
unsigned int hash = 0;
int j;

hash = sidHash(fp->baseNameId);
if (fp->subDirId) hash ^= sidHash(fp->subDirId);

hash ^= ((unsigned)fp->entry->dev);
for (j=0; j<4; j++) hash ^= ((fp->entry->ino >> (8*j)) & 0xFF) << ((3-j)*8);

return hash;
}

int fpEqual(const fingerPrint * k1, const fingerPrint * k2)
{
/* If the addresses are the same, so are the values. */
if (k1 == k2)
return 0;

/* Otherwise, compare fingerprints by value. */
if (FP_EQUAL(*k1, *k2))
return 0;
return 1;

}

const char * fpEntryDir(fingerPrintCache cache, fingerPrint *fp)
{
const char * dn = NULL;
Expand Down Expand Up @@ -325,10 +316,6 @@ static void fpLookupSubdir(rpmFpHash symlinks, fingerPrintCache fpc, fingerPrint
struct fingerPrint current_fp;
const char *currentsubdir;
size_t lensubDir, bnStart, bnEnd;

struct rpmffi_s * recs;
int numRecs;
int i;
int symlinkcount = 0;

for (;;) {
Expand All @@ -353,11 +340,11 @@ static void fpLookupSubdir(rpmFpHash symlinks, fingerPrintCache fpc, fingerPrint
currentsubdir + bnStart,
bnEnd - bnStart, 1);

rpmFpHashGetEntry(symlinks, &current_fp, &recs, &numRecs, NULL);

for (i = 0; i < numRecs; i++) {
rpmfiles foundfi = rpmteFiles(recs[i].p);
char const *linktarget = rpmfilesFLink(foundfi, recs[i].fileno);
auto range = symlinks.equal_range(&current_fp);
for (auto it = range.first; it != range.second; ++it) {
const rpmffi_s & rec = it->second;
rpmfiles foundfi = rpmteFiles(rec.p);
char const *linktarget = rpmfilesFLink(foundfi, rec.fileno);
char *link;
rpmsid linkId;

Expand Down Expand Up @@ -416,11 +403,10 @@ fingerPrint * fpCacheGetByFp(fingerPrintCache cache,
struct fingerPrint * fp, int ix,
std::vector<struct rpmffi_s> & recs)
{
struct rpmffi_s * rrecs = NULL;
int numRecs = 0;
if (rpmFpHashGetEntry(cache->fp, fp + ix, &rrecs, &numRecs, NULL)) {
for (int i = 0; i < numRecs; ++i)
recs.push_back(rrecs[i]);
auto range = cache->fp.equal_range(fp + ix);
if (range.first != range.second) {
for (auto it = range.first; it != range.second; ++it)
recs.push_back(it->second);
return fp + ix;
} else
return NULL;
Expand All @@ -435,11 +421,7 @@ void fpCachePopulate(fingerPrintCache fpc, rpmts ts, int fileCount)
int i, fc;
int havesymlinks = 0;

if (fpc->fp == NULL)
fpc->fp = rpmFpHashCreate(fileCount/2 + 10001, fpHashFunction, fpEqual,
NULL, NULL);

rpmFpHash symlinks = rpmFpHashCreate(fileCount/16+16, fpHashFunction, fpEqual, NULL, NULL);
rpmFpHash symlinks;

/* populate the fingerprints of all packages in the transaction */
/* also create a hash of all symlinks in the new packages */
Expand All @@ -466,7 +448,7 @@ void fpCachePopulate(fingerPrintCache fpc, rpmts ts, int fileCount)
continue;
ffi.p = p;
ffi.fileno = i;
rpmFpHashAddEntry(symlinks, fpList + i, ffi);
symlinks.insert({fpList + i, ffi});
havesymlinks = 1;
}
}
Expand Down Expand Up @@ -504,14 +486,12 @@ void fpCachePopulate(fingerPrintCache fpc, rpmts ts, int fileCount)
}
ffi.p = p;
ffi.fileno = i;
rpmFpHashAddEntry(fpc->fp, fpList + i, ffi);
fpc->fp.insert({fpList + i, ffi});
lastfp = fpList + i;
}
(void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
rpmfilesFree(fi);
}
rpmtsiFree(pi);

rpmFpHashFree(symlinks);
}

10 changes: 0 additions & 10 deletions lib/fprint.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,16 +86,6 @@ int fpLookupId(fingerPrintCache cache,
rpmsid dirNameId, rpmsid BaseNameId,
fingerPrint **fp);

/**
* Compare two finger print entries.
* This routine is exactly equivalent to the FP_EQUAL macro.
* @param key1 finger print 1
* @param key2 finger print 2
* @return result of comparing key1 and key2
*/
RPM_GNUC_INTERNAL
int fpEqual(const fingerPrint * key1, const fingerPrint * key2);

/**
* Return finger prints of an array of file paths.
* @param cache pointer to fingerprint cache
Expand Down

0 comments on commit 08a6a5e

Please sign in to comment.