/***************************************************************************** * Copyright (c) 2008, University of Florida * All rights reserved. * * This file is part of OpenJAUS. OpenJAUS is distributed under the BSD * license. See the LICENSE file for details. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * with the distribution. * * Neither the name of the University of Florida nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ****************************************************************************/ // File Name: NodeManagerComponent.cpp // // Written By: Danny Kent (jaus AT dannykent DOT com) // // Version: 3.3.0a // // Date: 08/07/08 // // Description: This file defines the behavior of the Node Manager JAUS Component. // It is based on the LocalComponent virtual class. #include "nodeManager/NodeManagerComponent.h" #include "nodeManager/JausComponentCommunicationManager.h" #include "nodeManager/events/SystemTreeEvent.h" #include "nodeManager/events/ErrorEvent.h" #include "nodeManager/events/DebugEvent.h" #include "nodeManager/EventHandler.h" #include "nodeManager/SystemTree.h" #include "jaus.h" #include "utils/timeLib.h" #define _USE_MATH_DEFINES #include NodeManagerComponent::NodeManagerComponent(FileLoader *configData, EventHandler *handler, JausComponentCommunicationManager *cmptComms) { int subsystemId, nodeId; this->eventHandler = handler; if(configData == NULL) { // OK, don't do this. This is bad. throw "NodeManagerComponent: configData is NULL"; return; } if(cmptComms == NULL) { // OK, don't do this. This is bad. throw "NodeManagerComponent: cmptComms is NULL"; return; } this->type = COMPONENT_INTERFACE; this->commMngr = cmptComms; this->configData = configData; this->name = "OpenJAUS Node Manager"; this->cmptRateHz = NM_RATE_HZ; this->systemTree = cmptComms->getSystemTree(); this->systemTree->registerEventHandler(this); for(int i = 0; i < MAXIMUM_EVENT_ID; i++) { eventId[i] = false; } // NOTE: These two values should exist in the properties file and should be checked // in the NodeManager class prior to constructing this object subsystemId = configData->GetConfigDataInt("JAUS", "SubsystemId"); if(subsystemId < JAUS_MINIMUM_SUBSYSTEM_ID || subsystemId > JAUS_MAXIMUM_SUBSYSTEM_ID) { // Invalid ID throw "NodeManagerComponent: Invalid SubsystemId"; return; } nodeId = configData->GetConfigDataInt("JAUS", "NodeId"); if(nodeId < JAUS_MINIMUM_NODE_ID || nodeId > JAUS_MAXIMUM_NODE_ID) { // Invalid ID throw "NodeManagerComponent: Invalid NodeId"; return; } this->cmpt = jausComponentCreate(); if(!this->cmpt) { throw "NodeManagerComponent: Cannot create component"; return; } this->cmpt->address->subsystem = subsystemId; this->cmpt->address->node = nodeId; this->cmpt->address->component = JAUS_NODE_MANAGER; this->cmpt->address->instance = JAUS_MINIMUM_INSTANCE_ID; this->setupJausServices(); this->cmpt->identification = (char *)calloc(strlen(this->name.c_str()) + 1, sizeof(char)); strcpy(this->cmpt->identification, this->name.c_str()); } NodeManagerComponent::~NodeManagerComponent(void) { HASH_MAP ::iterator iterator; if(running) { this->stopInterface(); } jausComponentDestroy(this->cmpt); for(iterator = subsystemChangeList.begin(); iterator != subsystemChangeList.end(); iterator++) { jausAddressDestroy(iterator->second); } for(iterator = nodeChangeList.begin(); iterator != nodeChangeList.end(); iterator++) { jausAddressDestroy(iterator->second); } } bool NodeManagerComponent::startInterface() { // Set our thread control flag to true this->running = true; // Setup our pThread this->startThread(); if(!systemTree->addComponent(this->cmpt->address, this->cmpt)) { ErrorEvent *e = new ErrorEvent(ErrorEvent::Configuration, __FUNCTION__, __LINE__, "Cannot add Node Manager component"); this->eventHandler->handleEvent(e); return false; } return true; } bool NodeManagerComponent::stopInterface() { // Send our shutdown events sendNodeShutdownEvents(); sendSubsystemShutdownEvents(); // Set out thread control flag to false this->running = false; // Stop our pThread this->stopThread(); return true; } bool NodeManagerComponent::processMessage(JausMessage message) { if(!message || !message->destination) { ErrorEvent *e = new ErrorEvent(ErrorEvent::NullPointer, __FUNCTION__, __LINE__, "Invalid JausMessage."); this->eventHandler->handleEvent(e); return false; } switch(message->commandCode) { case JAUS_SET_COMPONENT_AUTHORITY: case JAUS_SHUTDOWN: case JAUS_STANDBY: case JAUS_RESUME: case JAUS_RESET: case JAUS_SET_EMERGENCY: case JAUS_CLEAR_EMERGENCY: // These messages are ignored! jausMessageDestroy(message); return true; case JAUS_CREATE_SERVICE_CONNECTION: return processCreateServiceConnection(message); case JAUS_ACTIVATE_SERVICE_CONNECTION: return processActivateServiceConnection(message); case JAUS_SUSPEND_SERVICE_CONNECTION: return processSuspendServiceConnection(message); case JAUS_TERMINATE_SERVICE_CONNECTION: return processTerminateServiceConnection(message); case JAUS_REQUEST_COMPONENT_CONTROL: return processRequestComponentControl(message); case JAUS_QUERY_COMPONENT_AUTHORITY: return processQueryComponentAuthority(message); case JAUS_QUERY_COMPONENT_STATUS: return processQueryComponentStatus(message); case JAUS_QUERY_HEARTBEAT_PULSE: return processQueryHeartbeatPulse(message); case JAUS_REPORT_HEARTBEAT_PULSE: return processReportHeartbeatPulse(message); case JAUS_QUERY_CONFIGURATION: return processQueryConfiguration(message); case JAUS_QUERY_IDENTIFICATION: return processQueryIdentification(message); case JAUS_QUERY_SERVICES: return processQueryServices(message); case JAUS_REPORT_CONFIGURATION: return processReportConfiguration(message); case JAUS_REPORT_IDENTIFICATION: return processReportIdentification(message); case JAUS_REPORT_SERVICES: return processReportServices(message); case JAUS_CANCEL_EVENT: return processCancelEvent(message); case JAUS_CONFIRM_EVENT_REQUEST: return processConfirmEvent(message); case JAUS_CREATE_EVENT: return processCreateEvent(message); case JAUS_EVENT: return processEvent(message); default: // Unhandled message received by node manager component jausMessageDestroy(message); return false; } } std::string NodeManagerComponent::toString() { return "Node Manager Component"; } JausAddress NodeManagerComponent::checkInLocalComponent(int cmptId) { JausComponent component = jausComponentCreate(); if(!component) return NULL; // Setup query address component->address->subsystem = this->cmpt->address->subsystem; component->address->node = this->cmpt->address->node; component->address->component = cmptId; component->address->instance = 0; // Query SystemTree for next valid instance ID component->address->instance = this->getCommunicationManager()->getSystemTree()->getNextInstanceId(component->address); // Check returned value if(component->address->instance == JAUS_INVALID_INSTANCE_ID) { jausComponentDestroy(component); return NULL; } else { if(this->commMngr->getSystemTree()->addComponent(component->address, component)) { JausAddress address = jausAddressClone(component->address); jausComponentDestroy(component); sendNodeChangedEvents(); sendSubsystemChangedEvents(); return address; } else { jausComponentDestroy(component); return NULL; } } } void NodeManagerComponent::checkOutLocalComponent(JausAddress address) { return checkOutLocalComponent(address->subsystem, address->node, address->component, address->instance); } void NodeManagerComponent::checkOutLocalComponent(int subsId, int nodeId, int cmptId, int instId) { if(systemTree->removeComponent(subsId, nodeId, cmptId, instId)) { sendNodeChangedEvents(); sendSubsystemChangedEvents(); } } void NodeManagerComponent::startupState() { } void NodeManagerComponent::intializeState() { // Nothing to do this->cmpt->state = JAUS_READY_STATE; } void NodeManagerComponent::standbyState() { // Nothing to do } void NodeManagerComponent::readyState() { // Nothing to do } void NodeManagerComponent::emergencyState() { // Nothing to do } void NodeManagerComponent::failureState() { // Nothing to do } void NodeManagerComponent::shutdownState() { // Nothing to do } void NodeManagerComponent::allState() { static double refreshTime = 0; generateHeartbeats(); if(ojGetTimeSec() >= refreshTime) { systemTree->refresh(); refreshTime = ojGetTimeSec() + REFRESH_TIME_SEC; } // TODO: Check for serviceConnections } bool NodeManagerComponent::processReportConfiguration(JausMessage message) { // This function follows the flowchart designed for NM 2.0 by D. Kent and T. Galluzzo ReportConfigurationMessage reportConf = NULL; reportConf = reportConfigurationMessageFromJausMessage(message); if(!reportConf) { // Error unpacking the reportConf ErrorEvent *e = new ErrorEvent(ErrorEvent::Memory, __FUNCTION__, __LINE__, "Cannot unpack ReportConf"); this->eventHandler->handleEvent(e); jausMessageDestroy(message); return false; } // Has Subs? if(!systemTree->hasSubsystem(reportConf->source)) { ErrorEvent *e = new ErrorEvent(ErrorEvent::Message, __FUNCTION__, __LINE__, "Received ReportConf from unknown subsystem"); this->eventHandler->handleEvent(e); reportConfigurationMessageDestroy(reportConf); jausMessageDestroy(message); return false; } // My Subs? if(reportConf->source->subsystem != this->cmpt->address->subsystem) { // Test for special case if(reportConf->subsystem->nodes->elementCount == 0) { // Special Case: This is an empty subsystem report, this means that the source subsystem is going offline systemTree->removeSubsystem(reportConf->source); reportConfigurationMessageDestroy(reportConf); jausMessageDestroy(message); return true; } systemTree->replaceSubsystem(reportConf->source, reportConf->subsystem); JausSubsystem subs = systemTree->getSubsystem(reportConf->source); for(int i = 0; i < subs->nodes->elementCount; i++) { JausNode node = (JausNode) subs->nodes->elementData[i]; if(!jausNodeHasIdentification(node)) { JausAddress address = jausAddressCreate(); if(!address) { ErrorEvent *e = new ErrorEvent(ErrorEvent::Memory, __FUNCTION__, __LINE__, "Cannot create address"); this->eventHandler->handleEvent(e); reportConfigurationMessageDestroy(reportConf); jausMessageDestroy(message); return false; } address->subsystem = reportConf->source->subsystem; address->node = reportConf->source->node; address->component = JAUS_NODE_MANAGER; address->instance = 1; sendQueryNodeIdentification(address); jausAddressDestroy(address); } for(int j = 0; j < node->components->elementCount; j++) { JausComponent cmpt = (JausComponent) node->components->elementData[j]; if(!jausComponentHasIdentification(cmpt)) { sendQueryComponentIdentification(cmpt->address); } if(!jausComponentHasServices(cmpt)) { sendQueryComponentServices(cmpt->address); } } // End For(Components) } // End For(Nodes) jausSubsystemDestroy(subs); reportConfigurationMessageDestroy(reportConf); jausMessageDestroy(message); return true; } // End !MySubs? if(!systemTree->hasNode(reportConf->source)) { // Report Conf from unknown node! This is an unsolicited report ErrorEvent *e = new ErrorEvent(ErrorEvent::Message, __FUNCTION__, __LINE__, "Report Conf from unknown node! This is an unsolicited report"); this->eventHandler->handleEvent(e); reportConfigurationMessageDestroy(reportConf); jausMessageDestroy(message); return true; } // This is a node-level report // Should only have 1 node attached! if(reportConf->subsystem->nodes->elementCount > 1) { // Warning ErrorEvent *e = new ErrorEvent(ErrorEvent::Warning, __FUNCTION__, __LINE__, "Node-level Report Conf with more than 1 node included. Ignoring other nodes."); this->eventHandler->handleEvent(e); } JausNode node = (JausNode) reportConf->subsystem->nodes->elementData[0]; // Test for special case if(node->components->elementCount == 0) { // Special Case: This is an empty node report, this means that the source node is going offline systemTree->removeNode(reportConf->source); reportConfigurationMessageDestroy(reportConf); jausMessageDestroy(message); return true; } // Replace Node systemTree->replaceNode(reportConf->source, node); for(int i = 0; i < node->components->elementCount; i++) { JausComponent cmpt = (JausComponent) node->components->elementData[i]; if(!jausComponentHasIdentification(cmpt)) { sendQueryComponentIdentification(cmpt->address); } if(!jausComponentHasServices(cmpt)) { sendQueryComponentServices(cmpt->address); } } // Send subs changed events sendSubsystemChangedEvents(); reportConfigurationMessageDestroy(reportConf); jausMessageDestroy(message); return true; } bool NodeManagerComponent::processReportIdentification(JausMessage message) { // This function follows the flowchart designed for NM 2.0 by D. Kent and T. Galluzzo ReportIdentificationMessage reportId = NULL; reportId = reportIdentificationMessageFromJausMessage(message); if(!reportId) { // Error unpacking the reportId msg // TODO: Log Error. Throw Exception? jausMessageDestroy(message); return false; } switch(reportId->queryType) { case JAUS_QUERY_FIELD_SYSTEM_IDENTITY: // We don't care about this (actually we never ask for this, so this shouldn't happen) reportIdentificationMessageDestroy(reportId); jausMessageDestroy(message); return true; case JAUS_QUERY_FIELD_SS_IDENTITY: // Has Subs? if(!systemTree->hasSubsystem(reportId->source)) { // Report ID from unknown Subsystem // TODO: Log Error. Throw Exception reportIdentificationMessageDestroy(reportId); jausMessageDestroy(message); return false; } // Add Identification systemTree->setSubsystemIdentification(reportId->source, reportId->identification); // Query Subs Conf & Setup event sendQuerySubsystemConfiguration(reportId->source, true); reportIdentificationMessageDestroy(reportId); jausMessageDestroy(message); return true; case JAUS_QUERY_FIELD_NODE_IDENTITY: // Has Node? if(!systemTree->hasNode(reportId->source)) { // Report ID from unknown Node // TODO: Log Error. Throw Exception reportIdentificationMessageDestroy(reportId); jausMessageDestroy(message); return false; } // Add Identification systemTree->setNodeIdentification(reportId->source, reportId->identification); // Query Subs Conf & Setup event sendQueryNodeConfiguration(reportId->source, true); reportIdentificationMessageDestroy(reportId); jausMessageDestroy(message); return true; case JAUS_QUERY_FIELD_COMPONENT_IDENTITY: // Has Cmpt? if(!systemTree->hasComponent(reportId->source)) { // Report ID from unknown Component // TODO: Log Error. Throw Exception reportIdentificationMessageDestroy(reportId); jausMessageDestroy(message); return false; } // Add Identification systemTree->setComponentIdentification(reportId->source, reportId->identification); reportIdentificationMessageDestroy(reportId); jausMessageDestroy(message); return true; default: // TODO: Log Error. Throw Exception. reportIdentificationMessageDestroy(reportId); jausMessageDestroy(message); return true; } reportIdentificationMessageDestroy(reportId); jausMessageDestroy(message); return true; } bool NodeManagerComponent::processReportServices(JausMessage message) { ReportServicesMessage reportServices = NULL; reportServices = reportServicesMessageFromJausMessage(message); if(!reportServices) { // TODO: Log error. Throw Exception. jausMessageDestroy(message); return false; } if(systemTree->hasComponent(reportServices->source)) { systemTree->setComponentServices(reportServices->source, reportServices->jausServices); } reportServicesMessageDestroy(reportServices); jausMessageDestroy(message); return true; } bool NodeManagerComponent::processReportHeartbeatPulse(JausMessage message) { // This function follows the flowchart designed for NM 2.0 by D. Kent and T. Galluzzo char buf[256]; sprintf(buf, "Process HB from: %d.%d.%d.%d", message->source->subsystem, message->source->node, message->source->component, message->source->instance); DebugEvent *e = new DebugEvent("HB", __FUNCTION__, __LINE__, buf); this->eventHandler->handleEvent(e); // Has Subs? if(!systemTree->hasSubsystem(message->source)) { // Add Subs systemTree->addSubsystem(message->source, NULL); // Query SubsId sendQuerySubsystemIdentification(message->source); jausMessageDestroy(message); return true; } // Update Subsystem Timestamp systemTree->updateSubsystemTimestamp(message->source); // Has SubsId? if(!systemTree->hasSubsystemIdentification(message->source)) { // Query SubsId sendQuerySubsystemIdentification(message->source); jausMessageDestroy(message); return true; } // My Subs? if(message->source->subsystem != this->cmpt->address->subsystem) { // Has SubsConf? if(!systemTree->hasSubsystemConfiguration(message->source)) { sendQuerySubsystemConfiguration(message->source, true); jausMessageDestroy(message); return true; } JausSubsystem subs = systemTree->getSubsystem(message->source); if(!subs) { // TODO: Throw Exception. Log Error. jausMessageDestroy(message); return false; } for(int i = 0; i < subs->nodes->elementCount; i++) { JausNode node = (JausNode) subs->nodes->elementData[i]; if(!jausNodeHasIdentification(node)) { JausAddress address = jausAddressCreate(); if(!address) { // TODO: Throw Exception. Log Error. jausSubsystemDestroy(subs); jausMessageDestroy(message); return false; } address->subsystem = message->source->subsystem; address->node = node->id; address->component = JAUS_NODE_MANAGER; address->instance = 1; sendQueryNodeIdentification(address); jausAddressDestroy(address); } for(int j = 0; j < node->components->elementCount; j++) { JausComponent cmpt = (JausComponent) node->components->elementData[j]; if(!jausComponentHasIdentification(cmpt)) { sendQueryComponentIdentification(cmpt->address); } if(!jausComponentHasServices(cmpt)) { sendQueryComponentServices(cmpt->address); } } // end For(Components) } // end For(Nodes) jausSubsystemDestroy(subs); jausMessageDestroy(message); return true; } // End !MySubs // Has Node? if(!systemTree->hasNode(message->source)) { // Add Node systemTree->addNode(message->source, NULL); // Query NodeID // Setup Query Address JausAddress address = jausAddressCreate(); if(!address) { // TODO: Throw Exception. Log Error. jausMessageDestroy(message); return false; } address->subsystem = message->source->subsystem; address->node = message->source->node; address->component = JAUS_NODE_MANAGER; address->instance = 1; // Query Node ID sendQueryNodeIdentification(address); jausAddressDestroy(address); jausMessageDestroy(message); return true; } // Update Node Timestamp systemTree->updateNodeTimestamp(message->source); // Has NodeId? if(!systemTree->hasNodeIdentification(message->source)) { // Query NodeID // Setup Query Address JausAddress address = jausAddressCreate(); if(!address) { // TODO: Throw Exception. Log Error. jausMessageDestroy(message); return false; } address->subsystem = message->source->subsystem; address->node = message->source->node; address->component = JAUS_NODE_MANAGER; address->instance = 1; // Query Node ID sendQueryNodeIdentification(address); jausAddressDestroy(address); jausMessageDestroy(message); return true; } // My Node? if(message->source->node != this->cmpt->address->node) { // Has NodeConf? if(!systemTree->hasNodeConfiguration(message->source)) { // Query NodeConf JausAddress address = jausAddressCreate(); if(!address) { // TODO: Throw Exception. Log Error. jausMessageDestroy(message); return false; } address->subsystem = message->source->subsystem; address->node = message->source->node; address->component = JAUS_NODE_MANAGER; address->instance = 1; sendQueryNodeConfiguration(address, true); jausAddressDestroy(address); jausMessageDestroy(message); return true; } else { JausNode node = systemTree->getNode(message->source); // Check for component ID and Services for(int i = 0; i < node->components->elementCount; i++) { JausComponent cmpt = (JausComponent) node->components->elementData[i]; if(!jausComponentHasIdentification(cmpt)) { sendQueryComponentIdentification(cmpt->address); } if(!jausComponentHasServices(cmpt)) { sendQueryComponentServices(cmpt->address); } } jausNodeDestroy(node); jausMessageDestroy(message); return false; } }// End !MyNode // Has Component? if(!systemTree->hasComponent(message->source)) { // Add Component systemTree->addComponent(message->source, NULL); } else { // Update Component Timestamp systemTree->updateComponentTimestamp(message->source); } if(!systemTree->hasComponentIdentification(message->source)) { //printf("Send Query Cmpt Id\n"); sendQueryComponentIdentification(message->source); } if(!systemTree->hasComponentServices(message->source)) { //printf("Send Query Cmpt Services\n"); sendQueryComponentServices(message->source); } jausMessageDestroy(message); return true; } bool NodeManagerComponent::processCreateEvent(JausMessage message) { // Only support Configuration Changed events CreateEventMessage createEvent = NULL; QueryConfigurationMessage queryConf = NULL; ConfirmEventRequestMessage confirmEventRequest = NULL; JausMessage txMessage = NULL; int nextEventId = -1; HASH_MAP ::iterator iterator; confirmEventRequest = confirmEventRequestMessageCreate(); if(!confirmEventRequest) { //TODO: Log Error. Throw Exception jausMessageDestroy(message); return false; } jausAddressCopy(confirmEventRequest->destination, message->source); jausAddressCopy(confirmEventRequest->source, cmpt->address); createEvent = createEventMessageFromJausMessage(message); if(!createEvent) { //TODO: Log Error. Throw Exception confirmEventRequest->responseCode = INVALID_EVENT_RESPONSE; txMessage = confirmEventRequestMessageToJausMessage(confirmEventRequest); if(txMessage) { this->commMngr->receiveJausMessage(txMessage, this); } confirmEventRequestMessageDestroy(confirmEventRequest); jausMessageDestroy(message); return false; } if(createEvent->reportMessageCode != JAUS_REPORT_CONFIGURATION) { // Currently the NM only supports configuration changed events confirmEventRequest->responseCode = MESSAGE_UNSUPPORTED_RESPONSE; txMessage = confirmEventRequestMessageToJausMessage(confirmEventRequest); if(txMessage) { this->commMngr->receiveJausMessage(txMessage, this); } confirmEventRequestMessageDestroy(confirmEventRequest); char buf[256]; sprintf(buf, "Rejected event from %d.%d.%d.%d. Unsupported command code (0x%04X)", createEvent->source->subsystem, createEvent->source->node, createEvent->source->component, createEvent->source->instance, createEvent->reportMessageCode); DebugEvent *e = new DebugEvent("Event", __FUNCTION__, __LINE__, buf); this->eventHandler->handleEvent(e); jausMessageDestroy(message); return false; } confirmEventRequest->messageCode = JAUS_REPORT_CONFIGURATION; queryConf = queryConfigurationMessageFromJausMessage(createEvent->queryMessage); if(!queryConf) { // ERROR: Cannot unpack query message // TODO: Log Error. Throw Exception confirmEventRequest->responseCode = INVALID_EVENT_RESPONSE; txMessage = confirmEventRequestMessageToJausMessage(confirmEventRequest); if(txMessage) { this->commMngr->receiveJausMessage(txMessage, this); } confirmEventRequestMessageDestroy(confirmEventRequest); jausMessageDestroy(message); return false; } switch(queryConf->queryField) { case JAUS_SUBSYSTEM_CONFIGURATION: for(iterator = subsystemChangeList.begin(); iterator != subsystemChangeList.end(); iterator++) { if(jausAddressEqual(createEvent->source, iterator->second)) { // Event already created confirmEventRequest->responseCode = SUCCESSFUL_RESPONSE; confirmEventRequest->eventId = iterator->first; break; } } nextEventId = getNextEventId(); if(nextEventId >= 0) { confirmEventRequest->eventId = (JausByte) nextEventId; eventId[nextEventId] = true; subsystemChangeList[nextEventId] = jausAddressClone(createEvent->source); confirmEventRequest->responseCode = SUCCESSFUL_RESPONSE; char buf[256]; sprintf(buf, "Added Subsystem Configuration event for %d.%d.%d.%d.", createEvent->source->subsystem, createEvent->source->node, createEvent->source->component, createEvent->source->instance); DebugEvent *e = new DebugEvent("Event", __FUNCTION__, __LINE__, buf); this->eventHandler->handleEvent(e); } else { confirmEventRequest->responseCode = CONNECTION_REFUSED_RESPONSE; confirmEventRequest->eventId = 0; char buf[256]; // sprintf(buf, "Rejected event from %d.%d.%d.%d. No available Event Ids.", createEvent->source->subsystem, createEvent->source->node, createEvent->source->component, createEvent->source->instance, createEvent->reportMessageCode); //NMJ sprintf(buf, "Rejected event from %d.%d.%d.%d. No available Event Ids.", createEvent->source->subsystem, createEvent->source->node, createEvent->source->component, createEvent->source->instance); // NMJ DebugEvent *e = new DebugEvent("Event", __FUNCTION__, __LINE__, buf); this->eventHandler->handleEvent(e); } break; case JAUS_NODE_CONFIGURATION: for(iterator = nodeChangeList.begin(); iterator != nodeChangeList.end(); iterator++) { if(jausAddressEqual(createEvent->source, iterator->second)) { // Event already created confirmEventRequest->responseCode = SUCCESSFUL_RESPONSE; confirmEventRequest->eventId = iterator->first; break; } } nextEventId = getNextEventId(); if(nextEventId >= 0) { confirmEventRequest->eventId = (JausByte) nextEventId; eventId[nextEventId] = true; nodeChangeList[nextEventId] = jausAddressClone(createEvent->source); confirmEventRequest->responseCode = SUCCESSFUL_RESPONSE; char buf[256]; sprintf(buf, "Added Node Configuration event for %d.%d.%d.%d.", createEvent->source->subsystem, createEvent->source->node, createEvent->source->component, createEvent->source->instance); DebugEvent *e = new DebugEvent("Event", __FUNCTION__, __LINE__, buf); this->eventHandler->handleEvent(e); } else { confirmEventRequest->responseCode = CONNECTION_REFUSED_RESPONSE; confirmEventRequest->eventId = 0; char buf[256]; // sprintf(buf, "Rejected event from %d.%d.%d.%d. No available Event Ids.", createEvent->source->subsystem, createEvent->source->node, createEvent->source->component, createEvent->source->instance, createEvent->reportMessageCode); // NMJ sprintf(buf, "Rejected event from %d.%d.%d.%d. No available Event Ids.", createEvent->source->subsystem, createEvent->source->node, createEvent->source->component, createEvent->source->instance); DebugEvent *e = new DebugEvent("Event", __FUNCTION__, __LINE__, buf); this->eventHandler->handleEvent(e); } break; default: // TODO: Log Error. Throw Exception. // Unknown Query Type confirmEventRequest->responseCode = INVALID_EVENT_RESPONSE; txMessage = confirmEventRequestMessageToJausMessage(confirmEventRequest); if(txMessage) { this->commMngr->receiveJausMessage(txMessage, this); } confirmEventRequestMessageDestroy(confirmEventRequest); jausMessageDestroy(message); return false; } // Send response txMessage = confirmEventRequestMessageToJausMessage(confirmEventRequest); if(txMessage) { this->commMngr->receiveJausMessage(txMessage, this); } confirmEventRequestMessageDestroy(confirmEventRequest); queryConfigurationMessageDestroy(queryConf); createEventMessageDestroy(createEvent); jausMessageDestroy(message); return true; } bool NodeManagerComponent::processCancelEvent(JausMessage message) { CancelEventMessage cancelEvent = NULL; cancelEvent = cancelEventMessageFromJausMessage(message); if(!cancelEvent) { // Error unpacking message // TODO: Throw Exception. Log Error. jausMessageDestroy(message); return false; } if(cancelEvent->messageCode == JAUS_QUERY_CONFIGURATION) { if(eventId[cancelEvent->eventId]) { eventId[cancelEvent->eventId] = false; if(subsystemChangeList.find(cancelEvent->eventId) != subsystemChangeList.end()) { // Remove that element subsystemChangeList.erase(subsystemChangeList.find(cancelEvent->eventId)); } else if(nodeChangeList.find(cancelEvent->eventId) != nodeChangeList.end()) { // Remove that element nodeChangeList.erase(nodeChangeList.find(cancelEvent->eventId)); } } } cancelEventMessageDestroy(cancelEvent); jausMessageDestroy(message); return true; } bool NodeManagerComponent::processCreateServiceConnection(JausMessage message) { // Not implemented right now jausMessageDestroy(message); return true; } bool NodeManagerComponent::processActivateServiceConnection(JausMessage message) { // Not Implemented right now jausMessageDestroy(message); return true; } bool NodeManagerComponent::processSuspendServiceConnection(JausMessage message) { // Not Implemented right now jausMessageDestroy(message); return true; } bool NodeManagerComponent::processTerminateServiceConnection(JausMessage message) { // Not Implemented right now jausMessageDestroy(message); return true; } bool NodeManagerComponent::processRequestComponentControl(JausMessage message) { RequestComponentControlMessage requestComponentControl = NULL; RejectComponentControlMessage rejectComponentControl = NULL; ConfirmComponentControlMessage confirmComponentControl = NULL; JausMessage txMessage = NULL; requestComponentControl = requestComponentControlMessageFromJausMessage(message); if(!requestComponentControl) { // Error unpacking message // TODO: Log Error. Throw Exception jausMessageDestroy(message); return false; } if(cmpt->controller.active) { if(requestComponentControl->authorityCode > cmpt->controller.authority) // Test for higher authority { // Terminate control of current component rejectComponentControl = rejectComponentControlMessageCreate(); jausAddressCopy(rejectComponentControl->source, cmpt->address); jausAddressCopy(rejectComponentControl->destination, cmpt->controller.address); txMessage = rejectComponentControlMessageToJausMessage(rejectComponentControl); if(txMessage) { this->commMngr->receiveJausMessage(txMessage, this); } // Accept control of new component confirmComponentControl = confirmComponentControlMessageCreate(); jausAddressCopy(confirmComponentControl->source, cmpt->address); jausAddressCopy(confirmComponentControl->destination, message->source); confirmComponentControl->responseCode = JAUS_CONTROL_ACCEPTED; txMessage = confirmComponentControlMessageToJausMessage(confirmComponentControl); if(txMessage) { this->commMngr->receiveJausMessage(txMessage, this); } // Update cmpt controller information jausAddressCopy(cmpt->controller.address, message->source); cmpt->controller.authority = requestComponentControl->authorityCode; rejectComponentControlMessageDestroy(rejectComponentControl); confirmComponentControlMessageDestroy(confirmComponentControl); } else { if(!jausAddressEqual(message->source, cmpt->controller.address)) { rejectComponentControl = rejectComponentControlMessageCreate(); jausAddressCopy(rejectComponentControl->source, cmpt->address); jausAddressCopy(rejectComponentControl->destination, message->source); txMessage = rejectComponentControlMessageToJausMessage(rejectComponentControl); if(txMessage) { this->commMngr->receiveJausMessage(txMessage, this); } rejectComponentControlMessageDestroy(rejectComponentControl); } else { // Reaccept control of new component confirmComponentControl = confirmComponentControlMessageCreate(); jausAddressCopy(confirmComponentControl->source, cmpt->address); jausAddressCopy(confirmComponentControl->destination, message->source); confirmComponentControl->responseCode = JAUS_CONTROL_ACCEPTED; txMessage = confirmComponentControlMessageToJausMessage(confirmComponentControl); if(txMessage) { this->commMngr->receiveJausMessage(txMessage, this); } confirmComponentControlMessageDestroy(confirmComponentControl); } } } else // Not currently under component control, so give control { confirmComponentControl = confirmComponentControlMessageCreate(); jausAddressCopy(confirmComponentControl->source, cmpt->address); jausAddressCopy(confirmComponentControl->destination, message->source); confirmComponentControl->responseCode = JAUS_CONTROL_ACCEPTED; txMessage = confirmComponentControlMessageToJausMessage(confirmComponentControl); if(txMessage) { this->commMngr->receiveJausMessage(txMessage, this); } jausAddressCopy(cmpt->controller.address, message->source); cmpt->controller.authority = requestComponentControl->authorityCode; cmpt->controller.active = JAUS_TRUE; confirmComponentControlMessageDestroy(confirmComponentControl); } requestComponentControlMessageDestroy(requestComponentControl); jausMessageDestroy(message); return true; } bool NodeManagerComponent::processQueryComponentAuthority(JausMessage message) { ReportComponentAuthorityMessage report = NULL; JausMessage txMessage = NULL; report = reportComponentAuthorityMessageCreate(); if(!report) { // TODO: Throw Exception. Log Error. jausMessageDestroy(message); return false; } jausAddressCopy(report->source, cmpt->address); jausAddressCopy(report->destination, message->source); report->authorityCode = cmpt->authority; txMessage = reportComponentAuthorityMessageToJausMessage(report); if(txMessage) { this->commMngr->receiveJausMessage(txMessage, this); } reportComponentAuthorityMessageDestroy(report); jausMessageDestroy(message); return true; } bool NodeManagerComponent::processQueryComponentStatus(JausMessage message) { ReportComponentStatusMessage reportComponentStatus = NULL; JausMessage txMessage = NULL; reportComponentStatus = reportComponentStatusMessageCreate(); jausAddressCopy(reportComponentStatus->source, cmpt->address); jausAddressCopy(reportComponentStatus->destination, message->source); reportComponentStatus->primaryStatusCode = cmpt->state; txMessage = reportComponentStatusMessageToJausMessage(reportComponentStatus); if(txMessage) { this->commMngr->receiveJausMessage(txMessage, this); } reportComponentStatusMessageDestroy(reportComponentStatus); jausMessageDestroy(message); return true; } bool NodeManagerComponent::processQueryHeartbeatPulse(JausMessage message) { JausMessage txMessage = NULL; ReportHeartbeatPulseMessage reportHeartbeat = NULL; reportHeartbeat = reportHeartbeatPulseMessageCreate(); if(!reportHeartbeat) { // TODO: Log Error. Throw Exception. jausMessageDestroy(message); return false; } jausAddressCopy(reportHeartbeat->source, cmpt->address); jausAddressCopy(reportHeartbeat->destination, message->source); txMessage = reportHeartbeatPulseMessageToJausMessage(reportHeartbeat); if(txMessage) { this->commMngr->receiveJausMessage(txMessage, this); } jausMessageDestroy(message); return true; } bool NodeManagerComponent::processQueryConfiguration(JausMessage message) { QueryConfigurationMessage queryConf = NULL; ReportConfigurationMessage reportConf = NULL; JausMessage txMessage = NULL; JausNode node = NULL; queryConf = queryConfigurationMessageFromJausMessage(message); if(!queryConf) { // TODO: Log Error. Throw Exception. // Error unpacking message jausMessageDestroy(message); return false; } switch(queryConf->queryField) { case JAUS_SUBSYSTEM_CONFIGURATION: // Subsystem Configuration requests should go to the Communicator! // This is included for backwards compatibility and other implementation support if(this->commMngr->getMessageRouter()->subsystemCommunicationEnabled()) { reportConf = reportConfigurationMessageCreate(); if(!reportConf) { // TODO: Log Error. Throw Exception queryConfigurationMessageDestroy(queryConf); jausMessageDestroy(message); return false; } // Remove the subsystem created by the constructor jausSubsystemDestroy(reportConf->subsystem); // This call to the systemTree returns a copy, so safe to set this pointer to it reportConf->subsystem = systemTree->getSubsystem(this->cmpt->address->subsystem); if(reportConf->subsystem) { txMessage = reportConfigurationMessageToJausMessage(reportConf); jausAddressCopy(txMessage->source, cmpt->address); jausAddressCopy(txMessage->destination, reportConf->source); if(txMessage) { this->commMngr->receiveJausMessage(txMessage, this); } } reportConfigurationMessageDestroy(reportConf); queryConfigurationMessageDestroy(queryConf); jausMessageDestroy(message); return true; } else { // This NM is not connected to the subsystem network, // therefore no one should be asking us for subsystem configuration // TODO: Log Error. Throw Exception. queryConfigurationMessageDestroy(queryConf); jausMessageDestroy(message); return false; } case JAUS_NODE_CONFIGURATION: reportConf = reportConfigurationMessageCreate(); if(!reportConf) { // TODO: Log Error. Throw Exception queryConfigurationMessageDestroy(queryConf); jausMessageDestroy(message); return false; } // This call to the systemTree returns a copy, so safe to set this pointer to it node = systemTree->getNode(this->cmpt->address->subsystem, this->cmpt->address->node); if(node) { jausArrayAdd(reportConf->subsystem->nodes, node); } txMessage = reportConfigurationMessageToJausMessage(reportConf); jausAddressCopy(txMessage->source, cmpt->address); jausAddressCopy(txMessage->destination, queryConf->source); if(txMessage) { this->commMngr->receiveJausMessage(txMessage, this); } reportConfigurationMessageDestroy(reportConf); queryConfigurationMessageDestroy(queryConf); jausMessageDestroy(message); return true; default: // TODO: Log Error. Throw Exception. // Unknown query type queryConfigurationMessageDestroy(queryConf); jausMessageDestroy(message); return false; } } bool NodeManagerComponent::processQueryIdentification(JausMessage message) { QueryIdentificationMessage queryId = NULL; ReportIdentificationMessage reportId = NULL; JausMessage txMessage = NULL; char *identification = NULL; queryId = queryIdentificationMessageFromJausMessage(message); if(!queryId) { // TODO: Log Error. Throw Exception. // Error unpacking message jausMessageDestroy(message); return false; } switch(queryId->queryField) { case JAUS_QUERY_FIELD_SS_IDENTITY: // Subsystem Configuration requests should go to the Communicator! // This is included for backwards compatibility and other implementation support if(this->commMngr->getMessageRouter()->subsystemCommunicationEnabled()) { reportId = reportIdentificationMessageCreate(); if(!reportId) { // TODO: Log Error. Throw Exception queryIdentificationMessageDestroy(queryId); jausMessageDestroy(message); return false; } identification = systemTree->getSubsystemIdentification(cmpt->address); if(strlen(identification) < JAUS_IDENTIFICATION_LENGTH_BYTES) { sprintf(reportId->identification, "%s", identification); } else { memcpy(reportId->identification, identification, JAUS_IDENTIFICATION_LENGTH_BYTES-1); reportId->identification[JAUS_IDENTIFICATION_LENGTH_BYTES-1] = 0; } reportId->queryType = JAUS_QUERY_FIELD_SS_IDENTITY; jausAddressCopy(reportId->source, cmpt->address); jausAddressCopy(reportId->destination, queryId->source); txMessage = reportIdentificationMessageToJausMessage(reportId); if(txMessage) { this->commMngr->receiveJausMessage(txMessage, this); } reportIdentificationMessageDestroy(reportId); queryIdentificationMessageDestroy(queryId); jausMessageDestroy(message); return true; } else { // This NM is not connected to the subsystem network, // therefore no one should be asking us for subsystem configuration // TODO: Log Error. Throw Exception. queryIdentificationMessageDestroy(queryId); jausMessageDestroy(message); return false; } case JAUS_QUERY_FIELD_NODE_IDENTITY: reportId = reportIdentificationMessageCreate(); if(!reportId) { // TODO: Log Error. Throw Exception queryIdentificationMessageDestroy(queryId); jausMessageDestroy(message); return false; } identification = systemTree->getNodeIdentification(cmpt->address); if(strlen(identification) < JAUS_IDENTIFICATION_LENGTH_BYTES) { sprintf(reportId->identification, "%s", identification); } else { memcpy(reportId->identification, identification, JAUS_IDENTIFICATION_LENGTH_BYTES-1); reportId->identification[JAUS_IDENTIFICATION_LENGTH_BYTES-1] = 0; } free(identification); reportId->queryType = JAUS_QUERY_FIELD_NODE_IDENTITY; txMessage = reportIdentificationMessageToJausMessage(reportId); jausAddressCopy(txMessage->source, cmpt->address); jausAddressCopy(txMessage->destination, queryId->source); if(txMessage) { this->commMngr->receiveJausMessage(txMessage, this); } reportIdentificationMessageDestroy(reportId); queryIdentificationMessageDestroy(queryId); jausMessageDestroy(message); return true; case JAUS_QUERY_FIELD_COMPONENT_IDENTITY: reportId = reportIdentificationMessageCreate(); if(!reportId) { // TODO: Log Error. Throw Exception queryIdentificationMessageDestroy(queryId); jausMessageDestroy(message); return false; } identification = cmpt->identification; if(strlen(identification) < JAUS_IDENTIFICATION_LENGTH_BYTES) { sprintf(reportId->identification, "%s", identification); } else { memcpy(reportId->identification, identification, JAUS_IDENTIFICATION_LENGTH_BYTES-1); reportId->identification[JAUS_IDENTIFICATION_LENGTH_BYTES-1] = 0; } reportId->queryType = JAUS_QUERY_FIELD_COMPONENT_IDENTITY; txMessage = reportIdentificationMessageToJausMessage(reportId); jausAddressCopy(txMessage->source, cmpt->address); jausAddressCopy(txMessage->destination, queryId->source); if(txMessage) { this->commMngr->receiveJausMessage(txMessage, this); } reportIdentificationMessageDestroy(reportId); queryIdentificationMessageDestroy(queryId); jausMessageDestroy(message); return true; default: queryIdentificationMessageDestroy(queryId); jausMessageDestroy(message); return false; } } bool NodeManagerComponent::processQueryServices(JausMessage message) { QueryServicesMessage queryServices = NULL; ReportServicesMessage reportServices = NULL; JausMessage txMessage = NULL; queryServices = queryServicesMessageFromJausMessage(message); if(!queryServices) { // TODO: Log Error. Throw Exception. jausMessageDestroy(message); return false; } // Respond with our services reportServices = reportServicesMessageCreate(); if(!reportServices) { // TODO: Log Error. Throw Exception. queryServicesMessageDestroy(queryServices); jausMessageDestroy(message); return false; } jausAddressCopy(reportServices->destination, message->source); jausAddressCopy(reportServices->source, cmpt->address); jausServicesDestroy(reportServices->jausServices); reportServices->jausServices = jausServicesClone(cmpt->services); txMessage = reportServicesMessageToJausMessage(reportServices); if(txMessage) { this->commMngr->receiveJausMessage(txMessage, this); } reportServicesMessageDestroy(reportServices); queryServicesMessageDestroy(queryServices); jausMessageDestroy(message); return true; } bool NodeManagerComponent::processConfirmEvent(JausMessage message) { // Not currently implemented jausMessageDestroy(message); return true; } bool NodeManagerComponent::processEvent(JausMessage message) { EventMessage eventMessage; eventMessage = eventMessageFromJausMessage(message); if(!eventMessage) { // Error unpacking the eventMessage ErrorEvent *e = new ErrorEvent(ErrorEvent::Memory, __FUNCTION__, __LINE__, "Cannot unpack EventMessage!"); this->eventHandler->handleEvent(e); jausMessageDestroy(message); return false; } processMessage(jausMessageClone(eventMessage->reportMessage)); eventMessageDestroy(eventMessage); jausMessageDestroy(message); return true; } void NodeManagerComponent::sendNodeChangedEvents() { ReportConfigurationMessage reportConf = NULL; JausMessage txMessage = NULL; EventMessage eventMessage = NULL; HASH_MAP ::iterator iterator; JausNode thisNode = systemTree->getNode(this->cmpt->address); if(!thisNode) { // TODO: Record an error. Throw Exception return; } reportConf = reportConfigurationMessageCreate(); if(!reportConf) { // TODO: Record an error. Throw Exception jausNodeDestroy(thisNode); return; } jausArrayAdd(reportConf->subsystem->nodes, (void *)thisNode); eventMessage = eventMessageCreate(); if(!eventMessage) { // TODO: Record an error. Throw Exception reportConfigurationMessageDestroy(reportConf); return; } eventMessage->reportMessage = reportConfigurationMessageToJausMessage(reportConf); if(!eventMessage->reportMessage) { // TODO: Record an error. Throw Exception reportConfigurationMessageDestroy(reportConf); eventMessageDestroy(eventMessage); return; } jausAddressCopy(eventMessage->source, cmpt->address); // TODO: Go through nodeChangeList looking for dead addresses for(iterator = nodeChangeList.begin(); iterator != nodeChangeList.end(); iterator++) { eventMessage->eventId = iterator->first; jausAddressCopy(eventMessage->destination, iterator->second); txMessage = eventMessageToJausMessage(eventMessage); this->commMngr->receiveJausMessage(jausMessageClone(txMessage), this); char buf[256]; sprintf(buf, "Send Node Changed event to %d.%d.%d.%d.", txMessage->destination->subsystem, txMessage->destination->node, txMessage->destination->component, txMessage->destination->instance); DebugEvent *e = new DebugEvent("Event", __FUNCTION__, __LINE__, buf); this->eventHandler->handleEvent(e); } eventMessageDestroy(eventMessage); // NMJ jausMessageDestroy(txMessage); reportConfigurationMessageDestroy(reportConf); } void NodeManagerComponent::sendSubsystemChangedEvents() { ReportConfigurationMessage reportConf = NULL; JausMessage txMessage = NULL; EventMessage eventMessage = NULL; HASH_MAP ::iterator iterator; JausSubsystem thisSubs = systemTree->getSubsystem(this->cmpt->address); if(!thisSubs) { // TODO: Record an error. Throw Exception return; } reportConf = reportConfigurationMessageCreate(); if(!reportConf) { // TODO: Record an error. Throw Exception jausSubsystemDestroy(thisSubs); return; } jausSubsystemDestroy(reportConf->subsystem); reportConf->subsystem = thisSubs; eventMessage = eventMessageCreate(); if(!eventMessage) { // TODO: Record an error. Throw Exception reportConfigurationMessageDestroy(reportConf); return; } eventMessage->reportMessage = reportConfigurationMessageToJausMessage(reportConf); if(!eventMessage->reportMessage) { // TODO: Record an error. Throw Exception reportConfigurationMessageDestroy(reportConf); eventMessageDestroy(eventMessage); return; } jausAddressCopy(eventMessage->source, cmpt->address); // TODO: check subsystemChangeList for dead addresses for(iterator = subsystemChangeList.begin(); iterator != subsystemChangeList.end(); iterator++) { eventMessage->eventId = iterator->first; jausAddressCopy(eventMessage->destination, iterator->second); txMessage = eventMessageToJausMessage(eventMessage); this->commMngr->receiveJausMessage(jausMessageClone(txMessage), this); char buf[256]; sprintf(buf, "Send Subs Changed event to %d.%d.%d.%d.", txMessage->destination->subsystem, txMessage->destination->node, txMessage->destination->component, txMessage->destination->instance); DebugEvent *e = new DebugEvent("Event", __FUNCTION__, __LINE__, buf); this->eventHandler->handleEvent(e); } eventMessageDestroy(eventMessage); jausMessageDestroy(txMessage); reportConfigurationMessageDestroy(reportConf); } void NodeManagerComponent::sendNodeShutdownEvents() { ReportConfigurationMessage reportConf = NULL; JausMessage txMessage = NULL; EventMessage eventMessage = NULL; HASH_MAP ::iterator iterator; reportConf = reportConfigurationMessageCreate(); if(!reportConf) { // TODO: Record an error. Throw Exception return; } JausNode emptyNode = jausNodeCreate(); if(!emptyNode) { // TODO: Record an error. Throw Exception reportConfigurationMessageDestroy(reportConf); return; } emptyNode->id = this->cmpt->address->node; jausArrayAdd(reportConf->subsystem->nodes, (void *)emptyNode); eventMessage = eventMessageCreate(); if(!eventMessage) { // TODO: Record an error. Throw Exception reportConfigurationMessageDestroy(reportConf); return; } eventMessage->reportMessage = reportConfigurationMessageToJausMessage(reportConf); if(!eventMessage->reportMessage) { // TODO: Record an error. Throw Exception reportConfigurationMessageDestroy(reportConf); eventMessageDestroy(eventMessage); return; } jausAddressCopy(eventMessage->source, cmpt->address); // TODO: Go through nodeChangeList looking for dead addresses for(iterator = nodeChangeList.begin(); iterator != nodeChangeList.end(); iterator++) { eventMessage->eventId = iterator->first; jausAddressCopy(eventMessage->destination, iterator->second); txMessage = eventMessageToJausMessage(eventMessage); this->commMngr->receiveJausMessage(jausMessageClone(txMessage), this); char buf[256]; sprintf(buf, "Send Node Shutdown event to %d.%d.%d.%d.", txMessage->destination->subsystem, txMessage->destination->node, txMessage->destination->component, txMessage->destination->instance); DebugEvent *e = new DebugEvent("Event", __FUNCTION__, __LINE__, buf); this->eventHandler->handleEvent(e); } eventMessageDestroy(eventMessage); jausMessageDestroy(txMessage); reportConfigurationMessageDestroy(reportConf); } void NodeManagerComponent::sendSubsystemShutdownEvents() { ReportConfigurationMessage reportConf = NULL; JausMessage txMessage = NULL; EventMessage eventMessage = NULL; HASH_MAP ::iterator iterator; reportConf = reportConfigurationMessageCreate(); if(!reportConf) { // TODO: Record an error. Throw Exception return; } // Empty Subsystem for message JausSubsystem emptySubs = jausSubsystemCreate(); if(!emptySubs) { // TODO: Record an error. Throw Exception reportConfigurationMessageDestroy(reportConf); return; } emptySubs->id = this->cmpt->address->subsystem; jausSubsystemDestroy(reportConf->subsystem); reportConf->subsystem = emptySubs; eventMessage = eventMessageCreate(); if(!eventMessage) { // TODO: Record an error. Throw Exception reportConfigurationMessageDestroy(reportConf); return; } eventMessage->reportMessage = reportConfigurationMessageToJausMessage(reportConf); if(!eventMessage->reportMessage) { // TODO: Record an error. Throw Exception reportConfigurationMessageDestroy(reportConf); eventMessageDestroy(eventMessage); return; } jausAddressCopy(eventMessage->source, cmpt->address); // TODO: check subsystemChangeList for dead addresses for(iterator = subsystemChangeList.begin(); iterator != subsystemChangeList.end(); iterator++) { eventMessage->eventId = iterator->first; jausAddressCopy(eventMessage->destination, iterator->second); txMessage = eventMessageToJausMessage(eventMessage); this->commMngr->receiveJausMessage(jausMessageClone(txMessage), this); char buf[256]; sprintf(buf, "Send Subs Shutdown event to %d.%d.%d.%d.", txMessage->destination->subsystem, txMessage->destination->node, txMessage->destination->component, txMessage->destination->instance); DebugEvent *e = new DebugEvent("Event", __FUNCTION__, __LINE__, buf); this->eventHandler->handleEvent(e); } eventMessageDestroy(eventMessage); jausMessageDestroy(txMessage); reportConfigurationMessageDestroy(reportConf); } void NodeManagerComponent::generateHeartbeats() { static double nextSendTime = ojGetTimeSec(); ReportHeartbeatPulseMessage heartbeat; JausMessage nodeHeartbeat; JausMessage cmptHeartbeat; if(ojGetTimeSec() >= nextSendTime) { heartbeat = reportHeartbeatPulseMessageCreate(); if(!heartbeat) { // Error constructing message // TODO: Log Error. return; } jausAddressCopy(heartbeat->source, cmpt->address); nodeHeartbeat = reportHeartbeatPulseMessageToJausMessage(heartbeat); if(!nodeHeartbeat) { // Error constructing message // TODO: Log Error. reportHeartbeatPulseMessageDestroy(heartbeat); return; } cmptHeartbeat = reportHeartbeatPulseMessageToJausMessage(heartbeat); if(!cmptHeartbeat) { // Error constructing message // TODO: Log Error. jausMessageDestroy(nodeHeartbeat); reportHeartbeatPulseMessageDestroy(heartbeat); return; } // Send Heartbeat to other node managers on this subsystem nodeHeartbeat->destination->subsystem = cmpt->address->subsystem; nodeHeartbeat->destination->node = JAUS_BROADCAST_NODE_ID; nodeHeartbeat->destination->component = JAUS_NODE_MANAGER_COMPONENT; nodeHeartbeat->destination->instance = 1; this->commMngr->receiveJausMessage(nodeHeartbeat, this); // Send Heartbeat to components on this node cmptHeartbeat->destination->subsystem = cmpt->address->subsystem; cmptHeartbeat->destination->node = cmpt->address->node; cmptHeartbeat->destination->component = JAUS_BROADCAST_COMPONENT_ID; cmptHeartbeat->destination->instance = JAUS_BROADCAST_INSTANCE_ID; this->commMngr->receiveJausMessage(cmptHeartbeat, this); nextSendTime = ojGetTimeSec() + 1.0; reportHeartbeatPulseMessageDestroy(heartbeat); } } bool NodeManagerComponent::sendQueryNodeIdentification(JausAddress address) { QueryIdentificationMessage queryId = NULL; JausMessage txMessage = NULL; // TODO: Check timeout and request limit if( systemTree->hasNode(address) && !systemTree->hasNodeIdentification(address)) { // Create query message queryId = queryIdentificationMessageCreate(); if(!queryId) { // Constructor Failed return false; } queryId->queryField = JAUS_QUERY_FIELD_NODE_IDENTITY; txMessage = queryIdentificationMessageToJausMessage(queryId); if(!txMessage) { // ToJausMessage Failed queryIdentificationMessageDestroy(queryId); return false; } jausAddressCopy(txMessage->destination, address); jausAddressCopy(txMessage->source, cmpt->address); this->commMngr->receiveJausMessage(txMessage, this); queryIdentificationMessageDestroy(queryId); return true; } return false; } bool NodeManagerComponent::sendQuerySubsystemIdentification(JausAddress address) { QueryIdentificationMessage queryId = NULL; JausMessage txMessage = NULL; // TODO: Check timeout and request limit if( systemTree->hasSubsystem(address) && !systemTree->hasSubsystemIdentification(address)) { // Create query message queryId = queryIdentificationMessageCreate(); if(!queryId) { // Constructor Failed return false; } queryId->queryField = JAUS_QUERY_FIELD_SS_IDENTITY; txMessage = queryIdentificationMessageToJausMessage(queryId); if(!txMessage) { // ToJausMessage Failed queryIdentificationMessageDestroy(queryId); return false; } jausAddressCopy(txMessage->destination, address); jausAddressCopy(txMessage->source, cmpt->address); this->commMngr->receiveJausMessage(txMessage, this); queryIdentificationMessageDestroy(queryId); return true; } return false; } bool NodeManagerComponent::sendQueryComponentIdentification(JausAddress address) { QueryIdentificationMessage queryId = NULL; JausMessage txMessage = NULL; // TODO: Check timeout and request limit if(systemTree->hasComponent(address) && !systemTree->hasComponentIdentification(address)) { // Create query message queryId = queryIdentificationMessageCreate(); if(!queryId) { // Constructor Failed return false; } queryId->queryField = JAUS_QUERY_FIELD_COMPONENT_IDENTITY; txMessage = queryIdentificationMessageToJausMessage(queryId); if(!txMessage) { // ToJausMessage Failed queryIdentificationMessageDestroy(queryId); return false; } jausAddressCopy(txMessage->destination, address); jausAddressCopy(txMessage->source, cmpt->address); this->commMngr->receiveJausMessage(txMessage, this); queryIdentificationMessageDestroy(queryId); return true; } return false; } bool NodeManagerComponent::sendQueryComponentServices(JausAddress address) { QueryServicesMessage query = NULL; JausMessage txMessage = NULL; // TODO: Check timeout and request limit if( systemTree->hasComponent(address) && !systemTree->hasComponentServices(address)) { // Create query message query = queryServicesMessageCreate(); if(!query) { // Constructor Failed return false; } txMessage = queryServicesMessageToJausMessage(query); if(!txMessage) { // ToJausMessage Failed queryServicesMessageDestroy(query); return false; } jausAddressCopy(txMessage->destination, address); jausAddressCopy(txMessage->source, cmpt->address); this->commMngr->receiveJausMessage(txMessage, this); queryServicesMessageDestroy(query); return true; } return false; } bool NodeManagerComponent::sendQueryNodeConfiguration(JausAddress address, bool createEvent) { QueryConfigurationMessage query = NULL; JausMessage txMessage = NULL; CreateEventMessage createEventMsg = NULL; // TODO: Check timeout and request limit if( systemTree->hasNode(address) && !systemTree->hasNodeConfiguration(address)) { // Create query message query = queryConfigurationMessageCreate(); if(!query) { // Constructor Failed return false; } query->queryField = JAUS_NODE_CONFIGURATION; txMessage = queryConfigurationMessageToJausMessage(query); if(!txMessage) { // ToJausMessage Failed queryConfigurationMessageDestroy(query); return false; } jausAddressCopy(txMessage->destination, address); jausAddressCopy(txMessage->source, cmpt->address); this->commMngr->receiveJausMessage(txMessage, this); if(createEvent) { createEventMsg = createEventMessageCreate(); if(!createEventMsg) { queryConfigurationMessageDestroy(query); return false; } // Setup Create Event PV createEventMsg->presenceVector = 0; jausByteSetBit(&createEventMsg->presenceVector, CREATE_EVENT_PV_QUERY_MESSAGE_BIT); createEventMsg->reportMessageCode = jausMessageGetComplimentaryCommandCode(query->commandCode); createEventMsg->eventType = EVENT_EVERY_CHANGE_TYPE; createEventMsg->queryMessage = queryConfigurationMessageToJausMessage(query); if(!createEventMsg->queryMessage) { // Problem with queryConfigurationMessageToJausMessage createEventMessageDestroy(createEventMsg); queryConfigurationMessageDestroy(query); return false; } txMessage = createEventMessageToJausMessage(createEventMsg); if(!txMessage) { // Problem with createEventMsgMessageToJausMessage createEventMessageDestroy(createEventMsg); queryConfigurationMessageDestroy(query); return false; } jausAddressCopy(txMessage->destination, address); jausAddressCopy(txMessage->source, cmpt->address); this->commMngr->receiveJausMessage(txMessage, this); createEventMessageDestroy(createEventMsg); } queryConfigurationMessageDestroy(query); return true; } return false; } bool NodeManagerComponent::sendQuerySubsystemConfiguration(JausAddress address, bool createEvent) { QueryConfigurationMessage query = NULL; JausMessage txMessage = NULL; CreateEventMessage createEventMsg = NULL; // TODO: Check timeout and request limit if( systemTree->hasSubsystem(address) && !systemTree->hasSubsystemConfiguration(address)) { // Create query message query = queryConfigurationMessageCreate(); if(!query) { // Constructor Failed return false; } query->queryField = JAUS_SUBSYSTEM_CONFIGURATION; txMessage = queryConfigurationMessageToJausMessage(query); if(!txMessage) { // ToJausMessage Failed queryConfigurationMessageDestroy(query); return false; } jausAddressCopy(txMessage->destination, address); jausAddressCopy(txMessage->source, cmpt->address); this->commMngr->receiveJausMessage(txMessage, this); // Send Query Node Configuration if(createEvent) { createEventMsg = createEventMessageCreate(); if(!createEventMsg) { queryConfigurationMessageDestroy(query); return false; } // Setup Create Event PV createEventMsg->presenceVector = 0; jausByteSetBit(&createEventMsg->presenceVector, CREATE_EVENT_PV_QUERY_MESSAGE_BIT); createEventMsg->reportMessageCode = jausMessageGetComplimentaryCommandCode(query->commandCode); createEventMsg->eventType = EVENT_EVERY_CHANGE_TYPE; createEventMsg->queryMessage = queryConfigurationMessageToJausMessage(query); if(!createEventMsg->queryMessage) { // Problem with queryConfigurationMessageToJausMessage createEventMessageDestroy(createEventMsg); queryConfigurationMessageDestroy(query); return false; } txMessage = createEventMessageToJausMessage(createEventMsg); if(!txMessage) { // Problem with createEventMsgMessageToJausMessage createEventMessageDestroy(createEventMsg); queryConfigurationMessageDestroy(query); return false; } jausAddressCopy(txMessage->destination, address); jausAddressCopy(txMessage->source, cmpt->address); this->commMngr->receiveJausMessage(txMessage, this); createEventMessageDestroy(createEventMsg); } queryConfigurationMessageDestroy(query); return true; } return false; } int NodeManagerComponent::getNextEventId() { int i; for(i = 0; i < MAXIMUM_EVENT_ID; i++) { if(eventId[i] == false) { return i; } } return -1; } bool NodeManagerComponent::setupJausServices() { JausService service; service = jausServiceCreate(0); if(!service) return false; jausServiceAddInputCommand(service, JAUS_SET_COMPONENT_AUTHORITY, NO_PRESENCE_VECTOR); jausServiceAddInputCommand(service, JAUS_SHUTDOWN, NO_PRESENCE_VECTOR); jausServiceAddInputCommand(service, JAUS_STANDBY, NO_PRESENCE_VECTOR); jausServiceAddInputCommand(service, JAUS_RESUME, NO_PRESENCE_VECTOR); jausServiceAddInputCommand(service, JAUS_RESET, NO_PRESENCE_VECTOR); jausServiceAddInputCommand(service, JAUS_SET_EMERGENCY, NO_PRESENCE_VECTOR); jausServiceAddInputCommand(service, JAUS_CLEAR_EMERGENCY, NO_PRESENCE_VECTOR); jausServiceAddInputCommand(service, JAUS_CREATE_SERVICE_CONNECTION, NO_PRESENCE_VECTOR); jausServiceAddInputCommand(service, JAUS_ACTIVATE_SERVICE_CONNECTION, NO_PRESENCE_VECTOR); jausServiceAddInputCommand(service, JAUS_SUSPEND_SERVICE_CONNECTION, NO_PRESENCE_VECTOR); jausServiceAddInputCommand(service, JAUS_TERMINATE_SERVICE_CONNECTION, NO_PRESENCE_VECTOR); jausServiceAddInputCommand(service, JAUS_REQUEST_COMPONENT_CONTROL, NO_PRESENCE_VECTOR); jausServiceAddInputCommand(service, JAUS_QUERY_COMPONENT_AUTHORITY, NO_PRESENCE_VECTOR); jausServiceAddInputCommand(service, JAUS_QUERY_COMPONENT_STATUS, NO_PRESENCE_VECTOR); jausServiceAddInputCommand(service, JAUS_QUERY_HEARTBEAT_PULSE, NO_PRESENCE_VECTOR); jausServiceAddOutputCommand(service, JAUS_CREATE_SERVICE_CONNECTION, NO_PRESENCE_VECTOR); jausServiceAddOutputCommand(service, JAUS_CONFIRM_SERVICE_CONNECTION, NO_PRESENCE_VECTOR); jausServiceAddOutputCommand(service, JAUS_TERMINATE_SERVICE_CONNECTION, NO_PRESENCE_VECTOR); jausServiceAddOutputCommand(service, JAUS_CONFIRM_COMPONENT_CONTROL, NO_PRESENCE_VECTOR); jausServiceAddOutputCommand(service, JAUS_REJECT_COMPONENT_CONTROL, NO_PRESENCE_VECTOR); jausServiceAddOutputCommand(service, JAUS_REPORT_COMPONENT_AUTHORITY, NO_PRESENCE_VECTOR); jausServiceAddOutputCommand(service, JAUS_REPORT_COMPONENT_STATUS, NO_PRESENCE_VECTOR); jausServiceAddOutputCommand(service, JAUS_REPORT_HEARTBEAT_PULSE, NO_PRESENCE_VECTOR); jausServiceAddOutputCommand(service, JAUS_QUERY_COMPONENT_STATUS, NO_PRESENCE_VECTOR); // Add Core Service jausServiceAddService(cmpt->services, service); service = jausServiceCreate(JAUS_NODE_MANAGER); if(!service) return false; jausServiceAddInputCommand(service, JAUS_QUERY_CONFIGURATION, NO_PRESENCE_VECTOR); jausServiceAddInputCommand(service, JAUS_QUERY_IDENTIFICATION, NO_PRESENCE_VECTOR); jausServiceAddInputCommand(service, JAUS_QUERY_SERVICES, NO_PRESENCE_VECTOR); jausServiceAddInputCommand(service, JAUS_REPORT_CONFIGURATION, NO_PRESENCE_VECTOR); jausServiceAddInputCommand(service, JAUS_REPORT_IDENTIFICATION, NO_PRESENCE_VECTOR); jausServiceAddInputCommand(service, JAUS_REPORT_SERVICES, NO_PRESENCE_VECTOR); jausServiceAddInputCommand(service, JAUS_CANCEL_EVENT, NO_PRESENCE_VECTOR); jausServiceAddInputCommand(service, JAUS_CONFIRM_EVENT_REQUEST, NO_PRESENCE_VECTOR); jausServiceAddInputCommand(service, JAUS_CREATE_EVENT, NO_PRESENCE_VECTOR); jausServiceAddOutputCommand(service, JAUS_QUERY_CONFIGURATION, NO_PRESENCE_VECTOR); jausServiceAddOutputCommand(service, JAUS_QUERY_IDENTIFICATION, NO_PRESENCE_VECTOR); jausServiceAddOutputCommand(service, JAUS_QUERY_SERVICES, NO_PRESENCE_VECTOR); jausServiceAddOutputCommand(service, JAUS_REPORT_CONFIGURATION, NO_PRESENCE_VECTOR); jausServiceAddOutputCommand(service, JAUS_REPORT_IDENTIFICATION, NO_PRESENCE_VECTOR); jausServiceAddOutputCommand(service, JAUS_REPORT_SERVICES, NO_PRESENCE_VECTOR); jausServiceAddOutputCommand(service, JAUS_CANCEL_EVENT, NO_PRESENCE_VECTOR); jausServiceAddOutputCommand(service, JAUS_CONFIRM_EVENT_REQUEST, NO_PRESENCE_VECTOR); jausServiceAddOutputCommand(service, JAUS_CREATE_EVENT, NO_PRESENCE_VECTOR); // Add Node Manager Service jausServiceAddService(cmpt->services, service); return true; } void NodeManagerComponent::handleEvent(NodeManagerEvent *e) { SystemTreeEvent *treeEvent; switch(e->getType()) { case NodeManagerEvent::SystemTreeEvent: treeEvent = (SystemTreeEvent *)e; switch(treeEvent->getSubType()) { case SystemTreeEvent::NodeTimeout: this->sendSubsystemChangedEvents(); break; case SystemTreeEvent::ComponentTimeout: this->sendSubsystemChangedEvents(); this->sendNodeChangedEvents(); break; default: // Nothing break; } delete e; break; default: delete e; break; } }