Skip to content

Commit a020bb2

Browse files
committed
feat(daemon): initial support for nested endpoints
1 parent a242946 commit a020bb2

File tree

6 files changed

+86
-49
lines changed

6 files changed

+86
-49
lines changed

daemon/daemon_endpoint.cpp

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ uint32_t HopperDaemon::create_endpoint(const std::filesystem::path &path) {
1515
if (inotify_watch_fd < 0)
1616
return 0;
1717

18-
auto *endpoint = new HopperEndpoint(endpoint_id, inotify_watch_fd, path);
18+
auto name = path.lexically_relative(m_path);
19+
auto *endpoint =
20+
new HopperEndpoint(endpoint_id, inotify_watch_fd, path, name);
1921
m_endpoints[endpoint_id] = endpoint;
2022

2123
std::cout << "CREATE " << *endpoint << std::endl;
@@ -25,15 +27,23 @@ uint32_t HopperDaemon::create_endpoint(const std::filesystem::path &path) {
2527
const auto &p = dir_entry.path();
2628

2729
PipeType pipe_type = detect_pipe_type(p);
28-
if (pipe_type == PipeType::NONE)
30+
if (pipe_type == PipeType::NONE && std::filesystem::is_directory(p)) {
31+
// nested endpoint
32+
if (create_endpoint(p) == 0)
33+
std::cerr << "Endpoint creation failed! Out of IDs?"
34+
<< std::endl;
35+
} else if (pipe_type == PipeType::NONE) {
36+
// nothing of interest
2937
continue;
30-
31-
HopperPipe *pipe =
32-
(pipe_type == PipeType::IN ? endpoint->add_input_pipe(p)
33-
: endpoint->add_output_pipe(p));
34-
35-
if (pipe != nullptr)
36-
add_pipe(pipe);
38+
} else {
39+
// pipe
40+
HopperPipe *pipe =
41+
(pipe_type == PipeType::IN ? endpoint->add_input_pipe(p)
42+
: endpoint->add_output_pipe(p));
43+
44+
if (pipe != nullptr)
45+
add_pipe(pipe);
46+
}
3747
}
3848

3949
return endpoint_id;
@@ -65,4 +75,12 @@ HopperEndpoint *HopperDaemon::endpoint_by_watch(int watch) {
6575
return nullptr;
6676
}
6777

78+
HopperEndpoint *
79+
HopperDaemon::endpoint_by_path(const std::filesystem::path &path) {
80+
for (const auto &[_, endpoint] : m_endpoints)
81+
if (endpoint->path() == path)
82+
return endpoint;
83+
return nullptr;
84+
}
85+
6886
}; // namespace hopper

daemon/daemon_inotify.cpp

Lines changed: 54 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "hopper/daemon/daemon.hpp"
22
#include "hopper/daemon/util.hpp"
33

4+
#include <filesystem>
45
#include <iostream>
56
#include <limits.h>
67
#include <unistd.h>
@@ -54,60 +55,78 @@ void HopperDaemon::handle_endpoint_inotify(struct inotify_event *ev,
5455
p /= ev->name;
5556

5657
PipeType pipe_type = detect_pipe_type(p);
57-
if (pipe_type == PipeType::NONE)
58+
if (pipe_type == PipeType::NONE && std::filesystem::is_directory(p)) {
59+
// nested endpoint
60+
if (create_endpoint(p) == 0)
61+
std::cerr << "Endpoint creation failed! Out of IDs?"
62+
<< std::endl;
63+
} else if (pipe_type == PipeType::NONE) {
64+
// nothing of interest
5865
return;
59-
60-
HopperPipe *pipe =
61-
(pipe_type == PipeType::IN ? endpoint->add_input_pipe(p)
62-
: endpoint->add_output_pipe(p));
63-
64-
if (pipe != nullptr)
65-
add_pipe(pipe);
66+
} else {
67+
// pipe
68+
HopperPipe *pipe =
69+
(pipe_type == PipeType::IN ? endpoint->add_input_pipe(p)
70+
: endpoint->add_output_pipe(p));
71+
72+
if (pipe != nullptr)
73+
add_pipe(pipe);
74+
}
6675
}
6776

6877
if (ev->mask & IN_DELETE) {
6978
std::filesystem::path p = endpoint->path();
7079
p /= ev->name;
7180

72-
HopperPipe *pipe = endpoint->pipe_by_path(p);
73-
74-
if (pipe != nullptr) {
75-
if (pipe->status() == PipeStatus::ACTIVE)
76-
remove_pipe(endpoint, pipe->id());
77-
78-
endpoint->remove_by_id(pipe->id());
81+
if (std::filesystem::is_directory(p)) {
82+
// nested endpoint
83+
HopperEndpoint *tgt_endpoint = endpoint_by_path(p);
84+
if (tgt_endpoint != nullptr)
85+
delete_endpoint(tgt_endpoint->id());
86+
} else {
87+
// pipe
88+
HopperPipe *pipe = endpoint->pipe_by_path(p);
89+
90+
if (pipe != nullptr) {
91+
if (pipe->status() == PipeStatus::ACTIVE)
92+
remove_pipe(endpoint, pipe->id());
93+
94+
endpoint->remove_by_id(pipe->id());
95+
}
7996
}
8097
}
8198
}
8299

83100
void HopperDaemon::handle_inotify() {
84-
struct inotify_event *iev = reinterpret_cast<struct inotify_event *>(
85-
std::malloc(sizeof(struct inotify_event) + NAME_MAX + 1));
101+
char buf[4096];
102+
ssize_t size;
103+
struct inotify_event *iev = {};
86104

87-
if (read(m_inotify_fd, iev, sizeof(struct inotify_event) + NAME_MAX + 1) <=
88-
0)
105+
if ((size = read(m_inotify_fd, &buf, 4096)) <= 0)
89106
return;
90107

91-
if (iev->wd == m_inotify_root_watch) {
92-
handle_root_inotify(iev);
93-
std::free(iev);
94-
return;
95-
}
108+
for (char *ptr = buf; ptr < buf + size;
109+
ptr += sizeof(struct inotify_event) + iev->len) {
110+
iev = reinterpret_cast<struct inotify_event *>(ptr);
96111

97-
HopperEndpoint *endpoint = endpoint_by_watch(iev->wd);
98-
if (endpoint == nullptr) {
99-
std::cout << "No endpoint found for watch ID " << iev->wd << std::endl;
100-
std::free(iev);
101-
return;
102-
}
112+
if (iev->wd == m_inotify_root_watch) {
113+
handle_root_inotify(iev);
114+
continue;
115+
}
103116

104-
handle_endpoint_inotify(iev, endpoint);
117+
HopperEndpoint *endpoint = endpoint_by_watch(iev->wd);
118+
if (endpoint == nullptr) {
119+
std::cout << "No endpoint found for watch ID " << iev->wd
120+
<< std::endl;
121+
continue;
122+
}
105123

106-
// The endpoint is now closed
107-
if (iev->mask & IN_IGNORED)
108-
delete_endpoint(endpoint->id());
124+
handle_endpoint_inotify(iev, endpoint);
109125

110-
std::free(iev);
126+
// The endpoint is now closed
127+
if (iev->mask & IN_IGNORED)
128+
delete_endpoint(endpoint->id());
129+
}
111130
}
112131

113132
}; // namespace hopper

daemon/endpoint.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@
88
namespace hopper {
99

1010
HopperEndpoint::HopperEndpoint(uint32_t id, int watch_fd,
11-
std::filesystem::path path)
12-
: m_path(path), m_id(id), m_watch_fd(watch_fd) {
13-
m_name = path.filename();
11+
std::filesystem::path path, std::string name)
12+
: m_path(path), m_name(name), m_id(id), m_watch_fd(watch_fd) {
1413
}
1514

1615
HopperEndpoint::~HopperEndpoint() {

daemon/util.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
namespace hopper {
44

55
PipeType detect_pipe_type(const std::filesystem::path &path) {
6-
if (!path.has_extension())
6+
if (!path.has_extension() || !std::filesystem::is_fifo(path))
77
return PipeType::NONE;
88

99
if (path.extension() == ".in")

include/hopper/daemon/daemon.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class HopperDaemon {
4242
void delete_endpoint(uint32_t id);
4343

4444
HopperEndpoint *endpoint_by_watch(int watch);
45+
HopperEndpoint *endpoint_by_path(const std::filesystem::path &path);
4546
void setup_inotify();
4647
void handle_inotify();
4748
void handle_root_inotify(struct inotify_event *ev);

include/hopper/daemon/endpoint.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class HopperEndpoint {
3838
int m_watch_fd;
3939

4040
public:
41-
HopperEndpoint(uint32_t id, int watch_fd, std::filesystem::path path);
41+
HopperEndpoint(uint32_t id, int watch_fd, std::filesystem::path path, std::string name);
4242
~HopperEndpoint();
4343

4444
void on_pipe_readable(uint64_t id);

0 commit comments

Comments
 (0)