Add new FM API methods
New API methods have been added to allow getting, setting, and clearing faults by providing both alarm_id and entity_instance_id. Changes in this commit: - For clear_fault operation, the query has been updated to allow the removal of multiple rows with a single query. The entity_instance_id parameter can now be a prefix, enabling the matching of multiple alarms with the same alarm_id. This change does not affect existing use cases. - New method get_faults_by_id_n_eid, This method allows API clients to retrieve a list of alarms that match an alarm_id and a prefix of entity_instance_id, thereby matching multiple alarms. - New method set_faults. This method accepts a list of alarms as a parameter and calls the same core set_fault function for each alarm. [PASS] Build and install packages [PASS] Remove several alarms that matches 'alarm_id', 'entity_instance_id=%' [PASS] Get list of alarms that match 'alarm_id' and 'entity_instance_id=%' [PASS] Verify that the new behavior for removing alarms does not affect previous use cases. [PASS] Test set_faults API function providing a list of alarms. Verify the alarms in the list are being created. [PASS] Enable debug mode to verify that queries are as expected. Story: 2011106 task: 50756 Change-Id: Ib9dcfa97960a5d50865133a61810681e5a09edbe Signed-off-by: fperez <fabrizio.perez@windriver.com>
This commit is contained in:
parent
05f5d63de9
commit
625e253b7c
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2013-2018 Wind River Systems, Inc.
|
||||
# Copyright (c) 2013-2024 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
@ -185,6 +185,19 @@ class FaultAPIs(FaultAPIsBase):
|
||||
except (RuntimeError, SystemError, TypeError):
|
||||
return None
|
||||
|
||||
def set_faults(self, data):
|
||||
buff_list = []
|
||||
with fm_api_lock:
|
||||
for alarm_data in data:
|
||||
self._check_required_attributes(alarm_data)
|
||||
self._validate_attributes(alarm_data)
|
||||
buff = self._alarm_to_str(alarm_data)
|
||||
buff_list.append(buff)
|
||||
try:
|
||||
return fm_core.set_fault_list(buff_list)
|
||||
except (RuntimeError, SystemError, TypeError):
|
||||
return None
|
||||
|
||||
def clear_fault(self, alarm_id, entity_instance_id):
|
||||
with fm_api_lock:
|
||||
sep = constants.FM_CLIENT_STR_SEP
|
||||
@ -244,6 +257,22 @@ class FaultAPIs(FaultAPIsBase):
|
||||
pass
|
||||
return None
|
||||
|
||||
def get_faults_by_id_n_eid(self, alarm_id, entity_instance_id):
|
||||
with fm_api_lock:
|
||||
sep = constants.FM_CLIENT_STR_SEP
|
||||
buff = (sep + self._check_val(alarm_id) + sep +
|
||||
self._check_val(entity_instance_id) + sep)
|
||||
try:
|
||||
resp = fm_core.get_by_id_n_eid(buff)
|
||||
if resp:
|
||||
data = []
|
||||
for i in resp:
|
||||
data.append(self._str_to_alarm(i))
|
||||
return data
|
||||
except (RuntimeError, SystemError, TypeError):
|
||||
pass
|
||||
return None
|
||||
|
||||
def get_faults_by_id(self, alarm_id):
|
||||
with fm_api_lock:
|
||||
try:
|
||||
|
@ -81,6 +81,17 @@ def get_all(instance_id):
|
||||
print("No alarm returned")
|
||||
|
||||
|
||||
def get_all_by_id_n_eid(alarm_id, instance_id):
|
||||
ll = ser.get_faults_by_id_n_eid(alarm_id, instance_id)
|
||||
if ll is not None:
|
||||
print("Total alarm returned: %d\n"
|
||||
% len(ll))
|
||||
for i in ll:
|
||||
print_alarm(i)
|
||||
else:
|
||||
print("No alarm returned")
|
||||
|
||||
|
||||
def get_list(alarm_id):
|
||||
ll = ser.get_faults_by_id(alarm_id)
|
||||
if ll is not None:
|
||||
@ -105,3 +116,5 @@ if __name__ == "__main__":
|
||||
sys.exit(del_all(sys.argv[2]))
|
||||
elif sys.argv[1] == "get_list":
|
||||
sys.exit(get_list(sys.argv[2]))
|
||||
elif sys.argv[1] == "get_list_id_eid":
|
||||
sys.exit(get_all_by_id_n_eid(sys.argv[2], sys.argv[3]))
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2017,2023 Wind River Systems, Inc.
|
||||
// Copyright (c) 2017,2024 Wind River Systems, Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
@ -287,7 +287,24 @@ EFmErrorT fm_set_fault(const SFmAlarmDataT *alarm,
|
||||
return FM_ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clears fault entries based on the specified filter.
|
||||
*
|
||||
* This function sends a request to the FM server which performs the
|
||||
* query for the clear_fault operation.
|
||||
* In addition, this allows the removal of multiple rows with a single query.
|
||||
*
|
||||
* **Parameters:**
|
||||
* - `filter`: A pointer to an `AlarmFilter` structure. This includes `alarm_id`
|
||||
* and `entity_instance_id`.
|
||||
*
|
||||
* **Returns:**
|
||||
* - `FM_ERR_OK` if the operation was successful.
|
||||
* - `FM_ERR_NOCONNECT` if the function failed to connect to the server or if the
|
||||
* connection was lost during the operation.
|
||||
* - Other error codes as defined in the `EFmErrorT` enumeration if the operation
|
||||
* encountered other issues.
|
||||
*/
|
||||
EFmErrorT fm_clear_fault(AlarmFilter *filter) {
|
||||
|
||||
CFmMutexGuard m(getAPIMutex());
|
||||
@ -479,6 +496,90 @@ EFmErrorT fm_get_faults_by_id(fm_alarm_id *alarm_id,
|
||||
return FM_ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves alarms based on a filter with alarm_id and
|
||||
* entity_instance_id.
|
||||
*
|
||||
* This function sends a request to the FM server to retrieve faults
|
||||
* information matching the given filter criteria.
|
||||
* The entity_instance_id parameter can now be a prefix (not complete),
|
||||
* enabling the matching of multiple alarms with the same alarm_id
|
||||
*
|
||||
* **Parameters:**
|
||||
* - `filter`: A pointer to an `AlarmFilter` structure. This includes `alarm_id`
|
||||
* and `entity_instance_id`.
|
||||
* - `alarm`: A pointer to an array of `SFmAlarmDataT` structures where
|
||||
* the retrieved alarms will be stored.
|
||||
* - `max_alarms_to_get`: On input, specifies the maximum number of alarms
|
||||
* to retrieve. On output, specifies the number of alarms actually retrieved.
|
||||
*
|
||||
* **Returns:**
|
||||
* An error code indicating the result of the operation. Possible values include:
|
||||
* - `FM_ERR_OK`: Operation was successful.
|
||||
* - `FM_ERR_NOCONNECT`: Failed to connect to the FM core.
|
||||
* - Other error codes as defined in the `EFmErrorT` enumeration.
|
||||
*/
|
||||
EFmErrorT fm_get_faults_by_id_n_eid(AlarmFilter *filter,
|
||||
SFmAlarmDataT *alarm,
|
||||
unsigned int *max_alarms_to_get) {
|
||||
|
||||
CFmMutexGuard m(getAPIMutex());
|
||||
if (!fm_lib_reconnect()) return FM_ERR_NOCONNECT;
|
||||
fm_check_thread_pending_request();
|
||||
|
||||
fm_buff_t buff;
|
||||
buff.clear();
|
||||
EFmErrorT erc = fm_msg_utils_prep_requet_msg(buff, EFmGetFaultsByIdnEid,
|
||||
filter,sizeof(*filter));
|
||||
if (erc!=FM_ERR_OK) return erc;
|
||||
|
||||
// if it was not correctly sent by the API, set to the expected value
|
||||
if (*max_alarms_to_get == 0){
|
||||
*max_alarms_to_get = DEF_MAX_ALARMS;
|
||||
}
|
||||
|
||||
if (m_client.write_packet(buff)) {
|
||||
if (!m_client.read_packet(buff)) {
|
||||
m_connected = false;
|
||||
return FM_ERR_NOCONNECT;
|
||||
}
|
||||
|
||||
if (ptr_to_hdr(buff)->msg_rc != FM_ERR_OK){
|
||||
*max_alarms_to_get = 0;
|
||||
EFmErrorT rc = (EFmErrorT)ptr_to_hdr(buff)->msg_rc;
|
||||
return rc;
|
||||
}
|
||||
|
||||
uint32_t pkt_size = ptr_to_hdr(buff)->msg_size;
|
||||
if (pkt_size < sizeof(uint32_t)) {
|
||||
FM_ERROR_LOG("Received invalid pkt size: %u\n",pkt_size );
|
||||
m_connected = false;
|
||||
return FM_ERR_COMMUNICATIONS;
|
||||
}
|
||||
// Decrement pkt_size by the size of the length field in the header
|
||||
// to get the size of the actual alarm data
|
||||
pkt_size-=sizeof(uint32_t);
|
||||
|
||||
char *dptr = (char*)ptr_to_data(buff);
|
||||
|
||||
uint32_t *len = (uint32_t*)dptr;
|
||||
dptr+=sizeof(uint32_t);
|
||||
if (*max_alarms_to_get < *len) {
|
||||
return FM_ERR_NOT_ENOUGH_SPACE;
|
||||
}
|
||||
if (pkt_size < (*len*sizeof(SFmAlarmDataT)) ) {
|
||||
return FM_ERR_COMMUNICATIONS;
|
||||
}
|
||||
*max_alarms_to_get = *len;
|
||||
memcpy(alarm,dptr,pkt_size);
|
||||
} else {
|
||||
m_connected = false;
|
||||
return FM_ERR_NOCONNECT;
|
||||
}
|
||||
|
||||
return FM_ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* APIs that enqueue the request and return ok for acknowledgment.
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2017 Wind River Systems, Inc.
|
||||
// Copyright (c) 2024 Wind River Systems, Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
@ -27,6 +27,8 @@ typedef unsigned char FMBoolTypeT;
|
||||
|
||||
#define FM_FALSE 0
|
||||
|
||||
static const size_t DEF_MAX_ALARMS (1000);
|
||||
|
||||
typedef enum{
|
||||
FM_ALARM_STATE_CLEAR = 0,
|
||||
FM_ALARM_STATE_SET = 1,
|
||||
@ -204,6 +206,10 @@ EFmErrorT fm_get_faults(fm_ent_inst_t *inst_id, SFmAlarmDataT *alarm,
|
||||
EFmErrorT fm_get_faults_by_id(fm_alarm_id *alarm_id, SFmAlarmDataT *alarm,
|
||||
unsigned int *max_alarms_to_get);
|
||||
|
||||
EFmErrorT fm_get_faults_by_id_n_eid(AlarmFilter *filter,
|
||||
SFmAlarmDataT *alarm,
|
||||
unsigned int *max_alarms_to_get);
|
||||
|
||||
|
||||
/*
|
||||
* APIs that enqueue the request and return ok for acknowledgment.
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2014-2018 Wind River Systems, Inc.
|
||||
// Copyright (c) 2014-2024 Wind River Systems, Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
@ -250,47 +250,29 @@ bool CFmDbAlarmOperation::get_alarm(CFmDBSession &sess, AlarmFilter &af, fm_db_r
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CFmDbAlarmOperation::get_alarms(CFmDBSession &sess,const char *id, fm_db_result_t & alarms) {
|
||||
/** Function similar to 'get_alarm', the only difference is that this could match
|
||||
* several rows, since this is using the LIKE % clause.
|
||||
*/
|
||||
bool CFmDbAlarmOperation::get_alarms_eid_not_strict(CFmDBSession &sess, AlarmFilter &af, fm_db_result_t & alarms) {
|
||||
|
||||
std::string sql;
|
||||
|
||||
char query[FM_MAX_SQL_STATEMENT_MAX];
|
||||
fm_db_result_t res;
|
||||
res.clear();
|
||||
|
||||
sql = FM_DB_SELECT_FROM_TABLE(FM_ALARM_TABLE_NAME);
|
||||
sql += " ";
|
||||
|
||||
sql += " INNER JOIN ";
|
||||
sql += FM_EVENT_SUPPRESSION_TABLE_NAME;
|
||||
sql += " ON ";
|
||||
sql += FM_ALARM_TABLE_NAME;
|
||||
sql += ".";
|
||||
sql += FM_ALARM_COLUMN_ALARM_ID;
|
||||
sql += " = ";
|
||||
sql += FM_EVENT_SUPPRESSION_TABLE_NAME;
|
||||
sql += ".";
|
||||
sql += FM_EVENT_SUPPRESSION_COLUMN_ALARM_ID;
|
||||
|
||||
sql += " WHERE ";
|
||||
sql += FM_EVENT_SUPPRESSION_TABLE_NAME;
|
||||
sql += ".";
|
||||
sql += FM_EVENT_SUPPRESSION_COLUMN_SUPPRESSION_STATUS;
|
||||
sql += " = '";
|
||||
sql += FM_EVENT_SUPPRESSION_UNSUPPRESSED;
|
||||
sql += "'";
|
||||
|
||||
if (id != NULL){
|
||||
snprintf(query, sizeof(query),"%s like '%s%s'", FM_ALARM_COLUMN_ENTITY_INSTANCE_ID, id,"%");
|
||||
if (NULL!=query) {
|
||||
sql += " AND ";
|
||||
sql += query;
|
||||
}
|
||||
if (strlen(af.entity_instance_id) == 0){
|
||||
snprintf(query, sizeof(query),"%s = '%s' AND %s = ' '",
|
||||
FM_ALARM_COLUMN_ALARM_ID, af.alarm_id,
|
||||
FM_ALARM_COLUMN_ENTITY_INSTANCE_ID);
|
||||
}
|
||||
|
||||
FM_DEBUG_LOG("CMD:(%s)\n", sql.c_str());
|
||||
if ((sess.query(sql.c_str(), alarms)) != true)
|
||||
else {
|
||||
snprintf(query, sizeof(query), "%s = '%s' AND %s LIKE '%s%%'",
|
||||
FM_ALARM_COLUMN_ALARM_ID, af.alarm_id,
|
||||
FM_ALARM_COLUMN_ENTITY_INSTANCE_ID, af.entity_instance_id);
|
||||
}
|
||||
fm_db_util_build_sql_query((const char*)FM_ALARM_TABLE_NAME, query, sql);
|
||||
FM_DEBUG_LOG("get_alarm:(%s)\n", sql.c_str());
|
||||
if ((sess.query(sql.c_str(), alarms)) != true){
|
||||
return false;
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -311,6 +293,71 @@ bool CFmDbAlarmOperation::get_alarms_by_id(CFmDBSession &sess,const char *id, fm
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CFmDbAlarmOperation::get_alarms(CFmDBSession &sess, const char *entity_instance_id, fm_db_result_t &alarms) {
|
||||
std::string sql = CFmDbAlarmOperation::build_base_alarm_query(entity_instance_id);
|
||||
|
||||
FM_DEBUG_LOG("CMD:(%s)\n", sql.c_str());
|
||||
if (!sess.query(sql.c_str(), alarms))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CFmDbAlarmOperation::get_alarms_by_id_n_eid(CFmDBSession &sess, const AlarmFilter &af, fm_db_result_t &alarms) {
|
||||
std::string sql = CFmDbAlarmOperation::build_base_alarm_query(af.entity_instance_id);
|
||||
|
||||
if (strlen(af.alarm_id) > 0) {
|
||||
char query[FM_MAX_SQL_STATEMENT_MAX];
|
||||
snprintf(query, sizeof(query), "%s.%s = '%s'", FM_ALARM_TABLE_NAME,
|
||||
FM_ALARM_COLUMN_ALARM_ID, af.alarm_id);
|
||||
sql += " AND ";
|
||||
sql += query;
|
||||
}else{
|
||||
FM_INFO_LOG("Alarm_id not provided \n");
|
||||
return false;
|
||||
}
|
||||
|
||||
FM_DEBUG_LOG("CMD:(%s)\n", sql.c_str());
|
||||
if (!sess.query(sql.c_str(), alarms))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string CFmDbAlarmOperation::build_base_alarm_query(const char *entity_instance_id) {
|
||||
std::string sql;
|
||||
char query[FM_MAX_SQL_STATEMENT_MAX];
|
||||
|
||||
sql = FM_DB_SELECT_FROM_TABLE(FM_ALARM_TABLE_NAME);
|
||||
sql += " INNER JOIN ";
|
||||
sql += FM_EVENT_SUPPRESSION_TABLE_NAME;
|
||||
sql += " ON ";
|
||||
sql += FM_ALARM_TABLE_NAME;
|
||||
sql += ".";
|
||||
sql += FM_ALARM_COLUMN_ALARM_ID;
|
||||
sql += " = ";
|
||||
sql += FM_EVENT_SUPPRESSION_TABLE_NAME;
|
||||
sql += ".";
|
||||
sql += FM_EVENT_SUPPRESSION_COLUMN_ALARM_ID;
|
||||
|
||||
sql += " WHERE ";
|
||||
sql += FM_EVENT_SUPPRESSION_TABLE_NAME;
|
||||
sql += ".";
|
||||
sql += FM_EVENT_SUPPRESSION_COLUMN_SUPPRESSION_STATUS;
|
||||
sql += " = '";
|
||||
sql += FM_EVENT_SUPPRESSION_UNSUPPRESSED;
|
||||
sql += "'";
|
||||
|
||||
if (entity_instance_id != nullptr) {
|
||||
snprintf(query, sizeof(query), "%s.%s LIKE '%s%s'", FM_ALARM_TABLE_NAME,
|
||||
FM_ALARM_COLUMN_ENTITY_INSTANCE_ID, entity_instance_id, "%");
|
||||
sql += " AND ";
|
||||
sql += query;
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
bool CFmDbAlarmOperation::get_all_alarms(CFmDBSession &sess, SFmAlarmDataT **alarms, size_t *len ) {
|
||||
fm_db_result_t res;
|
||||
|
||||
|
@ -66,9 +66,16 @@ public:
|
||||
|
||||
bool get_alarms_by_id(CFmDBSession &sess, const char *id, fm_db_result_t & alarms);
|
||||
|
||||
bool get_alarms_by_id_n_eid(CFmDBSession &sess, const AlarmFilter &af, fm_db_result_t &alarms);
|
||||
|
||||
bool get_alarms_eid_not_strict(CFmDBSession &sess, AlarmFilter &af, fm_db_result_t & alarms);
|
||||
|
||||
bool mask_unmask_alarms(CFmDBSession &sess, SFmAlarmDataT &a, bool mask = true);
|
||||
|
||||
bool add_alarm_history(CFmDBSession &sess, SFmAlarmDataT &a, bool set);
|
||||
|
||||
private:
|
||||
static std::string build_base_alarm_query(const char *entity_instance_id);
|
||||
};
|
||||
|
||||
#endif /* FMDBALARM_H_ */
|
||||
|
@ -436,14 +436,14 @@ bool fm_db_util_build_sql_delete(const char* db_table, AlarmFilter *db_data,
|
||||
char sql[FM_MAX_SQL_STATEMENT_MAX];
|
||||
|
||||
if (strlen(db_data->entity_instance_id) == 0){
|
||||
snprintf(sql, sizeof(sql), "DElETE FROM %s WHERE %s = '%s' AND %s = ' '",
|
||||
snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE %s = '%s' AND %s = ' '",
|
||||
db_table, FM_ALARM_COLUMN_ALARM_ID, db_data->alarm_id,
|
||||
FM_ALARM_COLUMN_ENTITY_INSTANCE_ID);
|
||||
}
|
||||
else{
|
||||
snprintf(sql, sizeof(sql), "DElETE FROM %s WHERE %s = '%s' AND %s = '%s'",
|
||||
snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE %s = '%s' AND %s like '%s%s'",
|
||||
db_table, FM_ALARM_COLUMN_ALARM_ID, db_data->alarm_id,
|
||||
FM_ALARM_COLUMN_ENTITY_INSTANCE_ID, db_data->entity_instance_id);
|
||||
FM_ALARM_COLUMN_ENTITY_INSTANCE_ID, db_data->entity_instance_id,"%");
|
||||
}
|
||||
db_cmd.assign(sql);
|
||||
return true;
|
||||
@ -456,7 +456,7 @@ bool fm_db_util_build_sql_delete_row(const char* db_table, int id,
|
||||
|
||||
char sql[FM_MAX_SQL_STATEMENT_MAX];
|
||||
|
||||
snprintf(sql, sizeof(sql), "DElETE FROM %s WHERE %s = %d",
|
||||
snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE %s = %d",
|
||||
db_table, FM_ALARM_COLUMN_ID, id);
|
||||
db_cmd.assign(sql);
|
||||
return true;
|
||||
@ -467,7 +467,7 @@ bool fm_db_util_build_sql_delete_all(const char* db_table, const char *id,
|
||||
|
||||
char sql[FM_MAX_SQL_STATEMENT_MAX];
|
||||
|
||||
snprintf(sql, sizeof(sql), "DElETE FROM %s WHERE %s like '%s%s'", db_table,
|
||||
snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE %s like '%s%s'", db_table,
|
||||
FM_ALARM_COLUMN_ENTITY_INSTANCE_ID, id,"%");
|
||||
db_cmd.assign(sql);
|
||||
return true;
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2014 Wind River Systems, Inc.
|
||||
// Copyright (c) 2024 Wind River Systems, Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
@ -36,6 +36,7 @@ typedef enum {
|
||||
EFmGetFaults,
|
||||
EFmReturnUUID,
|
||||
EFmGetFaultsById,
|
||||
EFmGetFaultsByIdnEid,
|
||||
EFmActMax
|
||||
}EFmMsgActionsT;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2017-2018 Wind River Systems, Inc.
|
||||
// Copyright (c) 2017-2024 Wind River Systems, Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
@ -288,6 +288,97 @@ void get_db_alarms_by_id(CFmDBSession &sess, sFmGetReq &req, void *context){
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves faults from the database based on the specified alarm ID and entity instance ID.
|
||||
*
|
||||
* This function queries the database for alarms that match the provided alarm ID
|
||||
* and entity instance ID. The results are then sent back to the client through
|
||||
* the provided socket server processor.
|
||||
*
|
||||
* **Parameters:**
|
||||
* - `sess`: A reference to a `CFmDBSession` object representing the database session.
|
||||
* - `req`: A reference to an `sFmGetReq` structure containing the request data.
|
||||
* - `context`: A pointer to a context object.
|
||||
*
|
||||
* **Process Flow:**
|
||||
* - The function initializes a buffer with the request data and extracts the header and data
|
||||
* sections.
|
||||
* - It casts the data section to an `AlarmFilter` pointer and the context to an
|
||||
* `FmSocketServerProcessor` pointer.
|
||||
* - Database Query
|
||||
* - If alarms are found, it fills a vector with the alarm data.
|
||||
* - Sets the number of alarms found in the buffer and copies the alarm data into the buffer.
|
||||
* - It sends the response back to the client using the `send_response` method of the
|
||||
* `FmSocketServerProcessor`.
|
||||
*
|
||||
* - If no alarms are found, it logs a message and sets the response code to
|
||||
* `FM_ERR_ENTITY_NOT_FOUND`.
|
||||
*
|
||||
* **Returns:**
|
||||
* - The function does not return a value but sends a response back to the client
|
||||
* through the provided socket server processor.
|
||||
*/
|
||||
void get_db_alarms_by_id_n_eid(CFmDBSession &sess, sFmGetReq &req, void *context){
|
||||
|
||||
fm_buff_t buff = req.data;
|
||||
SFmMsgHdrT *hdr = (SFmMsgHdrT *)&buff[0];
|
||||
void * data = &buff[sizeof(SFmMsgHdrT)];
|
||||
AlarmFilter *filter = (AlarmFilter *)data;
|
||||
FmSocketServerProcessor *srv = (FmSocketServerProcessor *)context;
|
||||
CFmDbAlarmOperation op;
|
||||
fm_db_result_t res;
|
||||
std::vector<SFmAlarmDataT> alarmv;
|
||||
|
||||
FM_DEBUG_LOG("handle get_db_alarms_by_id_n_eid:%s\n", filter->alarm_id);
|
||||
|
||||
hdr->msg_rc = FM_ERR_OK;
|
||||
res.clear();
|
||||
if (op.get_alarms_by_id_n_eid(sess, *filter, res) != true){
|
||||
hdr->msg_rc = FM_ERR_DB_OPERATION_FAILURE;
|
||||
}else if (res.size() > 0){
|
||||
int ix = 0;
|
||||
int resp_len = res.size();
|
||||
SFmAlarmDataT alarm;
|
||||
alarmv.clear();
|
||||
// Fill the tuple data vector for the response.
|
||||
for ( ; ix < resp_len ; ++ix ) {
|
||||
CFmDbAlarm::convert_to(res[ix],&alarm);
|
||||
alarmv.push_back(alarm);
|
||||
}
|
||||
} else {
|
||||
FM_DEBUG_LOG("No alarms found for alarm id (%s), "
|
||||
"entity_instance_id (%s)\n",
|
||||
filter->alarm_id, filter->entity_instance_id);
|
||||
hdr->msg_rc = FM_ERR_ENTITY_NOT_FOUND;
|
||||
}
|
||||
|
||||
if ((hdr->msg_rc==FM_ERR_OK) && (alarmv.size() > 0)){
|
||||
int found_num_alarms=alarmv.size();
|
||||
FM_DEBUG_LOG("Get faults: found alarms: (%d)", found_num_alarms);
|
||||
|
||||
// (num of alarms found * size of alarm structure) +
|
||||
// space to report number of alarms found.
|
||||
int total_len =(found_num_alarms * sizeof(SFmAlarmDataT)) + sizeof(uint32_t);
|
||||
|
||||
void * buffer = malloc(total_len);
|
||||
if (buffer==NULL) {
|
||||
hdr->msg_rc =FM_ERR_SERVER_NO_MEM;
|
||||
srv->send_response(req.fd,hdr,NULL,0);
|
||||
return;
|
||||
}
|
||||
uint32_t *alen = (uint32_t*) buffer;
|
||||
*alen = found_num_alarms;
|
||||
|
||||
SFmAlarmDataT * alarms = (SFmAlarmDataT*) ( ((char*)buffer)+sizeof(uint32_t));
|
||||
|
||||
memcpy(alarms,&(alarmv[0]),alarmv.size() * sizeof(SFmAlarmDataT));
|
||||
srv->send_response(req.fd,hdr,buffer,total_len);
|
||||
free(buffer);
|
||||
} else {
|
||||
srv->send_response(req.fd,hdr,NULL,0);
|
||||
}
|
||||
}
|
||||
|
||||
void fm_handle_job_request(CFmDBSession &sess, sFmJobReq &req){
|
||||
CFmDbAlarmOperation op;
|
||||
CFmEventSuppressionOperation event_suppression_op;
|
||||
@ -333,6 +424,7 @@ void fm_handle_get_request(CFmDBSession &sess, sFmGetReq &req,
|
||||
case EFmGetFault:get_db_alarm(sess,req,context); break;
|
||||
case EFmGetFaults:get_db_alarms(sess,req,context); break;
|
||||
case EFmGetFaultsById:get_db_alarms_by_id(sess,req,context); break;
|
||||
case EFmGetFaultsByIdnEid:get_db_alarms_by_id_n_eid(sess,req,context); break;
|
||||
default:
|
||||
FM_ERROR_LOG("Unexpected job request, action:%u\n",hdr->action);
|
||||
break;
|
||||
@ -471,8 +563,29 @@ void FmSocketServerProcessor::handle_delete_faults(int fd,
|
||||
send_response(fd,hdr,NULL,0);
|
||||
}
|
||||
|
||||
void FmSocketServerProcessor::handle_delete_fault(int fd,
|
||||
SFmMsgHdrT *hdr, std::vector<char> &rdata, CFmDBSession &sess) {
|
||||
/**
|
||||
* Handles the deletion of faults based on the specified filter.
|
||||
*
|
||||
* This function processes the request to delete faults from the database.
|
||||
* It first validates the request, then retrieves matching alarms and deletes
|
||||
* them from the database. If multiple alarms are found, it handles each
|
||||
* alarm separately and enqueues a job for each cleared alarm.
|
||||
*
|
||||
* **Parameters:**
|
||||
* - `fd`: The file descriptor for the client connection.
|
||||
* - `hdr`: A pointer to an `SFmMsgHdrT` structure containing the message header.
|
||||
* - `rdata`: A reference to a vector of characters containing the request data.
|
||||
* - `sess`: A reference to a `CFmDBSession` object representing the database session.
|
||||
*
|
||||
* **Returns:**
|
||||
* - The function does not return a value but sends a response back to the client through
|
||||
* the provided file descriptor.
|
||||
*/
|
||||
void FmSocketServerProcessor::handle_delete_fault(
|
||||
int fd,
|
||||
SFmMsgHdrT *hdr,
|
||||
std::vector<char> &rdata,
|
||||
CFmDBSession &sess) {
|
||||
|
||||
CFmDbAlarmOperation op;
|
||||
sFmJobReq req;
|
||||
@ -480,36 +593,54 @@ void FmSocketServerProcessor::handle_delete_fault(int fd,
|
||||
SFmAlarmDataT alarm;
|
||||
fm_db_result_t res;
|
||||
|
||||
is_request_valid(hdr->msg_size,AlarmFilter);
|
||||
is_request_valid(hdr->msg_size, AlarmFilter);
|
||||
void * data = &(rdata[sizeof(SFmMsgHdrT)]);
|
||||
AlarmFilter *filter = (AlarmFilter *)(data);
|
||||
hdr->msg_rc = FM_ERR_OK;
|
||||
res.clear();
|
||||
if ((op.get_alarm(sess, *filter, res)) != true){
|
||||
if ((op.get_alarms_eid_not_strict(sess, *filter, res)) != true) {
|
||||
hdr->msg_rc = FM_ERR_DB_OPERATION_FAILURE;
|
||||
}else{
|
||||
if (res.size() > 0){
|
||||
if(op.delete_alarm(sess, *filter) > 0){
|
||||
FM_INFO_LOG("Deleted alarm: (%s) (%s)\n",
|
||||
filter->alarm_id, filter->entity_instance_id);
|
||||
CFmDbAlarm::convert_to(res[0],&alarm);
|
||||
fm_uuid_create(alarm.uuid);
|
||||
req.type = FM_ALARM_CLEAR;
|
||||
req.set = false;
|
||||
req.data = alarm;
|
||||
enqueue_job(req);
|
||||
}else{
|
||||
} else {
|
||||
if (res.size() > 0) {
|
||||
if (op.delete_alarm(sess, *filter) > 0) {
|
||||
FM_INFO_LOG("Deleted alarm(s): (%s) (%s)\n",
|
||||
filter->alarm_id, filter->entity_instance_id);
|
||||
if (res.size() == 1) {
|
||||
// normal workflow, just one alarm match
|
||||
CFmDbAlarm::convert_to(res[0], &alarm);
|
||||
fm_uuid_create(alarm.uuid);
|
||||
req.type = FM_ALARM_CLEAR;
|
||||
req.set = false;
|
||||
req.data = alarm;
|
||||
enqueue_job(req);
|
||||
} else {
|
||||
// Multiple alarms received
|
||||
for (const auto &entry : res) {
|
||||
SFmAlarmDataT alarm;
|
||||
CFmDbAlarm::data_type entry_copy = entry;
|
||||
CFmDbAlarm::convert_to(entry_copy, &alarm);
|
||||
fm_uuid_create(alarm.uuid);
|
||||
req.type = FM_ALARM_CLEAR;
|
||||
req.set = false;
|
||||
req.data = alarm;
|
||||
enqueue_job(req);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
hdr->msg_rc = FM_ERR_DB_OPERATION_FAILURE;
|
||||
FM_INFO_LOG("Deleted alarm failed: (%s) (%s) (%s)\n",
|
||||
filter->alarm_id, filter->entity_instance_id,
|
||||
fm_error_from_int((EFmErrorT)hdr->msg_rc).c_str());
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
hdr->msg_rc = FM_ERR_ENTITY_NOT_FOUND;
|
||||
FM_INFO_LOG("Deleted alarm failed: (%s) (%s) (%s)\n",
|
||||
filter->alarm_id, filter->entity_instance_id,
|
||||
fm_error_from_int((EFmErrorT)hdr->msg_rc).c_str());
|
||||
filter->alarm_id, filter->entity_instance_id,
|
||||
fm_error_from_int((EFmErrorT)hdr->msg_rc).c_str());
|
||||
}
|
||||
}
|
||||
FM_INFO_LOG("Response to delete fault: %u\n", hdr->msg_rc);
|
||||
send_response(fd,hdr,NULL,0);
|
||||
send_response(fd, hdr, NULL, 0);
|
||||
}
|
||||
|
||||
void FmSocketServerProcessor::handle_get_faults_by_id(int fd,
|
||||
@ -522,6 +653,16 @@ void FmSocketServerProcessor::handle_get_faults_by_id(int fd,
|
||||
enqueue_get(req);
|
||||
}
|
||||
|
||||
void FmSocketServerProcessor::handle_get_faults_by_id_n_eid(int fd,
|
||||
SFmMsgHdrT *hdr, std::vector<char> &rdata) {
|
||||
|
||||
is_request_valid(hdr->msg_size,AlarmFilter);
|
||||
sFmGetReq req;
|
||||
req.fd = fd;
|
||||
req.data = rdata;
|
||||
enqueue_get(req);
|
||||
}
|
||||
|
||||
void FmSocketServerProcessor::handle_get_faults(int fd,
|
||||
SFmMsgHdrT *hdr, std::vector<char> &rdata) {
|
||||
|
||||
@ -555,6 +696,7 @@ void FmSocketServerProcessor::handle_socket_data(int fd,
|
||||
case EFmGetFault:handle_get_fault(fd,hdr,rdata); break;
|
||||
case EFmGetFaults:handle_get_faults(fd,hdr,rdata); break;
|
||||
case EFmGetFaultsById:handle_get_faults_by_id(fd,hdr,rdata); break;
|
||||
case EFmGetFaultsByIdnEid:handle_get_faults_by_id_n_eid(fd,hdr,rdata); break;
|
||||
default:
|
||||
FM_ERROR_LOG("Unexpected client request, action:%u\n",hdr->action);
|
||||
break;
|
||||
|
@ -31,6 +31,8 @@ protected:
|
||||
std::vector<char> &rdata);
|
||||
virtual void handle_get_faults_by_id(int fd, SFmMsgHdrT *hdr,
|
||||
std::vector<char> &rdata);
|
||||
virtual void handle_get_faults_by_id_n_eid(int fd, SFmMsgHdrT *hdr,
|
||||
std::vector<char> &rdata);
|
||||
public:
|
||||
void send_response(int fd, SFmMsgHdrT *hdr, void *data, size_t len);
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2018 Wind River Systems, Inc.
|
||||
// Copyright (c) 2024 Wind River Systems, Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
@ -13,7 +13,6 @@
|
||||
#include "fmAlarmUtils.h"
|
||||
|
||||
|
||||
static const size_t DEF_MAX_ALARMS (1000);
|
||||
static const size_t MAXSTRINGSIZE (500);
|
||||
static PyObject *logging = NULL;
|
||||
|
||||
@ -21,8 +20,8 @@ enum { error, warning, info, debug, max_level };
|
||||
|
||||
|
||||
#define LOG_MSG(level,data,...) \
|
||||
log_msg(level, "fm_python_extension: "\
|
||||
data, ## __VA_ARGS__ )
|
||||
log_msg(level, "%s:%d:%s: " data, __FILE__, __LINE__, \
|
||||
__FUNCTION__, ##__VA_ARGS__)
|
||||
|
||||
#define ERROR_LOG(data,...) \
|
||||
LOG_MSG(error, data, ## __VA_ARGS__)
|
||||
@ -100,6 +99,65 @@ static PyObject * _fm_set(PyObject * self, PyObject *args) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject * _fm_set_list(PyObject * self, PyObject *args) {
|
||||
/* Receives a PyObject expected to be a list of strings
|
||||
containing different alarm information.
|
||||
The function then parses each string into different alarm
|
||||
structures, which are filled and sent to the C++ core. */
|
||||
|
||||
std::string alarm;
|
||||
fm_uuid_t tmp_uuid;
|
||||
PyObject *uuidList = PyList_New(0);
|
||||
EFmErrorT rc = FM_ERR_INVALID_REQ;
|
||||
|
||||
PyObject *listObj = nullptr;
|
||||
if (!PyArg_ParseTuple(args, "O", &listObj)) {
|
||||
ERROR_LOG("Failed to parse args.");
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
if (!PyList_Check(listObj)) {
|
||||
ERROR_LOG("Expected a list.");
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
Py_ssize_t num_items = PyList_Size(listObj);
|
||||
for (Py_ssize_t i = 0; i < num_items; i++) {
|
||||
PyObject *item = PyList_GetItem(listObj, i);
|
||||
if (!PyUnicode_Check(item)) {
|
||||
ERROR_LOG("List items must be strings.");
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
const char *alm_str = PyUnicode_AsUTF8(item);
|
||||
std::string alarm(alm_str);
|
||||
|
||||
SFmAlarmDataT alm_data;
|
||||
if (!fm_alarm_from_string(alarm, &alm_data)) {
|
||||
ERROR_LOG("Failed to convert string to alarm.");
|
||||
continue;
|
||||
}
|
||||
|
||||
rc = fm_set_fault(&alm_data, &tmp_uuid);
|
||||
if (rc == FM_ERR_OK) {
|
||||
PyObject *uuidStr = PyUnicode_FromString(tmp_uuid);
|
||||
PyList_Append(uuidList, uuidStr);
|
||||
Py_DECREF(uuidStr);
|
||||
} else if (rc == FM_ERR_NOCONNECT) {
|
||||
WARNING_LOG("Failed to connect to FM manager");
|
||||
} else {
|
||||
ERROR_LOG("Failed to generate an alarm: (%s) (%s)",
|
||||
alm_data.alarm_id, alm_data.entity_instance_id);
|
||||
}
|
||||
}
|
||||
|
||||
if (rc == FM_ERR_OK) {
|
||||
return uuidList;
|
||||
}
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject * _fm_get(PyObject * self, PyObject *args) {
|
||||
|
||||
const char *filter;
|
||||
@ -237,6 +295,71 @@ static PyObject * _fm_get_by_eid(PyObject * self, PyObject *args, PyObject* kwar
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
static PyObject * _fm_get_by_id_n_eid(PyObject * self, PyObject *args) {
|
||||
/* Receive a PyObject expected to be a filter containing
|
||||
alarm_id and entity_instance_id. The entity_instance_id
|
||||
does not need to be complete, allowing it to match
|
||||
more than one row.
|
||||
The function parses this object into different alarm
|
||||
strings and fills a filter alarm structure that is
|
||||
sent to the C++ core. */
|
||||
const char *filter;
|
||||
AlarmFilter af;
|
||||
std::string alm_str, filter_str;
|
||||
std::vector< SFmAlarmDataT > lst;
|
||||
unsigned int max= DEF_MAX_ALARMS;
|
||||
EFmErrorT rc;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s", &filter)) {
|
||||
ERROR_LOG("Failed to parse args.");
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
filter_str.assign(filter);
|
||||
if (!fm_alarm_filter_from_string(filter_str, &af)) {
|
||||
ERROR_LOG("Invalid alarm filter: (%s)",
|
||||
filter_str.c_str());
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
try {
|
||||
lst.resize(max);
|
||||
} catch(...) {
|
||||
ERROR_LOG("Failed to allocate memory.");
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
unsigned int max_alarms_to_get = max;
|
||||
rc = fm_get_faults_by_id_n_eid(&af, &(lst[0]), &max_alarms_to_get);
|
||||
if (rc == FM_ERR_OK) {
|
||||
PyObject *__lst = PyList_New(0);
|
||||
for ( size_t ix = 0; ix < max_alarms_to_get; ++ix ) {
|
||||
std::string s;
|
||||
fm_alarm_to_string(&lst[ix], s);
|
||||
if (s.size() > 0) {
|
||||
if (PyList_Append(__lst,PyUnicode_FromString(s.c_str())) != 0) {
|
||||
ERROR_LOG("Failed to append alarm to the list");
|
||||
}
|
||||
}
|
||||
}
|
||||
/* python will garbage collect if the reference count is correct
|
||||
(it should be 1 at this point) */
|
||||
return __lst;
|
||||
}
|
||||
|
||||
if (rc == FM_ERR_ENTITY_NOT_FOUND) {
|
||||
DEBUG_LOG("Alarm id (%s), Entity id:(%s) not found",
|
||||
af.alarm_id, af.entity_instance_id);
|
||||
Py_RETURN_NONE;
|
||||
} else if (rc == FM_ERR_NOCONNECT) {
|
||||
WARNING_LOG("Failed to connect to FM manager");
|
||||
} else {
|
||||
ERROR_LOG("Failed to get alarm list for entity id (%s), error code: (%d)",
|
||||
af.entity_instance_id, rc);
|
||||
}
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
static PyObject * _fm_clear(PyObject * self, PyObject *args) {
|
||||
|
||||
const char *filter;
|
||||
@ -312,6 +435,10 @@ static PyMethodDef _methods [] = {
|
||||
"Get alarms by alarm id" },
|
||||
{ "get_by_eid", (PyCFunction)_fm_get_by_eid, METH_VARARGS | METH_KEYWORDS,
|
||||
"Get alarms by entity instance id" },
|
||||
{ "get_by_id_n_eid", _fm_get_by_id_n_eid, METH_VARARGS,
|
||||
"Get list of alarms by filter" },
|
||||
{ "set_fault_list", _fm_set_list, METH_VARARGS,
|
||||
"Set alarm list" },
|
||||
{ NULL, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user