00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "core.h"
00023 #include "leaf.h"
00024 #include "object.h"
00025 #include "object_c.h"
00026 #include "node.h"
00027 #include "corecontext.h"
00028 #include "fileserver/fileserver.h"
00029 #include "fileserver/filesystem.h"
00030 #include "logserver/logserver.h"
00031
00032 #include "scriptserver/scriptserver.h"
00033 #include "randomserver/randomserver.h"
00034
00035 #include <salt/path.h>
00036 #include <salt/sharedlibrary.h>
00037 #include <iostream>
00038
00039 using namespace boost;
00040 using namespace salt;
00041 using namespace std;
00042 using namespace zeitgeist;
00043
00044
00045
00046 bool Core::CacheKey::operator == (const CacheKey& key) const
00047 {
00048 return (
00049 (root.expired() == key.root.expired()) &&
00050 (
00051 (root.expired()) ||
00052 (root.lock() == key.root.lock())
00053 ) &&
00054 (path == key.path)
00055 );
00056 }
00057
00058 bool Core::CacheKey::operator < (const CacheKey& key) const
00059 {
00060 if (root.expired())
00061 {
00062 if (! key.root.expired())
00063 {
00064 return true;
00065 }
00066 } else
00067 {
00068 if (key.root.expired())
00069 {
00070 return false;
00071 }
00072
00073 }
00074
00075 shared_ptr<Leaf> myRoot = root.lock();
00076 shared_ptr<Leaf> keyRoot = key.root.lock();
00077
00078 if (myRoot != keyRoot)
00079 {
00080 return (myRoot.get() < keyRoot.get());
00081 }
00082
00083 return (path < key.path);
00084 }
00085
00086
00087
00090 Core::Core()
00091 {
00092 mClassClass = shared_ptr<Class>(new CLASS(Class));
00093 mClassClass->Construct(mClassClass, shared_ptr<Class>());
00094 }
00095
00096 Core::~Core()
00097 {
00098 mBundles.clear();
00099 }
00100
00101 void Core::Construct(const boost::weak_ptr<Core>& self)
00102 {
00103 mSelf = self;
00104
00105
00106 mNodeClass.reset(new CLASS(Node));
00107 BindClass(mNodeClass);
00108
00109
00110 mRoot = shared_static_cast<Leaf>(mNodeClass->Create());
00111 mRoot->SetName("");
00112
00113 shared_ptr<CoreContext> context = CreateContext();
00114
00115
00116 RegisterClassObject(mNodeClass, "zeitgeist/");
00117 RegisterClassObject(mClassClass, "zeitgeist/");
00118 RegisterClassObject(new CLASS(Leaf), "zeitgeist/");
00119 RegisterClassObject(new CLASS(FileServer), "zeitgeist/");
00120 RegisterClassObject(new CLASS(FileSystem), "zeitgeist/");
00121 RegisterClassObject(new CLASS(LogServer), "zeitgeist/");
00122 RegisterClassObject(new CLASS(RandomServer), "zeitgeist/");
00123 RegisterClassObject(new CLASS(ScriptServer), "zeitgeist/");
00124 #ifdef THE_TELNETSERVER_COMPILES_FOR_OLIVER
00125 RegisterClassObject(new CLASS(TelnetServer), "zeitgeist/");
00126 #endif
00127
00128 mLogServer = shared_static_cast<LogServer>
00129 (context->New("zeitgeist/LogServer", "/sys/server/log"));
00130
00131 #if INIT_DEBUG
00132 mLogServer->AddStream(&cout,
00133 LogServer::eNormal |
00134 LogServer::eWarning |
00135 LogServer::eError);
00136 #endif
00137
00138 mFileServer = shared_static_cast<FileServer>
00139 (context->New("zeitgeist/FileServer", "/sys/server/file"));
00140
00141
00142 mScriptServer = shared_static_cast<ScriptServer>
00143 (context->New("zeitgeist/ScriptServer", "/sys/server/script"));
00144
00145
00146 mRandomServer = shared_static_cast<RandomServer>
00147 (context->New("zeitgeist/RandomServer", "/sys/server/random"));
00148 }
00149
00150 void Core::Desctruct()
00151 {
00152
00153 mRoot.reset();
00154
00155
00156 mRandomServer.reset();
00157 mClassClass.reset();
00158 mNodeClass.reset();
00159 mFileServer.reset();
00160 mLogServer.reset();
00161 mScriptServer.reset();
00162 }
00163
00164 boost::shared_ptr<CoreContext> Core::CreateContext()
00165 {
00166 return shared_ptr<CoreContext>(new CoreContext(make_shared(mSelf), GetRoot()));
00167 }
00168
00169 boost::shared_ptr<Object>
00170 Core::New(const std::string& className)
00171 {
00172
00173 shared_ptr<CoreContext> context = CreateContext();
00174 shared_ptr<Class> theClass = shared_dynamic_cast<Class>
00175 (context->Get("/classes/"+className));
00176
00177
00178 shared_ptr<Object> instance;
00179
00180 if (theClass.get() == 0)
00181 {
00182 mLogServer->Error() << "(Core::New) unkown class '"
00183 << className << "'\n";
00184 } else
00185 {
00186 instance = theClass->Create();
00187 }
00188
00189 return instance;
00190 }
00191
00192 bool
00193 Core::ExistsClass(const std::string& className)
00194 {
00195 return (Test("/classes/"+className));
00196 }
00197
00198 bool Core::RegisterClassObject(const boost::shared_ptr<Class> &classObject,
00199 const std::string &subDir)
00200 {
00201 shared_ptr<CoreContext> context = CreateContext();
00202 BindClass(classObject);
00203
00204 return context->Install(classObject, "/classes/" + subDir, true);
00205 }
00206
00207 bool Core::RegisterClassObject(Class *classObject, const std::string &subDir)
00208 {
00209 return RegisterClassObject(shared_ptr<Class>(classObject), subDir);
00210 }
00211
00212 bool Core::ImportBundle(const std::string& bundleName)
00213 {
00214 shared_ptr<SharedLibrary> bundle(new SharedLibrary());
00215
00216 if (!bundle->Open(bundleName))
00217 {
00218 mLogServer->Error() << "(Core) ERROR: Could not open '"
00219 << bundleName << "'" << endl;
00220 return false;
00221 }
00222
00223 std::list <shared_ptr<Class> > classes;
00224 void(*Zeitgeist_RegisterBundle)(std::list <shared_ptr<Class> > &) = NULL;
00225
00226 Zeitgeist_RegisterBundle = (void(*)(std::list <shared_ptr<Class> > &))
00227 bundle->GetProcAddress("Zeitgeist_RegisterBundle");
00228
00229 if (Zeitgeist_RegisterBundle == NULL)
00230 {
00231 mLogServer->Error() << "ERROR: (Core) No entry point!" << std::endl;
00232 return false;
00233 }
00234
00235 Zeitgeist_RegisterBundle(classes);
00236
00237 bool usingClass = false;
00238 while(!classes.empty())
00239 {
00240
00241 if (RegisterClassObject(classes.back(), ""))
00242 {
00243 classes.back()->SetBundle(bundle);
00244 usingClass = true;
00245 }
00246
00247 classes.pop_back();
00248 }
00249
00250
00251 if (usingClass)
00252 mBundles.push_back(bundle);
00253
00254 return true;
00255 }
00256
00257 const boost::shared_ptr<FileServer>& Core::GetFileServer() const
00258 {
00259 return mFileServer;
00260 }
00261
00262 const boost::shared_ptr<LogServer>& Core::GetLogServer() const
00263 {
00264 return mLogServer;
00265 }
00266
00267 const boost::shared_ptr<ScriptServer>& Core::GetScriptServer() const
00268 {
00269 return mScriptServer;
00270 }
00271
00272 boost::shared_ptr<Leaf> Core::GetInternal(const std::string &pathStr,
00273 const boost::shared_ptr<Leaf>& leaf)
00274 {
00275
00276 CacheKey key(leaf, pathStr);
00277
00278 TPathCache::iterator iter = mPathCache.find(key);
00279 if (iter != mPathCache.end())
00280 {
00281 boost::weak_ptr<Leaf>& entry = (*iter).second;
00282 if (! entry.expired())
00283 {
00284 return entry.lock();
00285 }
00286
00287
00288 mPathCache.erase(key);
00289 }
00290
00291
00292 Path path(pathStr);
00293 boost::shared_ptr<Leaf> current;
00294
00295 if (
00296 (path.IsAbsolute()) ||
00297 (leaf.get() == NULL)
00298 )
00299 {
00300 current= mRoot;
00301 } else
00302 {
00303 current = leaf;
00304 }
00305
00306 while (
00307 (! path.IsEmpty()) &&
00308 (current.get()!=NULL)
00309 )
00310 {
00311
00312 current = current->GetChild(path.Front());
00313 path.PopFront();
00314 }
00315
00316
00317
00318 if (current.get() != 0)
00319 {
00320 mPathCache[key] = current;
00321 }
00322
00323 return current;
00324 }
00325
00326 boost::shared_ptr<Leaf> Core::Get(const std::string &pathStr)
00327 {
00328 return Get(pathStr, mRoot);
00329 }
00330
00331 boost::shared_ptr<Leaf> Core::Get(const std::string &pathStr,
00332 const boost::shared_ptr<Leaf>& leaf)
00333 {
00334 boost::shared_ptr<Leaf> current = GetInternal(pathStr,leaf);
00335
00336 if (current.get() == NULL)
00337 {
00338 mLogServer->Error() << "(Core::Get) ERROR: Could not find object '"
00339 << pathStr << "'" << std::endl;
00340 }
00341
00342 return current;
00343 }
00344
00345 bool Core::Test(const std::string &pathStr)
00346 {
00347 return Test(pathStr, mRoot);
00348 }
00349
00350 bool Core::Test(const std::string &pathStr,
00351 const boost::shared_ptr<Leaf>& leaf)
00352 {
00353 return (GetInternal(pathStr,leaf).get() != 0);
00354 }
00355
00356
00357 boost::shared_ptr<Leaf> Core::GetChild(const boost::shared_ptr<Leaf> &parent,
00358 const std::string &childName)
00359 {
00360
00361 if (parent->IsLeaf()) return shared_ptr<Leaf>();
00362
00363
00364 boost::shared_ptr<Leaf> child = parent->GetChild(childName);
00365
00366 if (child.get() == NULL)
00367 {
00368
00369
00370 child = shared_static_cast<Leaf>(mNodeClass->Create());
00371 child->SetName(childName);
00372
00373 if (parent->AddChildReference(child) == false)
00374 {
00375 return shared_ptr<Leaf>();
00376 }
00377 }
00378
00379 return child;
00380 }
00381
00382 void Core::BindClass(const boost::shared_ptr<Class> &newClass) const
00383 {
00384 if (newClass != mClassClass)
00385 {
00386 newClass->Construct(newClass, mClassClass);
00387 newClass->AttachTo(mSelf);
00388 }
00389 }
00390
00391 template <class T>
00392 struct isUnique: public unary_function<T, bool>
00393 {
00394 bool operator()(const T& x){ return x.unique(); }
00395 };
00396
00397 void Core::GarbageCollectBundles()
00398 {
00399
00400 mBundles.erase(remove_if(
00401 mBundles.begin(), mBundles.end(),
00402 isUnique<shared_ptr<SharedLibrary> >()
00403 ), mBundles.end());
00404 }