FileMonitor.cpp
author František Kučera <franta-hg@frantovo.cz>
Tue, 08 Oct 2024 22:24:40 +0200
branchv_0
changeset 34 8cf3812a92eb
parent 23 42341f66de52
permissions -rw-r--r--
improved Makefile + small fixes
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
7
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     1
/**
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     2
 * ShaderShark
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     3
 * Copyright © 2023 František Kučera (Frantovo.cz, GlobalCode.info)
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     4
 *
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     5
 * This program is free software: you can redistribute it and/or modify
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     6
 * it under the terms of the GNU General Public License as published by
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     7
 * the Free Software Foundation, version 3 of the License.
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     8
 *
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     9
 * This program is distributed in the hope that it will be useful,
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    12
 * GNU General Public License for more details.
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    13
 *
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    14
 * You should have received a copy of the GNU General Public License
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    15
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    16
 */
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    17
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    18
#include <string>
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    19
#include <stdexcept>
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    20
#include <map>
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    21
#include <sys/inotify.h>
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    22
#include <string.h>
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    23
#include <unistd.h>
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    24
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    25
#include "FileMonitor.h"
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    26
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    27
void checkError(bool hasError, const std::string& message) {
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    28
	if (hasError) throw std::logic_error(message + strerror(errno));
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    29
}
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    30
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    31
class WatchedFile::Impl {
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    32
public:
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    33
	int fd;
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    34
	int wd;
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    35
	std::string fileName;
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    36
	uint32_t mask;
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    37
	std::shared_ptr<FileMonitor::Impl> fileMonitorImpl;
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    38
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    39
	virtual ~Impl();
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    40
};
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    41
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    42
WatchedFile::WatchedFile() {
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    43
	impl = std::make_shared<Impl>();
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    44
}
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    45
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    46
WatchedFile::~WatchedFile() {
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    47
}
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    48
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    49
class FileMonitor::Impl {
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    50
public:
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    51
	int fd;
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    52
	std::map<int, std::string> fileNames;
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    53
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    54
	void unwatch(int wd) {
23
42341f66de52 monitor texture and shader file writes using inotify: improved resource management
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
    55
		fileNames.erase(wd);
7
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    56
		int result = inotify_rm_watch(fd, wd);
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    57
		checkError(result < 0, "unable to stop monitoring a file: ");
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    58
	}
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    59
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    60
	virtual ~Impl() {
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    61
		close(fd);
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    62
	}
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    63
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    64
};
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    65
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    66
FileMonitor::FileMonitor() : FileMonitor(std::make_shared<Impl>()) {
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    67
}
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    68
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    69
FileMonitor::FileMonitor(std::shared_ptr<Impl> impl) {
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    70
	this->impl = impl;
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    71
	impl->fd = inotify_init1(IN_NONBLOCK);
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    72
	checkError(impl->fd < 0, "unable to initialize FileMonitor: ");
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    73
}
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    74
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    75
FileMonitor::~FileMonitor() {
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    76
}
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    77
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    78
int FileMonitor::getFD() const {
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    79
	return impl->fd;
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    80
}
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    81
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    82
WatchedFile FileMonitor::watch(const std::string& fileName) {
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    83
	return watch(fileName, IN_CLOSE_WRITE);
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    84
}
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    85
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    86
WatchedFile FileMonitor::watch(const std::string& fileName, uint32_t mask) {
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    87
	int wd = inotify_add_watch(impl->fd, fileName.c_str(), mask);
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    88
	checkError(wd < 0, "unable to monitor a file: ");
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    89
	impl->fileNames[wd] = fileName;
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    90
	WatchedFile wf;
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    91
	wf.impl->fd = impl->fd;
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    92
	wf.impl->wd = wd;
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    93
	wf.impl->fileMonitorImpl = impl;
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    94
	wf.impl->fileName = fileName;
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    95
	wf.impl->mask = mask;
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    96
	return wf;
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    97
}
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    98
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    99
bool FileMonitor::readEvent(FileEvent& event) {
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   100
	struct inotify_event rawEvent;
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   101
	int result = ::read(impl->fd, &rawEvent, sizeof (rawEvent));
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   102
	if (result == sizeof (rawEvent)) {
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   103
		event.fileName = impl->fileNames[rawEvent.wd];
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   104
		event.mask = rawEvent.mask;
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   105
		return true;
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   106
	} else {
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   107
		return false;
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   108
	}
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   109
}
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   110
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   111
WatchedFile::Impl::~Impl() {
23
42341f66de52 monitor texture and shader file writes using inotify: improved resource management
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   112
	try {
42341f66de52 monitor texture and shader file writes using inotify: improved resource management
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   113
		fileMonitorImpl->unwatch(wd);
42341f66de52 monitor texture and shader file writes using inotify: improved resource management
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   114
	} catch (const std::exception& e) {
42341f66de52 monitor texture and shader file writes using inotify: improved resource management
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   115
		// ignored, fails after file deletion
42341f66de52 monitor texture and shader file writes using inotify: improved resource management
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   116
		// std::cerr << "unwatch failed: " << e.what() << std::endl;
42341f66de52 monitor texture and shader file writes using inotify: improved resource management
František Kučera <franta-hg@frantovo.cz>
parents: 7
diff changeset
   117
	}
7
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   118
}
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   119
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   120
FileMonitor WatchedFile::getFileMonitor() const {
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   121
	return FileMonitor(impl->fileMonitorImpl);
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   122
}
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   123
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   124
std::string WatchedFile::getFileName() const {
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   125
	return impl->fileName;
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   126
}
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   127
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   128
uint32_t WatchedFile::getMask() const {
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   129
	return impl->mask;
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   130
}
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   131
e6065118326f monitor texture and shader file writes using inotify: print file events
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   132