1023 lines
37 KiB
C++
Executable File
1023 lines
37 KiB
C++
Executable File
#include <cdevMonitorTable.h>
|
|
|
|
// *****************************************************************************
|
|
// * cdevMonitorNode::cdevMonitorEntry Static Variables.
|
|
// *****************************************************************************
|
|
int cdevMonitorNode::cdevMonitorEntry::VALUE_TAG = 0;
|
|
int cdevMonitorNode::cdevMonitorEntry::STATUS_TAG = 0;
|
|
int cdevMonitorNode::cdevMonitorEntry::TIME_TAG = 0;
|
|
int cdevMonitorNode::cdevMonitorEntry::DEVICE_TAG = 0;
|
|
|
|
|
|
// *****************************************************************************
|
|
// * cdevMonitorData::cdevMonitorData:
|
|
// * This is the default constructor.
|
|
// *****************************************************************************
|
|
cdevMonitorData::cdevMonitorData ( void ) :
|
|
criticalTags(NULL), criticalTagCnt(0), cdevData()
|
|
{
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// * cdevMonitorData::cdevMonitorData:
|
|
// * This builds a cdevMonitorData from a cdevData.
|
|
// *****************************************************************************
|
|
cdevMonitorData::cdevMonitorData ( const cdevData & data ) :
|
|
criticalTags(NULL), criticalTagCnt(0), cdevData(data)
|
|
{
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// * cdevMonitorData::cdevMonitorData:
|
|
// * This builds a cdevMonitorData from a cdevMonitorData.
|
|
// *****************************************************************************
|
|
cdevMonitorData::cdevMonitorData ( const cdevMonitorData & data ) :
|
|
criticalTags(data.criticalTags),
|
|
criticalTagCnt(data.criticalTagCnt),
|
|
cdevData(*(const cdevData *)&data)
|
|
{
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// * isTagCritical :
|
|
// * This method will walk through the list of tags and attempt to find
|
|
// * the caller specified tag. This method returns 1 if it is present, or
|
|
// * 0 if it is not.
|
|
// *****************************************************************************
|
|
int cdevMonitorData::isTagCritical ( int tag )
|
|
{
|
|
for(int i=0; i<criticalTagCnt && tag!=criticalTags[i]; i++);
|
|
return i<criticalTagCnt?1:0;
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// * setCriticalTags :
|
|
// * This method is used to specify the tags in the cdevData object that
|
|
// * are critical.
|
|
// *****************************************************************************
|
|
void cdevMonitorData::setCriticalTags ( int * tags, int tagCnt )
|
|
{
|
|
criticalTags = tags;
|
|
criticalTagCnt = tagCnt;
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// * changeTag :
|
|
// * This method is called when the tags in the cdevData object are remapped
|
|
// * to the client tags. When the tag is remapped in this method, the
|
|
// * critical tag value (if it exists) will also be remapped.
|
|
// *****************************************************************************
|
|
int cdevMonitorData::changeTag ( int oldTag, int newTag )
|
|
{
|
|
for(int i=0; i<criticalTagCnt && criticalTags[i]!=oldTag; i++);
|
|
if(criticalTags[i]==oldTag) criticalTags[i] = newTag;
|
|
return cdevData::changeTag(oldTag, newTag);
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// * xdrSize:
|
|
// * Calculates the size of the XDR Buffer necessary to store the cdevData
|
|
// * object. This function may be used to determine the size of a
|
|
// * preallocated buffer for storing the xdr representation of a cdevData
|
|
// * object. The bufLen parameter will receive the size of the buffer, and
|
|
// * the elementCount variable will receive the number of elements that will
|
|
// * be stored in the buffer.
|
|
// *****************************************************************************
|
|
int cdevMonitorData::xdrSize (size_t * bufLen, size_t * elementCount)
|
|
{
|
|
cdevDataEntry * ptr = entries;
|
|
int xdrDataSize = 0;
|
|
int cdevElementCnt = 0;
|
|
int i;
|
|
|
|
// ************************************#
|
|
// * CALCULATE THE SIZE OF THE BUFFER #
|
|
// ************************************#
|
|
// *************************************
|
|
// * Add the size of the tag count int *
|
|
// *************************************
|
|
xdrDataSize += XDR_Sizeof(cdevElementCnt);
|
|
|
|
// *************************************
|
|
// * Add the size of each valid item *
|
|
// *************************************
|
|
for(ptr=entries; ptr!=NULL; ptr = ptr->next_)
|
|
{
|
|
// *****************************
|
|
// * Do not process entries *
|
|
// * with CDEV_INVALID as the *
|
|
// * dataType or 0 as the tag. *
|
|
// *****************************
|
|
if(ptr->dataType_==CDEV_INVALID ||
|
|
ptr->tag_==0 ||
|
|
!isTagCritical(ptr->tag_)) continue;
|
|
|
|
// *****************************
|
|
// * Calculate the number of *
|
|
// * elements in this tagged *
|
|
// * data item. *
|
|
// *****************************
|
|
int numElements = ptr->dim_!=0?ptr->elems_:1;
|
|
|
|
// *****************************
|
|
// * Increment the counter *
|
|
// *****************************
|
|
cdevElementCnt++;
|
|
|
|
// *****************************
|
|
// * Add the size of the *
|
|
// * cdevDataEntries tag_, *
|
|
// * dataType_, dim_, elems_. *
|
|
// *****************************
|
|
xdrDataSize += 4 * XDR_Sizeof((int)1);
|
|
|
|
// *****************************
|
|
// * Add the size of the *
|
|
// * cdevBounds data. *
|
|
// *****************************
|
|
xdrDataSize += ptr->dim_ * (XDR_Sizeof((int)1) * 2);
|
|
|
|
// *****************************
|
|
// * Add the size of the data *
|
|
// *****************************
|
|
if (ptr->dataType_==CDEV_BYTE) xdrDataSize += numElements * XDR_Sizeof((unsigned char)'c');
|
|
else if(ptr->dataType_==CDEV_INT16) xdrDataSize += numElements * XDR_Sizeof((short)1);
|
|
else if(ptr->dataType_==CDEV_UINT16) xdrDataSize += numElements * XDR_Sizeof((unsigned short)1);
|
|
else if(ptr->dataType_==CDEV_INT32) xdrDataSize += numElements * XDR_Sizeof((long)1);
|
|
else if(ptr->dataType_==CDEV_UINT32) xdrDataSize += numElements * XDR_Sizeof((unsigned long)1);
|
|
else if(ptr->dataType_==CDEV_FLOAT) xdrDataSize += numElements * XDR_Sizeof((float)1);
|
|
else if(ptr->dataType_==CDEV_DOUBLE) xdrDataSize += numElements * XDR_Sizeof((double)1);
|
|
else if(ptr->dataType_==CDEV_STRING)
|
|
{
|
|
if(numElements==1) xdrDataSize += XDR_Sizeof(ptr->data_.str);
|
|
else for(i=0; i<numElements; i++) xdrDataSize += XDR_Sizeof(ptr->data_.strarr[i]);
|
|
}
|
|
else if(ptr->dataType_==CDEV_TIMESTAMP) xdrDataSize += numElements * XDR_Sizeof(ptr->data_.ts);
|
|
}
|
|
|
|
*elementCount = cdevElementCnt;
|
|
*bufLen = xdrDataSize;
|
|
|
|
return *bufLen>0?CDEV_SUCCESS:CDEV_ERROR;
|
|
}
|
|
|
|
|
|
// *****************************************************************************
|
|
// * xdrExport:
|
|
// * This function encapsulates the contents of the cdevData class into a
|
|
// * binary stream. This function allocates the buffer and returns the new
|
|
// * buffer and the buffer size.
|
|
// *****************************************************************************
|
|
int cdevMonitorData::xdrExport ( char ** buf, size_t * bufLen )
|
|
{
|
|
size_t count = 0;
|
|
|
|
// ************************************#
|
|
// * Calculate the size of the buffer #
|
|
// ************************************#
|
|
xdrSize(bufLen, &count);
|
|
|
|
// ************************************#
|
|
// * Allocate the buffer and call the #
|
|
// * export function. #
|
|
// ************************************#
|
|
if((*buf = new char[*bufLen])!=NULL) xdrExport(*buf, *bufLen, count);
|
|
|
|
return buf==NULL?CDEV_ERROR:CDEV_SUCCESS;
|
|
}
|
|
|
|
|
|
// *****************************************************************************
|
|
// * xdrExport:
|
|
// * This function encapsulates the contents of the cdevData class into a
|
|
// * preallocated binary stream. The buf parameter contains the address of
|
|
// * the caller allocated buffer, the bufLen parameter specifies the size
|
|
// * of the buffer, and the count parameter specifies the number of tagged
|
|
// * data items that will be copied from the cdevData object into the
|
|
// * binary stream.
|
|
// *****************************************************************************
|
|
int cdevMonitorData::xdrExport ( char * buf, size_t bufLen, size_t count )
|
|
{
|
|
cdevDataEntry * ptr;
|
|
XDR_Writer writer;
|
|
int xdrDataSize = bufLen;
|
|
int cdevElementCnt = count;
|
|
int i;
|
|
|
|
// ************************************#
|
|
// * Allocate the buffer #
|
|
// ************************************#
|
|
writer.attachData(buf, bufLen);
|
|
|
|
// ************************************#
|
|
// * Transfer the data to the buffer #
|
|
// ************************************#
|
|
// *************************************
|
|
// * Write the number of elements *
|
|
// *************************************
|
|
writer.put(cdevElementCnt);
|
|
|
|
// *************************************
|
|
// * Write each valid item. *
|
|
// *************************************
|
|
for(ptr = entries; ptr != NULL; ptr = ptr->next_)
|
|
{
|
|
// *****************************
|
|
// * Do not process entries *
|
|
// * with CDEV_INVALID as the *
|
|
// * dataType or 0 as the tag. *
|
|
// *****************************
|
|
if(ptr->dataType_==CDEV_INVALID ||
|
|
ptr->tag_==0 ||
|
|
!isTagCritical(ptr->tag_)) continue;
|
|
|
|
// *****************************
|
|
// * Calculate the number of *
|
|
// * elements in this tagged *
|
|
// * data item. *
|
|
// *****************************
|
|
int numElements = ptr->dim_!=0?ptr->elems_:1;
|
|
|
|
// *****************************
|
|
// * Decrement the counter *
|
|
// *****************************
|
|
cdevElementCnt--;
|
|
|
|
// *****************************
|
|
// * Write the tag_, dataType_ *
|
|
// * dim_, and elems_ of the *
|
|
// * cdevDataEntry object. *
|
|
// *****************************
|
|
writer.put((int)ptr->tag_);
|
|
writer.put((int)ptr->dataType_);
|
|
writer.put((int)ptr->dim_);
|
|
writer.put((int)ptr->elems_);
|
|
|
|
// *****************************
|
|
// * Write the cdevBounds *
|
|
// * values asssociated with *
|
|
// * the cdevDataEntry (if any)*
|
|
// *****************************
|
|
cdevBounds * bounds = ptr->bounds();
|
|
for(i=0; i<ptr->dim_; i++)
|
|
{
|
|
writer.put((int)bounds[i].offset);
|
|
writer.put((int)bounds[i].length);
|
|
}
|
|
|
|
// *****************************
|
|
// * Write the data *
|
|
// *****************************
|
|
if(ptr->dataType_==CDEV_BYTE)
|
|
{
|
|
if(numElements==1) writer.put(ptr->data_.cval);
|
|
else for(i=0; i<numElements; i++) writer.put(ptr->data_.cptr[i]);
|
|
}
|
|
else if(ptr->dataType_==CDEV_INT16)
|
|
{
|
|
if(numElements==1) writer.put(ptr->data_.sval);
|
|
else for(i=0; i<numElements; i++) writer.put(ptr->data_.sptr[i]);
|
|
}
|
|
else if(ptr->dataType_==CDEV_UINT16)
|
|
{
|
|
if(numElements==1) writer.put(ptr->data_.usval);
|
|
else for(i=0; i<numElements; i++) writer.put(ptr->data_.usptr[i]);
|
|
}
|
|
else if(ptr->dataType_==CDEV_INT32)
|
|
{
|
|
if(numElements==1) writer.put(ptr->data_.lval);
|
|
else for(i=0; i<numElements; i++) writer.put(ptr->data_.lptr[i]);
|
|
}
|
|
else if(ptr->dataType_==CDEV_UINT32)
|
|
{
|
|
if(numElements==1) writer.put(ptr->data_.ulval);
|
|
else for(i=0; i<numElements; i++) writer.put(ptr->data_.ulptr[i]);
|
|
}
|
|
else if(ptr->dataType_==CDEV_FLOAT)
|
|
{
|
|
if(numElements==1) writer.put(ptr->data_.fval);
|
|
else for(i=0; i<numElements; i++) writer.put(ptr->data_.fptr[i]);
|
|
}
|
|
else if(ptr->dataType_==CDEV_DOUBLE)
|
|
{
|
|
if(numElements==1) writer.put(ptr->data_.dval);
|
|
else for(i=0; i<numElements; i++) writer.put(ptr->data_.dptr[i]);
|
|
}
|
|
else if(ptr->dataType_==CDEV_STRING)
|
|
{
|
|
if(numElements==1) writer.put(ptr->data_.str);
|
|
else for(i=0; i<numElements; i++) writer.put(ptr->data_.strarr[i]);
|
|
}
|
|
else if(ptr->dataType_==CDEV_TIMESTAMP)
|
|
{
|
|
if(numElements==1) writer.put(ptr->data_.ts);
|
|
}
|
|
}
|
|
|
|
// *************************************
|
|
// * Detach the data from the writer *
|
|
// * object before the object is *
|
|
// * destroyed. *
|
|
// *************************************
|
|
writer.detachData();
|
|
|
|
return CDEV_SUCCESS;
|
|
}
|
|
|
|
|
|
// *****************************************************************************
|
|
// * cdevMonitorNode::cdevMonitorEntry::cdevMonitorEntry :
|
|
// * This is the constructor for the cdevMonitorEntry class that is internal to the
|
|
// * cdevMonitorNode class.
|
|
// *
|
|
// * This constructor will initialize all data items and will then populate
|
|
// * the list of triggers with all properties from the context that are
|
|
// * marked with 2 or 3. It will then populate the properties list with
|
|
// * all properties from the context that have any value other than 0.
|
|
// *
|
|
// * If not properties are in the context, then the following settings will
|
|
// * be used by default...
|
|
// * value = 3
|
|
// * status = 1
|
|
// * time = 1
|
|
// *
|
|
// * The cdevMessage object becomes the property of the cdevMonitorNode
|
|
// * object and should not be accessed again by the caller.
|
|
// *
|
|
// * The deviceIdx indicates the specific device that is being monitored
|
|
// * within a multi-device list.
|
|
// *****************************************************************************
|
|
cdevMonitorNode::cdevMonitorEntry::cdevMonitorEntry( cdevMessage * Message, int DeviceIdx=0 )
|
|
: next(NULL), message(Message), triggers(NULL), trigType(NULL),
|
|
trigCnt(0), properties(NULL), propCnt(0), deviceIdx(DeviceIdx)
|
|
{
|
|
// *********************************************************************
|
|
// * Populate the static variables if they have not already been set.
|
|
// *********************************************************************
|
|
if(VALUE_TAG==0)
|
|
{
|
|
cdevData::tagC2I("value", &VALUE_TAG);
|
|
cdevData::tagC2I("status", &STATUS_TAG);
|
|
cdevData::tagC2I("time", &TIME_TAG);
|
|
|
|
// *************************************************************
|
|
// * Added to support multi-device monitors.
|
|
// *************************************************************
|
|
cdevData::tagC2I("device", &DEVICE_TAG);
|
|
}
|
|
|
|
if(message!=NULL)
|
|
{
|
|
int tag;
|
|
size_t tagElems;
|
|
int tagVal;
|
|
|
|
// *************************************************************
|
|
// * Start by removing the cdevData data if it has been
|
|
// * included. This component will not be necessary to process
|
|
// * the monitors.
|
|
// *************************************************************
|
|
message->setData(NULL);
|
|
|
|
// *************************************************************
|
|
// * If the context has been specified, then read the context
|
|
// * to determine the number of monitorable data items.
|
|
// *************************************************************
|
|
if(message->getContext()!=NULL)
|
|
{
|
|
cdevData * context = message->getContext();
|
|
cdevDataIterator iter(context);
|
|
iter.init();
|
|
|
|
while((tag=iter.tag())!=0)
|
|
{
|
|
tagElems = 0;
|
|
tagVal = 0;
|
|
context->getElems(tag, &tagElems);
|
|
if(tagElems==1)
|
|
{
|
|
context->get(tag, &tagVal);
|
|
if(tagVal>1) trigCnt++;
|
|
if(tagVal>0) propCnt++;
|
|
}
|
|
++iter;
|
|
}
|
|
// *****************************************************
|
|
// * If the number of monitorable data items is greater
|
|
// * than 0, then allocate a sufficient buffer and copy
|
|
// * the tag names and tag types into the buffer.
|
|
// *****************************************************
|
|
if(trigCnt>0)
|
|
{
|
|
// *********************************************
|
|
// * Added to support multi-device list.
|
|
// *********************************************
|
|
if(message->getDeviceCount()>1) propCnt++;
|
|
|
|
iter.init();
|
|
triggers = new int[trigCnt+trigCnt+propCnt];
|
|
trigType = &triggers[trigCnt];
|
|
properties = &triggers[trigCnt+trigCnt];
|
|
trigCnt = 0;
|
|
propCnt = 0;
|
|
while((tag=iter.tag())!=0)
|
|
{
|
|
tagElems = 0;
|
|
tagVal = 0;
|
|
context->getElems(tag, &tagElems);
|
|
if(tagElems==1)
|
|
{
|
|
context->get(tag, &tagVal);
|
|
if(tagVal>1)
|
|
{
|
|
triggers[trigCnt] = tag;
|
|
trigType[trigCnt++] = tagVal;
|
|
}
|
|
if(tagVal>0) properties[propCnt++] = tag;
|
|
}
|
|
++iter;
|
|
}
|
|
// *********************************************
|
|
// * Added to support multi-device list.
|
|
// *********************************************
|
|
if(message->getDeviceCount()>1)
|
|
properties[propCnt++] = DEVICE_TAG;
|
|
}
|
|
}
|
|
|
|
// *************************************************************
|
|
// * If not tags were specified or the context was blank... then
|
|
// * use the default setup.
|
|
// *************************************************************
|
|
if(trigCnt<=0)
|
|
{
|
|
trigCnt = 1;
|
|
propCnt = 3;
|
|
|
|
// *****************************************************
|
|
// * Added to support multi-device list.
|
|
// *****************************************************
|
|
if(message->getDeviceCount()>1) propCnt++;
|
|
|
|
triggers = new int[2+propCnt];
|
|
trigType = &triggers[1];
|
|
properties = &triggers[2];
|
|
triggers[0] = VALUE_TAG;
|
|
trigType[0] = 3;
|
|
properties[0] = VALUE_TAG;
|
|
properties[1] = STATUS_TAG;
|
|
properties[2] = TIME_TAG;
|
|
// *****************************************************
|
|
// * Added to support multi-device list.
|
|
// *****************************************************
|
|
if(message->getDeviceCount()>1) properties[3] = DEVICE_TAG;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// *****************************************************************************
|
|
// * cdevMonitorNode::cdevMonitorEntry::~cdevMonitorEntry :
|
|
// * This is the destructor for the node object that is internal to the
|
|
// * cdevMonitorNode class. It is responsible for deleteing the cdevMessage
|
|
// * object and freeing any memory that was allocated to the triggers
|
|
// * object.
|
|
// *
|
|
// * Note that this destructor will delete all of the nodes that are stored
|
|
// * below this one in the list.
|
|
// ******************************************************************************
|
|
cdevMonitorNode::cdevMonitorEntry::~cdevMonitorEntry ( void )
|
|
{
|
|
if(message) delete message;
|
|
if(triggers) delete triggers;
|
|
if(next!=NULL) delete next;
|
|
}
|
|
|
|
|
|
// *****************************************************************************
|
|
// * cdevMonitorNode::cdevMonitorNode :
|
|
// * This is the constructor for the cdevMonitorNode class. It will save a
|
|
// * copy of the Parent variable and will use the user specified Device and
|
|
// * Attrib to create the hashString.
|
|
// *****************************************************************************
|
|
cdevMonitorNode::cdevMonitorNode ( cdevMonitorTable * Parent,
|
|
char * Device,
|
|
char * Attrib )
|
|
: parent(Parent), hashString(NULL), nodes(NULL)
|
|
{
|
|
hashString = new char[strlen(Device)+strlen(Attrib)+2];
|
|
sprintf(hashString, "%s %s", Device, Attrib);
|
|
}
|
|
|
|
|
|
// *****************************************************************************
|
|
// * cdevMonitorNode::~cdevMonitorNode :
|
|
// * This is the destructor for the cdevMonitorNode object. It will delete
|
|
// * the hashString and each node from the list of monitors.
|
|
// *****************************************************************************
|
|
cdevMonitorNode::~cdevMonitorNode ( void )
|
|
{
|
|
if(hashString) delete hashString;
|
|
if(nodes)
|
|
{
|
|
// *************************************************************
|
|
// * Prior to deleteing itself, this class will first fire its
|
|
// * monitors once more using a 1 in the endOfTransaction
|
|
// * parameter in order to inform the client side that it will
|
|
// * receive no further transactions.
|
|
// *************************************************************
|
|
cdevMonitorEntry * node = nodes;
|
|
while(node)
|
|
{
|
|
fireMonitor(node, -1, &mData, 1);
|
|
node = node->next;
|
|
}
|
|
delete nodes;
|
|
}
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// * cdevMonitorNode::insertMonitor :
|
|
// * This method is used to add a new monitor for the device / attribute
|
|
// * pair associated with this object.
|
|
// *
|
|
// * The cdevData object that is provided in the cdevData object is the
|
|
// * collection of all current property values for the device / attribute
|
|
// * pair. This data will be used to automatically dispatch the first
|
|
// * callback when the monitor is initially installed.
|
|
// *
|
|
// * The deviceIdx indicates the specific device that is being monitored
|
|
// * within a multi-device list.
|
|
// *****************************************************************************
|
|
int cdevMonitorNode::insertMonitor ( cdevMessage * request,
|
|
cdevData * data,
|
|
int deviceIdx = 0 )
|
|
{
|
|
int result = 0;
|
|
cdevMonitorEntry * node = new cdevMonitorEntry(request, deviceIdx);
|
|
if(node->trigCnt > 0)
|
|
{
|
|
node->next = nodes;
|
|
nodes = node;
|
|
}
|
|
else {
|
|
delete node;
|
|
result = -1;
|
|
}
|
|
if(data!=NULL)
|
|
{
|
|
mData = *data;
|
|
fireMonitor(node, -1, &mData);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// * cdevMonitorNode::removeMonitor :
|
|
// * This method is used to remove a specific monitor by submitting a
|
|
// * cdevMessage that contains the transaction index to be canceled in the
|
|
// * cancelTransIndex element.
|
|
// *****************************************************************************
|
|
int cdevMonitorNode::removeMonitor ( cdevMessage * request )
|
|
{
|
|
return request==NULL?-1:removeMonitor(request->getCancelTransIndex());
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// * cdevMonitorNode::removeMonitor :
|
|
// * This method is used to remove a specific monitor by submitting a
|
|
// * the transaction index to be canceled.
|
|
// *****************************************************************************
|
|
int cdevMonitorNode::removeMonitor ( unsigned cancelTransIndex )
|
|
{
|
|
int result = -1;
|
|
cdevMonitorEntry * node = nodes, *prev = NULL;
|
|
|
|
while(node!=NULL &&
|
|
node->message->getTransIndex() != cancelTransIndex)
|
|
{
|
|
prev = node;
|
|
node = node->next;
|
|
}
|
|
if(node!=NULL)
|
|
{
|
|
if(prev==NULL) nodes = node->next;
|
|
else prev->next = node->next;
|
|
node->next = NULL;
|
|
|
|
// *************************************************************
|
|
// * This code portion added to inform client side that the
|
|
// * monitor is terminating. When a monitor returns an
|
|
// * operationCode of 0 - it indicates that there will be no
|
|
// * further data transmissions.
|
|
// *
|
|
// * The 1 provided in the endOfTransaction parameter indicates
|
|
// * that this transaction is finished.
|
|
// *************************************************************
|
|
fireMonitor(node, -1, &mData, 1);
|
|
|
|
delete node;
|
|
result = 0;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
// *****************************************************************************
|
|
// * cdevMonitorNode::removeClientMonitors :
|
|
// * This method is used to remove all nodes that are associated with a
|
|
// * specified clientID.
|
|
// *****************************************************************************
|
|
int cdevMonitorNode::removeClientMonitors ( short clientID, int fire )
|
|
{
|
|
cdevMonitorEntry * node = nodes, *prev = NULL;
|
|
while(node!=NULL)
|
|
{
|
|
if(node->message->getClientID() == clientID)
|
|
{
|
|
cdevMonitorEntry * nextcdevMonitorEntry = node->next;
|
|
node->next = NULL;
|
|
|
|
// *****************************************************
|
|
// * This code portion added to inform client side that
|
|
// * the monitor is terminating. When a monitor returns
|
|
// * an operationCode of 0 - it indicates that there
|
|
// * will be no further data transmissions.
|
|
// *
|
|
// * The 1 provided in the endOfTransaction parameter
|
|
// * indicates that this transaction is finished.
|
|
// *****************************************************
|
|
if(fire) fireMonitor(node, -1, &mData, 1);
|
|
|
|
delete node;
|
|
|
|
if(prev==NULL) nodes = nextcdevMonitorEntry;
|
|
else prev->next = nextcdevMonitorEntry;
|
|
node = nextcdevMonitorEntry;
|
|
}
|
|
else {
|
|
prev = node;
|
|
node = node->next;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// * cdevMonitorNode::fireMonitor :
|
|
// * This method is used to submit a change to a monitored property. If the
|
|
// * value of property is NULL, then all of the trigger properties will be
|
|
// * fired.
|
|
// *
|
|
// * Note that the data parameter should be populated with all of the
|
|
// * properties that are associated with the particular device / attribute
|
|
// * pair.
|
|
// *****************************************************************************
|
|
int cdevMonitorNode::fireMonitor( char * property, cdevData * data )
|
|
{
|
|
int tag = -1;
|
|
if(property!=NULL) cdevData::tagC2I(property, &tag);
|
|
return fireMonitor(tag, data);
|
|
}
|
|
|
|
|
|
// *****************************************************************************
|
|
// * cdevMonitorNode::fireMonitor :
|
|
// * This method is used to submit a change to a monitored property. If the
|
|
// * value of property is -1, then it will fire all monitors that are listed
|
|
// * in the triggers parameter.
|
|
// *
|
|
// * Note that the data parameter should be populated with all of the
|
|
// * properties that are associated with the particular device / attribute
|
|
// * pair.
|
|
// *
|
|
// * This method will return 0 if any monitors were actually dispatched,
|
|
// * otherwise it will return -1.
|
|
// *****************************************************************************
|
|
int cdevMonitorNode::fireMonitor( int property, cdevData * data )
|
|
{
|
|
int result = -1;
|
|
cdevMonitorEntry * node = nodes;
|
|
|
|
// *********************************************************************
|
|
// * Attach the data that is contained in the cdevData object to the
|
|
// * cdevMonitorData object.
|
|
// *********************************************************************
|
|
if(data!=NULL)
|
|
{
|
|
// *************************************************************
|
|
// * Note here I am copying the contents of the user provided
|
|
// * data to the mData structure that is local to the
|
|
// * cdevMonitorNode.
|
|
// *************************************************************
|
|
mData = *data;
|
|
while(node!=NULL)
|
|
{
|
|
if(fireMonitor(node, property, &mData)==0) result = 0;
|
|
node = node->next;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// * cdevMonitorNode::fireMonitor :
|
|
// * This method is used to submit a change to a monitored property. If the
|
|
// * value of property is -1, then it will fire all monitors that are listed
|
|
// * in the triggers parameter.
|
|
// *
|
|
// * The endOfTransaction flag indicates that this is the last monitor that
|
|
// * will be returned in association with this cdevMonitorNode and,
|
|
// * therefore, the cdevMessage's operationCode should be set to indicate
|
|
// * that.
|
|
// *
|
|
// * Note that the data parameter should be populated with all of the
|
|
// * properties that are associated with the particular device / attribute
|
|
// * pair.
|
|
// *
|
|
// * This method will return 0 if any monitors were actually dispatched,
|
|
// * otherwise it will return -1.
|
|
// *****************************************************************************
|
|
int cdevMonitorNode::fireMonitor( cdevMonitorEntry * entry,
|
|
int property,
|
|
cdevMonitorData *data,
|
|
int endOfTransaction )
|
|
{
|
|
int result = -1;
|
|
|
|
if(entry!=NULL && data!=NULL)
|
|
{
|
|
int found = 0;
|
|
|
|
// *************************************************************
|
|
// * An operationCode value with bit one set indicates that this
|
|
// * is NOT the end of the transaction, an operationCode value
|
|
// * with bit one unset indicates that this IS the end of the
|
|
// * transaction.
|
|
// *************************************************************
|
|
entry->message->setOperationCode(endOfTransaction?0:1);
|
|
|
|
for(int i=0; !found && i<entry->trigCnt; i++)
|
|
{
|
|
if(property<0 || entry->triggers[i]==property)
|
|
{
|
|
if(property>0) found = 1;
|
|
// *********************************************
|
|
// * Trigger type 3 means that the callback
|
|
// * wants the changed value and all other
|
|
// * values that were specified in the
|
|
// * context.
|
|
// *********************************************
|
|
if(entry->trigType[i]==3)
|
|
data->setCriticalTags(entry->properties,
|
|
entry->propCnt);
|
|
|
|
// *********************************************
|
|
// * Trigger type 2 means that the callback
|
|
// * wants only the changed value.
|
|
// *********************************************
|
|
if(entry->trigType[i]==2)
|
|
data->setCriticalTags(&entry->triggers[i], 1);
|
|
|
|
// *********************************************
|
|
// * Determine if the changed data item exists
|
|
// * in the user provided data. If it does,
|
|
// * then execute the fireCallback method on
|
|
// * the cdevMonitorTable to dispatch the
|
|
// * monitor.
|
|
// *********************************************
|
|
if(data->getType(entry->triggers[i])!=CDEV_INVALID)
|
|
{
|
|
// *************************************
|
|
// * Added to support multi-device
|
|
// *************************************
|
|
if(entry->message->getDeviceCount()>1)
|
|
data->insert(cdevMonitorEntry::DEVICE_TAG,
|
|
entry->message->getDeviceList()
|
|
[entry->deviceIdx]);
|
|
|
|
entry->message->setData(data, 1);
|
|
parent->fireCallback(entry->message);
|
|
|
|
// *************************************
|
|
// * Added to support multi-device
|
|
// *************************************
|
|
if(entry->message->getDeviceCount()>0)
|
|
data->remove(cdevMonitorEntry::DEVICE_TAG);
|
|
|
|
result = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
// *****************************************************************************
|
|
// * cdevMonitorTable::cdevMonitorTable :
|
|
// * This is the constructor for the cdevMonitortable class. This class
|
|
// * contains a hash table that maintains a list of all of the monitored
|
|
// * device / attribute pairs on the system.
|
|
// *****************************************************************************
|
|
cdevMonitorTable::cdevMonitorTable ( void )
|
|
: monitors(0)
|
|
{
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// * cdevMonitorTable::~cdevMonitorTable :
|
|
// * This method walks through the monitors hash table and deletes all
|
|
// * cdevMonitorNodes that have been allocated.
|
|
// *****************************************************************************
|
|
cdevMonitorTable::~cdevMonitorTable ( void )
|
|
{
|
|
char * ptr;
|
|
StringHashIterator iter(&monitors);
|
|
|
|
iter.first();
|
|
while((ptr= iter.key())!=NULL)
|
|
{
|
|
cdevMonitorNode * node = (cdevMonitorNode *)iter.data();
|
|
monitors.remove(ptr);
|
|
delete node;
|
|
iter.first();
|
|
}
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// * cdevMonitorTable::insertMonitor:
|
|
// * This method allows the caller to add a new monitored device / attribute
|
|
// * pair to the cdevMonitorTable.
|
|
// *
|
|
// * The cdevData object that is provided in the cdevData object is the
|
|
// * collection of all current property values for the device / attribute
|
|
// * pair. This data will be used to automatically dispatch the first
|
|
// * callback when the monitor is initially installed.
|
|
// *****************************************************************************
|
|
int cdevMonitorTable::insertMonitor ( cdevMessage * request, cdevData * data )
|
|
{
|
|
return insertMonitor(request, &data, 1);
|
|
}
|
|
|
|
|
|
// *****************************************************************************
|
|
// * cdevMonitorTable::insertMonitor:
|
|
// * This method allows the caller to add a new monitored device / attribute
|
|
// * pair to the cdevMonitorTable.
|
|
// *
|
|
// * The cdevData objects that are provided in the data parameter are the
|
|
// * initial values for each item in the deviceList in sequence. This data
|
|
// * will be used to automatically dispatch the first callback when the
|
|
// * monitor is initially installed.
|
|
// *****************************************************************************
|
|
int cdevMonitorTable::insertMonitor ( cdevMessage * request, cdevData ** data, size_t dataCnt )
|
|
{
|
|
if(request!=NULL && request->getDeviceList()!=NULL && request->getMessage()!=NULL)
|
|
{
|
|
char * attrib = strchr(request->getMessage(), ' ');
|
|
if(attrib)
|
|
{
|
|
attrib++;
|
|
cdevMonitorNode * node;
|
|
cdevMessage ** msgList;
|
|
|
|
// *****************************************************
|
|
// * Allocate additional cdevMessage objects if a
|
|
// * deviceList greater than 1 is specified.
|
|
// *****************************************************
|
|
if(request->getDeviceCount()>1)
|
|
{
|
|
msgList = new cdevMessage *[request->getDeviceCount()];
|
|
msgList[0] = request;
|
|
}
|
|
else msgList = &request;
|
|
|
|
// *****************************************************
|
|
// * Walk through each device in the list.
|
|
// *****************************************************
|
|
for(int i=0; i<request->getDeviceCount(); i++)
|
|
{
|
|
if(i>0) msgList[i] = new cdevMessage(*request);
|
|
if((node=findMonitor(request->getDeviceList()[i], attrib))==NULL)
|
|
{
|
|
node = new cdevMonitorNode(this, request->getDeviceList()[i], attrib);
|
|
monitors.insert(node->getHashString(), node);
|
|
}
|
|
if(dataCnt>0 && data!=NULL)
|
|
{
|
|
node->insertMonitor(msgList[i], ((i<dataCnt)?data[i]:data[dataCnt-1]), i);
|
|
}
|
|
else node->insertMonitor(msgList[i], NULL, i);
|
|
}
|
|
|
|
// *****************************************************
|
|
// * Delete the containing array of cdevMessage pointers
|
|
// *****************************************************
|
|
if(request->getDeviceCount()>1) delete msgList;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
// *****************************************************************************
|
|
// * cdevMonitorTable::removeMonitor :
|
|
// * This method allows the caller to remove a specific monitor using the
|
|
// * cancelTransIndex component of the cdevMessage object.
|
|
// *****************************************************************************
|
|
int cdevMonitorTable::removeMonitor ( cdevMessage * request )
|
|
{
|
|
int cancelTransIndex = request->getCancelTransIndex();
|
|
if(cancelTransIndex > 0)
|
|
{
|
|
StringHashIterator iter(&monitors);
|
|
iter.first();
|
|
|
|
while(iter.key()!=NULL)
|
|
{
|
|
cdevMonitorNode * node = (cdevMonitorNode *)iter.data();
|
|
node->removeMonitor(cancelTransIndex);
|
|
++iter;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// * cdevMonitorTable::removeClientMonitors :
|
|
// * This method will walk through the hash table and will remove all
|
|
// * monitors that are associated with a specific clientID.
|
|
// *****************************************************************************
|
|
int cdevMonitorTable::removeClientMonitors ( short clientID, int fire )
|
|
{
|
|
char * ptr;
|
|
StringHashIterator iter(&monitors);
|
|
|
|
iter.first();
|
|
while((ptr= iter.key())!=NULL)
|
|
{
|
|
cdevMonitorNode * node = (cdevMonitorNode *)iter.data();
|
|
node->removeClientMonitors(clientID, fire);
|
|
iter++;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// * cdevMonitorTable::findMonitor :
|
|
// * This method locates a cdevMonitorNode associated with the specified
|
|
// * device / attribute pair and returns it to the caller.
|
|
// *****************************************************************************
|
|
cdevMonitorNode * cdevMonitorTable::findMonitor ( char * device, char * attrib )
|
|
{
|
|
char hashString [512];
|
|
sprintf(hashString, "%s %s", device, attrib);
|
|
return (cdevMonitorNode *)monitors.find(hashString);
|
|
}
|
|
|
|
|
|
// *****************************************************************************
|
|
// * cdevMonitorTable:fireMonitor :
|
|
// * This method is used to deploy all monitors associated with the
|
|
// * device / attribute / property set.
|
|
// *
|
|
// * If the property parameter is NULL, then all properties will be fired
|
|
// * for all monitor associated with the device / attribute pair.
|
|
// *****************************************************************************
|
|
int cdevMonitorTable::fireMonitor ( char * device, char * attrib,
|
|
char * property, cdevData * data )
|
|
{
|
|
cdevMonitorNode * node = findMonitor(device, attrib);
|
|
return node==NULL?-1:node->fireMonitor(property, data);
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// * cdevMonitorTable:fireMonitor :
|
|
// * This method is used to deploy all monitors associated with the
|
|
// * device / attribute / property set.
|
|
// *
|
|
// * If the property parameter is -1, then all properties will be fired
|
|
// * for all monitors associated with the device / attribute pair.
|
|
// *****************************************************************************
|
|
int cdevMonitorTable::fireMonitor ( char * device, char * attrib,
|
|
int property, cdevData * data )
|
|
{
|
|
cdevMonitorNode * node = findMonitor(device, attrib);
|
|
return node==NULL?-1:node->fireMonitor(property, data);
|
|
}
|
|
|
|
|
|
// *****************************************************************************
|
|
// * cdevMonitorTable::fireCallback :
|
|
// * This is a stub for the fireCallback method that must b e provided by
|
|
// * the developer. This method is provided here - because this method may
|
|
// * potentially be called during program termination - resulting in the
|
|
// * attempted execution of a pure virtual function.
|
|
// *****************************************************************************
|
|
int cdevMonitorTable::fireCallback ( cdevMessage * /* message */ )
|
|
{
|
|
return CDEV_SUCCESS;
|
|
}
|