Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert the last rpmhash user to STL and remove rpmhash #3184

Merged
merged 5 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 67 additions & 99 deletions lib/fprint.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

#include "system.h"

#include <unordered_map>

#include <rpm/rpmfileutil.h> /* for rpmCleanPath */
#include <rpm/rpmstring.h>
#include <rpm/rpmts.h>
Expand All @@ -17,35 +19,12 @@
#include "debug.h"
#include <libgen.h>

/* Create new hash table type rpmFpEntryHash */
#define HASHTYPE rpmFpEntryHash
#define HTKEYTYPE rpmsid
#define HTDATATYPE const struct fprintCacheEntry_s *
#include "rpmhash.H"
#include "rpmhash.C"
#undef HASHTYPE
#undef HTKEYTYPE
#undef HTDATATYPE

/* 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)
{
return sid;
}

static int sidCmp(rpmsid a, rpmsid b)
{
return (a != b);
}

/**
* Finger print cache entry.
Expand All @@ -63,7 +42,7 @@ struct fprintCacheEntry_s {
* Associates a trailing sub-directory and final base name with an existing
* directory finger print.
*/
struct fingerPrint_s {
struct fingerPrint {
/*! directory finger print entry (the directory path is stat(2)-able */
const struct fprintCacheEntry_s * entry;
/*! trailing sub-directory path (directories that are not stat(2)-able */
Expand All @@ -79,6 +58,42 @@ struct fingerPrint_s {
((a).subDirId == (b).subDirId) \
)

/* 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 @@ -91,17 +106,13 @@ struct fprintCache_s {
fingerPrintCache fpCacheCreate(int sizeHint, rpmstrPool pool)
{
fingerPrintCache fpc = new fprintCache_s {};
fpc->ht = rpmFpEntryHashCreate(sizeHint, sidHash, sidCmp,
NULL, (rpmFpEntryHashFreeData)free);
fpc->pool = (pool != NULL) ? rpmstrPoolLink(pool) : rpmstrPoolCreate();
return fpc;
}

fingerPrintCache fpCacheFree(fingerPrintCache cache)
{
if (cache) {
cache->ht = rpmFpEntryHashFree(cache->ht);
cache->fp = rpmFpHashFree(cache->fp);
cache->pool = rpmstrPoolFree(cache->pool);
delete cache;
}
Expand All @@ -117,10 +128,9 @@ fingerPrintCache fpCacheFree(fingerPrintCache cache)
static const struct fprintCacheEntry_s * cacheContainsDirectory(
fingerPrintCache cache, rpmsid dirId)
{
const struct fprintCacheEntry_s ** data;

if (rpmFpEntryHashGetEntry(cache->ht, dirId, &data, NULL, NULL))
return data[0];
auto entry = cache->ht.find(dirId);
if (entry != cache->ht.end())
return &entry->second;
return NULL;
}

Expand Down Expand Up @@ -177,15 +187,13 @@ static int doLookupId(fingerPrintCache cache,
if (cacheHit != NULL) {
fp->entry = cacheHit;
} else if (!stat(rpmstrPoolStr(cache->pool, fpId), &sb)) {
struct fprintCacheEntry_s * newEntry =
(struct fprintCacheEntry_s *)xmalloc(sizeof(* newEntry));

newEntry->ino = sb.st_ino;
newEntry->dev = sb.st_dev;
newEntry->dirId = fpId;
fp->entry = newEntry;

rpmFpEntryHashAddEntry(cache->ht, fpId, fp->entry);
struct fprintCacheEntry_s newEntry = {
.dirId = fpId,
.dev = sb.st_dev,
.ino = sb.st_ino,
};
auto ret = cache->ht.insert({fpId, newEntry});
fp->entry = &ret->second;
}

if (fp->entry) {
Expand Down Expand Up @@ -243,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 All @@ -292,15 +267,15 @@ dev_t fpEntryDev(fingerPrintCache cache, fingerPrint *fp)
int fpLookupEquals(fingerPrintCache cache, fingerPrint *fp,
const char * dirName, const char * baseName)
{
struct fingerPrint_s ofp;
struct fingerPrint ofp;
doLookup(cache, dirName, baseName, &ofp);
return FP_EQUAL(*fp, ofp);
}

int fpLookupEqualsId(fingerPrintCache cache, fingerPrint *fp,
rpmsid dirNameId, rpmsid baseNameId)
{
struct fingerPrint_s ofp;
struct fingerPrint ofp;
doLookupId(cache, dirNameId, baseNameId, &ofp);
return FP_EQUAL(*fp, ofp);
}
Expand Down Expand Up @@ -338,13 +313,9 @@ fingerPrint * fpLookupList(fingerPrintCache cache, rpmstrPool pool,
/* Check file for to be installed symlinks in their path and correct their fp */
static void fpLookupSubdir(rpmFpHash symlinks, fingerPrintCache fpc, fingerPrint *fp)
{
struct fingerPrint_s current_fp;
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 @@ -369,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 @@ -429,12 +400,15 @@ static void fpLookupSubdir(rpmFpHash symlinks, fingerPrintCache fpc, fingerPrint
}

fingerPrint * fpCacheGetByFp(fingerPrintCache cache,
struct fingerPrint_s * fp, int ix,
struct rpmffi_s ** recs, int * numRecs)
struct fingerPrint * fp, int ix,
std::vector<struct rpmffi_s> & recs)
{
if (rpmFpHashGetEntry(cache->fp, fp + ix, recs, numRecs, NULL))
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
} else
return NULL;
}

Expand All @@ -447,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 @@ -478,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 @@ -516,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);
}

