00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <lua/interface_importer.h>
00024 #include <lua/context.h>
00025
00026 #include <config/config.h>
00027 #include <interface/interface.h>
00028 #include <blackboard/blackboard.h>
00029 #include <utils/logging/logger.h>
00030
00031 #include <cstring>
00032
00033 namespace fawkes {
00034 #if 0
00035 }
00036 #endif
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 LuaInterfaceImporter::LuaInterfaceImporter(LuaContext *context,
00057 BlackBoard *blackboard,
00058 Configuration *config,
00059 Logger *logger)
00060 {
00061 __context = context;
00062 __blackboard = blackboard;
00063 __config = config;
00064 __logger = logger;
00065 __context->add_watcher(this);
00066
00067 __interfaces_pushed = false;
00068 }
00069
00070
00071
00072 LuaInterfaceImporter::~LuaInterfaceImporter()
00073 {
00074 __context->remove_watcher(this);
00075 close_writing_interfaces();
00076 close_reading_interfaces();
00077 __ext_rifs.clear();
00078 __ext_wifs.clear();
00079 }
00080
00081
00082
00083
00084
00085
00086
00087 void
00088 LuaInterfaceImporter::open_interfaces(std::string &prefix, InterfaceMap &imap, bool write)
00089 {
00090 if (! __config) throw NullPointerException("Config has not been set");
00091
00092 Configuration::ValueIterator *vi = __config->search(prefix.c_str());
00093 while (vi->next()) {
00094 if (strcmp(vi->type(), "string") != 0) {
00095 TypeMismatchException e("Only values of type string may occur in %s, "
00096 "but found value of type %s",
00097 prefix.c_str(), vi->type());
00098 delete vi;
00099 throw e;
00100 }
00101 std::string uid = vi->get_string();
00102
00103 if (uid.find("::") == std::string::npos) {
00104 delete vi;
00105 throw Exception("Interface UID '%s' at %s is not valid, missing double colon",
00106 uid.c_str(), vi->path());
00107 }
00108 std::string varname = std::string(vi->path()).substr(prefix.length());
00109 std::string iftype = uid.substr(0, uid.find("::"));
00110 std::string ifname = uid.substr(uid.find("::") + 2);
00111
00112 if ( __reading_ifs.find(varname) != __reading_ifs.end() ) {
00113 delete vi;
00114 throw Exception("Reading interface with varname %s already opened", varname.c_str());
00115 }
00116 if ( __reading_multi_ifs.find(varname) != __reading_multi_ifs.end() ) {
00117 delete vi;
00118 throw Exception("Reading multi interface with varname %s already opened", varname.c_str());
00119 }
00120 if ( __writing_ifs.find(varname) != __writing_ifs.end() ) {
00121 delete vi;
00122 throw Exception("Writing interface with varname %s already opened", varname.c_str());
00123 }
00124
00125
00126 if (ifname.find_first_of("*?[") == std::string::npos) {
00127 __logger->log_info("LuaInterfaceImporter", "Adding %s interface %s::%s with name %s",
00128 write ? "writing" : "reading",
00129 iftype.c_str(), ifname.c_str(), varname.c_str());
00130 try {
00131 Interface *iface;
00132 if (write) {
00133 iface = __blackboard->open_for_writing(iftype.c_str(), ifname.c_str());
00134 } else {
00135 iface = __blackboard->open_for_reading(iftype.c_str(), ifname.c_str());
00136 }
00137 imap[varname] = iface;
00138 } catch (Exception &e) {
00139 delete vi;
00140 throw;
00141 }
00142 } else {
00143 if (write) {
00144 delete vi;
00145 throw Exception("Illegal config entry %s=%s, multiple interfaces can "
00146 "only be opened for reading", vi->path(), uid.c_str());
00147 }
00148 __logger->log_info("LuaInterfaceImporter", "Adding multiple %s interfaces %s::%s with in table %s",
00149 write ? "writing" : "reading",
00150 iftype.c_str(), ifname.c_str(), varname.c_str());
00151
00152 std::list<Interface *> interfaces = __blackboard->open_multiple_for_reading(iftype.c_str(), ifname.c_str());
00153 __reading_multi_ifs[varname] = interfaces;
00154 InterfaceObserver *observer = new InterfaceObserver(this, varname, iftype.c_str(), ifname.c_str());
00155 __observers[varname] = observer;
00156 __blackboard->register_observer(observer, BlackBoard::BBIO_FLAG_CREATED);
00157 }
00158 }
00159 delete vi;
00160 }
00161
00162
00163
00164
00165
00166 void
00167 LuaInterfaceImporter::open_reading_interfaces(std::string &prefix)
00168 {
00169 open_interfaces(prefix, __reading_ifs, false);
00170 }
00171
00172
00173
00174
00175 void
00176 LuaInterfaceImporter::open_writing_interfaces(std::string &prefix)
00177 {
00178 open_interfaces(prefix, __writing_ifs, true);
00179 }
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191 void
00192 LuaInterfaceImporter::add_interface(std::string varname, Interface *interface)
00193 {
00194 if ( interface->is_writer() ) {
00195 __ext_wifs[varname] = interface;
00196 } else {
00197 __ext_rifs[varname] = interface;
00198 }
00199 }
00200
00201
00202 void
00203 LuaInterfaceImporter::add_observed_interface(std::string varname,
00204 const char *type, const char *id)
00205 {
00206 try {
00207 if (__reading_multi_ifs.find(varname) == __reading_multi_ifs.end() ) {
00208 throw Exception("Notified about unknown interface varname %s", varname.c_str());
00209 }
00210 Interface *iface = __blackboard->open_for_reading(type, id);
00211 __context->add_package((std::string("interfaces.") + iface->type()).c_str());
00212 __reading_multi_ifs[varname].push_back(iface);
00213 __context->get_global("interfaces");
00214 __context->get_field(-1, "reading");
00215 __context->get_field(-1, varname.c_str());
00216 __context->push_usertype(iface, iface->type(), "fawkes");
00217 __context->raw_seti(-2, __reading_multi_ifs[varname].size());
00218 __context->push_usertype(iface, iface->type(), "fawkes");
00219 __context->set_field(iface->uid(), -2);
00220 __context->pop(3);
00221 } catch (Exception &e) {
00222 __logger->log_warn("LuaInterfaceImporter", "Failed to add observed interface "
00223 "%s:%s, exception follows", type, id);
00224 __logger->log_warn("LuaInterfaceImporter", e);
00225 }
00226 }
00227
00228
00229
00230 void
00231 LuaInterfaceImporter::close_reading_interfaces()
00232 {
00233 for (InterfaceMap::iterator i = __reading_ifs.begin(); i != __reading_ifs.end(); ++i) {
00234 __blackboard->close(i->second);
00235 }
00236 __reading_ifs.clear();
00237
00238 for (ObserverMap::iterator o = __observers.begin(); o != __observers.end(); ++o) {
00239 __blackboard->unregister_observer(o->second);
00240 delete o->second;
00241 }
00242 __observers.clear();
00243
00244 for (InterfaceListMap::iterator i = __reading_multi_ifs.begin(); i != __reading_multi_ifs.end(); ++i) {
00245 for (std::list<Interface *>::iterator j = i->second.begin(); j != i->second.end(); ++j) {
00246 __blackboard->close(*j);
00247 }
00248 }
00249 __reading_multi_ifs.clear();
00250 }
00251
00252
00253
00254 void
00255 LuaInterfaceImporter::close_writing_interfaces()
00256 {
00257 for (InterfaceMap::iterator i = __writing_ifs.begin(); i != __writing_ifs.end(); ++i) {
00258 __blackboard->close(i->second);
00259 }
00260 __writing_ifs.clear();
00261 }
00262
00263
00264
00265
00266 LuaInterfaceImporter::InterfaceMap &
00267 LuaInterfaceImporter::reading_interfaces()
00268 {
00269 return __reading_ifs;
00270 }
00271
00272
00273
00274
00275
00276 LuaInterfaceImporter::InterfaceMap &
00277 LuaInterfaceImporter::writing_interfaces()
00278 {
00279 return __writing_ifs;
00280 }
00281
00282
00283
00284 void
00285 LuaInterfaceImporter::read()
00286 {
00287 for (InterfaceMap::iterator i = __reading_ifs.begin(); i != __reading_ifs.end(); ++i) {
00288 i->second->read();
00289 }
00290 }
00291
00292
00293 void
00294 LuaInterfaceImporter::write()
00295 {
00296 for (InterfaceMap::iterator i = __writing_ifs.begin(); i != __writing_ifs.end(); ++i) {
00297 try {
00298 i->second->write();
00299 } catch (Exception &e) {
00300 e.append("Failed to write interface %s, ignoring.", i->second->uid());
00301 e.print_trace();
00302 }
00303 }
00304 }
00305
00306 void
00307 LuaInterfaceImporter::push_interfaces_varname(LuaContext *context, InterfaceMap &imap)
00308 {
00309 InterfaceMap::iterator imi;
00310 for (imi = imap.begin(); imi != imap.end(); ++imi) {
00311 context->add_package((std::string("interfaces.") + imi->second->type()).c_str());
00312 context->push_usertype(imi->second, imi->second->type(), "fawkes");
00313 context->set_field(imi->first.c_str());
00314 }
00315 }
00316
00317 void
00318 LuaInterfaceImporter::push_multi_interfaces_varname(LuaContext *context, InterfaceListMap &imap)
00319 {
00320 InterfaceListMap::iterator imi;
00321 for (imi = imap.begin(); imi != imap.end(); ++imi) {
00322 context->create_table(0, imi->second.size());
00323 int idx = 0;
00324 for (std::list<Interface *>::iterator i = imi->second.begin(); i != imi->second.end(); ++i) {
00325 context->add_package((std::string("interfaces.") + (*i)->type()).c_str());
00326 context->push_usertype(*i, (*i)->type(), "fawkes");
00327 context->raw_seti(-2, ++idx);
00328 context->push_usertype(*i, (*i)->type(), "fawkes");
00329 context->set_field((*i)->uid(), -2);
00330 }
00331 context->set_field(imi->first.c_str());
00332 }
00333 }
00334
00335 void
00336 LuaInterfaceImporter::push_interfaces_uid(LuaContext *context, InterfaceMap &imap)
00337 {
00338 InterfaceMap::iterator imi;
00339 for (imi = imap.begin(); imi != imap.end(); ++imi) {
00340 context->add_package((std::string("interfaces.") + imi->second->type()).c_str());
00341 context->push_usertype(imi->second, imi->second->type(), "fawkes");
00342 context->set_field(imi->second->uid());
00343 }
00344 }
00345
00346 void
00347 LuaInterfaceImporter::push_interfaces(LuaContext *context)
00348 {
00349
00350
00351 context->create_table(0, 4);
00352
00353 context->create_table(0, __reading_ifs.size() + __ext_rifs.size());
00354 push_interfaces_varname(context, __reading_ifs);
00355 push_interfaces_varname(context, __ext_rifs);
00356 push_multi_interfaces_varname(context, __reading_multi_ifs);
00357 context->set_field("reading");
00358
00359 context->create_table(0, __reading_ifs.size() + __ext_rifs.size());
00360 push_interfaces_uid(context, __reading_ifs);
00361 push_interfaces_uid(context, __ext_rifs);
00362 context->set_field("reading_by_uid");
00363
00364 context->create_table(0, __writing_ifs.size() + __ext_wifs.size());
00365 push_interfaces_varname(context, __writing_ifs);
00366 push_interfaces_varname(context, __ext_wifs);
00367 context->set_field("writing");
00368
00369 context->create_table(0, __writing_ifs.size());
00370 push_interfaces_uid(context, __writing_ifs);
00371 push_interfaces_uid(context, __ext_wifs);
00372 context->set_field("writing_by_uid");
00373
00374 context->set_global("interfaces");
00375 }
00376
00377
00378
00379
00380
00381
00382 void
00383 LuaInterfaceImporter::push_interfaces()
00384 {
00385 __interfaces_pushed = true;
00386 push_interfaces(__context);
00387 }
00388
00389
00390 void
00391 LuaInterfaceImporter::lua_restarted(LuaContext *context)
00392 {
00393 try {
00394 if ( __interfaces_pushed ) {
00395 push_interfaces(context);
00396 }
00397 } catch (Exception &e) {
00398 __logger->log_warn("LuaInterfaceImporter", "Failed to re-push interfacs, exception follows");
00399 __logger->log_warn("LuaInterfaceImporter", e);
00400 throw;
00401 }
00402 }
00403
00404
00405
00406
00407
00408
00409
00410
00411 LuaInterfaceImporter::InterfaceObserver::InterfaceObserver(LuaInterfaceImporter *lii,
00412 std::string varname,
00413 const char *type, const char *id_pattern)
00414 {
00415 __lii = lii;
00416 __varname = varname;
00417
00418 bbio_add_observed_create(type, id_pattern);
00419 }
00420
00421
00422 void
00423 LuaInterfaceImporter::InterfaceObserver::bb_interface_created(const char *type, const char *id) throw()
00424 {
00425 __lii->add_observed_interface(__varname, type, id);
00426 }
00427
00428 }