Fawkes API
Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * blackboard.cpp - BlackBoard Interface 00004 * 00005 * Created: Sat Sep 16 17:11:13 2006 (on train to Cologne) 00006 * Copyright 2006-2008 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. A runtime exception applies to 00014 * this software (see LICENSE.GPL_WRE file mentioned below for details). 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Library General Public License for more details. 00020 * 00021 * Read the full text in the LICENSE.GPL_WRE file in the doc directory. 00022 */ 00023 00024 #include <blackboard/blackboard.h> 00025 00026 #include <string> 00027 #include <cstring> 00028 00029 namespace fawkes { 00030 00031 /** @class BlackBoard blackboard.h <blackboard/blackboard.h> 00032 * The BlackBoard. 00033 * This class is the single one entry point for programs that use the BlackBoard. 00034 * It is used to open and close interfaces, register and unregister listeners and 00035 * observers and to maintain the BlackBoard shared memory segment. Not other classes 00036 * shall be used directly. 00037 * 00038 * The BlackBoard holds a number of so-called interfaces. The interfaces store 00039 * data and provide means to pass messages. The BlackBoard also allows for registering 00040 * listeners and observers. The listeners can be used to get events for specific 00041 * interfaces while the observer gets global interface creation and destruction 00042 * events for a specified set of types of interfaces. 00043 00044 * An interface consists of a few parts. First there is the storage block. This 00045 * is a chunk of memory in the shared memory segment where the actual data is stored. 00046 * Then there is the accessor object, an instance of a derivate of the Interface 00047 * class which is used to access the data in the shared memory segment. Last but 00048 * not least there is an internal message queue that can be used to pass messages 00049 * from readers to the writer (not the other way around!). 00050 * 00051 * The interface manager keeps track of all the allocated interfaces. Events 00052 * can be triggered if a specific interface changes (like logging the data to 00053 * a file, sending it over the network or notifying another interface of such 00054 * a change). 00055 * 00056 * Interfaces can only be instantiated through the BlackBoard. The BlackBoard 00057 * instantiates an interface on request and guarantees that the instance 00058 * is fully initialized and usable. This cannot be guaranteed if instantiating an 00059 * interface through any other means! 00060 * 00061 * Interfaces can be opened for reading or writing, not both! There can be only 00062 * one writer at a time for any given interface. Interfaces are identified via a 00063 * type (which denotes the data and its semantics) and an identifier. There may 00064 * be several interfaces for a given type, but the identifier has to be unique. 00065 * The identifier is in most cases a well-known string that is used to share data 00066 * among plugins. 00067 * 00068 * Interfaces provide a way to propagate data to the writer via messages. Available 00069 * messages types depend on the interface type. Only matching messages are accepted 00070 * and can be queued. 00071 * 00072 * The BlackBoard can operate in two modes, master and slave. Only the master 00073 * creates and destroys the shared memory segment. Currently, the slave mode is not 00074 * fully implemented and thus may not be used. 00075 * 00076 * @see Interface 00077 * @see Message 00078 * 00079 * @author Tim Niemueller 00080 * 00081 * 00082 * @fn Interface * BlackBoard::open_for_reading(const char *type, const char *identifier) 00083 * Open interface for reading. 00084 * This will create a new interface instance of the given type. The result can be 00085 * casted to the appropriate type. 00086 * @param type type of the interface 00087 * @param identifier identifier of the interface 00088 * @return new fully initialized interface instance of requested type 00089 * @exception OutOfMemoryException thrown if there is not enough free space for 00090 * the requested interface. 00091 * 00092 * 00093 * @fn Interface * BlackBoard::open_for_writing(const char *type, const char *identifier) 00094 * Open interface for writing. 00095 * This will create a new interface instance of the given type. The result can be 00096 * casted to the appropriate type. This will only succeed if there is not already 00097 * a writer for the given interface type/id! 00098 * @param type type of the interface 00099 * @param identifier identifier of the interface 00100 * @return new fully initialized interface instance of requested type 00101 * @exception OutOfMemoryException thrown if there is not enough free space for 00102 * the requested interface. 00103 * @exception BlackBoardWriterActiveException thrown if there is already a writing 00104 * instance with the same type/id 00105 * 00106 * 00107 * @fn void BlackBoard::close(Interface *interface) 00108 * Close interface. 00109 * @param interface interface to close 00110 * 00111 * 00112 * @fn bool BlackBoard::is_alive() const throw() = 0 00113 * Check if the BlackBoard is still alive. 00114 * @return true, if the BlackBoard is still alive and may be used, false otherwise. 00115 * 00116 * @fn bool BlackBoard::try_aliveness_restore() throw() 00117 * Try to restore the aliveness of the BlackBoard instance. 00118 * Note that even though the aliveness of the BlackBoard is restored single 00119 * interfaces may still be invalid. That can for instance happen if a remote 00120 * connection is re-established and a writer has been created during the 00121 * downtime and an own writer instance of that very interface cannot be restored. 00122 * @return true if the aliveness could be restored and the BlackBoard is 00123 * operational again, false otherwise. 00124 * 00125 * @fn std::list<Interface *> BlackBoard::open_multiple_for_reading(const char *type, const char *id_pattern = "*") 00126 * Open multiple interfaces for reading. 00127 * This will create interface instances for currently registered interfaces of 00128 * the given type that match the given ID pattern. The result can be casted to 00129 * the appropriate type. 00130 * @param type type of the interface 00131 * @param id_pattern pattern of interface IDs to open, supports wildcards similar 00132 * to filenames (*, ?, []), see "man fnmatch" for all supported. 00133 * @return list of new fully initialized interface instances of requested type. 00134 * You have to close all interfaces on your own when done with the list! 00135 * 00136 * 00137 * @fn InterfaceInfoList * BlackBoard::list_all() 00138 * Get list of interfaces. 00139 * @return list of interfaces 00140 * 00141 * 00142 * @fn void BlackBoard::register_listener(BlackBoardInterfaceListener *listener, unsigned int flags) 00143 * Register BB event listener. 00144 * @param listener BlackBoard event listener to register 00145 * @param flags an or'ed combination of BBIL_FLAG_DATA, BBIL_FLAG_READER, BBIL_FLAG_WRITER 00146 * and BBIL_FLAG_INTERFACE. Only for the given types the event listener is registered. 00147 * BBIL_FLAG_ALL can be supplied to register for all events. 00148 * 00149 * 00150 * @fn void BlackBoard::unregister_listener(BlackBoardInterfaceListener *listener) 00151 * Unregister BB interface listener. 00152 * This will remove the given BlackBoard interface listener from any event that it was 00153 * previously registered for. 00154 * @param listener BlackBoard event listener to remove 00155 * 00156 * 00157 * @fn void BlackBoard::register_observer(BlackBoardInterfaceObserver *observer, unsigned int flags) 00158 * Register BB interface observer. 00159 * @param observer BlackBoard interface observer to register 00160 * @param flags an or'ed combination of BBIO_FLAG_CREATED, BBIO_FLAG_DESTROYED 00161 * 00162 * 00163 * @fn void BlackBoard::unregister_observer(BlackBoardInterfaceObserver *observer) 00164 * Unregister BB interface observer. 00165 * This will remove the given BlackBoard event listener from any event that it was 00166 * previously registered for. 00167 * @param observer BlackBoard event listener to remove 00168 */ 00169 00170 00171 /** Data changed notification flag. */ 00172 const unsigned int BlackBoard::BBIL_FLAG_DATA = 1; 00173 /** Message received notification flag. */ 00174 const unsigned int BlackBoard::BBIL_FLAG_MESSAGES = 2; 00175 /** Reader added/removed notification flag. */ 00176 const unsigned int BlackBoard::BBIL_FLAG_READER = 4; 00177 /** Writer added/removed notification flag. */ 00178 const unsigned int BlackBoard::BBIL_FLAG_WRITER = 8; 00179 00180 /** All interface listener notifications. */ 00181 const unsigned int BlackBoard::BBIL_FLAG_ALL = 00182 BBIL_FLAG_DATA | BBIL_FLAG_MESSAGES | BBIL_FLAG_READER | BBIL_FLAG_WRITER; 00183 00184 /** Interface creation notification flag. */ 00185 const unsigned int BlackBoard::BBIO_FLAG_CREATED = 1; 00186 00187 /** Interface destruction notification flag. */ 00188 const unsigned int BlackBoard::BBIO_FLAG_DESTROYED = 2; 00189 00190 /** All interface observer notifications */ 00191 const unsigned int BlackBoard::BBIO_FLAG_ALL = 00192 BBIO_FLAG_CREATED | BBIO_FLAG_DESTROYED; 00193 00194 00195 00196 /** Virtual empty destructor. */ 00197 BlackBoard::~BlackBoard() 00198 { 00199 } 00200 00201 00202 /** Produce interface name from C++ signature. 00203 * This extracts the interface name for a mangled signature. It has 00204 * has been coded with GCC (4) in mind and assumes interfaces to be 00205 * in the fawkes namespace. It cannot deal with anythin else. 00206 * @param type type name to strip 00207 * @return stripped class type, use delete to free it after you are done 00208 */ 00209 std::string 00210 BlackBoard::demangle_fawkes_interface_name(const char *type) 00211 { 00212 std::string t = type; 00213 t = t.substr( 8 ); // Hack to remove N6fawkes namespace prefix 00214 t = t.substr( t.find_first_not_of("0123456789") ); 00215 t = t.substr(0, t.length() - 1); // Hack to remove trailing letter 00216 return t; 00217 } 00218 00219 00220 } // end namespace fawkes