20 changes: 4 additions & 16 deletions lib/fprint.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,14 @@
* Identify a file name path by a unique "finger print".
*/

#include <vector>
#include <rpm/rpmtypes.h>

/**
*/
typedef struct fprintCache_s * fingerPrintCache;

/**
* @todo Convert to pointer and make abstract.
*/
typedef struct fingerPrint_s fingerPrint;
struct fingerPrint;

struct rpmffi_s {
rpmte p;
Expand All @@ -41,8 +39,8 @@ fingerPrintCache fpCacheFree(fingerPrintCache cache);

RPM_GNUC_INTERNAL
fingerPrint * fpCacheGetByFp(fingerPrintCache cache,
struct fingerPrint_s * fp, int ix,
struct rpmffi_s ** recs, int * numRecs);
struct fingerPrint * fp, int ix,
std::vector<struct rpmffi_s> & recs);

RPM_GNUC_INTERNAL
void fpCachePopulate(fingerPrintCache cache, rpmts ts, int fileCount);
Expand Down Expand Up @@ -88,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
4 changes: 2 additions & 2 deletions lib/rpmfi.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ struct rpmfiles_s {

rpmfiFlags fiflags; /*!< file info set control flags */

struct fingerPrint_s * fps; /*!< File fingerprint(s). */
struct fingerPrint * fps; /*!< File fingerprint(s). */

int digestalgo; /*!< File digest algorithm */
uint32_t *signatureoffs; /*!< File signature offsets */
Expand Down Expand Up @@ -829,7 +829,7 @@ int rpmfilesStat(rpmfiles fi, int ix, int flags, struct stat *sb)
return rc;
}

struct fingerPrint_s *rpmfilesFps(rpmfiles fi)
struct fingerPrint *rpmfilesFps(rpmfiles fi)
{
return (fi != NULL) ? fi->fps : NULL;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/rpmfi_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ RPM_GNUC_INTERNAL
rpmsid rpmfilesODNId(rpmfiles fi, int jx);

RPM_GNUC_INTERNAL
struct fingerPrint_s *rpmfilesFps(rpmfiles fi);
struct fingerPrint *rpmfilesFps(rpmfiles fi);

/** \ingroup rpmfi
* Check if the file in new package, in old package and on the disk have the same contents.
Expand Down
Loading
Loading