Implement a transaction set change notification callback

Add support for an optional callback hook for reveiving notifications
about added and deleted transaction elements. This lets API clients
easily track which elements get created and/or replaced by a single
rpmtsAddFoo() call and adjust their own book-keeping accordingly.
Also makes for an easy place to set application private data pointers
for newly added elements.

Currently there's no way to delete individual transaction elements from
the API but that can happen via rpmtsEmpty(), which we do send notifications
for. rpmtsFree() does NOT send notification though, it would be precarious
and most likely totally pointless to do so when the ts is being torn down.
This commit is contained in:
Panu Matilainen 2020-09-21 14:48:37 +03:00
parent 45449d5acf
commit 257077a60c
4 changed files with 65 additions and 0 deletions

View File

@ -135,6 +135,7 @@ static int removePackage(rpmts ts, Header h, rpmte depends)
tsmem->order[tsmem->orderCount] = p;
tsmem->orderCount++;
rpmtsNotifyChange(ts, RPMTS_EVENT_ADD, p, depends);
return 0;
}
@ -430,6 +431,7 @@ static int addPackage(rpmts ts, Header h,
oc = findPos(ts, tscolor, p, (op == RPMTE_UPGRADE));
/* If we're replacing a previously added element, free the old one */
if (oc >= 0 && oc < tsmem->orderCount) {
rpmtsNotifyChange(ts, RPMTS_EVENT_DEL, tsmem->order[oc], p);
rpmalDel(tsmem->addedPackages, tsmem->order[oc]);
tsmem->order[oc] = rpmteFree(tsmem->order[oc]);
/* If newer NEVR was already added, we're done */
@ -450,6 +452,8 @@ static int addPackage(rpmts ts, Header h,
if (oc == tsmem->orderCount) {
tsmem->orderCount++;
}
rpmtsNotifyChange(ts, RPMTS_EVENT_ADD, p, NULL);
if (tsmem->addedPackages == NULL) {
tsmem->addedPackages = rpmalCreate(ts, 5);

View File

@ -707,6 +707,7 @@ void rpmtsEmpty(rpmts ts)
rpmtsClean(ts);
for (int oc = 0; oc < tsmem->orderCount; oc++) {
rpmtsNotifyChange(ts, RPMTS_EVENT_DEL, tsmem->order[oc], NULL);
tsmem->order[oc] = rpmteFree(tsmem->order[oc]);
}
@ -759,6 +760,8 @@ rpmts rpmtsFree(rpmts ts)
if (ts->nrefs > 1)
return rpmtsUnlink(ts);
/* Don't issue element change callbacks when freeing */
rpmtsSetChangeCallback(ts, NULL, NULL);
rpmtsEmpty(ts);
(void) rpmtsCloseDB(ts);
@ -940,6 +943,15 @@ void * rpmtsNotify(rpmts ts, rpmte te,
return ptr;
}
int rpmtsNotifyChange(rpmts ts, int event, rpmte te, rpmte other)
{
int rc = 0;
if (ts && ts->change) {
rc = ts->change(event, te, other, ts->changeData);
}
return rc;
}
int rpmtsNElements(rpmts ts)
{
int nelements = 0;
@ -1042,6 +1054,15 @@ int rpmtsSetNotifyCallback(rpmts ts,
return 0;
}
int rpmtsSetChangeCallback(rpmts ts, rpmtsChangeFunction change, void *data)
{
if (ts != NULL) {
ts->change = change;
ts->changeData = data;
}
return 0;
}
tsMembers rpmtsMembers(rpmts ts)
{
return (ts != NULL) ? ts->members : NULL;

View File

@ -179,6 +179,26 @@ enum rpmtxnFlags_e {
};
typedef rpmFlags rpmtxnFlags;
typedef enum rpmtsEvent_e {
RPMTS_EVENT_ADD = 1,
RPMTS_EVENT_DEL = 2,
} rpmtsEvent;
/** \ingroup rpmts
* Transaction change callback type.
*
* On explicit install/erase add events, "other" is NULL, on implicit
* add events (erasures due to obsolete/upgrade, replaced by newer)
* it points to the replacing package.
*
* @param event Change event (see rpmtsEvent enum)
* @param te Transaction element
* @param other Related transaction element (or NULL)
* @param data Application private data from rpmtsSetChangeCallback()
*/
typedef int (*rpmtsChangeFunction)
(int event, rpmte te, rpmte other, void *data);
/** \ingroup rpmts
* Perform dependency resolution on the transaction set.
*
@ -585,6 +605,19 @@ int rpmtsSetNotifyCallback(rpmts ts,
rpmCallbackFunction notify,
rpmCallbackData notifyData);
/** \ingroup rpmts
* Set transaction change callback function and argument.
*
* The change callback gets called when transaction elements are added,
* replaced or removed from a transaction set.
*
* @param ts transaction set
* @param notify element change callback
* @param data element change callback private data
* @return 0 on success
*/
int rpmtsSetChangeCallback(rpmts ts, rpmtsChangeFunction notify, void *data);
/** \ingroup rpmts
* Create an empty transaction set.
* @return new transaction set

View File

@ -51,6 +51,9 @@ struct rpmts_s {
rpmCallbackFunction notify; /*!< Callback function. */
rpmCallbackData notifyData; /*!< Callback private data. */
rpmtsChangeFunction change; /*!< Change callback function. */
void *changeData; /*!< Change callback private data. */
rpmprobFilterFlags ignoreSet;
/*!< Bits to filter current problems. */
@ -123,6 +126,10 @@ RPM_GNUC_INTERNAL
rpmRC runScript(rpmts ts, rpmte te, Header h, ARGV_const_t prefixes,
rpmScript script, int arg1, int arg2);
RPM_GNUC_INTERNAL
int rpmtsNotifyChange(rpmts ts, int event, rpmte te, rpmte other);
#ifdef __cplusplus
}
#endif