void Device::addDeviceDataItem(DataItem& dataItem) { if (!dataItem.getSource().empty()) mDeviceDataItemsBySource[dataItem.getSource()] = &dataItem; if (!dataItem.getName().empty()) mDeviceDataItemsByName[dataItem.getName()] = &dataItem; if (mDeviceDataItemsById[dataItem.getId()] != NULL) { sLogger << dlib::LERROR << "Duplicate data item id: " << dataItem.getId() << " for device " << mName << ", skipping"; } else { mDeviceDataItemsById[dataItem.getId()] = &dataItem; } }
/* Agent public methods */ Agent::Agent(const string& configXmlPath) { try { // Load the configuration for the Agent mConfig = new XmlParser(configXmlPath); } catch (exception & e) { logEvent("Agent::Agent", "Error loading xml configuration: " + configXmlPath); delete mConfig; throw (string) e.what(); } // Grab data from configuration mDevices = mConfig->getDevices(); list<Device *>::iterator device; for (device = mDevices.begin(); device != mDevices.end(); device++) { mDeviceMap[(*device)->getName()] = *device; std::map<string, DataItem*> items = (*device)->getDeviceDataItems(); std::map<string, DataItem *>::iterator item; for (item = items.begin(); item != items.end(); item++) { DataItem *d = item->second; mDataItemMap[d->getId()] = d; } } // Unique id number for agent instance mInstanceId = getCurrentTimeInSec(); // Sequence number and sliding buffer for data mSequence = 1; mSlidingBuffer = new sliding_buffer_kernel_1<ComponentEvent *>(); mSlidingBuffer->set_size(SLIDING_BUFFER_EXP); // Initialize the buffer for (unsigned int i = 0; i < mSlidingBuffer->size(); i++) { (*mSlidingBuffer)[i] = 0; } // Mutex used for synchronized access to sliding buffer and sequence number mSequenceLock = new dlib::mutex; }
/* Add values for related data items UNAVAILABLE */ void Agent::disconnected(Adapter *anAdapter, vector<Device*> aDevices) { string time = getCurrentTime(GMT_UV_SEC); sLogger << LDEBUG << "Disconnected from adapter, setting all values to UNAVAILABLE"; std::vector<Device*>::iterator iter; for (iter = aDevices.begin(); iter != aDevices.end(); ++iter) { std::map<std::string, DataItem *> dataItems = (*iter)->getDeviceDataItems(); std::map<std::string, DataItem*>::iterator dataItemAssoc; for (dataItemAssoc = dataItems.begin(); dataItemAssoc != dataItems.end(); ++dataItemAssoc) { DataItem *dataItem = (*dataItemAssoc).second; if (dataItem != NULL && (dataItem->getDataSource() == anAdapter || (anAdapter->isAutoAvailable() && dataItem->getDataSource() == NULL && dataItem->getType() == "AVAILABILITY"))) { ComponentEventPtr *ptr = mLatest.getEventPtr(dataItem->getId()); if (ptr != NULL) { const string *value = NULL; if (dataItem->isCondition()) { if ((*ptr)->getLevel() != ComponentEvent::UNAVAILABLE) value = &sConditionUnavailable; } else if (dataItem->hasConstraints()) { std::vector<std::string> &values = dataItem->getConstrainedValues(); if (values.size() > 1 && (*ptr)->getValue() != sUnavailable) value = &sUnavailable; } else if ((*ptr)->getValue() != sUnavailable) { value = &sUnavailable; } if (value != NULL) addToBuffer(dataItem, *value, time); } } else if (dataItem == NULL) { sLogger << LWARN << "No data Item for " << (*dataItemAssoc).first; } } } }
void Checkpoint::addComponentEvent (ComponentEvent *anEvent) { if ( mHasFilter ) { if ( mFilter.count(anEvent->getDataItem( )->getId( )) == 0 ) { return; } } DataItem * item = anEvent->getDataItem( ); string id = item->getId( ); ComponentEventPtr *ptr = mEvents[id]; if ( ptr != NULL ) { bool assigned = false; if ( item->isCondition( ) ) { // Chain event only if it is normal or unavailable and the // previous condition was not normal or unavailable if ( ( ( *ptr )->getLevel( ) != ComponentEvent::NORMAL ) && ( anEvent->getLevel( ) != ComponentEvent::NORMAL ) && ( ( *ptr )->getLevel( ) != ComponentEvent::UNAVAILABLE ) && ( anEvent->getLevel( ) != ComponentEvent::UNAVAILABLE ) ) { // Check to see if the native code matches an existing // active condition ComponentEvent *e = ( *ptr )->find(anEvent->getCode( )); if ( e != NULL ) { // Replace in chain. ComponentEvent *n = ( *ptr )->deepCopyAndRemove(e); // Check if this is the only event... ( *ptr ) = n; if ( n != NULL ) { n->unrefer( ); } } // Chain the event if ( ptr->getObject( ) != NULL ) { anEvent->appendTo(*ptr); } } else if ( anEvent->getLevel( ) == ComponentEvent::NORMAL ) { // Check for a normal that clears an active condition by code if ( anEvent->getCode( )[0] != '\0' ) { ComponentEvent *e = ( *ptr )->find(anEvent->getCode( )); if ( e != NULL ) { // Clear the one condition by removing it from the chain ComponentEvent *n = ( *ptr )->deepCopyAndRemove(e); ( *ptr ) = n; if ( n != NULL ) { n->unrefer( ); } else { // Need to put a normal event in with no code since this // is the last one. n = new ComponentEvent(*anEvent); n->normal( ); ( *ptr ) = n; n->unrefer( ); } } else { // Not sure if we should register code specific normals if // previous normal was not found // (*ptr) = anEvent; } assigned = true; } } } if ( !assigned ) { ( *ptr ) = anEvent; } } else { mEvents[id] = new ComponentEventPtr(anEvent); } }
/* Agent public methods */ Agent::Agent(const string& configXmlPath, int aBufferSize, int aMaxAssets, int aCheckpointFreq) : mPutEnabled(false), mLogStreamData(false) { try { // Load the configuration for the Agent mXmlParser = new XmlParser(); mDevices = mXmlParser->parseFile(configXmlPath); vector<Device *>::iterator device; std::set<std::string> uuids; for (device = mDevices.begin(); device != mDevices.end(); ++device) { if (uuids.count((*device)->getUuid()) > 0) throw runtime_error("Duplicate UUID: " + (*device)->getUuid()); uuids.insert((*device)->getUuid()); } } catch (runtime_error & e) { sLogger << LFATAL << "Error loading xml configuration: " + configXmlPath; sLogger << LFATAL << "Error detail: " << e.what(); cerr << e.what() << endl; throw e; } catch (exception &f) { sLogger << LFATAL << "Error loading xml configuration: " + configXmlPath; sLogger << LFATAL << "Error detail: " << f.what(); cerr << f.what() << endl; throw f; } // Grab data from configuration string time = getCurrentTime(GMT_UV_SEC); // Unique id number for agent instance mInstanceId = getCurrentTimeInSec(); // Sequence number and sliding buffer for data mSequence = 1; mSlidingBufferSize = 1 << aBufferSize; mSlidingBuffer = new sliding_buffer_kernel_1<ComponentEventPtr>(); mSlidingBuffer->set_size(aBufferSize); mCheckpointFreq = aCheckpointFreq; mCheckpointCount = (mSlidingBufferSize / aCheckpointFreq) + 1; // Asset sliding buffer mMaxAssets = aMaxAssets; // Create the checkpoints at a regular frequency mCheckpoints = new Checkpoint[mCheckpointCount]; // Mutex used for synchronized access to sliding buffer and sequence number mSequenceLock = new dlib::mutex; mAssetLock = new dlib::mutex; // Add the devices to the device map and create availability and // asset changed events if they don't exist vector<Device *>::iterator device; for (device = mDevices.begin(); device != mDevices.end(); ++device) { mDeviceMap[(*device)->getName()] = *device; // Make sure we have two device level data items: // 1. Availability // 2. AssetChanged if ((*device)->getAvailability() == NULL) { // Create availability data item and add it to the device. std::map<string,string> attrs; attrs["type"] = "AVAILABILITY"; attrs["id"] = (*device)->getId() + "_avail"; attrs["category"] = "EVENT"; DataItem *di = new DataItem(attrs); di->setComponent(*(*device)); (*device)->addDataItem(*di); (*device)->addDeviceDataItem(*di); (*device)->mAvailabilityAdded = true; } if ((*device)->getAssetChanged() == NULL) { // Create availability data item and add it to the device. std::map<string,string> attrs; attrs["type"] = "ASSET_CHANGED"; attrs["id"] = (*device)->getId() + "_asset_chg"; attrs["category"] = "EVENT"; DataItem *di = new DataItem(attrs); di->setComponent(*(*device)); (*device)->addDataItem(*di); (*device)->addDeviceDataItem(*di); } } // Reload the document for path resolution mXmlParser->loadDocument(XmlPrinter::printProbe(mInstanceId, mSlidingBufferSize, mMaxAssets, mAssets.size(), mSequence, mDevices)); /* Initialize the id mapping for the devices and set all data items to UNAVAILABLE */ for (device = mDevices.begin(); device != mDevices.end(); ++device) { const std::map<string, DataItem*> &items = (*device)->getDeviceDataItems(); std::map<string, DataItem *>::const_iterator item; for (item = items.begin(); item != items.end(); ++item) { // Check for single valued constrained data items. DataItem *d = item->second; const string *value = &sUnavailable; if (d->isCondition()) { value = &sConditionUnavailable; } else if (d->hasConstraints()) { std::vector<std::string> &values = d->getConstrainedValues(); if (values.size() == 1) value = &values[0]; } addToBuffer(d, *value, time); if (mDataItemMap.count(d->getId()) == 0) mDataItemMap[d->getId()] = d; else { sLogger << LFATAL << "Duplicate DataItem id " << d->getId() << " for device: " << (*device)->getName() << " and data item name: " << d->getName(); exit(1); } } } }