00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef OCL_COMPONENT_ONLY
00036
00037 #include <rtt/rtt-config.h>
00038 #ifdef OS_RT_MALLOC
00039
00040 #define ORO_MEMORY_POOL
00041 #include <rtt/os/tlsf/tlsf.h>
00042 #endif
00043 #include <rtt/os/main.h>
00044 #include <rtt/RTT.hpp>
00045 #include <rtt/Logger.hpp>
00046 #ifdef ORO_BUILD_LOGGING
00047 # ifndef OS_RT_MALLOC
00048 # warning "Logging needs rtalloc!"
00049 # endif
00050 #include <log4cpp/HierarchyMaintainer.hh>
00051 #include "logging/Category.hpp"
00052 #endif
00053
00054 extern "C" {
00055 #include "lua-repl.h"
00056 void dotty (lua_State *L);
00057 void l_message (const char *pname, const char *msg);
00058 int dofile (lua_State *L, const char *name);
00059 int dostring (lua_State *L, const char *s, const char *name);
00060 int main_args(lua_State *L, int argc, char **argv);
00061
00062 #include <sys/types.h>
00063 #include <sys/stat.h>
00064 #include <unistd.h>
00065 #include <wordexp.h>
00066 }
00067 #endif
00068
00069 #include "rtt.hpp"
00070
00071 #include <string>
00072 #include <rtt/os/main.h>
00073 #include <rtt/os/Mutex.hpp>
00074 #include <rtt/os/MutexLock.hpp>
00075 #include <rtt/TaskContext.hpp>
00076 #include <ocl/OCL.hpp>
00077 #if defined(LUA_RTT_CORBA)
00078 #include <rtt/transports/corba/TaskContextServer.hpp>
00079 #include <deployment/CorbaDeploymentComponent.hpp>
00080 #else
00081 #include <deployment/DeploymentComponent.hpp>
00082 #endif
00083
00084 #ifdef LUA_RTT_TLSF
00085 extern "C" {
00086 #include "tlsf_rtt.h"
00087 }
00088 #endif
00089
00090 #ifdef LUA_RTT_TLSF
00091 #define LuaComponent LuaTLSFComponent
00092 #else
00093 #define LuaComponent LuaComponent
00094 #endif
00095
00096 #define INIT_FILE "~/.rttlua"
00097
00098 using namespace std;
00099 using namespace RTT;
00100 using namespace Orocos;
00101 #if defined(LUA_RTT_CORBA)
00102 using namespace RTT::corba;
00103 #endif
00104
00105 namespace OCL
00106 {
00107 class LuaComponent : public TaskContext
00108 {
00109 protected:
00110 std::string lua_string;
00111 std::string lua_file;
00112 lua_State *L;
00113 os::MutexRecursive m;
00114 #if LUA_RTT_TLSF
00115 struct lua_tlsf_info tlsf_inf;
00116 #endif
00117
00118 public:
00119 LuaComponent(std::string name)
00120 : TaskContext(name, PreOperational)
00121 {
00122 os::MutexLock lock(m);
00123 #if LUA_RTT_TLSF
00124 if(tlsf_rtt_init_mp(&tlsf_inf, TLSF_INITIAL_POOLSIZE)) {
00125 Logger::log(Logger::Error) << "LuaComponent '" << name << ": failed to create tlsf pool ("
00126 << std::hex << TLSF_INITIAL_POOLSIZE << "bytes)" << endlog();
00127 throw;
00128 }
00129
00130 L = lua_newstate(tlsf_alloc, &tlsf_inf);
00131 tlsf_inf.L = L;
00132 set_context_tlsf_info(&tlsf_inf);
00133 register_tlsf_api(L);
00134 #else
00135 L = luaL_newstate();
00136 #endif
00137 if (L == NULL) {
00138 Logger::log(Logger::Error) << "LuaComponent '" << name
00139 << "': failed to allocate memory for Lua state" << endlog();
00140 throw;
00141 }
00142
00143 lua_gc(L, LUA_GCSTOP, 0);
00144 luaL_openlibs(L);
00145 lua_gc(L, LUA_GCRESTART, 0);
00146
00147
00148 lua_pushcfunction(L, luaopen_rtt);
00149 lua_call(L, 0, 0);
00150
00151 set_context_tc(this, L);
00152
00153 this->addProperty("lua_string", lua_string).doc("string of lua code to be executed during configureHook");
00154 this->addProperty("lua_file", lua_file).doc("file with lua program to be executed during configuration");
00155
00156 this->addOperation("exec_file", &LuaComponent::exec_file, this, OwnThread)
00157 .doc("load (and run) the given lua script")
00158 .arg("filename", "filename of the lua script");
00159
00160 this->addOperation("exec_str", &LuaComponent::exec_str, this, OwnThread)
00161 .doc("evaluate the given string in the lua environment")
00162 .arg("lua-string", "string of lua code to evaluate");
00163
00164 #ifdef LUA_RTT_TLSF
00165 this->addOperation("tlsf_incmem", &LuaComponent::tlsf_incmem, this, OwnThread)
00166 .doc("increase the TLSF memory pool")
00167 .arg("size", "size in bytes to add to pool");
00168 #endif
00169 }
00170
00171 ~LuaComponent()
00172 {
00173 os::MutexLock lock(m);
00174 lua_close(L);
00175 #ifdef LUA_RTT_TLSF
00176 tlsf_rtt_free_mp(&tlsf_inf);
00177 #endif
00178 }
00179
00180 #ifdef LUA_RTT_TLSF
00181 bool tlsf_incmem(unsigned int size)
00182 {
00183 return tlsf_rtt_incmem(&tlsf_inf, size);
00184 }
00185 #endif
00186
00187
00188 bool exec_file(const std::string &file)
00189 {
00190 os::MutexLock lock(m);
00191 if (luaL_dofile(L, file.c_str())) {
00192 Logger::log(Logger::Error) << "LuaComponent '" << this->getName() << "': " << lua_tostring(L, -1) << endlog();
00193 return false;
00194 }
00195 return true;
00196 }
00197
00198 bool exec_str(const std::string &str)
00199 {
00200 os::MutexLock lock(m);
00201 if (luaL_dostring(L, str.c_str())) {
00202 Logger::log(Logger::Error) << "LuaComponent '" << this->getName() << "': " << lua_tostring(L, -1) << endlog();
00203 return false;
00204 }
00205 return true;
00206 }
00207
00208 #ifndef OCL_COMPONENT_ONLY
00209 void lua_repl()
00210 {
00211 os::MutexLock lock(m);
00212 dotty(L);
00213 }
00214
00215 int lua_repl(int argc, char **argv)
00216 {
00217 os::MutexLock lock(m);
00218 return main_args(L, argc, argv);
00219 }
00220 #endif
00221 bool configureHook()
00222 {
00223 if(!lua_string.empty())
00224 exec_str(lua_string);
00225
00226 if(!lua_file.empty())
00227 exec_file(lua_file);
00228 return call_func(L, "configureHook", this, 0, 1);
00229 }
00230
00231 bool activateHook()
00232 {
00233 os::MutexLock lock(m);
00234 return call_func(L, "activateHook", this, 0, 1);
00235 }
00236
00237 bool startHook()
00238 {
00239 os::MutexLock lock(m);
00240 return call_func(L, "startHook", this, 0, 1);
00241 }
00242
00243 void updateHook()
00244 {
00245 os::MutexLock lock(m);
00246 call_func(L, "updateHook", this, 0, 0);
00247 }
00248
00249 void stopHook()
00250 {
00251 os::MutexLock lock(m);
00252 call_func(L, "stopHook", this, 0, 0);
00253 }
00254
00255 void cleanupHook()
00256 {
00257 os::MutexLock lock(m);
00258 call_func(L, "cleanupHook", this, 0, 0);
00259 }
00260
00261 void errorHook()
00262 {
00263 os::MutexLock lock(m);
00264 call_func(L, "errorHook", this, 0, 0);
00265 }
00266 };
00267 }
00268
00269
00270 #ifndef OCL_COMPONENT_ONLY
00271
00272 int ORO_main(int argc, char** argv)
00273 {
00274 struct stat stb;
00275 wordexp_t init_exp;
00276
00277 #ifdef ORO_BUILD_RTALLOC
00278 size_t memSize = ORO_DEFAULT_RTALLOC_SIZE;
00279 void* rtMem = 0;
00280 size_t freeMem = 0;
00281 if (0 < memSize)
00282 {
00283
00284 rtMem = malloc(memSize);
00285 assert(0 != rtMem);
00286 freeMem = init_memory_pool(memSize, rtMem);
00287 if ((size_t)-1 == freeMem)
00288 {
00289 cerr << "Invalid memory pool size of " << memSize
00290 << " bytes (TLSF has a several kilobyte overhead)." << endl;
00291 free(rtMem);
00292 return -1;
00293 }
00294 cout << "Real-time memory: " << freeMem << " bytes free of "
00295 << memSize << " allocated." << endl;
00296 }
00297 #endif // ORO_BUILD_RTALLOC
00298
00299 #ifdef ORO_BUILD_LOGGING
00300 log4cpp::HierarchyMaintainer::set_category_factory(
00301 OCL::logging::Category::createOCLCategory);
00302 #endif
00303
00304 LuaComponent lua("lua");
00305 DeploymentComponent * dc = 0;
00306
00307 #if defined(LUA_RTT_CORBA)
00308 int orb_argc = argc;
00309 char** orb_argv = 0;
00310 char* orb_sep = 0;
00311
00312
00313 while(orb_argc) {
00314 if(0 == strcmp("--", argv[argc - orb_argc])) {
00315 orb_sep = argv[argc - orb_argc];
00316 argv[argc - orb_argc] = argv[0];
00317 orb_argv = &argv[argc - orb_argc];
00318 argc -= orb_argc;
00319 break;
00320 }
00321 orb_argc--;
00322 }
00323
00324
00325 if(orb_argc) {
00326 try {
00327 TaskContextServer::InitOrb(orb_argc, orb_argv);
00328
00329 dc = new CorbaDeploymentComponent("Deployer");
00330
00331 TaskContextServer::Create( dc, true, true );
00332
00333
00334 TaskContextServer::ThreadOrb();
00335 }
00336 catch( CORBA::Exception &e ) {
00337 log(Error) << argv[0] <<" ORO_main : CORBA exception raised!" << Logger::nl;
00338 log() << CORBA_EXCEPTION_INFO(e) << endlog();
00339 if(dc)
00340 {
00341 delete dc;
00342 dc = 0;
00343 }
00344 } catch (...) {
00345 log(Error) << "Uncaught exception." << endlog();
00346 if(dc)
00347 {
00348 delete dc;
00349 dc = 0;
00350 }
00351 }
00352
00353 argv[argc] = dc?NULL:orb_sep;
00354 }
00355
00356
00357 if(!dc)
00358 #endif
00359 dc = new DeploymentComponent("Deployer");
00360
00361 lua.connectPeers(dc);
00362
00363
00364 wordexp(INIT_FILE, &init_exp, 0);
00365 if(stat(init_exp.we_wordv[0], &stb) != -1) {
00366 if((stb.st_mode & S_IFMT) != S_IFREG)
00367 cout << "rttlua: warning: init file " << init_exp.we_wordv[0] << " is not a regular file" << endl;
00368 else
00369 lua.exec_file(init_exp.we_wordv[0]);
00370 }
00371 wordfree(&init_exp);
00372
00373 lua.lua_repl(argc, argv);
00374
00375 #if defined(LUA_RTT_CORBA)
00376 if(orb_argc) {
00377 TaskContextServer::ShutdownOrb();
00378 TaskContextServer::DestroyOrb();
00379 }
00380 #endif
00381
00382 delete dc;
00383
00384 #ifdef ORO_BUILD_LOGGING
00385 log4cpp::HierarchyMaintainer::getDefaultMaintainer().shutdown();
00386 log4cpp::HierarchyMaintainer::getDefaultMaintainer().deleteAllCategories();
00387 #endif
00388
00389 #ifdef ORO_BUILD_RTALLOC
00390 if (0 != rtMem)
00391 {
00392 std::cout << "TLSF bytes allocated=" << memSize
00393 << " overhead=" << (memSize - freeMem)
00394 << " max-used=" << get_max_size(rtMem)
00395 << " currently-used=" << get_used_size(rtMem)
00396 << " still-allocated=" << (get_used_size(rtMem) - (memSize - freeMem))
00397 << "\n";
00398
00399 destroy_memory_pool(rtMem);
00400 free(rtMem);
00401 }
00402 #endif
00403 return 0;
00404 }
00405
00406 #else
00407
00408 #include "ocl/Component.hpp"
00409
00410 ORO_CREATE_COMPONENT( OCL::LuaComponent )
00411 #endif