moving some non-portable code to stlplus
[chaz/yoink] / src / moof / resource.cc
index 3512878bb039f5cede9b164940c744eccadd664f..5cd75360d85d5c8c5041d76da80987bc830cccf0 100644 (file)
 *
 **************************************************************************/
 
+#include <queue>
+
 #include <boost/algorithm/string.hpp>
+#include <boost/weak_ptr.hpp>
+
+#include <stlplus/portability/file_system.hpp>
 
-#include "log.hh"
+#include "hash.hh"
 #include "resource.hh"
 
+#if HAVE_CONFIG_H
+#include "../config.h"
+#endif
+
+#ifdef USE_HOTLOADING
+#include <sys/inotify.h>
+#include <sys/ioctl.h>
+#endif
+
+#ifndef BUF_SIZE
+#define BUF_SIZE 4096
+#endif
+
 
 namespace moof {
+       
 
+static std::vector<std::string> search_paths_;
+
+typedef boost::weak_ptr<resource> resource_weakptr;
+static hash<std::string,resource_weakptr,hash_function> resource_table_;
 
 // static member
-std::vector<std::string> resource::search_paths_;
+resource::type_lookup_ptr resource::type_lookup_;
+
+
+#ifdef USE_HOTLOADING
+static hash<int,std::string,hash_function> monitor_lookup_;
+static int monitor_fd_ = inotify_init1(IN_NONBLOCK);
+#endif
+
+int resource::reload_as_needed()
+{
+       int num_resources = 0;
+
+#ifdef USE_HOTLOADING
+       log_info("hotloading?");
+       char bytes[BUF_SIZE];
+       int num_bytes;
+       if (0 < (num_bytes = read(monitor_fd_, bytes, num_bytes)))
+       {
+               char* end = bytes + num_bytes;
+               char* byte = bytes;
+
+               log_warning("num_bytes:", num_bytes);
+               log_error("1");
+
+               while (byte < end)
+               {
+                       struct inotify_event* event = (struct inotify_event*)byte;
+
+                       if (event->mask & IN_IGNORED)
+                       {
+                               log_warning("watch", event->wd, "removed");
+                       }
+
+                       log_error("2");
+                       hash<int,std::string,hash_function>::iterator it;
+                       it = monitor_lookup_.find(event->wd);
+                       if (it != monitor_lookup_.end())
+                       {
+                               log_error("3");
+                               std::string path = (*it).second;
+                               monitor_lookup_.erase(it);
+                               resource::reload(path);
+                       }
+
+                       byte += sizeof(*event) + event->len;
+
+                       ++num_resources;
+               }
+       }
+#endif
+
+       return num_resources;
+}
+
+
+resource::~resource()
+{
+#ifdef USE_HOTLOADING
+       inotify_rm_watch(monitor_fd_, wd_);
+#endif
+}
+
+
+resource_ptr resource::load(const std::string& path)
+{
+       std::string extension = stlplus::extension_part(path);
+
+       if (!find(path)) return resource_ptr();
+
+       hash<std::string,resource_weakptr,hash_function>::iterator it;
+       it = resource_table_.find(path);
+       if (it != resource_table_.end())
+       {
+               resource_weakptr rsrc = (*it).second;
+               resource_ptr locked = rsrc.lock();
+               if (locked) return locked;
+       }
+
+       std::map<std::string,loader_ptr>::iterator jt;
+       jt = type_lookup_->find(extension);
+       if (jt != type_lookup_->end())
+       {
+               resource_ptr rsrc((*jt).second->load(path));
+               rsrc->set_loader(path, (*jt).second);
+               resource_table_[path] = rsrc;
+
+#ifdef USE_HOTLOADING
+               int wd = inotify_add_watch(monitor_fd_,
+                               path.c_str(), IN_MODIFY);
+               rsrc->set_watch_descriptor(wd);
+               monitor_lookup_[wd] = path;
+#endif
+
+               log_info("loaded", rsrc.get());
+               return rsrc;
+       }
+
+       return resource_ptr();
+}
+
+
+resource_ptr resource::reload(std::string& path)
+{
+       log_info("reloading...", path);
+       hash<std::string,resource_weakptr,hash_function>::iterator it;
+       it = resource_table_.find(path);
+       if (it != resource_table_.end())
+       {
+               resource_weakptr rsrc = (*it).second;
+               resource_ptr locked = rsrc.lock();
+               if (locked)
+               {
+                       locked->reload();
+                       return locked;
+               }
+       }
+
+       return load(path);
+}
+
+void resource::reload()
+{
+       log_info("reloaded", path_);
+
+       resource* resource = loader_->load(path_);
+       //*this = *resource;
+       resource_ = resource->resource_;
+       typeinfo_ = resource->typeinfo_;
+       unloader_ = resource->unloader_;
+
+#ifdef USE_HOTLOADING
+       int wd = inotify_add_watch(monitor_fd_,
+                       path_.c_str(), IN_MODIFY);
+       set_watch_descriptor(wd);
+       monitor_lookup_[wd] = path_;
+#endif
+
+       delete resource;
+}
 
 
 void resource::add_search_paths(const std::string& paths)
@@ -43,7 +204,7 @@ void resource::add_search_paths(const std::vector<std::string>& pathList)
                if (*path.rbegin() != '/') path += '/';
 
 #if defined(_WIN32)
-               boost::replace_all(path, "/", "\\");
+               //boost::replace_all(path, "/", "\\");
 #endif
 
                search_paths_.push_back(path);
@@ -52,11 +213,9 @@ void resource::add_search_paths(const std::vector<std::string>& pathList)
 }
 
 
