本文整理汇总了C++中Connection::CreateSMLCommand方法的典型用法代码示例。如果您正苦于以下问题:C++ Connection::CreateSMLCommand方法的具体用法?C++ Connection::CreateSMLCommand怎么用?C++ Connection::CreateSMLCommand使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类Connection
的用法示例。
在下文中一共展示了Connection::CreateSMLCommand方法的12个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: OnKernelEvent
// Called when an event occurs in the kernel
void RunListener::OnKernelEvent(int eventID, AgentSML* pAgentSML, void* pCallData)
{
// Get the first listener for this event (or return if there are none)
ConnectionListIter connectionIter ;
if (!EventManager<smlRunEventId>::GetBegin(smlRunEventId(eventID), &connectionIter))
{
return ;
}
// We need the first connection for when we're building the message. Perhaps this is a sign that
// we shouldn't have rolled these methods into Connection.
Connection* pConnection = *connectionIter ;
// Convert eventID to a string
char const* event = m_pKernelSML->ConvertEventToString(eventID) ;
// Convert phase to a string
int phase = static_cast<int>(reinterpret_cast<intptr_t>(pCallData)) ;
// Build the SML message we're doing to send.
soarxml::ElementXML* pMsg = pConnection->CreateSMLCommand(sml_Names::kCommand_Event) ;
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamAgent, pAgentSML->GetName()) ;
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamEventID, event) ;
char buf[TO_C_STRING_BUFSIZE];
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamPhase, to_c_string(phase, buf)) ;
// Send the message out
AnalyzeXML response ;
SendEvent(pAgentSML, pConnection, pMsg, &response, connectionIter, GetEnd(smlRunEventId(eventID))) ;
// Clean up
delete pMsg ;
}
示例2: OnKernelEvent
// Called when an event occurs in the kernel
void StringListener::OnKernelEvent(int eventIDIn, AgentSML* pAgentSML, void* pCallData)
{
// There are currently no kernel events corresponding to this SML event.
// They are all directly generated from SML. If we later add kernel callbacks
// for this class of events they would come here.
smlStringEventId eventID = static_cast<smlStringEventId>(eventIDIn);
StringListenerCallbackData* pCallbackData = static_cast<StringListenerCallbackData*>(pCallData);
assert(pCallbackData);
memset(pCallbackData->pReturnStringBuffer, 0, pCallbackData->maxLengthReturnStringBuffer);
// Get the first listener for this event (or return if there are none)
ConnectionListIter connectionIter ;
if (!EventManager<smlStringEventId>::GetBegin(eventID, &connectionIter))
{
return;
}
// We need the first connection for when we're building the message. Perhaps this is a sign that
// we shouldn't have rolled these methods into Connection.
Connection* pConnection = *connectionIter ;
// Convert eventID to a string
char const* event = m_pKernelSML->ConvertEventToString(eventID) ;
// Build the SML message we're doing to send.
soarxml::ElementXML* pMsg = pConnection->CreateSMLCommand(sml_Names::kCommand_Event) ;
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamEventID, event) ;
if (pCallbackData->pData)
{
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamValue, pCallbackData->pData) ;
}
// Note: we should be telling the client the maximum length of the result,
// however, we're planning on changing this so there is no maximum length
// so we're not implementing this.
// Send the message out
AnalyzeXML response ;
SendEvent(pAgentSML, pConnection, pMsg, &response, connectionIter, GetEnd(eventID)) ;
char const* pResult = response.GetResultString() ;
if (pResult != NULL)
{
// If the listener returns a result then take that
// value and return it in "pReturnValue" to the caller.
// If the client returns a longer string than the caller allowed we just truncate it.
// (In practice this shouldn't be a problem--just need to make sure nobody crashes on a super long return string).
strncpy(pCallbackData->pReturnStringBuffer, pResult, pCallbackData->maxLengthReturnStringBuffer) ;
pCallbackData->pReturnStringBuffer[ pCallbackData->maxLengthReturnStringBuffer - 1 ] = 0 ; // Make sure it's NULL terminated
}
// Clean up
delete pMsg ;
}
示例3: FireInputReceivedEvent
// Echo the list of wmes received back to any listeners
void XMLListener::FireInputReceivedEvent(soarxml::ElementXML const* pCommands)
{
smlXMLEventId eventID = smlEVENT_XML_INPUT_RECEIVED ;
// Get the first listener for this event (or return if there are none)
ConnectionListIter connectionIter ;
if (!EventManager<smlXMLEventId>::GetBegin(eventID, &connectionIter))
{
return ;
}
// Make a copy of pCommands and send it out.
// We need the first connection for when we're building the message. Perhaps this is a sign that
// we shouldn't have rolled these methods into Connection.
Connection* pConnection = *connectionIter;
// Convert eventID to a string
char const* event = m_pKernelSML->ConvertEventToString(eventID) ;
// Build the SML message we're going to send.
soarxml::ElementXML* pMsg = pConnection->CreateSMLCommand(sml_Names::kCommand_Event);
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamEventID, event);
// Add the agent parameter and as a side-effect, get a pointer to the <command> tag. This is an optimization.
ElementXML_Handle hCommand = pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamAgent, m_pCallbackAgentSML->GetName()) ;
soarxml::ElementXML command(hCommand) ;
// Copy the list of wmes from the input message over
int nWmes = pCommands->GetNumberChildren() ;
for (int i = 0 ; i < nWmes ; i++)
{
soarxml::ElementXML wme ;
pCommands->GetChild(&wme, i) ;
if (wme.IsTag(sml_Names::kTagWME))
{
soarxml::ElementXML* pCopy = wme.MakeCopy() ;
command.AddChild(pCopy) ;
}
}
// This is important. We are working with a subpart of pMsg.
// If we retain ownership of the handle and delete the object
// it will release the handle...deleting part of our message.
command.Detach() ;
// Send the message out
AnalyzeXML response ;
SendEvent(m_pCallbackAgentSML, pConnection, pMsg, &response, connectionIter, GetEnd(eventID)) ;
// Clean up
delete pMsg ;
}
示例4: OnKernelEvent
void XMLListener::OnKernelEvent(int eventIDIn, AgentSML* pAgentSML, void* pCallDataIn)
{
// If the print callbacks have been disabled, then don't forward this message
// on to the clients. This allows us to use the print callback within the kernel to
// retrieve information without it appearing in the trace. (One day we won't need to do this enable/disable game).
if (!m_EnablePrintCallback)
{
return ;
}
ElementXML* pXMLTrace = static_cast< ElementXML* >(pCallDataIn);
smlXMLEventId eventID = static_cast< smlXMLEventId >(eventIDIn);
// Nothing waiting to be sent, so we're done.
if (pXMLTrace->GetNumberChildren() == 0)
{
return ;
}
// Get the first listener for this event (or return if there are none)
ConnectionListIter connectionIter ;
if (!EventManager<smlXMLEventId>::GetBegin(eventID, &connectionIter))
{
return ;
}
// We need the first connection for when we're building the message. Perhaps this is a sign that
// we shouldn't have rolled these methods into Connection.
Connection* pConnection = *connectionIter;
// Convert eventID to a string
char const* event = m_pKernelSML->ConvertEventToString(eventID) ;
// Build the SML message we're going to send.
soarxml::ElementXML* pMsg = pConnection->CreateSMLCommand(sml_Names::kCommand_Event);
// NOTE: For this trace message we require that the agent name be the first param here (so we can look it up quickly)
// and any other changes to the structure of this message should be carefully checked to make sure they don't
// break the client side code as this path is more brittle and faster than the rest of the message passing.
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamAgent, m_pCallbackAgentSML->GetName());
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamEventID, event);
// Add it as a child of this message. This is just moving a few pointers around, nothing is getting copied.
// The structure of the message is <sml><command></command><trace></trace></sml>
pMsg->AddChild(pXMLTrace) ;
// Send the message out
AnalyzeXML response ;
SendEvent(pAgentSML, pConnection, pMsg, &response, connectionIter, GetEnd(eventID)) ;
// Clean up
delete pMsg ;
}
示例5: ExecuteCommandLine
// Execute the command line by building up an XML message and submitting it to our regular command processor.
bool RhsListener::ExecuteCommandLine(AgentSML* pAgent, char const* pFunctionName, char const* pArgument, int maxLengthReturnValue, char* pReturnValue)
{
KernelSML* pKernel = m_pKernelSML ;
// We'll pretend this came from the local (embedded) connection.
Connection* pConnection = pKernel->GetEmbeddedConnection() ;
// Build up a single command line from our functionName + argument combination
std::stringstream commandLine;
commandLine << pFunctionName;
if (pArgument)
{
commandLine << " " ;
commandLine << pArgument ;
}
// Build up a message to execute the command line
bool rawOutput = true ;
soarxml::ElementXML* pMsg = pConnection->CreateSMLCommand(sml_Names::kCommand_CommandLine, rawOutput) ;
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamAgent, pAgent->GetName());
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamLine, commandLine.str().c_str()) ;
AnalyzeXML incoming ;
incoming.Analyze(pMsg) ;
// Create a response object which the command line can fill in
soarxml::ElementXML* pResponse = pConnection->CreateSMLResponse(pMsg) ;
// Execute the command line
bool ok = pKernel->ProcessCommand(sml_Names::kCommand_CommandLine, pConnection, &incoming, pResponse) ;
if (ok)
{
// Take the result from executing the command line and fill it in to our "pReturnValue" array.
AnalyzeXML response ;
response.Analyze(pResponse) ;
char const* pResult = response.GetResultString() ;
if (pResult)
{
strncpy(pReturnValue, pResult, maxLengthReturnValue) ;
pReturnValue[maxLengthReturnValue-1] = 0 ;
}
}
// Clean up
delete pMsg ;
delete pResponse ;
return ok ;
}
示例6: OnKernelEvent
void ProductionListener::OnKernelEvent(int eventID, AgentSML* pAgentSML, void* pCallData)
{
// TODO: all event handlers should be doing this:
assert(IsProductionEventID(eventID)) ;
smlProductionEventId smlEventID = smlProductionEventId(eventID) ;
std::string productionName ;
// We're either passed a production* or an instantiation* depending on the type of event
production* p = 0;
if (smlEventID == smlEVENT_AFTER_PRODUCTION_ADDED || smlEventID == smlEVENT_BEFORE_PRODUCTION_REMOVED)
{
p = static_cast<production*>(pCallData) ;
}
else
{
instantiation* inst = static_cast<instantiation*>(pCallData) ;
assert(inst) ;
p = inst->prod ;
}
assert(p) ;
assert(p->name->sc.name) ;
productionName = p->name->sc.name ;
// Get the first listener for this event (or return if there are none)
ConnectionListIter connectionIter ;
if (!EventManager<smlProductionEventId>::GetBegin(smlProductionEventId(eventID), &connectionIter))
return ;
// We need the first connection for when we're building the message. Perhaps this is a sign that
// we shouldn't have rolled these methods into Connection.
Connection* pConnection = *connectionIter ;
// Convert eventID to a string
char const* event = m_pKernelSML->ConvertEventToString(eventID) ;
// Build the SML message we're doing to send.
soarxml::ElementXML* pMsg = pConnection->CreateSMLCommand(sml_Names::kCommand_Event) ;
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamAgent, pAgentSML->GetName()) ;
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamEventID, event) ;
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamName, productionName.c_str()) ;
// Send the message out
AnalyzeXML response ;
SendEvent(pAgentSML, pConnection, pMsg, &response, connectionIter, GetEnd(smlProductionEventId(eventID))) ;
// Clean up
delete pMsg ;
}
示例7: SendOutputInitEvent
void OutputListener::SendOutputInitEvent()
{
if (m_pCallbackAgentSML)
{
// Tell output link listeners about the reinitialize so they can clear out their output
// link identifier, as it may change due to existing smem lti (long term identifiers)
smlWorkingMemoryEventId outputEventId = smlEVENT_OUTPUT_PHASE_CALLBACK ;
// Get the first listener for this event (or return if there are none)
ConnectionListIter connectionIter ;
if (!EventManager<smlWorkingMemoryEventId>::GetBegin(outputEventId, &connectionIter))
{
return ;
}
// We need the first connection for when we're building the message. Perhaps this is a sign that
// we shouldn't have rolled these methods into Connection.
Connection* pConnection = *connectionIter ;
// Build the SML message we're doing to send.
soarxml::ElementXML* pMsg = pConnection->CreateSMLCommand(sml_Names::kCommand_OutputInit) ;
// Add the agent parameter and as a side-effect, get a pointer to the <command> tag. This is an optimization.
ElementXML_Handle hCommand = pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamAgent, m_pCallbackAgentSML->GetName()) ;
soarxml::ElementXML command(hCommand) ;
// This is important. We are working with a subpart of pMsg.
// If we retain ownership of the handle and delete the object
// it will release the handle...deleting part of our message.
command.Detach() ;
#ifdef _DEBUG
// Convert the XML to a string so we can look at it in the debugger
char* pStr = pMsg->GenerateXMLString(true) ;
#endif
// Send the message out
AnalyzeXML response ;
SendEvent(m_pCallbackAgentSML, pConnection, pMsg, &response, connectionIter, GetEnd(outputEventId)) ;
#ifdef _DEBUG
pMsg->DeleteString(pStr) ;
#endif
// Clean up
delete pMsg ;
}
}
示例8: FlushOutput
void PrintListener::FlushOutput(Connection* pSourceConnection, smlPrintEventId eventID)
{
int buffer = eventID - smlEVENT_FIRST_PRINT_EVENT ;
// Nothing waiting to be sent, so we're done.
if (!m_BufferedPrintOutput[buffer].str().size())
return ;
// Get the first listener for this event (or return if there are none)
ConnectionListIter connectionIter ;
if (!EventManager<smlPrintEventId>::GetBegin(eventID, &connectionIter))
return ;
// We need the first connection for when we're building the message. Perhaps this is a sign that
// we shouldn't have rolled these methods into Connection.
Connection* pConnection = *connectionIter;
// Convert eventID to a string
char const* event = m_pKernelSML->ConvertEventToString(eventID) ;
// Send the message out
AnalyzeXML response ;
// For non-echo events, just send it normally
if (eventID != smlEVENT_ECHO)
{
// Build the SML message we're going to send.
soarxml::ElementXML* pMsg = pConnection->CreateSMLCommand(sml_Names::kCommand_Event);
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamAgent, m_pCallbackAgentSML->GetName());
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamEventID, event);
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamMessage, m_BufferedPrintOutput[buffer].str().c_str());
// Send the message out
AnalyzeXML response ;
SendEvent(0, pConnection, pMsg, &response, connectionIter, GetEnd(eventID)) ;
// Clean up
delete pMsg ;
}
else
{
// For echo events build up the message on a connection by connection basis.
// This allows us to tell a sender if they were the cause of a given message so a client
// can filter out echoes from commands they originated.
while (connectionIter != GetEnd(eventID))
{
pConnection = *connectionIter ;
connectionIter++ ;
// Build the SML message we're going to send.
soarxml::ElementXML* pMsg = pConnection->CreateSMLCommand(sml_Names::kCommand_Event);
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamAgent, m_pCallbackAgentSML->GetName());
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamEventID, event);
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamMessage, m_BufferedPrintOutput[buffer].str().c_str());
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamSelf, (pSourceConnection == pConnection) ? sml_Names::kTrue : sml_Names::kFalse) ;
#ifdef _DEBUG
// Generate a text form of the XML so we can look at it in the debugger.
char* pStr = pMsg->GenerateXMLString(true) ;
#endif
// It would be faster to just send a message here without waiting for a response
// but that could produce incorrect behavior if the client expects to act *during*
// the event that we're notifying them about (e.g. notification that we're in the input phase).
pConnection->SendMessageGetResponse(&response, pMsg) ;
#ifdef _DEBUG
// Clean up the string form of the message.
pMsg->DeleteString(pStr) ;
#endif
// Clean up
delete pMsg ;
}
}
// Clear the buffer now that it's been sent
m_BufferedPrintOutput[buffer].str( std::string() );
}
示例9: OnKernelEvent
// Called when an event occurs in the kernel
void SystemListener::OnKernelEvent(int eventIDIn, AgentSML* pAgentSML, void* /*pCallData*/)
{
// All system events are currently implemented directly in kernel SML so there's
// no underlying kernel callbacks to connect to.
// If we ever change that, this is where the callbacks would come in.
smlSystemEventId eventID = static_cast<smlSystemEventId>(eventIDIn);
// The system start event can be suppressed by a client.
// This allows us to run a Soar agent without running the associated simulation
// (which should be listening for system-start/system-stop events).
// DJP May 2007: This was an earlier idea about how we'd control systems through SML. I'm
// not sure this model (and these events) are relevant anymore.
if (eventID == smlEVENT_SYSTEM_START)
{
bool suppress = m_pKernelSML->IsSystemStartSuppressed() ;
// The flag is reset forcing the client to repeatedly suppress the system
// start event each time they wish to run Soar and not generate this event.
m_pKernelSML->SetSuppressSystemStart(false) ;
if (suppress)
return ;
}
// Similarly, system stop can be suppressed.
if (eventID == smlEVENT_SYSTEM_STOP)
{
bool suppress = m_pKernelSML->IsSystemStopSuppressed() ;
// Clear our flags that control this event
m_pKernelSML->RequireSystemStop(false) ;
m_pKernelSML->SetSuppressSystemStop(false) ;
if (suppress)
return ;
}
// Get the first listener for this event (or return if there are none)
ConnectionListIter connectionIter ;
if (!EventManager<smlSystemEventId>::GetBegin(eventID, &connectionIter))
return ;
// We need the first connection for when we're building the message. Perhaps this is a sign that
// we shouldn't have rolled these methods into Connection.
Connection* pConnection = *connectionIter ;
// Convert eventID to a string
char const* eventString = m_pKernelSML->ConvertEventToString(eventID) ;
// Build the SML message we're doing to send.
soarxml::ElementXML* pMsg = pConnection->CreateSMLCommand(sml_Names::kCommand_Event) ;
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamEventID, eventString) ;
// Send the message out
AnalyzeXML response ;
SendEvent(pAgentSML, pConnection, pMsg, &response, connectionIter, GetEnd(eventID)) ;
// Clean up
delete pMsg ;
}
示例10: SendOutput
void OutputListener::SendOutput(smlWorkingMemoryEventId eventId, AgentSML* pAgentSML, int /*outputMode*/, io_wme* io_wmelist)
{
if (eventId != smlEVENT_OUTPUT_PHASE_CALLBACK)
{
return ;
}
// Get the first listener for this event (or return if there are none)
ConnectionListIter connectionIter ;
if (!EventManager<smlWorkingMemoryEventId>::GetBegin(eventId, &connectionIter))
{
return ;
}
// We need the first connection for when we're building the message. Perhaps this is a sign that
// we shouldn't have rolled these methods into Connection.
Connection* pConnection = *connectionIter ;
// Build the SML message we're doing to send.
soarxml::ElementXML* pMsg = pConnection->CreateSMLCommand(sml_Names::kCommand_Output) ;
// Add the agent parameter and as a side-effect, get a pointer to the <command> tag. This is an optimization.
ElementXML_Handle hCommand = pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamAgent, pAgentSML->GetName()) ;
soarxml::ElementXML command(hCommand) ;
// We are passed a list of all wmes in the transitive closure (TC) of the output link.
// We need to decide which of these we've already seen before, so we can just send the
// changes over to the client (rather than sending the entire TC each time).
// Reset everything in the current list of tags to "not in use". After we've processed all wmes,
// any still in this state have been removed.
for (OutputTimeTagIter iter = m_TimeTags.begin() ; iter != m_TimeTags.end() ; iter++)
{
iter->second = false ;
}
// Start with the output link itself
// The kernel seems to only output this itself during link initialization
// and we might be connecting up after that. Including it twice will not hurt on the client side.
output_link* ol = pAgentSML->GetSoarAgent()->existing_output_links ; // This is technically a list but we only support one output link
TagWme* pOutputLinkWme = OutputListener::CreateTagWme(pAgentSML, ol->link_wme) ;
command.AddChild(pOutputLinkWme) ;
for (io_wme* wme = io_wmelist ; wme != NIL ; wme = wme->next)
{
// Build the list of WME changes
uint64_t timeTag = wme->timetag ;
// See if we've already sent this wme to the client
OutputTimeTagIter iter = m_TimeTags.find(timeTag) ;
if (iter != m_TimeTags.end())
{
// This is a time tag we've already sent over, so mark it as still being in use
iter->second = true ;
continue ;
}
// If we reach here we need to send the wme to the client and add it to the list
// of tags currently in use.
m_TimeTags[timeTag] = true ;
// Create the wme tag
TagWme* pTag = CreateTagIOWme(pAgentSML, wme) ;
// Add it as a child of the command tag
command.AddChild(pTag) ;
}
// At this point we check the list of time tags and any which are not marked as "in use" must
// have been deleted, so we need to send them over to the client as deletions.
for (OutputTimeTagIter iter = m_TimeTags.begin() ; iter != m_TimeTags.end() ;)
{
// Ignore time tags that are still in use.
if (iter->second == true)
{
// We have to do manual iteration because we're deleting elements
// as we go and that invalidates iterators if we're not careful.
iter++ ;
continue ;
}
uint64_t timeTag = iter->first ;
// Create the wme tag
TagWme* pTag = new TagWme() ;
// For deletions we just send the time tag
pTag->SetTimeTag(static_cast<int64_t>(timeTag)) ;
pTag->SetActionRemove() ;
// Add it as a child of the command tag
command.AddChild(pTag) ;
// Delete the entry from the time tag map
m_TimeTags.erase(iter++);
}
// This is important. We are working with a subpart of pMsg.
// If we retain ownership of the handle and delete the object
//.........这里部分代码省略.........
示例11: ExecuteRhsCommand
bool RhsListener::ExecuteRhsCommand(AgentSML* pAgentSML, smlRhsEventId eventID, std::string const& functionName, std::string const& arguments, std::string* pResultStr)
{
bool result = false ;
// Get the list of connections (clients) who have registered to implement this right hand side (RHS) function.
ConnectionList* pList = GetRhsListeners(functionName.c_str()) ;
// If nobody is listening we're done (not a bug as we register for all rhs functions and only forward specific ones that the client has registered)
if (!pList || pList->size() == 0)
return result ;
ConnectionListIter connectionIter = pList->begin() ;
// We need the first connection for when we're building the message. Perhaps this is a sign that
// we shouldn't have rolled these methods into Connection.
Connection* pConnection = *connectionIter ;
// Convert eventID to a string
char const* event = m_pKernelSML->ConvertEventToString(eventID) ;
// Build the SML message we're doing to send.
// Pass the agent in the "name" parameter not the "agent" parameter as this is a kernel
// level event, not an agent level one (because you need to register with the kernel to get "agent created").
soarxml::ElementXML* pMsg = pConnection->CreateSMLCommand(sml_Names::kCommand_Event) ;
if (pAgentSML) pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamName, pAgentSML->GetName()) ;
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamEventID, event) ;
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamFunction, functionName.c_str()) ;
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamValue, arguments.c_str()) ;
#ifdef _DEBUG
// Generate a text form of the XML so we can look at it in the debugger.
char* pStr = pMsg->GenerateXMLString(true) ;
#endif
AnalyzeXML response ;
// We want to call embedded connections first, so that we get the best performance
// for these functions. I don't want to sort the list or otherwise change it so
// instead we'll just use a rather clumsy outer loop to do this.
for (int phase = 0 ; phase < 2 && !result ; phase++)
{
// Only call to embedded connections
bool embeddedPhase = (phase == 0) ;
// Reset the iterator to the beginning of the list
connectionIter = pList->begin();
// Keep looping until we get a result
while (connectionIter != pList->end() && !result)
{
pConnection = *connectionIter ;
// We call all embedded connections (same process) first before
// trying any remote methods. This ensures that if multiple folks register
// for the same function we execute the fastest one (w/o going over a socket for the result).
if (pConnection->IsRemoteConnection() && embeddedPhase)
{
connectionIter++ ;
continue ;
}
// It would be faster to just send a message here without waiting for a response
// but that could produce incorrect behavior if the client expects to act *during*
// the event that we're notifying them about (e.g. notification that we're in the input phase).
bool ok = pConnection->SendMessageGetResponse(&response, pMsg) ;
if (ok)
{
char const* pResult = response.GetResultString() ;
if (pResult != NULL)
{
(*pResultStr) = pResult ;
result = true ;
}
}
connectionIter++ ;
}
}
#ifdef _DEBUG
// Release the string form we generated for the debugger
pMsg->DeleteString(pStr) ;
#endif
// Clean up
delete pMsg ;
return result ;
}
示例12: HandleFilterEvent
bool RhsListener::HandleFilterEvent(smlRhsEventId eventID, AgentSML* pAgent, char const* pArgument,
std::string &pReturnValue)
{
// Currently only supporting one event here, but that could change in time.
assert(eventID == smlEVENT_FILTER) ;
// Filters are handled as a RHS function call internally, using a special reserved name.
char const* pFunctionName = sml_Names::kFilterName ;
// Get the list of connections (clients) who have registered to implement this right hand side (RHS) function.
ConnectionList* pList = GetRhsListeners(pFunctionName) ;
bool result = false ;
// If nobody is listening we're done (not a bug as we register for all rhs functions and only forward specific ones that the client has registered)
if (!pList || pList->size() == 0)
return result ;
ConnectionListIter connectionIter = pList->begin() ;
// We need the first connection for when we're building the message. Perhaps this is a sign that
// we shouldn't have rolled these methods into Connection.
Connection* pConnection = *connectionIter ;
// Convert eventID to a string
char const* event = m_pKernelSML->ConvertEventToString(eventID) ;
// Copy the initial command line into the return buffer and send that over.
// This will be sequentially replaced by each filter in turn and whatever
// is left in here at the end is the result of the filtering.
// This allows multiple filters to act on the data, each modifying it as it goes.
// A side effect of this is that the order the filters work on the data is significant.
// Anyone in the chain can set the string to be the empty string, which brings the
// whole process to a halt (they have eaten the command line at that point).
pReturnValue.reserve(strlen(pArgument) + 1); //adding 1 because strlen does not count the terminating null character
pReturnValue.assign(pArgument);
bool stop = false ;
while (connectionIter != pList->end() && !stop)
{
// Build the SML message we're doing to send.
// Pass the agent in the "name" parameter not the "agent" parameter as this is a kernel
// level event, not an agent level one (because you need to register with the kernel to get "agent created").
soarxml::ElementXML* pMsg = pConnection->CreateSMLCommand(sml_Names::kCommand_Event) ;
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamName, pAgent ? pAgent->GetName() : "") ;
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamEventID, event) ;
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamFunction, sml_Names::kFilterName) ;
pConnection->AddParameterToSMLCommand(pMsg, sml_Names::kParamValue, pReturnValue.c_str()) ; // We send the current command line over
#ifdef _DEBUG
// Generate a text form of the XML so we can look at it in the debugger.
char* pStr = pMsg->GenerateXMLString(true) ;
#endif
AnalyzeXML response ;
pConnection = *connectionIter ;
bool ok = pConnection->SendMessageGetResponse(&response, pMsg) ;
if (ok)
{
char const* pResult = response.GetResultString() ;
if (pResult != NULL)
{
// If the listener returns a result then take that
// value and return it in "pReturnValue" to the caller.
// If the client returns a longer string than the caller, pReturnValue is resized to fit it.
pReturnValue.reserve(strlen(pResult) + 1); //adding 1 because strlen does not count the terminating null character
pReturnValue.assign(pResult);
result = true ;
}
else
{
// If one of the filters returns an empty string, stop the process at that point
// because the command has been "eaten". Make the result the empty string.
pReturnValue[0] = 0 ;
result = true ;
stop = true ;
}
}
connectionIter++ ;
#ifdef _DEBUG
// Release the string form we generated for the debugger
pMsg->DeleteString(pStr) ;
#endif
// Clean up
delete pMsg ;
}
return result ;
}