Optimize COV Subscriptions using keylist (#1295)

* Added performance optimization in COV Subscriptions using keylist

* Add memory exhaustion check to Keylist_Data_Add, fix CheckArraySize return value
- Keylist_Data_Add: return -1 when node allocation fails
- CheckArraySize: return false instead of true when calloc fails (typo)
This commit is contained in:
KANG HYEONSEOK
2026-04-20 20:34:25 +09:00
committed by GitHub
parent 6a10cc643e
commit 52561f2336
2 changed files with 195 additions and 146 deletions
+184 -137
View File
@@ -6,6 +6,7 @@
* @copyright SPDX-License-Identifier: MIT * @copyright SPDX-License-Identifier: MIT
*/ */
#include <stddef.h> #include <stddef.h>
#include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@@ -28,6 +29,7 @@
#include "bacnet/basic/tsm/tsm.h" #include "bacnet/basic/tsm/tsm.h"
#include "bacnet/basic/object/device.h" #include "bacnet/basic/object/device.h"
#include "bacnet/basic/services.h" #include "bacnet/basic/services.h"
#include "bacnet/basic/sys/keylist.h"
#include "bacnet/basic/sys/debug.h" #include "bacnet/basic/sys/debug.h"
#include "bacnet/datalink/datalink.h" #include "bacnet/datalink/datalink.h"
@@ -43,7 +45,6 @@ typedef struct BACnet_COV_Address {
/* note: This COV service only monitors the properties /* note: This COV service only monitors the properties
of an object that have been specified in the standard. */ of an object that have been specified in the standard. */
typedef struct BACnet_COV_Subscription_Flags { typedef struct BACnet_COV_Subscription_Flags {
bool valid : 1;
bool issueConfirmedNotifications : 1; /* optional */ bool issueConfirmedNotifications : 1; /* optional */
bool send_requested : 1; bool send_requested : 1;
} BACNET_COV_SUBSCRIPTION_FLAGS; } BACNET_COV_SUBSCRIPTION_FLAGS;
@@ -57,12 +58,11 @@ typedef struct BACnet_COV_Subscription {
BACNET_OBJECT_ID monitoredObjectIdentifier; BACNET_OBJECT_ID monitoredObjectIdentifier;
} BACNET_COV_SUBSCRIPTION; } BACNET_COV_SUBSCRIPTION;
#ifndef MAX_COV_SUBCRIPTIONS #ifndef MAX_COV_SUBSCRIPTIONS
#define MAX_COV_SUBCRIPTIONS 128 #define MAX_COV_SUBSCRIPTIONS 128
#endif #endif
static BACNET_COV_SUBSCRIPTION COV_Subscriptions_List[MAX_NUM_DEVICES] static OS_Keylist COV_Subscriptions_List[MAX_NUM_DEVICES];
[MAX_COV_SUBCRIPTIONS];
#ifdef BAC_ROUTING #ifdef BAC_ROUTING
#define COV_Subscriptions (COV_Subscriptions_List[Routed_Device_Object_Index()]) #define COV_Subscriptions (COV_Subscriptions_List[Routed_Device_Object_Index()])
#else #else
@@ -73,6 +73,53 @@ static BACNET_COV_SUBSCRIPTION COV_Subscriptions_List[MAX_NUM_DEVICES]
#endif #endif
static BACNET_COV_ADDRESS COV_Addresses[MAX_COV_ADDRESSES]; static BACNET_COV_ADDRESS COV_Addresses[MAX_COV_ADDRESSES];
/**
* @brief Deletes a subscription
* @param list_idx - keylist index
* @return true if the subscription was deleted
*/
static bool cov_subscription_delete(uint32_t list_idx)
{
bool status = false;
BACNET_COV_SUBSCRIPTION *subscription = NULL;
subscription = Keylist_Data_Delete_By_Index(COV_Subscriptions, list_idx);
if (subscription) {
free(subscription);
status = true;
}
return status;
}
/**
* @brief Creates a subscription
* @param list_key - keylist key
* @return the subscription that was created, or NULL
*/
static BACNET_COV_SUBSCRIPTION *cov_subscription_create(uint32_t list_key)
{
BACNET_COV_SUBSCRIPTION *subscription = NULL;
int index = 0;
if (list_key >= MAX_COV_SUBSCRIPTIONS) {
return NULL;
}
subscription = Keylist_Data(COV_Subscriptions, list_key);
if (!subscription) {
subscription = calloc(1, sizeof(BACNET_COV_SUBSCRIPTION));
if (subscription) {
index = Keylist_Data_Add(COV_Subscriptions, list_key, subscription);
if (index < 0) {
free(subscription);
return NULL;
}
} else {
return NULL;
}
}
return subscription;
}
/** /**
* Gets the address from the list of COV addresses * Gets the address from the list of COV addresses
* *
@@ -103,6 +150,7 @@ static void cov_address_remove_unused(void)
unsigned index = 0; unsigned index = 0;
unsigned cov_index = 0; unsigned cov_index = 0;
bool found = false; bool found = false;
BACNET_COV_SUBSCRIPTION *subscription = NULL;
#ifdef BAC_ROUTING #ifdef BAC_ROUTING
uint16_t current_dev_id = Routed_Device_Object_Index(); uint16_t current_dev_id = Routed_Device_Object_Index();
@@ -112,9 +160,11 @@ static void cov_address_remove_unused(void)
found = false; found = false;
for (dev_id = 0; dev_id < Get_Num_Managed_Devices(); dev_id++) { for (dev_id = 0; dev_id < Get_Num_Managed_Devices(); dev_id++) {
Set_Routed_Device_Object_Index(dev_id); Set_Routed_Device_Object_Index(dev_id);
for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) { for (index = 0; index < Keylist_Count(COV_Subscriptions);
if ((COV_Subscriptions[index].flag.valid) && index++) {
(COV_Subscriptions[index].dest_index == cov_index)) { subscription = Keylist_Data_Index(COV_Subscriptions, index);
if (subscription &&
(subscription->dest_index == cov_index)) {
found = true; found = true;
break; break;
} }
@@ -133,9 +183,9 @@ static void cov_address_remove_unused(void)
for (cov_index = 0; cov_index < MAX_COV_ADDRESSES; cov_index++) { for (cov_index = 0; cov_index < MAX_COV_ADDRESSES; cov_index++) {
if (COV_Addresses[cov_index].valid) { if (COV_Addresses[cov_index].valid) {
found = false; found = false;
for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) { for (index = 0; index < Keylist_Count(COV_Subscriptions); index++) {
if ((COV_Subscriptions[index].flag.valid) && subscription = Keylist_Data_Index(COV_Subscriptions, index);
(COV_Subscriptions[index].dest_index == cov_index)) { if (subscription && (subscription->dest_index == cov_index)) {
found = true; found = true;
break; break;
} }
@@ -323,14 +373,15 @@ int handler_cov_encode_subscriptions(uint8_t *apdu, int max_apdu)
}; };
unsigned index = 0; unsigned index = 0;
int apdu_len = 0; int apdu_len = 0;
BACNET_COV_SUBSCRIPTION *subscription = NULL;
for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) { for (index = 0; index < Keylist_Count(COV_Subscriptions); index++) {
if (COV_Subscriptions[index].flag.valid) { subscription = Keylist_Data_Index(COV_Subscriptions, index);
if (subscription) {
/* Lets encode a COV subscription into an intermediate buffer /* Lets encode a COV subscription into an intermediate buffer
* that can hold it */ * that can hold it */
int len = cov_encode_subscription( int len = cov_encode_subscription(
&cov_sub[0], max_apdu - apdu_len, &cov_sub[0], max_apdu - apdu_len, subscription);
&COV_Subscriptions[index]);
if ((apdu_len + len) > max_apdu) { if ((apdu_len + len) > max_apdu) {
return -2; return -2;
@@ -359,34 +410,18 @@ void handler_cov_init(void)
uint16_t dev_id = 0; uint16_t dev_id = 0;
for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) { for (dev_id = 0; dev_id < MAX_NUM_DEVICES; dev_id++) {
Set_Routed_Device_Object_Index(dev_id); Set_Routed_Device_Object_Index(dev_id);
for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) { if (!COV_Subscriptions) {
/* initialize with invalid COV address */ COV_Subscriptions = Keylist_Create();
COV_Subscriptions[index].flag.valid = false; } else {
COV_Subscriptions[index].dest_index = MAX_COV_ADDRESSES; Keylist_Data_Free(COV_Subscriptions);
COV_Subscriptions[index].subscriberProcessIdentifier = 0;
COV_Subscriptions[index].monitoredObjectIdentifier.type =
OBJECT_ANALOG_INPUT;
COV_Subscriptions[index].monitoredObjectIdentifier.instance = 0;
COV_Subscriptions[index].flag.issueConfirmedNotifications = false;
COV_Subscriptions[index].invokeID = 0;
COV_Subscriptions[index].lifetime = 0;
COV_Subscriptions[index].flag.send_requested = false;
} }
} }
Set_Routed_Device_Object_Index(current_dev_id); Set_Routed_Device_Object_Index(current_dev_id);
#else #else
for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) { if (!COV_Subscriptions) {
/* initialize with invalid COV address */ COV_Subscriptions = Keylist_Create();
COV_Subscriptions[index].flag.valid = false; } else {
COV_Subscriptions[index].dest_index = MAX_COV_ADDRESSES; Keylist_Data_Free(COV_Subscriptions);
COV_Subscriptions[index].subscriberProcessIdentifier = 0;
COV_Subscriptions[index].monitoredObjectIdentifier.type =
OBJECT_ANALOG_INPUT;
COV_Subscriptions[index].monitoredObjectIdentifier.instance = 0;
COV_Subscriptions[index].flag.issueConfirmedNotifications = false;
COV_Subscriptions[index].invokeID = 0;
COV_Subscriptions[index].lifetime = 0;
COV_Subscriptions[index].flag.send_requested = false;
} }
#endif #endif
for (index = 0; index < MAX_COV_ADDRESSES; index++) { for (index = 0; index < MAX_COV_ADDRESSES; index++) {
@@ -402,57 +437,54 @@ static bool cov_list_subscribe(
{ {
bool existing_entry = false; bool existing_entry = false;
int index; int index;
int first_invalid_index = -1;
bool found = true; bool found = true;
bool address_match = false; bool address_match = false;
const BACNET_ADDRESS *dest = NULL; const BACNET_ADDRESS *dest = NULL;
BACNET_COV_SUBSCRIPTION *subscription = NULL;
/* unable to subscribe - resources? */ /* unable to subscribe - resources? */
/* unable to cancel subscription - other? */ /* unable to cancel subscription - other? */
/* existing? - match Object ID and Process ID and address */ /* existing? - match Object ID and Process ID and address */
for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) { for (index = 0; index < Keylist_Count(COV_Subscriptions); index++) {
if (COV_Subscriptions[index].flag.valid) { subscription = Keylist_Data_Index(COV_Subscriptions, index);
dest = cov_address_get(COV_Subscriptions[index].dest_index); if (subscription) {
dest = cov_address_get(subscription->dest_index);
if (dest) { if (dest) {
address_match = bacnet_address_same(src, dest); address_match = bacnet_address_same(src, dest);
} else { } else {
/* skip address matching - we don't have an address */ /* skip address matching - we don't have an address */
address_match = true; address_match = true;
} }
if ((COV_Subscriptions[index].monitoredObjectIdentifier.type == if ((subscription->monitoredObjectIdentifier.type ==
cov_data->monitoredObjectIdentifier.type) && cov_data->monitoredObjectIdentifier.type) &&
(COV_Subscriptions[index].monitoredObjectIdentifier.instance == (subscription->monitoredObjectIdentifier.instance ==
cov_data->monitoredObjectIdentifier.instance) && cov_data->monitoredObjectIdentifier.instance) &&
(COV_Subscriptions[index].subscriberProcessIdentifier == (subscription->subscriberProcessIdentifier ==
cov_data->subscriberProcessIdentifier) && cov_data->subscriberProcessIdentifier) &&
address_match) { address_match) {
existing_entry = true; existing_entry = true;
if (subscription->invokeID) {
tsm_free_invoke_id(subscription->invokeID);
subscription->invokeID = 0;
}
if (cov_data->cancellationRequest) { if (cov_data->cancellationRequest) {
/* initialize with invalid COV address */ cov_subscription_delete(index);
COV_Subscriptions[index].flag.valid = false;
COV_Subscriptions[index].dest_index = MAX_COV_ADDRESSES;
cov_address_remove_unused(); cov_address_remove_unused();
} else { } else {
COV_Subscriptions[index].dest_index = cov_address_add(src); subscription->dest_index = cov_address_add(src);
COV_Subscriptions[index].flag.issueConfirmedNotifications = subscription->flag.issueConfirmedNotifications =
cov_data->issueConfirmedNotifications; cov_data->issueConfirmedNotifications;
COV_Subscriptions[index].lifetime = cov_data->lifetime; subscription->lifetime = cov_data->lifetime;
COV_Subscriptions[index].flag.send_requested = true; subscription->flag.send_requested = true;
}
if (COV_Subscriptions[index].invokeID) {
tsm_free_invoke_id(COV_Subscriptions[index].invokeID);
COV_Subscriptions[index].invokeID = 0;
} }
break; break;
} }
} else {
if (first_invalid_index < 0) {
first_invalid_index = index;
}
} }
} }
if (!existing_entry && (first_invalid_index >= 0) && if (!existing_entry &&
(Keylist_Count(COV_Subscriptions) < MAX_COV_SUBSCRIPTIONS) &&
(!cov_data->cancellationRequest)) { (!cov_data->cancellationRequest)) {
const int addr_add_ret = cov_address_add(src); const int addr_add_ret = cov_address_add(src);
@@ -461,24 +493,30 @@ static bool cov_list_subscribe(
*error_code = ERROR_CODE_NO_SPACE_TO_ADD_LIST_ELEMENT; *error_code = ERROR_CODE_NO_SPACE_TO_ADD_LIST_ELEMENT;
found = false; found = false;
} else { } else {
index = first_invalid_index;
found = true; found = true;
COV_Subscriptions[index].dest_index = addr_add_ret; index = Keylist_Next_Empty_Key(COV_Subscriptions, 0);
COV_Subscriptions[index].flag.valid = true; subscription = cov_subscription_create(index);
COV_Subscriptions[index].monitoredObjectIdentifier.type = if (subscription) {
cov_data->monitoredObjectIdentifier.type; subscription->dest_index = addr_add_ret;
COV_Subscriptions[index].monitoredObjectIdentifier.instance = subscription->monitoredObjectIdentifier.type =
cov_data->monitoredObjectIdentifier.instance; cov_data->monitoredObjectIdentifier.type;
COV_Subscriptions[index].subscriberProcessIdentifier = subscription->monitoredObjectIdentifier.instance =
cov_data->subscriberProcessIdentifier; cov_data->monitoredObjectIdentifier.instance;
COV_Subscriptions[index].flag.issueConfirmedNotifications = subscription->subscriberProcessIdentifier =
cov_data->issueConfirmedNotifications; cov_data->subscriberProcessIdentifier;
COV_Subscriptions[index].invokeID = 0; subscription->flag.issueConfirmedNotifications =
COV_Subscriptions[index].lifetime = cov_data->lifetime; cov_data->issueConfirmedNotifications;
COV_Subscriptions[index].flag.send_requested = true; subscription->invokeID = 0;
subscription->lifetime = cov_data->lifetime;
subscription->flag.send_requested = true;
} else {
*error_class = ERROR_CLASS_RESOURCES;
*error_code = ERROR_CODE_NO_SPACE_TO_ADD_LIST_ELEMENT;
found = false;
}
} }
} else if (!existing_entry) { } else if (!existing_entry) {
if (first_invalid_index < 0) { if (Keylist_Count(COV_Subscriptions) >= MAX_COV_SUBSCRIPTIONS) {
/* Out of resources */ /* Out of resources */
*error_class = ERROR_CLASS_RESOURCES; *error_class = ERROR_CLASS_RESOURCES;
*error_code = ERROR_CODE_NO_SPACE_TO_ADD_LIST_ELEMENT; *error_code = ERROR_CODE_NO_SPACE_TO_ADD_LIST_ELEMENT;
@@ -581,38 +619,38 @@ COV_FAILED:
static void cov_lifetime_expiration_handler( static void cov_lifetime_expiration_handler(
unsigned index, uint32_t elapsed_seconds, uint32_t lifetime_seconds) unsigned index, uint32_t elapsed_seconds, uint32_t lifetime_seconds)
{ {
if (index < MAX_COV_SUBCRIPTIONS) { if (index < MAX_COV_SUBSCRIPTIONS) {
BACNET_COV_SUBSCRIPTION *subscription =
Keylist_Data_Index(COV_Subscriptions, index);
/* handle lifetime expiration */ /* handle lifetime expiration */
if (lifetime_seconds >= elapsed_seconds) { if (lifetime_seconds >= elapsed_seconds) {
COV_Subscriptions[index].lifetime -= elapsed_seconds; subscription->lifetime -= elapsed_seconds;
#if 0 #if 0
fprintf(stderr, "COVtimer: subscription[%d].lifetime=%lu\n", index, fprintf(stderr, "COVtimer: subscription[%d].lifetime=%lu\n", index,
(unsigned long) COV_Subscriptions[index].lifetime); (unsigned long) subscription->lifetime);
#endif #endif
} else { } else {
COV_Subscriptions[index].lifetime = 0; subscription->lifetime = 0;
} }
if (COV_Subscriptions[index].lifetime == 0) { if (subscription->lifetime == 0) {
/* expire the subscription */ /* expire the subscription */
#if PRINT_ENABLED #if PRINT_ENABLED
debug_fprintf( debug_fprintf(
stderr, "COVtimer: PID=%u %s %u time remaining=%u seconds\n", stderr, "COVtimer: PID=%u %s %u time remaining=%u seconds\n",
COV_Subscriptions[index].subscriberProcessIdentifier, subscription->subscriberProcessIdentifier,
bactext_object_type_name( bactext_object_type_name(
COV_Subscriptions[index].monitoredObjectIdentifier.type), subscription->monitoredObjectIdentifier.type),
COV_Subscriptions[index].monitoredObjectIdentifier.instance, subscription->monitoredObjectIdentifier.instance,
COV_Subscriptions[index].lifetime); subscription->lifetime);
#endif #endif
/* initialize with invalid COV address */ if (subscription->flag.issueConfirmedNotifications) {
COV_Subscriptions[index].flag.valid = false; if (subscription->invokeID) {
COV_Subscriptions[index].dest_index = MAX_COV_ADDRESSES; tsm_free_invoke_id(subscription->invokeID);
cov_address_remove_unused(); subscription->invokeID = 0;
if (COV_Subscriptions[index].flag.issueConfirmedNotifications) {
if (COV_Subscriptions[index].invokeID) {
tsm_free_invoke_id(COV_Subscriptions[index].invokeID);
COV_Subscriptions[index].invokeID = 0;
} }
} }
cov_subscription_delete(index);
cov_address_remove_unused();
} }
} }
} }
@@ -640,18 +678,24 @@ static void cov_lifetime_expiration_handler(
*/ */
void handler_cov_timer_seconds(uint32_t elapsed_seconds) void handler_cov_timer_seconds(uint32_t elapsed_seconds)
{ {
unsigned index = 0; int index = 0;
uint32_t lifetime_seconds = 0; uint32_t lifetime_seconds = 0;
BACNET_COV_SUBSCRIPTION *subscription = NULL;
int list_cnt = 0;
#ifdef BAC_ROUTING #ifdef BAC_ROUTING
uint16_t current_dev_id = Routed_Device_Object_Index(); uint16_t current_dev_id = Routed_Device_Object_Index();
uint16_t dev_id = 0; uint16_t dev_id = 0;
if (elapsed_seconds) { if (elapsed_seconds) {
/* handle the subscription timeouts */ /* handle the subscription timeouts */
for (dev_id = 0; dev_id < Get_Num_Managed_Devices(); dev_id++) { for (dev_id = 0; dev_id < Get_Num_Managed_Devices(); dev_id++) {
Set_Routed_Device_Object_Index(dev_id); Set_Routed_Device_Object_Index(dev_id);
for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) { list_cnt = Keylist_Count(COV_Subscriptions);
if (COV_Subscriptions[index].flag.valid) { /* Iterate in reverse order due to subscription deletion */
lifetime_seconds = COV_Subscriptions[index].lifetime; for (index = list_cnt - 1; index >= 0; index--) {
subscription = Keylist_Data_Index(COV_Subscriptions, index);
if (subscription) {
lifetime_seconds = subscription->lifetime;
if (lifetime_seconds) { if (lifetime_seconds) {
/* only expire COV with definite lifetimes */ /* only expire COV with definite lifetimes */
cov_lifetime_expiration_handler( cov_lifetime_expiration_handler(
@@ -665,9 +709,12 @@ void handler_cov_timer_seconds(uint32_t elapsed_seconds)
#else #else
if (elapsed_seconds) { if (elapsed_seconds) {
/* handle the subscription timeouts */ /* handle the subscription timeouts */
for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) { list_cnt = Keylist_Count(COV_Subscriptions);
if (COV_Subscriptions[index].flag.valid) { /* Iterate in reverse order due to subscription deletion */
lifetime_seconds = COV_Subscriptions[index].lifetime; for (index = list_cnt - 1; index >= 0; index--) {
subscription = Keylist_Data_Index(COV_Subscriptions, index);
if (subscription) {
lifetime_seconds = subscription->lifetime;
if (lifetime_seconds) { if (lifetime_seconds) {
/* only expire COV with definite lifetimes */ /* only expire COV with definite lifetimes */
cov_lifetime_expiration_handler( cov_lifetime_expiration_handler(
@@ -708,81 +755,81 @@ bool handler_cov_fsm(void)
int index = indices[dev_id]; int index = indices[dev_id];
cov_fsm_state_t cov_task_state = cov_task_states[dev_id]; cov_fsm_state_t cov_task_state = cov_task_states[dev_id];
BACNET_COV_SUBSCRIPTION *subscription =
Keylist_Data_Index(COV_Subscriptions, index);
int list_cnt = Keylist_Count(COV_Subscriptions);
switch (cov_task_state) { switch (cov_task_state) {
case COV_STATE_IDLE: case COV_STATE_IDLE:
if (COV_Subscriptions[index].flag.valid) { if (subscription) {
cov_task_state = COV_STATE_MARK; cov_task_state = COV_STATE_MARK;
} else { } else {
index++; index++;
if (index >= MAX_COV_SUBCRIPTIONS) { if (index >= list_cnt) {
index = 0; index = 0;
} }
} }
break; break;
case COV_STATE_MARK: case COV_STATE_MARK:
/* mark any subscriptions where the value has changed */ /* mark any subscriptions where the value has changed */
if (COV_Subscriptions[index].flag.valid) { if (subscription) {
object_type = (BACNET_OBJECT_TYPE)COV_Subscriptions[index] object_type = (BACNET_OBJECT_TYPE)
.monitoredObjectIdentifier.type; subscription->monitoredObjectIdentifier.type;
object_instance = object_instance =
COV_Subscriptions[index].monitoredObjectIdentifier.instance; subscription->monitoredObjectIdentifier.instance;
status = Device_COV(object_type, object_instance); status = Device_COV(object_type, object_instance);
if (status) { if (status) {
COV_Subscriptions[index].flag.send_requested = true; subscription->flag.send_requested = true;
#if PRINT_ENABLED #if PRINT_ENABLED
debug_fprintf(stderr, "COVtask: Marking...\n"); debug_fprintf(stderr, "COVtask: Marking...\n");
#endif #endif
} }
} }
index++; index++;
if (index >= MAX_COV_SUBCRIPTIONS) { if (index >= list_cnt) {
index = 0; index = 0;
cov_task_state = COV_STATE_CLEAR; cov_task_state = COV_STATE_CLEAR;
} }
break; break;
case COV_STATE_CLEAR: case COV_STATE_CLEAR:
/* clear the COV flag after checking all subscriptions */ /* clear the COV flag after checking all subscriptions */
if ((COV_Subscriptions[index].flag.valid) && if (subscription && (subscription->flag.send_requested)) {
(COV_Subscriptions[index].flag.send_requested)) { object_type = (BACNET_OBJECT_TYPE)
object_type = (BACNET_OBJECT_TYPE)COV_Subscriptions[index] subscription->monitoredObjectIdentifier.type;
.monitoredObjectIdentifier.type;
object_instance = object_instance =
COV_Subscriptions[index].monitoredObjectIdentifier.instance; subscription->monitoredObjectIdentifier.instance;
Device_COV_Clear(object_type, object_instance); Device_COV_Clear(object_type, object_instance);
} }
index++; index++;
if (index >= MAX_COV_SUBCRIPTIONS) { if (index >= list_cnt) {
index = 0; index = 0;
cov_task_state = COV_STATE_FREE; cov_task_state = COV_STATE_FREE;
} }
break; break;
case COV_STATE_FREE: case COV_STATE_FREE:
/* confirmed notification house keeping */ /* confirmed notification house keeping */
if ((COV_Subscriptions[index].flag.valid) && if (subscription &&
(COV_Subscriptions[index].flag.issueConfirmedNotifications) && (subscription->flag.issueConfirmedNotifications) &&
(COV_Subscriptions[index].invokeID)) { (subscription->invokeID)) {
if (tsm_invoke_id_free(COV_Subscriptions[index].invokeID)) { if (tsm_invoke_id_free(subscription->invokeID)) {
COV_Subscriptions[index].invokeID = 0; subscription->invokeID = 0;
} else if (tsm_invoke_id_failed( } else if (tsm_invoke_id_failed(subscription->invokeID)) {
COV_Subscriptions[index].invokeID)) { tsm_free_invoke_id(subscription->invokeID);
tsm_free_invoke_id(COV_Subscriptions[index].invokeID); subscription->invokeID = 0;
COV_Subscriptions[index].invokeID = 0;
} }
} }
index++; index++;
if (index >= MAX_COV_SUBCRIPTIONS) { if (index >= list_cnt) {
index = 0; index = 0;
cov_task_state = COV_STATE_SEND; cov_task_state = COV_STATE_SEND;
} }
break; break;
case COV_STATE_SEND: case COV_STATE_SEND:
/* send any COVs that are requested */ /* send any COVs that are requested */
if ((COV_Subscriptions[index].flag.valid) && if (subscription && (subscription->flag.send_requested)) {
(COV_Subscriptions[index].flag.send_requested)) {
send = true; send = true;
if (COV_Subscriptions[index].flag.issueConfirmedNotifications) { if (subscription->flag.issueConfirmedNotifications) {
if (COV_Subscriptions[index].invokeID != 0) { if (subscription->invokeID != 0) {
/* already sending */ /* already sending */
send = false; send = false;
} }
@@ -792,10 +839,11 @@ bool handler_cov_fsm(void)
} }
} }
if (send) { if (send) {
object_type = (BACNET_OBJECT_TYPE)COV_Subscriptions[index] object_type =
.monitoredObjectIdentifier.type; (BACNET_OBJECT_TYPE)
object_instance = COV_Subscriptions[index] subscription->monitoredObjectIdentifier.type;
.monitoredObjectIdentifier.instance; object_instance =
subscription->monitoredObjectIdentifier.instance;
#if PRINT_ENABLED #if PRINT_ENABLED
debug_fprintf(stderr, "COVtask: Sending...\n"); debug_fprintf(stderr, "COVtask: Sending...\n");
#endif #endif
@@ -805,16 +853,15 @@ bool handler_cov_fsm(void)
status = Device_Encode_Value_List( status = Device_Encode_Value_List(
object_type, object_instance, &value_list[0]); object_type, object_instance, &value_list[0]);
if (status) { if (status) {
status = cov_send_request( status = cov_send_request(subscription, &value_list[0]);
&COV_Subscriptions[index], &value_list[0]);
} }
if (status) { if (status) {
COV_Subscriptions[index].flag.send_requested = false; subscription->flag.send_requested = false;
} }
} }
} }
index++; index++;
if (index >= MAX_COV_SUBCRIPTIONS) { if (index >= list_cnt) {
index = 0; index = 0;
cov_task_state = COV_STATE_IDLE; cov_task_state = COV_STATE_IDLE;
} }
+11 -9
View File
@@ -69,7 +69,7 @@ static bool CheckArraySize(OS_Keylist list)
/* See if we got the memory we wanted */ /* See if we got the memory we wanted */
if (!new_array) { if (!new_array) {
return true; return false;
} }
/* copy the nodes from the old array to the new array */ /* copy the nodes from the old array to the new array */
@@ -171,6 +171,11 @@ int Keylist_Data_Add(OS_Keylist list, KEY key, void *data)
int i; /* counts through the array */ int i; /* counts through the array */
if (list && CheckArraySize(list)) { if (list && CheckArraySize(list)) {
node = NodeCreate();
if (!node) {
return -1;
}
/* figure out where to put the new node */ /* figure out where to put the new node */
if (list->count) { if (list->count) {
(void)FindIndex(list, key, &index); (void)FindIndex(list, key, &index);
@@ -190,14 +195,11 @@ int Keylist_Data_Add(OS_Keylist list, KEY key, void *data)
index = 0; index = 0;
} }
/* create and add the node */ /* add the node */
node = NodeCreate(); list->count++;
if (node) { node->key = key;
list->count++; node->data = data;
node->key = key; list->array[index] = node;
node->data = data;
list->array[index] = node;
}
} }
return index; return index;
} }