Skip to content

Commit

Permalink
Add rpmlogOnce() and rpmlogReset()
Browse files Browse the repository at this point in the history
These are internal only for now to allow us gain soem more confidence on
the design.

rpmlogOnce allows showing a log message only once. rpmlogReset allows purging
the list of known message keys for a given domain. This allows for different
live times e.g. per transaction or per package.

Resolves: #3395
  • Loading branch information
ffesti committed Oct 31, 2024
1 parent 78cecdc commit f83a969
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 1 deletion.
38 changes: 37 additions & 1 deletion rpmio/rpmlog.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <mutex>
#include <shared_mutex>
#include <vector>
#include <map>
#include <string>

#include <stdarg.h>
Expand All @@ -22,6 +23,7 @@ struct rpmlogCtx_s {
unsigned mask;
int nrecsPri[RPMLOG_NPRIS];
std::vector<rpmlogRec_s> recs;
std::map<uint64_t, std::map<std::pair<int, std::string>, int>> seen;
rpmlogCallback cbfunc;
rpmlogCallbackData cbdata;
FILE *stdlog;
Expand All @@ -41,7 +43,7 @@ using rdlock = std::shared_lock<std::shared_mutex>;
static rpmlogCtx rpmlogCtxAcquire()
{
static struct rpmlogCtx_s _globalCtx = { RPMLOG_UPTO(RPMLOG_NOTICE),
{0}, {}, NULL, NULL, NULL };
{0}, {}, {}, NULL, NULL, NULL };
return &_globalCtx;
}

Expand Down Expand Up @@ -127,6 +129,7 @@ void rpmlogClose (void)
wrlock lock(ctx->mutex);

ctx->recs.clear();
ctx->seen.clear();
memset(ctx->nrecsPri, 0, sizeof(ctx->nrecsPri));
}

Expand Down Expand Up @@ -412,3 +415,36 @@ void rpmlog (int code, const char *fmt, ...)
exit:
errno = saved_errno;
}

int rpmlogOnce (uint64_t domain, const char * key, int code, const char *fmt, ...)
{
int saved_errno = errno;
rpmlogCtx ctx = rpmlogCtxAcquire();
int newkey = 0;

if (ctx) {
wrlock lock(ctx->mutex);
/* members get initialized automatically on first access */
newkey = !(ctx->seen[domain][{code, key}]++);
}

if (newkey) {
va_list ap;
char *msg = NULL;
va_start(ap, fmt);
if (rvasprintf(&msg, fmt, ap) >= 0) {
rpmlog(code, msg);
free(msg);
}
va_end(ap);
}
errno = saved_errno;
return newkey;
}

void rpmlogReset(uint64_t domain, int mode=0)
{
rpmlogCtx ctx = rpmlogCtxAcquire();
wrlock lock(ctx->mutex);
ctx->seen.erase(domain);
}
23 changes: 23 additions & 0 deletions rpmio/rpmlog_internal.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#ifndef H_RPMLOG_INTERNAL
#define H_RPMLOG_INTERNAL 1


/** \ingroup rpmlog
* Generate a log message using FMT string and option arguments.
* Only actually log on the first time passing the key value
* @param domain group of messages to be reset together
* @param key key to match log messages together
* @param code rpmlogLvl
* @param fmt format string and parameter to render
* @return 1 if actually logging 0 otherwise
*/
int rpmlogOnce (uint64_t domain, const char * key, int code, const char *fmt, ...) RPM_GNUC_PRINTF(4, 5);

/** \ingroup rpmlog
* Clear memory of logmessages for a given domain
* @param domain group of messages to be reset together
* @param mode curretnly only 0 supported whihc drops everything
*/
void rpmlogReset(uint64_t domain, int mode=0);

#endif

0 comments on commit f83a969

Please sign in to comment.