Fawkes API  Fawkes Development Version
blackboard.cpp
1 
2 /***************************************************************************
3  * blackboard.cpp - BlackBoard Interface
4  *
5  * Created: Sat Sep 16 17:11:13 2006 (on train to Cologne)
6  * Copyright 2006-2011 Tim Niemueller [www.niemueller.de]
7  ****************************************************************************/
8 
9 /* This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version. A runtime exception applies to
13  * this software (see LICENSE.GPL_WRE file mentioned below for details).
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Library General Public License for more details.
19  *
20  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
21  */
22 
23 #include <blackboard/blackboard.h>
24 #include <blackboard/internal/notifier.h>
25 
26 #include <string>
27 #include <cstring>
28 
29 namespace fawkes {
30 #if 0 /* just to make Emacs auto-indent happy */
31 }
32 #endif
33 
34 /** @class BlackBoard <blackboard/blackboard.h>
35  * The BlackBoard abstract class.
36  * This class is the single one entry point for programs that use the BlackBoard.
37  * It is used to open and close interfaces, register and unregister listeners and
38  * observers and to maintain the BlackBoard shared memory segment. Not other classes
39  * shall be used directly.
40  *
41  * The BlackBoard holds a number of so-called interfaces. The interfaces store
42  * data and provide means to pass messages. The BlackBoard also allows for registering
43  * listeners and observers. The listeners can be used to get events for specific
44  * interfaces while the observer gets global interface creation and destruction
45  * events for a specified set of types of interfaces.
46 
47  * An interface consists of a few parts. First there is the storage block. This
48  * is a chunk of memory in the shared memory segment where the actual data is stored.
49  * Then there is the accessor object, an instance of a derivate of the Interface
50  * class which is used to access the data in the shared memory segment. Last but
51  * not least there is an internal message queue that can be used to pass messages
52  * from readers to the writer (not the other way around!).
53  *
54  * The interface manager keeps track of all the allocated interfaces. Events
55  * can be triggered if a specific interface changes (like logging the data to
56  * a file, sending it over the network or notifying another interface of such
57  * a change).
58  *
59  * Interfaces can only be instantiated through the BlackBoard. The BlackBoard
60  * instantiates an interface on request and guarantees that the instance
61  * is fully initialized and usable. This cannot be guaranteed if instantiating an
62  * interface through any other means!
63  *
64  * Interfaces can be opened for reading or writing, not both! There can be only
65  * one writer at a time for any given interface. Interfaces are identified via a
66  * type (which denotes the data and its semantics) and an identifier. There may
67  * be several interfaces for a given type, but the identifier has to be unique.
68  * The identifier is in most cases a well-known string that is used to share data
69  * among plugins.
70  *
71  * Interfaces provide a way to propagate data to the writer via messages. Available
72  * messages types depend on the interface type. Only matching messages are accepted
73  * and can be queued.
74  *
75  * The BlackBoard can operate in two modes, master and slave. Only the master
76  * creates and destroys the shared memory segment. Currently, the slave mode is not
77  * fully implemented and thus may not be used.
78  *
79  * @see Interface
80  * @see Message
81  *
82  * @author Tim Niemueller
83  *
84  *
85  * @fn Interface * BlackBoard::open_for_reading(const char *type, const char *identifier)
86  * Open interface for reading.
87  * This will create a new interface instance of the given type. The result can be
88  * casted to the appropriate type.
89  * @param type type of the interface
90  * @param identifier identifier of the interface
91  * @return new fully initialized interface instance of requested type
92  * @exception OutOfMemoryException thrown if there is not enough free space for
93  * the requested interface.
94  *
95  *
96  * @fn Interface * BlackBoard::open_for_writing(const char *type, const char *identifier)
97  * Open interface for writing.
98  * This will create a new interface instance of the given type. The result can be
99  * casted to the appropriate type. This will only succeed if there is not already
100  * a writer for the given interface type/id!
101  * @param type type of the interface
102  * @param identifier identifier of the interface
103  * @return new fully initialized interface instance of requested type
104  * @exception OutOfMemoryException thrown if there is not enough free space for
105  * the requested interface.
106  * @exception BlackBoardWriterActiveException thrown if there is already a writing
107  * instance with the same type/id
108  *
109  *
110  * @fn void BlackBoard::close(Interface *interface)
111  * Close interface.
112  * @param interface interface to close
113  *
114  *
115  * @fn bool BlackBoard::is_alive() const throw() = 0
116  * Check if the BlackBoard is still alive.
117  * @return true, if the BlackBoard is still alive and may be used, false otherwise.
118  *
119  * @fn bool BlackBoard::try_aliveness_restore() throw()
120  * Try to restore the aliveness of the BlackBoard instance.
121  * Note that even though the aliveness of the BlackBoard is restored single
122  * interfaces may still be invalid. That can for instance happen if a remote
123  * connection is re-established and a writer has been created during the
124  * downtime and an own writer instance of that very interface cannot be restored.
125  * @return true if the aliveness could be restored and the BlackBoard is
126  * operational again, false otherwise.
127  *
128  * @fn std::list<Interface *> BlackBoard::open_multiple_for_reading(const char *type_pattern, const char *id_pattern = "*")
129  * Open multiple interfaces for reading.
130  * This will create interface instances for currently registered interfaces of
131  * the given type that match the given ID pattern. The result can be casted to
132  * the appropriate type.
133  * @param type_pattern pattern of interface types to open, supports wildcards
134  * similar to filenames (*, ?, []), see "man fnmatch" for all supported.
135  * @param id_pattern pattern of interface IDs to open, supports wildcards similar
136  * to filenames (*, ?, []), see "man fnmatch" for all supported.
137  * @return list of new fully initialized interface instances of requested type.
138  * You have to close all interfaces on your own when done with the list!
139  *
140  * @fn InterfaceInfoList * BlackBoard::list_all()
141  * Get list of all currently existing interfaces.
142  * @return list of interfaces
143  *
144  * @fn InterfaceInfoList * BlackBoard::list(const char *type_pattern, const char *id_pattern)
145  * Get list of interfaces matching type and ID patterns.
146  * See the fnmatch() documentation for possible patterns.
147  * @param type_pattern pattern with shell like globs (* for any number of
148  * characters, ? for exactly one character) to match the interface type.
149  * @param id_pattern pattern with shell like globs (* for any number of
150  * characters, ? for exactly one character) to match the interface ID.
151  * @return list of interfaces
152  *
153  */
154 
155 
156 /** Constructor. */
157 BlackBoard::BlackBoard()
158 {
159  __notifier = new BlackBoardNotifier();
160 }
161 
162 /** Destructor. */
163 BlackBoard::~BlackBoard()
164 {
165  delete __notifier;
166 }
167 
168 
169 /** Register BB event listener.
170  * @param listener BlackBoard event listener to register
171  * @param flag flags what to register for
172  */
173 void
174 BlackBoard::register_listener(BlackBoardInterfaceListener *listener,
176 {
177  __notifier->register_listener(listener, flag);
178 }
179 
180 
181 /** Update BB event listener.
182  * @param listener BlackBoard event listener to update
183  * @param flag flags what to update for
184  */
185 void
186 BlackBoard::update_listener(BlackBoardInterfaceListener *listener,
188 {
189  if (! listener) return;
190  __notifier->update_listener(listener, flag);
191 }
192 
193 
194 /** Unregister BB interface listener.
195  * This will remove the given BlackBoard interface listener from any
196  * event that it was previously registered for.
197  * @param listener BlackBoard event listener to remove
198  */
199 void
200 BlackBoard::unregister_listener(BlackBoardInterfaceListener *listener)
201 {
202  if (! listener) return;
203  __notifier->unregister_listener(listener);
204 }
205 
206 
207 /** Register BB interface observer.
208  * @param observer BlackBoard interface observer to register
209  */
210 void
211 BlackBoard::register_observer(BlackBoardInterfaceObserver *observer)
212 {
213  if (! observer) return;
214  __notifier->register_observer(observer);
215 }
216 
217 
218 /** Unregister BB interface observer.
219  * This will remove the given BlackBoard event listener from any event that it was
220  * previously registered for.
221  * @param observer BlackBoard event listener to remove
222  */
223 void
224 BlackBoard::unregister_observer(BlackBoardInterfaceObserver *observer)
225 {
226  if (! observer) return;
227  __notifier->unregister_observer(observer);
228 }
229 
230 
231 /** Produce interface name from C++ signature.
232  * This extracts the interface name for a mangled signature. It has
233  * has been coded with GCC (4) in mind and assumes interfaces to be
234  * in the fawkes namespace. It cannot deal with anythin else.
235  * @param type type name to strip
236  * @return stripped class type, use delete to free it after you are done
237  */
238 std::string
239 BlackBoard::demangle_fawkes_interface_name(const char *type)
240 {
241  std::string t = type;
242  t = t.substr( 8 ); // Hack to remove N6fawkes namespace prefix
243  t = t.substr( t.find_first_not_of("0123456789") );
244  t = t.substr(0, t.length() - 1); // Hack to remove trailing letter
245  return t;
246 }
247 
248 
249 } // end namespace fawkes
ListenerRegisterFlag
Flags to constrain listener registraion/updates.
Definition: blackboard.h:82
Fawkes library namespace.
BlackBoard notifier.
Definition: notifier.h:43
BlackBoard interface observer.
BlackBoard interface listener.