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 #include <algorithm>
29 #include <string.h>
30 
31 using namespace fawkes;
32 
33 /** @class BlackBoardInterfaceListMaintainer "interface_list_maintainer.h"
34  * opens and maintains multiple interfaces defined by a pattern
35  * @author Tobias Neumann
36  */
37 
38 /** Constructor
39  * @param n name of plugin to use this
40  * @param bb pointer to the BlackBoard given by abstract
41  * @param l pointer to the Logger given by abstract
42  * @param type the interface type
43  * @param pattern the pattern for interfaces to open
44  *
45  */
46 BlackBoardInterfaceListMaintainer::BlackBoardInterfaceListMaintainer(const char* n, BlackBoard* bb, Logger* l, const char *type, const char *pattern)
48 {
49  blackboard_ = bb;
50  logger_ = l;
51  name_ = strdup(n);
52 
53  bbio_add_observed_create(type, pattern);
54  blackboard_->register_observer(this);
55 
56  MutexLocker lock(ifs_.mutex());
57 
58  // for all interfaces of my pattern
59  std::list<fawkes::Interface *> ifs_tmp = blackboard_->open_multiple_for_reading(type, pattern);
60  std::list<fawkes::Interface *>::iterator pif_tmp;
61  for ( pif_tmp = ifs_tmp.begin(); pif_tmp != ifs_tmp.end(); ++pif_tmp ) {
62  // check if this is allready opened by me
63  std::string id_list_tmp( (*pif_tmp)->id() );
64  bool is_in_list = false;
66  for ( pif_class = ifs_.begin(); pif_class != ifs_.end(); ++pif_class ) {
67  std::string id_list_class( (*pif_class)->id() );
68 
69  if ( id_list_tmp.compare( id_list_class ) == 0 ) {
70  blackboard_->close( *pif_tmp );
71  is_in_list = true;
72  }
73  }
74 
75  if ( ! is_in_list ) {
76  ifs_.push_back( (*pif_tmp) );
77  }
78 
79  bbil_add_reader_interface((*pif_tmp));
80  bbil_add_writer_interface((*pif_tmp));
81  }
82  blackboard_->register_listener(this);
83 
84  lock.unlock();
85 }
86 
87 /** Destructor. */
89 {
90  delete(name_);
91 
92  MutexLocker lock( ifs_.mutex() );
94  for ( pif = ifs_.begin(); pif != ifs_.end(); ++pif ) {
97  blackboard_->update_listener(this);
98  blackboard_->close( *pif );
99  }
100 }
101 
102 /**
103  * Callback if interface defined by the pattern is created.
104  * Now we try to open it.
105  * @param type the type of the created interface
106  * @param id the name of the interface
107  */
108 void
109 BlackBoardInterfaceListMaintainer::bb_interface_created(const char *type, const char *id) throw()
110 {
111  Interface *pif;
112  try {
113  pif = blackboard_->open_for_reading(type, id);
114  } catch (Exception &e) {
115  // ignored
116  logger_->log_warn(name_, "Failed to open %s:%s: %s", type, id, e.what_no_backtrace());
117  return;
118  }
119 
120  try {
123  blackboard_->update_listener(this);
124  } catch (Exception &e) {
125  logger_->log_warn(name_, "Failed to register for %s:%s: %s",
126  type, id, e.what());
127  try {
130  blackboard_->update_listener(this);
131  blackboard_->close(pif);
132  } catch (Exception &e) {
133  logger_->log_error(name_, "Failed to deregister %s:%s during error recovery: %s",
134  type, id, e.what());
135  }
136  return;
137  }
138 
139  ifs_.push_back_locked(pif);
140 }
141 
142 /**
143  * Callback if writer is removed from an interface. Now we check if we can close this interface.
144  * @param interface the interface that raised the callback
145  * @param instance_serial defiend by the callback, not used here
146  */
147 void
148 BlackBoardInterfaceListMaintainer::bb_interface_writer_removed(fawkes::Interface *interface,
149  unsigned int instance_serial) throw()
150 {
151  conditional_close(interface);
152 }
153 
154 /**
155  * Callback if a reader is removed from an interface. Now we check if we can close this interface.
156  * @param interface the interface that raised the callback
157  * @param instance_serial defiend by the callback, not used here
158  */
159 void
160 BlackBoardInterfaceListMaintainer::bb_interface_reader_removed(fawkes::Interface *interface,
161  unsigned int instance_serial) throw()
162 {
163  conditional_close(interface);
164 }
165 
166 /**
167  * Checks if the given interface can be closed and does so if possible.
168  * The check is, no writer and just one reader (us)
169  * @param pif interface to close
170  */
171 void
172 BlackBoardInterfaceListMaintainer::conditional_close(Interface *pif) throw()
173 {
174  bool close = false;
175  MutexLocker lock(ifs_.mutex());
176 
178  std::find(ifs_.begin(), ifs_.end(), pif);
179 
180  if (c != ifs_.end() &&
181  (! pif->has_writer() && (pif->num_readers() == 1)))
182  {
183  // It's only us
184  logger_->log_info(name_, "Last on %s, closing", pif->uid());
185  close = true;
186  ifs_.erase(c);
187  }
188 
189  lock.unlock();
190 
191  if (close) {
192  std::string uid = pif->uid();
193  try {
196  blackboard_->update_listener(this);
197  blackboard_->close(pif);
198  } catch (Exception &e) {
199  logger_->log_error(name_, "Failed to unregister or close %s: %s",
200  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 }
virtual void register_observer(BlackBoardInterfaceObserver *observer)
Register BB interface observer.
Definition: blackboard.cpp:230
virtual void log_info(const char *component, const char *format,...)=0
Log informational message.
Fawkes library namespace.
Mutex locking helper.
Definition: mutex_locker.h:33
void bbil_add_writer_interface(Interface *interface)
Add an interface to the writer addition/removal watch list.
virtual const char * what() const
Get primary string.
Definition: exception.cpp:661
virtual void update_listener(BlackBoardInterfaceListener *listener, ListenerRegisterFlag flag=BBIL_FLAG_ALL)
Update BB event listener.
Definition: blackboard.cpp:203
Base class for all Fawkes BlackBoard interfaces.
Definition: interface.h:79
BlackBoardInterfaceListMaintainer(const char *n, BlackBoard *bb, Logger *l, const char *type, const char *pattern)
Constructor.
void bbil_remove_writer_interface(Interface *interface)
Remove an interface to the writer addition/removal watch list.
void push_back_locked(const Type &x)
Push element to list at back with lock protection.
Definition: lock_list.h:152
RefPtr< Mutex > mutex() const
Get access to the internal mutex.
Definition: lock_list.h:182
virtual void register_listener(BlackBoardInterfaceListener *listener, ListenerRegisterFlag flag=BBIL_FLAG_ALL)
Register BB event listener.
Definition: blackboard.cpp:190
void bbio_add_observed_create(const char *type_pattern, const char *id_pattern="*")
Add interface creation type to watch list.
const char * type() const
Get type of interface.
Definition: interface.cpp:651
Base class for exceptions in Fawkes.
Definition: exception.h:36
List with a lock.
Definition: thread.h:40
virtual void unlock() const
Unlock list.
Definition: lock_list.h:144
bool has_writer() const
Check if there is a writer for the interface.
Definition: interface.cpp:834
const char * uid() const
Get unique identifier of interface.
Definition: interface.cpp:687
virtual const char * what_no_backtrace() const
Get primary string (does not implicitly print the back trace).
Definition: exception.cpp:686
virtual void log_warn(const char *component, const char *format,...)=0
Log warning message.
virtual void log_error(const char *component, const char *format,...)=0
Log error message.
virtual std::list< Interface * > open_multiple_for_reading(const char *type_pattern, const char *id_pattern="*", const char *owner=NULL)=0
Open multiple interfaces for reading.
void bbil_add_reader_interface(Interface *interface)
Add an interface to the reader addition/removal watch list.
virtual Interface * open_for_reading(const char *interface_type, const char *identifier, const char *owner=NULL)=0
Open interface for reading.
unsigned int num_readers() const
Get the number of readers.
Definition: interface.cpp:863
The BlackBoard abstract class.
Definition: blackboard.h:48
void bbil_remove_reader_interface(Interface *interface)
Remove an interface to the reader addition/removal watch list.
void unlock_list()
unlocks the mutex in this class
BlackBoard interface listener.
virtual void close(Interface *interface)=0
Close interface.
Interface for logging.
Definition: logger.h:34