00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <blackboard/internal/interface_manager.h>
00025
00026 #include <blackboard/blackboard.h>
00027 #include <blackboard/internal/memory_manager.h>
00028 #include <blackboard/internal/message_manager.h>
00029 #include <blackboard/exceptions.h>
00030 #include <blackboard/internal/interface_mem_header.h>
00031 #include <blackboard/interface_listener.h>
00032 #include <blackboard/interface_observer.h>
00033 #include <blackboard/internal/instance_factory.h>
00034 #include <blackboard/internal/notifier.h>
00035
00036 #include <interface/interface.h>
00037 #include <interface/interface_info.h>
00038
00039 #include <core/threading/mutex.h>
00040 #include <core/threading/refc_rwlock.h>
00041 #include <core/exceptions/system.h>
00042 #include <utils/system/dynamic_module/module_dl.h>
00043 #include <utils/logging/liblogger.h>
00044
00045 #include <cstdlib>
00046 #include <cstring>
00047 #include <fnmatch.h>
00048
00049 namespace fawkes {
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 BlackBoardInterfaceManager::BlackBoardInterfaceManager(BlackBoardMemoryManager *bb_memmgr,
00068 BlackBoardMessageManager *bb_msgmgr,
00069 BlackBoardNotifier *bb_notifier)
00070 {
00071 memmgr = bb_memmgr;
00072 msgmgr = bb_msgmgr;
00073 notifier = bb_notifier;
00074
00075 instance_serial = 1;
00076 instance_factory = new BlackBoardInstanceFactory();
00077 mutex = new Mutex();
00078
00079 writer_interfaces.clear();
00080 rwlocks.clear();
00081 }
00082
00083
00084
00085 BlackBoardInterfaceManager::~BlackBoardInterfaceManager()
00086 {
00087 delete mutex;
00088 delete instance_factory;
00089 }
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 Interface *
00103 BlackBoardInterfaceManager::new_interface_instance(const char *type, const char *identifier)
00104 {
00105 Interface *iface = instance_factory->new_interface_instance(type, identifier);
00106
00107 iface->set_instance_serial(next_instance_serial());
00108 iface->set_mediators(this, msgmgr);
00109 return iface;
00110 }
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 void
00121 BlackBoardInterfaceManager::delete_interface_instance(Interface *interface)
00122 {
00123 instance_factory->delete_interface_instance(interface);
00124 }
00125
00126
00127
00128
00129
00130
00131
00132 void *
00133 BlackBoardInterfaceManager::find_interface_in_memory(const char *type, const char *identifier)
00134 {
00135 interface_header_t *ih;
00136 BlackBoardMemoryManager::ChunkIterator cit;
00137 for ( cit = memmgr->begin(); cit != memmgr->end(); ++cit ) {
00138 ih = (interface_header_t *)*cit;
00139 if ( (strncmp(ih->type, type, __INTERFACE_TYPE_SIZE) == 0) &&
00140 (strncmp(ih->id, identifier, __INTERFACE_ID_SIZE) == 0)
00141 ) {
00142
00143 return *cit;
00144 }
00145 }
00146
00147 return NULL;
00148 }
00149
00150
00151
00152
00153
00154 unsigned int
00155 BlackBoardInterfaceManager::next_mem_serial()
00156 {
00157 unsigned int serial = 1;
00158 interface_header_t *ih;
00159 BlackBoardMemoryManager::ChunkIterator cit;
00160 for ( cit = memmgr->begin(); cit != memmgr->end(); ++cit ) {
00161 ih = (interface_header_t *)*cit;
00162 if ( ih->serial >= serial ) {
00163 serial = ih->serial + 1;
00164 }
00165 }
00166
00167 return serial;
00168 }
00169
00170
00171
00172
00173
00174 unsigned int
00175 BlackBoardInterfaceManager::next_instance_serial()
00176 {
00177 if ( memmgr->is_master() ) {
00178
00179 return instance_serial++;
00180 } else {
00181 throw BBNotMasterException("Instance serial can only be requested by BB Master");
00182 }
00183 }
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196 void
00197 BlackBoardInterfaceManager::create_interface(const char *type, const char *identifier,
00198 Interface* &interface, void* &ptr)
00199 {
00200 interface_header_t *ih;
00201
00202
00203 interface = new_interface_instance(type, identifier);
00204 try {
00205 ptr = memmgr->alloc_nolock(interface->datasize() + sizeof(interface_header_t));
00206 ih = (interface_header_t *)ptr;
00207 } catch (OutOfMemoryException &e) {
00208 e.append("BlackBoardInterfaceManager::createInterface: interface of type %s could not be created", type);
00209 memmgr->unlock();
00210 mutex->unlock();
00211 throw;
00212 }
00213 memset(ptr, 0, interface->datasize() + sizeof(interface_header_t));
00214
00215 strncpy(ih->type, type, __INTERFACE_TYPE_SIZE);
00216 strncpy(ih->id, identifier, __INTERFACE_ID_SIZE);
00217 memcpy(ih->hash, interface->hash(), __INTERFACE_HASH_SIZE);
00218
00219 ih->refcount = 0;
00220 ih->serial = next_mem_serial();
00221 ih->flag_writer_active = 0;
00222 ih->num_readers = 0;
00223 rwlocks[ih->serial] = new RefCountRWLock();
00224
00225 interface->set_memory(ih->serial, ptr, (char *)ptr + sizeof(interface_header_t));
00226 }
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 Interface *
00239 BlackBoardInterfaceManager::open_for_reading(const char *type, const char *identifier)
00240 {
00241 mutex->lock();
00242 Interface *iface = NULL;
00243 void *ptr = NULL;
00244 interface_header_t *ih;
00245 bool created = false;
00246
00247 memmgr->lock();
00248
00249 ptr = find_interface_in_memory(type, identifier);
00250
00251 try {
00252 if ( ptr != NULL ) {
00253
00254 iface = new_interface_instance(type, identifier);
00255 ih = (interface_header_t *)ptr;
00256 if ( (iface->hash_size() != __INTERFACE_HASH_SIZE ) ||
00257 (memcmp(iface->hash(), ih->hash, __INTERFACE_HASH_SIZE) != 0) ) {
00258 throw BlackBoardInterfaceVersionMismatchException();
00259 }
00260 iface->set_memory(ih->serial, ptr, (char *)ptr + sizeof(interface_header_t));
00261 rwlocks[ih->serial]->ref();
00262 } else {
00263 created = true;
00264 create_interface(type, identifier, iface, ptr);
00265 ih = (interface_header_t *)ptr;
00266 }
00267
00268 iface->set_readwrite(false, rwlocks[ih->serial]);
00269 ih->refcount++;
00270 ih->num_readers++;
00271
00272 memmgr->unlock();
00273 mutex->unlock();
00274
00275 if ( created ) {
00276 notifier->notify_of_interface_created(type, identifier);
00277 }
00278 notifier->notify_of_reader_added(iface, iface->serial());
00279
00280 } catch (Exception &e) {
00281 if (iface) delete_interface_instance(iface);
00282 memmgr->unlock();
00283 mutex->unlock();
00284 throw;
00285 }
00286
00287 return iface;
00288 }
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 std::list<Interface *>
00302 BlackBoardInterfaceManager::open_multiple_for_reading(const char *type,
00303 const char *id_pattern)
00304 {
00305 mutex->lock();
00306 memmgr->lock();
00307
00308 std::list<Interface *> rv;
00309
00310 Interface *iface = NULL;
00311 interface_header_t *ih;
00312 BlackBoardMemoryManager::ChunkIterator cit;
00313
00314 try {
00315 for ( cit = memmgr->begin(); cit != memmgr->end(); ++cit ) {
00316 iface = NULL;
00317 ih = (interface_header_t *)*cit;
00318
00319 if ((strncmp(type, ih->type, __INTERFACE_TYPE_SIZE) != 0) ||
00320 (fnmatch(id_pattern, ih->id, 0) == FNM_NOMATCH) ) {
00321
00322 continue;
00323 }
00324
00325 void *ptr = *cit;
00326 iface = new_interface_instance(ih->type, ih->id);
00327 iface->set_memory(ih->serial, ptr, (char *)ptr + sizeof(interface_header_t));
00328
00329 if ( (iface->hash_size() != __INTERFACE_HASH_SIZE ) ||
00330 (memcmp(iface->hash(), ih->hash, __INTERFACE_HASH_SIZE) != 0) ) {
00331 throw BlackBoardInterfaceVersionMismatchException();
00332 }
00333
00334 rwlocks[ih->serial]->ref();
00335
00336 iface->set_readwrite(false, rwlocks[ih->serial]);
00337 ih->refcount++;
00338 ih->num_readers++;
00339
00340 rv.push_back(iface);
00341 }
00342
00343 mutex->unlock();
00344 memmgr->unlock();
00345
00346 for (std::list<Interface *>::iterator j = rv.begin(); j != rv.end(); ++j) {
00347 notifier->notify_of_reader_added(*j, (*j)->serial());
00348 }
00349
00350
00351 } catch (Exception &e) {
00352 if (iface) delete_interface_instance( iface );
00353 for (std::list<Interface *>::iterator i = rv.begin(); i != rv.end(); ++i) {
00354 delete_interface_instance(*i);
00355 }
00356 memmgr->unlock();
00357 mutex->unlock();
00358 throw;
00359 }
00360
00361 return rv;
00362 }
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377 Interface *
00378 BlackBoardInterfaceManager::open_for_writing(const char *type, const char *identifier)
00379 {
00380 mutex->lock();
00381 memmgr->lock();
00382
00383 Interface *iface = NULL;
00384 void *ptr = NULL;
00385 interface_header_t *ih;
00386 bool created = false;
00387
00388 try {
00389 ptr = find_interface_in_memory(type, identifier);
00390
00391 if ( ptr != NULL ) {
00392
00393
00394 ih = (interface_header_t *)ptr;
00395 if ( ih->flag_writer_active ) {
00396 throw BlackBoardWriterActiveException(identifier, type);
00397 }
00398 iface = new_interface_instance(type, identifier);
00399 if ( (iface->hash_size() != __INTERFACE_HASH_SIZE ) ||
00400 (memcmp(iface->hash(), ih->hash, __INTERFACE_HASH_SIZE) != 0) ) {
00401 throw BlackBoardInterfaceVersionMismatchException();
00402 }
00403 iface->set_memory(ih->serial, ptr, (char *)ptr + sizeof(interface_header_t));
00404 rwlocks[ih->serial]->ref();
00405 } else {
00406 created = true;
00407 create_interface(type, identifier, iface, ptr);
00408 ih = (interface_header_t *)ptr;
00409 }
00410
00411 iface->set_readwrite(true, rwlocks[ih->serial]);
00412 ih->flag_writer_active = 1;
00413 ih->refcount++;
00414
00415 memmgr->unlock();
00416 writer_interfaces[ih->serial] = iface;
00417
00418 mutex->unlock();
00419
00420 if ( created ) {
00421 notifier->notify_of_interface_created(type, identifier);
00422 }
00423 notifier->notify_of_writer_added(iface, iface->serial());
00424 } catch (Exception &e) {
00425 if (iface) delete_interface_instance(iface);
00426 memmgr->unlock();
00427 mutex->unlock();
00428 throw;
00429 }
00430
00431 return iface;
00432 }
00433
00434
00435
00436
00437
00438 void
00439 BlackBoardInterfaceManager::close(Interface *interface)
00440 {
00441 if ( interface == NULL ) return;
00442 mutex->lock();
00443 bool destroyed = false;
00444
00445
00446 interface_header_t *ih = (interface_header_t *)interface->__mem_real_ptr;
00447 bool killed_writer = interface->__write_access;
00448 if ( --(ih->refcount) == 0 ) {
00449
00450 if ( interface->__write_access ) {
00451 writer_interfaces.erase( interface->__mem_serial );
00452 }
00453 memmgr->free( interface->__mem_real_ptr );
00454 destroyed = true;
00455 } else {
00456 if ( interface->__write_access ) {
00457 ih->flag_writer_active = 0;
00458 writer_interfaces.erase( interface->__mem_serial );
00459 } else {
00460 ih->num_readers--;
00461 }
00462 }
00463
00464 mutex->unlock();
00465 if (killed_writer) {
00466 notifier->notify_of_writer_removed(interface, interface->serial());
00467 } else {
00468 notifier->notify_of_reader_removed(interface, interface->serial());
00469 }
00470 if ( destroyed ) {
00471 notifier->notify_of_interface_destroyed(interface->__type, interface->__id);
00472 }
00473
00474 mutex->lock();
00475 delete_interface_instance( interface );
00476 mutex->unlock();
00477 }
00478
00479
00480
00481
00482
00483
00484 InterfaceInfoList *
00485 BlackBoardInterfaceManager::list_all() const
00486 {
00487 InterfaceInfoList *infl = new InterfaceInfoList();
00488
00489 memmgr->lock();
00490 interface_header_t *ih;
00491 BlackBoardMemoryManager::ChunkIterator cit;
00492 for ( cit = memmgr->begin(); cit != memmgr->end(); ++cit ) {
00493 ih = (interface_header_t *)*cit;
00494 infl->append(ih->type, ih->id, ih->hash, ih->serial,
00495 ih->flag_writer_active, ih->num_readers);
00496 }
00497
00498 memmgr->unlock();
00499
00500 return infl;
00501 }
00502
00503
00504
00505
00506
00507
00508
00509
00510 Interface *
00511 BlackBoardInterfaceManager::writer_for_mem_serial(unsigned int mem_serial)
00512 {
00513 if ( writer_interfaces.find(mem_serial) != writer_interfaces.end() ) {
00514 return writer_interfaces[mem_serial];
00515 } else {
00516 throw BlackBoardNoWritingInstanceException();
00517 }
00518 }
00519
00520
00521 void
00522 BlackBoardInterfaceManager::notify_of_data_change(const Interface *interface)
00523 {
00524 notifier->notify_of_data_change(interface);
00525 }
00526
00527
00528 bool
00529 BlackBoardInterfaceManager::exists_writer(const Interface *interface) const
00530 {
00531 return (writer_interfaces.find(interface->__mem_serial) != writer_interfaces.end());
00532 }
00533
00534
00535 unsigned int
00536 BlackBoardInterfaceManager::num_readers(const Interface *interface) const
00537 {
00538 const interface_header_t *ih = (interface_header_t *)interface->__mem_real_ptr;
00539 return ih->num_readers;
00540 }
00541
00542 }