Skip to content

Commit

Permalink
Implement RollBack feature for SetMulti function
Browse files Browse the repository at this point in the history
Signed-off-by: Deepthi C Shetty <[email protected]>
  • Loading branch information
dshett549 committed Jan 16, 2025
1 parent aed0560 commit 8f913ce
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 19 deletions.
38 changes: 38 additions & 0 deletions include/rbus.h
Original file line number Diff line number Diff line change
Expand Up @@ -1121,6 +1121,44 @@ rbusError_t rbus_setMulti(
rbusProperty_t properties,
rbusSetOptions_t* opts);

/** @fn rbusError_t rbus_setMultiExt(
* rbusHandle_t handle,
* int numProps,
* rbusProperty_t properties,
* rbusSetOptions_t* opts,
* uint8_t timeout,
* char** failedParameterName);
*
* @brief A component uses this to perform a set operation for multiple parameters at once.
* This method identifies the provider component of each parameter, groups them and makes the SET call \n
* per provider component. The given order is NOT maintained.
*
* This API ensures rolling back of all the property to previous value upon failure to set any single parameter in the given list.
* Used by: All components that need to set multiple parameters
*
* @param handle Bus Handle
* @param numProps The number (count) of parameters
* @param properties The list of dml properties to set to.
* For each parameter, a property should be created which contains the parameter's name and
* the respective value to set that parameter to.
* @param opts Extra options such as session info.
* Set NULL if not needed, in which case a session
* is not used and the set is commited immediately.
* @param timeout Timeout to be used for each SET per provider; Set to 0 to use the default value (15s).
* @param failedParameterName Output parameter that represents the failed property. On success, it will returning NULL. Caller responsible to free() this.
* @return RBus error code as defined by rbusError_t.
* Possible values are:
* RBUS_ERROR_INVALID_INPUT: Given inputs are not correct.
* RBUS_ERROR_ACCESS_NOT_ALLOWED: Access to requested parameter is not permitted.
* RBUS_ERROR_DESTINATION_NOT_REACHABLE: Destination element was not reachable.
*/
rbusError_t rbus_setMultiExt(
rbusHandle_t handle,
int numProps,
rbusProperty_t properties,
rbusSetOptions_t* opts,
uint8_t timeout,
char** failedParameterName);

/** @fn rbusError_t rbus_setBoolean(
* rbusHandle_t handle,
Expand Down
4 changes: 2 additions & 2 deletions include/rbus_property.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,12 +302,12 @@ void rbusProperty_Append(rbusProperty_t property, rbusProperty_t back);

#define rbusProperty_PushBack(prop, back) rbusProperty_Append((prop),(back))

/** @fn void rbusProperty_Count(rbusProperty_t property)
/** @fn int rbusProperty_Count(rbusProperty_t property)
* @brief Return the number or properties in the list
* @param property A property (the first in list).
* @return The number of properties in the list.
*/
uint32_t rbusProperty_Count(rbusProperty_t property);
int rbusProperty_Count(rbusProperty_t property);

void rbusProperty_fwrite(rbusProperty_t prop, int depth, FILE* fout);

Expand Down
126 changes: 111 additions & 15 deletions src/rbus/rbus.c
Original file line number Diff line number Diff line change
Expand Up @@ -1419,23 +1419,28 @@ static int _master_event_callback_handler(char const* sender, char const* eventN
static void _set_callback_handler (rbusHandle_t handle, rbusMessage request, rbusMessage *response)
{
rbusError_t rc = 0;
rbusError_t err = 0;
int sessionId = 0;
int numVals = 0;
int loopCnt = 0;
int rollBack = 0;
char* pCompName = NULL;
char* pIsCommit = NULL;
bool isCommit = false;
char const* pFailedElement = NULL;
rbusProperty_t* pProperties = NULL;
struct _rbusHandle* handleInfo = (struct _rbusHandle*)handle;
rbusSetHandlerOptions_t opts;
rbusProperty_t cachedData = NULL;

memset(&opts, 0, sizeof(opts));
rbusGetHandlerOptions_t options;
memset(&options, 0, sizeof(rbusGetHandlerOptions_t));

rbusMessage_GetInt32(request, &sessionId);
rbusMessage_GetString(request, (char const**) &pCompName);
rbusMessage_GetInt32(request, &rollBack);
rbusMessage_GetInt32(request, &numVals);

if(numVals > 0)
{
/* Update the Get Handler input options */
Expand Down Expand Up @@ -1470,8 +1475,21 @@ static void _set_callback_handler (rbusHandle_t handle, rbusMessage request, rbu
el = retrieveInstanceElementEx(handle, handleInfo->elementRoot, paramName, true);
if(el != NULL)
{
rbusProperty_t currentData = NULL;
if(el->cbTable.setHandler)
{
if(rollBack == 1)
{
if(el->cbTable.getHandler)
{
rbusProperty_Init(&currentData, paramName, NULL);
ELM_PRIVATE_LOCK(el);
rc = el->cbTable.getHandler(handle, currentData, &options);
ELM_PRIVATE_UNLOCK(el);
}
else
RBUSLOG_INFO("%s is a write only parameter",paramName);
}
if(isCommit && loopCnt == numVals -1)
opts.commit = true;

Expand All @@ -1482,11 +1500,42 @@ static void _set_callback_handler (rbusHandle_t handle, rbusMessage request, rbu
{
RBUSLOG_WARN("Set Failed for %s; Component Owner returned Error", paramName);
pFailedElement = paramName;
if(rollBack == 1)
{
RBUSLOG_DEBUG("Reverting because set failed for this param:%s",pFailedElement);
/*===========< Rollback old values >============*/
rbusProperty_t prevProp = cachedData;
while(prevProp)
{
char const* prevParamName = rbusProperty_GetName(prevProp);
el = retrieveInstanceElement(handleInfo->elementRoot, prevParamName);
ELM_PRIVATE_LOCK(el);
err = el->cbTable.setHandler(handle, prevProp, &opts);
ELM_PRIVATE_UNLOCK(el);
prevProp = rbusProperty_GetNext(prevProp);
if(err != RBUS_ERROR_SUCCESS)
{
RBUSLOG_WARN("Reverting paramValues of %s to initial values failed",prevParamName);
}
}
}
break;
}
else
{
setPropertyChangeComponent(el, pCompName);
/* ======== < Old values backup >============= */
if (currentData)
{
if (cachedData == NULL)
cachedData = currentData;
else
{
rbusProperty_Append(cachedData, currentData);
rbusProperty_Release(currentData);
}
}

}
}
else
Expand Down Expand Up @@ -1523,7 +1572,12 @@ static void _set_callback_handler (rbusHandle_t handle, rbusMessage request, rbu
exit:
rbusMessage_Init(response);
rbusMessage_SetInt32(*response, (int) rc);
if (pFailedElement)
if (rc == RBUS_ERROR_SUCCESS)
{
rbusPropertyList_appendToMessage(cachedData, *response);
rbusProperty_Release(cachedData);
}
else if(pFailedElement)
rbusMessage_SetString(*response, pFailedElement);

if(pProperties)
Expand Down Expand Up @@ -3835,6 +3889,7 @@ rbusError_t rbus_set(rbusHandle_t handle, char const* name,rbusValue_t value, rb

/* Set the Component name that invokes the set */
rbusMessage_SetString(setRequest, handleInfo->componentName);
rbusMessage_SetInt32(setRequest, 0);//needRollBack
/* Set the Size of params */
rbusMessage_SetInt32(setRequest, 1);

Expand Down Expand Up @@ -3950,20 +4005,25 @@ rbusError_t rbus_setCommit(rbusHandle_t handle, char const* name, rbusSetOptions
return errorcode;
}

rbusError_t rbus_setMulti(rbusHandle_t handle, int numProps, rbusProperty_t properties, rbusSetOptions_t* opts)
rbusError_t _setMultiInternal(rbusHandle_t handle, int numProps, rbusProperty_t properties, rbusSetOptions_t* opts, uint8_t timeout, char** pFailedElement, bool rollBack)
{
rbusError_t errorcode = RBUS_ERROR_INVALID_INPUT;
rbusCoreError_t err = RBUSCORE_SUCCESS;
VERIFY_HANDLE(handle);
VERIFY_HANDLE(handle);
rbusMessage setRequest, setResponse;
struct _rbusHandle* handleInfo = (struct _rbusHandle*) handle;
rbusValueType_t type = RBUS_NONE;
rbusProperty_t current;

int cachedNumProps = 0;
rbusProperty_t cachedProperties = NULL;
VERIFY_NULL(handle);
if(timeout == 0)
timeout = rbusConfig_ReadSetTimeout();

if (handleInfo->m_handleType != RBUS_HWDL_TYPE_REGULAR)
{
return RBUS_ERROR_INVALID_HANDLE;
}

if (numProps > 0 && properties != NULL)
{
Expand Down Expand Up @@ -4032,7 +4092,6 @@ rbusError_t rbus_setMulti(rbusHandle_t handle, int numProps, rbusProperty_t prop
char* componentName = NULL;
char const* firstParamName = NULL;
int batchCount = 0;

for(i = 0; i < numProps; ++i)
{
if(componentNames[i])
Expand All @@ -4053,7 +4112,6 @@ rbusError_t rbus_setMulti(rbusHandle_t handle, int numProps, rbusProperty_t prop

if(componentName)
{

rbusMessage_Init(&setRequest);

/* Set the Session ID first */
Expand All @@ -4064,6 +4122,10 @@ rbusError_t rbus_setMulti(rbusHandle_t handle, int numProps, rbusProperty_t prop

/* Set the Component name that invokes the set */
rbusMessage_SetString(setRequest, handleInfo->componentName);
if(rollBack)
rbusMessage_SetInt32(setRequest, 1);
else
rbusMessage_SetInt32(setRequest, 0);
/* Set the Size of params */
rbusMessage_SetInt32(setRequest, batchCount);

Expand All @@ -4082,40 +4144,62 @@ rbusError_t rbus_setMulti(rbusHandle_t handle, int numProps, rbusProperty_t prop
free(componentNames[i]);
componentNames[i] = NULL;
}
}
}

/* Set the Commit value; FIXME: Should we use string? */
rbusMessage_SetString(setRequest, (!opts || opts->commit) ? "TRUE" : "FALSE");

if((err = rbus_invokeRemoteMethod(firstParamName, METHOD_SETPARAMETERVALUES, setRequest, rbusConfig_ReadSetTimeout(), &setResponse)) != RBUSCORE_SUCCESS)
if((err = rbus_invokeRemoteMethod(firstParamName, METHOD_SETPARAMETERVALUES, setRequest, (int)timeout, &setResponse)) != RBUSCORE_SUCCESS)
{
RBUSLOG_ERROR("set by %s failed; Received error %d from RBUS Daemon for the object %s", handle->componentName, err, firstParamName);
errorcode = rbusCoreError_to_rbusError(err);
}
else
{
char const* pErrorReason = NULL;
rbusLegacyReturn_t legacyRetCode = RBUS_LEGACY_ERR_FAILURE;
int ret = -1;
rbusMessage_GetInt32(setResponse, &ret);

RBUSLOG_DEBUG("Response from the remote method is [%d]!", ret);
errorcode = (rbusError_t) ret;
legacyRetCode = (rbusLegacyReturn_t) ret;

if((errorcode == RBUS_ERROR_SUCCESS) || (legacyRetCode == RBUS_LEGACY_ERR_SUCCESS))
{
errorcode = RBUS_ERROR_SUCCESS;
RBUSLOG_DEBUG("Successfully Set the Value");
rbusPropertyList_initFromMessage(&cachedProperties, setResponse);
pFailedElement = NULL;
}
else
{
rbusMessage_GetString(setResponse, &pErrorReason);
RBUSLOG_WARN("Failed to Set the Value for %s", pErrorReason);
rbusMessage_GetString(setResponse, (char const**)pFailedElement);
RBUSLOG_WARN("Failed to Set the Value for %s", *pFailedElement);
if(rollBack)
{
char *pTempFailedElement = NULL;
rbusSetOptions_t revertOpts;
if ((opts) && (opts->sessionId != 0))
{
revertOpts.commit = true;
revertOpts.sessionId= opts->sessionId;
}
else
{
revertOpts.commit = true;
revertOpts.sessionId = 0;
}
cachedNumProps = 0;
cachedNumProps = rbusProperty_Count(cachedProperties);
rbusError_t result;
result = _setMultiInternal(handle, cachedNumProps, cachedProperties, &revertOpts, (int)timeout, &pTempFailedElement, false);
if(result == RBUS_ERROR_SUCCESS)
RBUSLOG_WARN("Successfully reverted back the values");
else if((result != RBUS_ERROR_SUCCESS) && (pTempFailedElement))
RBUSLOG_WARN("Failed to rollback %s\n",pTempFailedElement);
}
if(legacyRetCode > RBUS_LEGACY_ERR_SUCCESS)
{
errorcode = CCSPError_to_rbusError(legacyRetCode);
}
break;
}

/* Release the reponse message */
Expand Down Expand Up @@ -4147,9 +4231,21 @@ rbusError_t rbus_setMulti(rbusHandle_t handle, int numProps, rbusProperty_t prop
if(componentNames)
free(componentNames);
}
if(cachedProperties)
free(cachedProperties);
return errorcode;
}

rbusError_t rbus_setMulti(rbusHandle_t handle, int numProps, rbusProperty_t properties, rbusSetOptions_t* opts)
{
return _setMultiInternal(handle, numProps, properties, opts, 0, NULL, true);
}

rbusError_t rbus_setMultiExt(rbusHandle_t handle, int numProps, rbusProperty_t properties, rbusSetOptions_t* opts, uint8_t timeout, char** failedParameterName)
{
return _setMultiInternal(handle, numProps, properties, opts, timeout, failedParameterName, true);
}

static rbusError_t rbus_setByType(rbusHandle_t handle, char const* paramName, void const* paramVal, rbusValueType_t type)
{
rbusError_t errorcode = RBUS_ERROR_INVALID_INPUT;
Expand Down
4 changes: 2 additions & 2 deletions src/rbus/rbus_property.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,9 @@ void rbusProperty_Append(rbusProperty_t property, rbusProperty_t back)
rbusProperty_SetNext(last, back);
}

uint32_t rbusProperty_Count(rbusProperty_t property)
int rbusProperty_Count(rbusProperty_t property)
{
uint32_t count = 1;
int count = 1;
rbusProperty_t prop = property;
if(!prop)
return 0;
Expand Down

0 comments on commit 8f913ce

Please sign in to comment.