Fawkes API Fawkes Development Version

blackboard.cpp

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
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends