359d1b4dcdfc35fcb3b2bb8d8a3394ecbee60925
[chaz/yoink] / src / moof / resource.cc
1
2 /*] Copyright (c) 2009-2010, Charles McGarvey [**************************
3 **] All rights reserved.
4 *
5 * vi:ts=4 sw=4 tw=75
6 *
7 * Distributable under the terms and conditions of the 2-clause BSD license;
8 * see the file COPYING for a complete text of the license.
9 *
10 **************************************************************************/
11
12 #include "config.h"
13
14 #ifdef USE_HOTLOADING
15 #include <sys/inotify.h>
16 #include <sys/ioctl.h>
17 #endif
18
19 #include <queue>
20
21 #include <boost/algorithm/string.hpp>
22 #include <boost/weak_ptr.hpp>
23 #include <stlplus/portability/file_system.hpp>
24
25 #include "hash.hh"
26 #include "resource.hh"
27
28
29 #ifndef BUF_SIZE
30 #define BUF_SIZE 4096
31 #endif
32
33
34 namespace moof {
35
36
37 static std::string search_paths_;
38
39 typedef boost::weak_ptr<resource> resource_weakptr;
40 static hash<std::string,resource_weakptr,hash_function> resource_table_;
41
42 // static member
43 resource::type_lookup_ptr resource::type_lookup_;
44
45
46 #ifdef USE_HOTLOADING
47 static hash<int,std::string,hash_function> monitor_lookup_;
48 static int monitor_fd_ = inotify_init1(IN_NONBLOCK);
49 #endif
50
51 int resource::reload_as_needed()
52 {
53 int num_resources = 0;
54
55 #ifdef USE_HOTLOADING
56 log_info("hotloading?");
57 char bytes[BUF_SIZE];
58 int num_bytes;
59 if (0 < (num_bytes = read(monitor_fd_, bytes, num_bytes)))
60 {
61 char* end = bytes + num_bytes;
62 char* byte = bytes;
63
64 log_warning("num_bytes:", num_bytes);
65 log_error("1");
66
67 while (byte < end)
68 {
69 struct inotify_event* event = (struct inotify_event*)byte;
70
71 if (event->mask & IN_IGNORED)
72 {
73 log_warning("watch", event->wd, "removed");
74 }
75
76 log_error("2");
77 hash<int,std::string,hash_function>::iterator it;
78 it = monitor_lookup_.find(event->wd);
79 if (it != monitor_lookup_.end())
80 {
81 log_error("3");
82 std::string path = (*it).second;
83 monitor_lookup_.erase(it);
84 resource::reload(path);
85 }
86
87 byte += sizeof(*event) + event->len;
88
89 ++num_resources;
90 }
91 }
92 #endif
93
94 return num_resources;
95 }
96
97
98 resource::~resource()
99 {
100 #ifdef USE_HOTLOADING
101 inotify_rm_watch(monitor_fd_, wd_);
102 #endif
103 }
104
105
106 resource_ptr resource::load(const std::string& path)
107 {
108 std::string extension = stlplus::extension_part(path);
109
110 if (!find(path))
111 {
112 log_error("trying to load missing resource:", path);
113 return resource_ptr();
114 }
115
116 hash<std::string,resource_weakptr,hash_function>::iterator it;
117 it = resource_table_.find(path);
118 if (it != resource_table_.end())
119 {
120 resource_weakptr rsrc = (*it).second;
121 resource_ptr locked = rsrc.lock();
122 if (locked) return locked;
123 }
124
125 std::map<std::string,loader_ptr>::iterator jt;
126 jt = type_lookup_->find(extension);
127 if (jt != type_lookup_->end())
128 {
129 resource_ptr rsrc((*jt).second->load(path));
130 rsrc->set_loader(path, (*jt).second);
131 resource_table_[path] = rsrc;
132
133 #ifdef USE_HOTLOADING
134 int wd = inotify_add_watch(monitor_fd_, path.c_str(), IN_MODIFY);
135 rsrc->set_watch_descriptor(wd);
136 monitor_lookup_[wd] = path;
137 #endif
138
139 log_info("loaded", rsrc.get());
140 return rsrc;
141 }
142
143 return resource_ptr();
144 }
145
146
147 resource_ptr resource::reload(std::string& path)
148 {
149 log_info("reloading...", path);
150 hash<std::string,resource_weakptr,hash_function>::iterator it;
151 it = resource_table_.find(path);
152 if (it != resource_table_.end())
153 {
154 resource_weakptr rsrc = (*it).second;
155 resource_ptr locked = rsrc.lock();
156 if (locked)
157 {
158 locked->reload();
159 return locked;
160 }
161 }
162
163 return load(path);
164 }
165
166 void resource::reload()
167 {
168 log_info("reloaded", path_);
169
170 resource* resource = loader_->load(path_);
171 //*this = *resource;
172 resource_ = resource->resource_;
173 typeinfo_ = resource->typeinfo_;
174 unloader_ = resource->unloader_;
175
176 #ifdef USE_HOTLOADING
177 int wd = inotify_add_watch(monitor_fd_, path_.c_str(), IN_MODIFY);
178 set_watch_descriptor(wd);
179 monitor_lookup_[wd] = path_;
180 #endif
181
182 delete resource;
183 }
184
185
186 void resource::add_search_paths(const std::string& paths)
187 {
188 search_paths_ = paths;
189 }
190
191
192 bool resource::find(const std::string& path)
193 {
194 std::string file = stlplus::lookup(path, search_paths_, ":");
195 log_info("found file", file, "in", search_paths_);
196 return !stlplus::lookup(path, search_paths_, ":").empty();
197 }
198
199 std::string resource::find_file(const std::string& name)
200 {
201 log_info("looking for", name, "in", search_paths_);
202 return stlplus::lookup(name, search_paths_, ":");
203 }
204
205 FILE* resource::open_file(const std::string& path, const std::string& mode)
206 {
207 std::string file = stlplus::lookup(path, search_paths_, ":");
208 return fopen(file.c_str(), mode.c_str());
209 }
210
211
212 } // namespace moof
213
This page took 0.036816 seconds and 3 git commands to generate.