Преглед изворни кода

resource: monitor all mapped source directories

Daniele Bartolini пре 6 година
родитељ
комит
6fc662da9c

+ 2 - 2
src/core/filesystem/file_monitor.h

@@ -43,8 +43,8 @@ struct FileMonitor
 	///
 	~FileMonitor();
 
-	/// Starts monitoring the @a path.
-	void start(const char* path, bool recursive, FileMonitorFunction fmf, void* user_data);
+	/// Starts monitoring the @a paths.
+	void start(u32 num, const char** paths, bool recursive, FileMonitorFunction fmf, void* user_data);
 
 	/// Stops monitoring.
 	void stop();

+ 5 - 5
src/core/filesystem/file_monitor_linux.cpp

@@ -98,9 +98,8 @@ struct FileMonitorImpl
 		closedir(dir);
 	}
 
-	void start(const char* path, bool recursive, FileMonitorFunction fmf, void* user_data)
+	void start(u32 num, const char** paths, bool recursive, FileMonitorFunction fmf, void* user_data)
 	{
-		CE_ENSURE(NULL != path);
 		CE_ENSURE(NULL != fmf);
 
 		_recursive = recursive;
@@ -110,7 +109,8 @@ struct FileMonitorImpl
 		_fd = inotify_init();
 		CE_ASSERT(_fd != -1, "inotify_init: errno: %d", errno);
 
-		add_watch(path, recursive);
+		for (u32 i = 0; i < num; ++i)
+			add_watch(paths[i], recursive);
 
 		_thread.start(run, this);
 	}
@@ -339,9 +339,9 @@ FileMonitor::~FileMonitor()
 	CE_DELETE(*_impl->_allocator, _impl);
 }
 
-void FileMonitor::start(const char* path, bool recursive, FileMonitorFunction fmf, void* user_data)
+void FileMonitor::start(u32 num, const char** paths, bool recursive, FileMonitorFunction fmf, void* user_data)
 {
-	_impl->start(path, recursive, fmf, user_data);
+	_impl->start(num, paths, recursive, fmf, user_data);
 }
 
 void FileMonitor::stop()

+ 94 - 47
src/resource/data_compiler.cpp

@@ -567,6 +567,9 @@ void DataCompiler::scan_and_restore(const char* data_dir)
 	// Scan all source directories
 	s64 time_start = time::now();
 
+	// FIXME: refactor this whole garbage
+	Array<const char*> directories(default_allocator());
+
 	auto cur = hash_map::begin(_source_dirs);
 	auto end = hash_map::end(_source_dirs);
 	for (; cur != end; ++cur)
@@ -575,6 +578,11 @@ void DataCompiler::scan_and_restore(const char* data_dir)
 
 		DynamicString prefix(default_allocator());
 		path::join(prefix, cur->second.c_str(), cur->first.c_str());
+
+		char* str = (char*)default_allocator().allocate(prefix.length() + 1);
+		strcpy(str, prefix.c_str());
+		array::push_back(directories, (const char*)str);
+
 		_source_fs.set_prefix(prefix.c_str());
 
 		if (_source_fs.exists(CROWN_DATAIGNORE))
@@ -622,7 +630,19 @@ void DataCompiler::scan_and_restore(const char* data_dir)
 	read_data_dependencies(*this, data_fs, CROWN_DATA_DEPENDENCIES);
 	logi(DATA_COMPILER, "Restored state in %.2fs", time::seconds(time::now() - time_start));
 
-	_file_monitor.start(hash_map::begin(_source_dirs)->second.c_str(), true, filemonitor_callback, this);
+	// Start file monitor
+	time_start = time::now();
+	_file_monitor.start(array::size(directories)
+		, array::begin(directories)
+		, true
+		, file_monitor_callback
+		, this
+		);
+	logi(DATA_COMPILER, "Started file monitor in %.2fs", time::seconds(time::now() - time_start));
+
+	// Cleanup
+	for (u32 i = 0, n = array::size(directories); i < n; ++i)
+		default_allocator().deallocate((void*)directories[n-1-i]);
 }
 
 void DataCompiler::save(const char* data_dir)
@@ -948,67 +968,94 @@ void DataCompiler::error(const char* msg, va_list args)
 	vloge(DATA_COMPILER, msg, args);
 }
 
