fipa_acl  1.4
conversation_monitor.cpp
Go to the documentation of this file.
1 #include "conversation_monitor.h"
2 #include <base-logging/Logging.hpp>
3 
4 namespace fipa {
5 namespace acl {
6 
7 ConversationMonitor::ConversationMonitor(const AgentID& self, const std::string& protocolDirectory)
8  : mSelf(self)
9 {
10  LOG_DEBUG("Creating conversation monitor for agent: '%s'", self.getName().c_str());
11  if(!protocolDirectory.empty())
12  {
13  LOG_DEBUG("Setting protocol resource directory: '%s'",protocolDirectory.c_str());
15  }
16 }
17 
19 {}
20 
22 {
23  boost::unique_lock<boost::mutex> lock(mMutex);
24  std::map<std::string, ConversationPtr>::iterator it;
25  std::string conversationId = msg.getConversationID();
26  it = mActiveConversations.find(conversationId);
27  // update if conversation already exists
28  if(it != mActiveConversations.end())
29  {
30  bool conversationEnded = false;
31  try {
32  conversationEnded = it->second->hasEnded();
33  } catch(const std::runtime_error& e)
34  {}
35 
36  if(conversationEnded)
37  {
38  std::string errorMsg = "Trying to update already completed conversation: " + conversationId + " performative: '" + msg.getPerformative() + "' content: '" + msg.getContent() + "'";
39  throw conversation::InvalidOperation(errorMsg);
40  } else {
41  LOG_INFO("Update existing conversation '%p' with conversation id '%s'", this, it->second->getConversationId().c_str());
42  it->second->update(msg);
43  return it->second;
44  }
45  }
46 
47  throw conversation::InvalidOperation("Can only update an existing conversation. Possibly the corresponding conversation did already end and this message does not conform to the respective protocol");
48 }
49 
51 {
52  boost::unique_lock<boost::mutex> lock(mMutex);
53  bool success = mActiveConversations.erase(conversationId);
54  return success;
55 }
56 
58 {
59  boost::unique_lock<boost::mutex> lock(mMutex);
60  // Start conversation with this agent as owner
62  mActiveConversations.insert(std::pair<std::string, ConversationPtr>(conversation->getConversationId(), conversation));
63  return conversation;
64 }
65 
67 {
68  // get conversation associated with command of uuid
69  boost::unique_lock<boost::mutex> lock(mMutex);
70  std::map<fipa::acl::ConversationID, ConversationPtr>::iterator it = mActiveConversations.find(conversationId);
71  if(it != mActiveConversations.end())
72  return it->second;
73 
74  return ConversationPtr();
75 }
76 
77 
79 {
80  // get conversation associated with comman of uuid
81  boost::unique_lock<boost::mutex> lock(mMutex);
82  std::map<fipa::acl::ConversationID, ConversationPtr>::iterator it = mActiveConversations.find(conversationId);
83  if(it != mActiveConversations.end())
84  return it->second;
85 
86  // create if it does not exist
87  ConversationPtr conversation(new Conversation(mSelf.getName(), conversationId));
88  mActiveConversations.insert(std::pair<fipa::acl::ConversationID, ConversationPtr>(conversationId, conversation));
89  LOG_INFO("Create new conversation '%p' with conversation id '%s'", this, conversationId.c_str());
90  return conversation;
91 }
92 
94 {
95  LOG_DEBUG_S << "Cleaning up conversation monitor.";
96  boost::unique_lock<boost::mutex> lock(mMutex);
97 
98  std::map<fipa::acl::ConversationID, ConversationPtr>::iterator it = mActiveConversations.begin();
99  std::vector<fipa::acl::ConversationID> endedConversations;
100  std::vector<fipa::acl::ConversationID>::iterator eit;
101 
102  // If conversation has ended move from active conversation to ended conversation after detaching
103  // any existing observers
104  for(; it != mActiveConversations.end(); ++it)
105  {
106  LOG_DEBUG_S << "Cleaning up conversation monitor: Processing conversation " << it->first;
107  ConversationPtr conversation = it->second;
108  assert(it->second);
109  if(conversation->hasEnded())
110  {
111  LOG_DEBUG_S << "Detaching observers from ended conversation " << it->first;
112  conversation->detachObservers();
113  endedConversations.push_back(it->first);
114  }
115  }
116 
117  LOG_DEBUG_S << "Erasing ended conversations from active conversations.";
118  for( eit = endedConversations.begin(); eit != endedConversations.end(); ++eit)
119  {
120  LOG_DEBUG_S << "Erasing ended conversation " << *eit << " from active conversations.";
121  mActiveConversations.erase(*eit);
122  }
123 }
124 
125 std::vector<fipa::acl::ConversationID> ConversationMonitor::getActiveConversations()
126 {
127  boost::unique_lock<boost::mutex> lock(mMutex);
128  std::map<fipa::acl::ConversationID, ConversationPtr>::iterator it = mActiveConversations.begin();
129  std::vector<fipa::acl::ConversationID> activeConversations;
130 
131  for(; it != mActiveConversations.end(); it++)
132  {
133  activeConversations.push_back(it->first);
134  }
135 
136  return activeConversations;
137 }
138 
139 } // end namespace acl
140 } // end namespace fipa
std::string ConversationID
Definition: acl_message.h:28
static fipa::acl::ConversationID generateConversationID(const std::string &topic="")
std::string getContent() const
Definition: acl_message.h:294
ConversationPtr getConversation(const fipa::acl::ConversationID &conversationId)
boost::shared_ptr< Conversation > ConversationPtr
Definition: conversation.h:408
bool removeConversation(const fipa::acl::ConversationID &conversationId)
ConversationMonitor(const AgentID &self, const std::string &protocolDirectory="")
ConversationPtr getOrCreateConversation(const fipa::acl::ConversationID &conversationId)
const std::string & getName() const
setter and getter methods for all fields; they do not result in deep-copies assignments/retreivals, but this can be easily changed if needed through the overloaded operator which do
Definition: agent_id.h:90
std::string getPerformative() const
Definition: acl_message.h:139
std::vector< fipa::acl::ConversationID > getActiveConversations()
static void setProtocolResourceDir(const std::string &resourceDir)
ConversationPtr updateConversation(const fipa::acl::ACLMessage &msg)
This class provides a representation of a message conforming to the FIPA specification SC00061...
Definition: acl_message.h:55
ConversationPtr startConversation(const std::string &topic)
Implements the general AgentID functionality, which is present throughout the fipa specifications(FIP...
Definition: agent_id.h:37
Foundation of Physical Intelligent Agents.
Definition: conversation.cpp:6
std::string getConversationID() const
Definition: acl_message.h:227