-bool resource::find_path(std::string& path,
-                                          const std::string& prefix,
-                                          const std::string& extension)
+bool resource::find(const std::string& path)
 {
-       FILE* file = open_file(path, prefix, extension);
+       FILE* file = open_file(path);
        if (file)
        {
                fclose(file);
@@ -66,60 +225,22 @@ bool resource::find_path(std::string& path,
        return false;
 }
 
-FILE* resource::open_file(std::string& path,
-                                                const std::string& prefix,
-                                                const std::string& extension,
-                                                const std::string& mode)
+FILE* resource::open_file(const std::string& path, const std::string& mode)
 {
 #if defined(_WIN32)
        // windows always has to be a little different
-       boost::replace_all(path, "/", "\\");
-       std::string temp_prefix(prefix);
-       boost::replace_all(temp_prefix, "/", "\\");
-       std::vector<std::string> preList;
-       boost::split(preList, temp_prefix, boost::is_any_of(":"));
-#else
-       std::vector<std::string> preList;
-       boost::split(preList, prefix, boost::is_any_of(":"));
+       //boost::replace_all(path, "/", "\\");
 #endif
 
-       std::vector<std::string> postList;
-       boost::split(postList, extension, boost::is_any_of(":"));
-
        std::vector<std::string>::iterator it;
        for (it = search_paths_.begin(); it != search_paths_.end(); ++it)
        {
-               std::vector<std::string>::iterator jt;
-               for (jt = preList.begin(); jt != preList.end(); ++jt)
-               {
-                       std::vector<std::string>::iterator kt;
-                       for (kt = postList.begin(); kt != postList.end(); ++kt)
-                       {
-                               std::string realPath(*it);
-                               realPath += *jt;
-                               realPath += path;
-                               realPath += ".";
-                               realPath += *kt;
-
-                               FILE* file = fopen(realPath.c_str(), mode.c_str());
-                               if (file)
-                               {
-                                       path = realPath;
-                                       return file;
-                               }
-                       }
-               }
-
                // check path relative to search path
-               std::string realPath(*it);
-               realPath += path;
+               std::string complete_path(*it);
+               complete_path += path;
 
-               FILE* file = fopen(realPath.c_str(), mode.c_str());
-               if (file)
-               {
-                       path = realPath;
-                       return file;
-               }
+               FILE* file = fopen(complete_path.c_str(), mode.c_str());
+               if (file) return file;
        }
 
        // last ditch effort; maybe it's already a path to a valid resource
This page took 0.022899 seconds and 4 git commands to generate.