-void DataCompiler::filemonitor_callback(FileMonitorEvent::Enum fme, bool is_dir, const char* path, const char* path_renamed)
+void DataCompiler::file_monitor_callback(FileMonitorEvent::Enum fme, bool is_dir, const char* path, const char* path_renamed)
 {
 	TempAllocator512 ta;
-	DynamicString resource_name(ta);
-	DynamicString resource_name_renamed(ta);
 	DynamicString source_dir(ta);
+	DynamicString resource_name(ta);
 
-	source_dir            = hash_map::get(_source_dirs, source_dir, source_dir);
-	resource_name         = &path[source_dir.length()+1]; // FIXME: add path::relative()
-	resource_name_renamed = path_renamed ? &path_renamed[source_dir.length()+1] : "";
-
-	switch (fme)
+	// Find source directory by matching mapped
+	// directory prefix with `path`.
+	auto cur = hash_map::begin(_source_dirs);
+	auto end = hash_map::end(_source_dirs);
+	for (; cur != end; ++cur)
 	{
-	case FileMonitorEvent::CREATED:
-		if (!is_dir)
-			add_file(resource_name.c_str());
-		else
-			add_tree(resource_name.c_str());
-		break;
+		HASH_MAP_SKIP_HOLE(_source_dirs, cur);
 
-	case FileMonitorEvent::DELETED:
-		if (!is_dir)
-			remove_file(resource_name.c_str());
-		else
-			remove_tree(resource_name.c_str());
-		break;
+		path::join(source_dir, cur->second.c_str(), cur->first.c_str());
+		if (str_has_prefix(path, source_dir.c_str()))
+			break;
+	}
 
-	case FileMonitorEvent::RENAMED:
-		if (!is_dir)
-		{
-			remove_file(resource_name.c_str());
-			add_file(resource_name_renamed.c_str());
-		}
-		else
-		{
-			remove_tree(resource_name.c_str());
-			add_tree(resource_name_renamed.c_str());
-		}
-		break;
+	if (cur != end)
+	{
+		// All events received must refer to directories
+		// mapped with map_source_dir().
+		const char* filename = &path[source_dir.length()+1];
+		path::join(resource_name, cur->first.c_str(), filename);
+
+#if 0
+		logi(DATA_COMPILER, "path         : %s", path);
+		logi(DATA_COMPILER, "source_dir   : %s", source_dir.c_str());
+		logi(DATA_COMPILER, "resource_name: %s", resource_name.c_str());
+#endif
 
-	case FileMonitorEvent::CHANGED:
-		if (!is_dir)
+		switch (fme)
 		{
-			FilesystemDisk fs(default_allocator());
-			fs.set_prefix(source_dir.c_str());
+		case FileMonitorEvent::CREATED:
+			if (!is_dir)
+				add_file(resource_name.c_str());
+			else
+				add_tree(resource_name.c_str());
+			break;
 
-			Stat stat;
-			stat = fs.stat(resource_name.c_str());
-			hash_map::set(_source_index._paths, resource_name, stat);
-		}
-		break;
+		case FileMonitorEvent::DELETED:
+			if (!is_dir)
+				remove_file(resource_name.c_str());
+			else
+				remove_tree(resource_name.c_str());
+			break;
+
+		case FileMonitorEvent::RENAMED:
+			{
+				DynamicString resource_name_renamed(ta);
+				path::join(resource_name_renamed, cur->first.c_str(), &path_renamed[source_dir.length()+1]);
+
+				if (!is_dir)
+				{
+					remove_file(resource_name.c_str());
+					add_file(resource_name_renamed.c_str());
+				}
+				else
+				{
+					remove_tree(resource_name.c_str());
+					add_tree(resource_name_renamed.c_str());
+				}
+			}
+			break;
 
-	default:
-		CE_ASSERT(false, "Unknown FileMonitorEvent: %d", fme);
-		break;
+		case FileMonitorEvent::CHANGED:
+			if (!is_dir)
+			{
+				FilesystemDisk fs(default_allocator());
+				fs.set_prefix(source_dir.c_str());
+
+				Stat stat;
+				stat = fs.stat(filename);
+				hash_map::set(_source_index._paths, resource_name, stat);
+			}
+			break;
+
+		default:
+			CE_ASSERT(false, "Unknown FileMonitorEvent: %d", fme);
+			break;
+		}
 	}
 }
 
-void DataCompiler::filemonitor_callback(void* thiz, FileMonitorEvent::Enum fme, bool is_dir, const char* path_original, const char* path_modified)
+void DataCompiler::file_monitor_callback(void* thiz, FileMonitorEvent::Enum fme, bool is_dir, const char* path_original, const char* path_modified)
 {
-	((DataCompiler*)thiz)->filemonitor_callback(fme, is_dir, path_original, path_modified);
+	((DataCompiler*)thiz)->file_monitor_callback(fme, is_dir, path_original, path_modified);
 }
 
 int main_data_compiler(const DeviceOptions& opts)

+ 2 - 2
src/resource/data_compiler.h

@@ -62,8 +62,8 @@ struct DataCompiler
 	void add_tree(const char* path);
 	void remove_tree(const char* path);
 
-	void filemonitor_callback(FileMonitorEvent::Enum fme, bool is_dir, const char* path, const char* path_renamed);
-	static void filemonitor_callback(void* thiz, FileMonitorEvent::Enum fme, bool is_dir, const char* path_original, const char* path_modified);
+	void file_monitor_callback(FileMonitorEvent::Enum fme, bool is_dir, const char* path, const char* path_renamed);
+	static void file_monitor_callback(void* thiz, FileMonitorEvent::Enum fme, bool is_dir, const char* path_original, const char* path_modified);
 
 	///
 	DataCompiler(ConsoleServer& cs);