Fawkes API  Fawkes Development Version
interface_list_maintainer.cpp
1 
2 /***************************************************************************
3  * interface_list_maintainer.cpp - BlackBoard interface list maintainer
4  *
5  * Created: Mon Mar 16 13:34:00 2015
6  * Copyright 2007-2014 Tim Niemueller [www.niemueller.de]
7  * 2015 Tobias Neumann
8  *
9  ****************************************************************************/
10 
11 /* This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version. A runtime exception applies to
15  * this software (see LICENSE.GPL_WRE file mentioned below for details).
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU Library General Public License for more details.
21  *
22  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
23  */
24 
25 #include "interface_list_maintainer.h"
26 
27 #include <core/threading/mutex_locker.h>
28 
29 #include <algorithm>
30 #include <string.h>
31 
32 using namespace fawkes;
33 
34 /** @class BlackBoardInterfaceListMaintainer "interface_list_maintainer.h"
35  * opens and maintains multiple interfaces defined by a pattern
36  * @author Tobias Neumann
37  */
38 
39 /** Constructor
40  * @param n name of plugin to use this
41  * @param bb pointer to the BlackBoard given by abstract
42  * @param l pointer to the Logger given by abstract
43  * @param type the interface type
44  * @param pattern the pattern for interfaces to open
45  *
46  */
48  BlackBoard *bb,
49  Logger * l,
50  const char *type,
51  const char *pattern)
53 {
54  blackboard_ = bb;
55  logger_ = l;
56  name_ = strdup(n);
57 
59  blackboard_->register_observer(this);
60 
61  MutexLocker lock(ifs_.mutex());
62 
63  // for all interfaces of my pattern
64  std::list<fawkes::Interface *> ifs_tmp = blackboard_->open_multiple_for_reading(type, pattern);
65  std::list<fawkes::Interface *>::iterator pif_tmp;
66  for (pif_tmp = ifs_tmp.begin(); pif_tmp != ifs_tmp.end(); ++pif_tmp) {
67  // check if this is allready opened by me
68  std::string id_list_tmp((*pif_tmp)->id());
69  bool is_in_list = false;
71  for (pif_class = ifs_.begin(); pif_class != ifs_.end(); ++pif_class) {
72  std::string id_list_class((*pif_class)->id());
73 
74  if (id_list_tmp.compare(id_list_class) == 0) {
75  blackboard_->close(*pif_tmp);
76  is_in_list = true;
77  }
78  }
79 
80  if (!is_in_list) {
81  ifs_.push_back((*pif_tmp));
82  }
83 
84  bbil_add_reader_interface((*pif_tmp));
85  bbil_add_writer_interface((*pif_tmp));
86  }
87  blackboard_->register_listener(this);
88 
89  lock.unlock();
90 }
91 
92 /** Destructor. */
94 {
95  free(name_);
96 
97  MutexLocker lock(ifs_.mutex());
99  for (pif = ifs_.begin(); pif != ifs_.end(); ++pif) {
102  blackboard_->update_listener(this);
103  blackboard_->close(*pif);
104  }
105 }
106 
107 /**
108  * Callback if interface defined by the pattern is created.
109  * Now we try to open it.
110  * @param type the type of the created interface
111  * @param id the name of the interface
112  */
113 void
114 BlackBoardInterfaceListMaintainer::bb_interface_created(const char *type, const char *id) throw()
115 {
116  Interface *pif;
117  try {
118  pif = blackboard_->open_for_reading(type, id);
119  } catch (Exception &e) {
120  // ignored
121  logger_->log_warn(name_, "Failed to open %s:%s: %s", type, id, e.what_no_backtrace());
122  return;
123  }
124 
125  try {
126  bbil_add_reader_interface(pif);
127  bbil_add_writer_interface(pif);
128  blackboard_->update_listener(this);
129  } catch (Exception &e) {
130  logger_->log_warn(name_, "Failed to register for %s:%s: %s", type, id, e.what());
131  try {
132  bbil_remove_reader_interface(pif);
133  bbil_remove_writer_interface(pif);
134  blackboard_->update_listener(this);
135  blackboard_->close(pif);
136  } catch (Exception &e) {
137  logger_->log_error(
138  name_, "Failed to deregister %s:%s during error recovery: %s", type, id, e.what());
139  }
140  return;
141  }
142 
143  ifs_.push_back_locked(pif);
144 }
145 
146 /**
147  * Callback if writer is removed from an interface. Now we check if we can close this interface.
148  * @param interface the interface that raised the callback
149  * @param instance_serial defiend by the callback, not used here
150  */
151 void
152 BlackBoardInterfaceListMaintainer::bb_interface_writer_removed(fawkes::Interface *interface,
153  unsigned int instance_serial) throw()
154 {
155  conditional_close(interface);
156 }
157 
158 /**
159  * Callback if a reader is removed from an interface. Now we check if we can close this interface.
160  * @param interface the interface that raised the callback
161  * @param instance_serial defiend by the callback, not used here
162  */
163 void
164 BlackBoardInterfaceListMaintainer::bb_interface_reader_removed(fawkes::Interface *interface,
165  unsigned int instance_serial) throw()
166 {
167  conditional_close(interface);
168 }
169 
170 /**
171  * Checks if the given interface can be closed and does so if possible.
172  * The check is, no writer and just one reader (us)
173  * @param pif interface to close
174  */
175 void
176 BlackBoardInterfaceListMaintainer::conditional_close(Interface *pif) throw()
177 {
178  bool close = false;
179  MutexLocker lock(ifs_.mutex());
180 
181  LockList<Interface *>::iterator c = std::find(ifs_.begin(), ifs_.end(), pif);
182 
183  if (c != ifs_.end() && (!pif->has_writer() && (pif->num_readers() == 1))) {
184  // It's only us
185  logger_->log_info(name_, "Last on %s, closing", pif->uid());
186  close = true;
187  ifs_.erase(c);
188  }
189 
190  lock.unlock();
191 
192  if (close) {
193  std::string uid = pif->uid();
194  try {
195  bbil_remove_reader_interface(pif);
196  bbil_remove_writer_interface(pif);
197  blackboard_->update_listener(this);
198  blackboard_->close(pif);
199  } catch (Exception &e) {
200  logger_->log_error(name_, "Failed to unregister or close %s: %s", uid.c_str(), e.what());
201  }
202  }
203 }
204 
205 /** unlocks the mutex in this class
206  *
207  * this method needs to be called after lock_and_get_list()
208  * the list returned by lock_and_get_list() is invalid and shouldn't be used after this method is called
209  */
210 void
212 {
213  ifs_.unlock();
214 }
fawkes::BlackBoard::register_listener
virtual void register_listener(BlackBoardInterfaceListener *listener, ListenerRegisterFlag flag=BBIL_FLAG_ALL)
Register BB event listener.
Definition: blackboard.cpp:188
fawkes::BlackBoardInterfaceListener::bbil_remove_reader_interface
void bbil_remove_reader_interface(Interface *interface)
Remove an interface to the reader addition/removal watch list.
Definition: interface_listener.cpp:307
fawkes::MutexLocker
Definition: mutex_locker.h:37
fawkes::LockList
Definition: thread.h:42
fawkes::BlackBoardInterfaceListener
Definition: interface_listener.h:45
fawkes::BlackBoard
Definition: blackboard.h:48
fawkes::Interface::type
const char * type() const
Get type of interface.
Definition: interface.cpp:643
fawkes::BlackBoardInterfaceListMaintainer::~BlackBoardInterfaceListMaintainer
virtual ~BlackBoardInterfaceListMaintainer()
Destructor.
Definition: interface_list_maintainer.cpp:93
fawkes::BlackBoardInterfaceObserver::bbio_add_observed_create
void bbio_add_observed_create(const char *type_pattern, const char *id_pattern="*")
Add interface creation type to watch list.
Definition: interface_observer.cpp:123
fawkes::BlackBoardInterfaceListener::bbil_remove_writer_interface
void bbil_remove_writer_interface(Interface *interface)
Remove an interface to the writer addition/removal watch list.
Definition: interface_listener.cpp:318
fawkes::LockList::mutex
RefPtr< Mutex > mutex() const
Get access to the internal mutex.
Definition: lock_list.h:176
fawkes::LockList::unlock
virtual void unlock() const
Unlock list.
Definition: lock_list.h:142
fawkes::BlackBoard::close
virtual void close(Interface *interface)=0
fawkes::Logger
Definition: logger.h:40
fawkes
fawkes::BlackBoard::register_observer
virtual void register_observer(BlackBoardInterfaceObserver *observer)
Register BB interface observer.
Definition: blackboard.cpp:228
fawkes::Interface
Definition: interface.h:77
fawkes::Interface::has_writer
bool has_writer() const
Check if there is a writer for the interface.
Definition: interface.cpp:817
fawkes::BlackBoardInterfaceListMaintainer::BlackBoardInterfaceListMaintainer
BlackBoardInterfaceListMaintainer(const char *n, BlackBoard *bb, Logger *l, const char *type, const char *pattern)
Constructor.
Definition: interface_list_maintainer.cpp:47
fawkes::Interface::uid
const char * uid() const
Get unique identifier of interface.
Definition: interface.cpp:677
fawkes::Interface::num_readers
unsigned int num_readers() const
Get the number of readers.
Definition: interface.cpp:845
fawkes::Exception::what_no_backtrace
virtual const char * what_no_backtrace() const
Get primary string (does not implicitly print the back trace).
Definition: exception.cpp:662
fawkes::Exception::what
virtual const char * what() const
Get primary string.
Definition: exception.cpp:638
fawkes::BlackBoardInterfaceListener::bbil_add_reader_interface
void bbil_add_reader_interface(Interface *interface)
Add an interface to the reader addition/removal watch list.
Definition: interface_listener.cpp:262
fawkes::BlackBoard::open_multiple_for_reading
virtual std::list< Interface * > open_multiple_for_reading(const char *type_pattern, const char *id_pattern="*", const char *owner=NULL)=0
fawkes::BlackBoardInterfaceListMaintainer::unlock_list
void unlock_list()
unlocks the mutex in this class
Definition: interface_list_maintainer.cpp:211
fawkes::BlackBoard::update_listener
virtual void update_listener(BlackBoardInterfaceListener *listener, ListenerRegisterFlag flag=BBIL_FLAG_ALL)
Update BB event listener.
Definition: blackboard.cpp:200
fawkes::BlackBoardInterfaceListener::bbil_add_writer_interface
void bbil_add_writer_interface(Interface *interface)
Add an interface to the writer addition/removal watch list.
Definition: interface_listener.cpp:274
fawkes::Exception
Definition: exception.h:39