io-watch 0.6.1 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/ext/io/watch/inotify.c +99 -6
- data/lib/io/watch/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +2 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0d6ca67070f5fe227f2e06b5c5fa8bc2498a640aa88fb7e21a21da0bf5a09434
|
4
|
+
data.tar.gz: 8973b98b3412da62ddcca9850ab04c3c69b1e00ab15e35e2bddf275a99f20823
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: db38f21e23045fb052299ee4974ee4cecd283ea406f32dd5a5e453ef7125c8d0a9086589ed6d0b8c0977311071367b2ba2429f93f71127f7e335b8f451208de4
|
7
|
+
data.tar.gz: c6c6af9a7975ea6912b582bddc8b52ac0ef480de0a30c83d70c1781036e46eb93d97b87c58b0e12a558d29bff57955c8a75db483d97b427775b2da13ad557481
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/ext/io/watch/inotify.c
CHANGED
@@ -9,6 +9,8 @@
|
|
9
9
|
#include <dirent.h>
|
10
10
|
#include <string.h>
|
11
11
|
#include <sys/stat.h>
|
12
|
+
#include <time.h>
|
13
|
+
#include <poll.h>
|
12
14
|
|
13
15
|
enum {
|
14
16
|
DEBUG = 0,
|
@@ -18,11 +20,16 @@ struct IO_Watch_Watch {
|
|
18
20
|
int watch_descriptor;
|
19
21
|
char *path;
|
20
22
|
int index;
|
23
|
+
|
24
|
+
int modified;
|
21
25
|
};
|
22
26
|
|
23
27
|
struct IO_Watch_Watch_Array {
|
24
28
|
size_t size;
|
25
29
|
size_t capacity;
|
30
|
+
|
31
|
+
size_t pending;
|
32
|
+
|
26
33
|
struct IO_Watch_Watch *watches;
|
27
34
|
};
|
28
35
|
|
@@ -31,6 +38,7 @@ struct IO_Watch_Watch_Array {
|
|
31
38
|
void IO_Watch_Watch_Array_initialize(struct IO_Watch_Watch_Array *array) {
|
32
39
|
array->size = 0;
|
33
40
|
array->capacity = 16;
|
41
|
+
array->pending = 0;
|
34
42
|
array->watches = malloc(array->capacity * sizeof(struct IO_Watch_Watch));
|
35
43
|
if (!array->watches) {
|
36
44
|
perror("io-watch:IO_Watch_Watch_Array_initialize:malloc");
|
@@ -176,6 +184,46 @@ void IO_Watch_INotify_print_event(struct inotify_event *event) {
|
|
176
184
|
fprintf(stderr, "\n");
|
177
185
|
}
|
178
186
|
|
187
|
+
static size_t IO_Watch_INotify_flush_events(struct IO_Watch_Watch_Array watch_array) {
|
188
|
+
size_t count = 0;
|
189
|
+
|
190
|
+
if (watch_array.pending == 0) {
|
191
|
+
return 0;
|
192
|
+
}
|
193
|
+
|
194
|
+
for (size_t i = 0; i < watch_array.size; i++) {
|
195
|
+
int modified = watch_array.watches[i].modified;
|
196
|
+
if (modified) {
|
197
|
+
count++;
|
198
|
+
|
199
|
+
printf("{\"index\":%d,\"mask\":%u}\n", watch_array.watches[i].index, modified);
|
200
|
+
watch_array.watches[i].modified = 0;
|
201
|
+
}
|
202
|
+
}
|
203
|
+
|
204
|
+
watch_array.pending = 0;
|
205
|
+
|
206
|
+
fflush(stdout);
|
207
|
+
|
208
|
+
if (DEBUG) fprintf(stderr, "io-watch:IO_Watch_INotify_flush_events: Flushed %zu events\n", count);
|
209
|
+
|
210
|
+
return count;
|
211
|
+
}
|
212
|
+
|
213
|
+
static float IO_Watch_handle_timeout(float latency, struct timespec *start_time) {
|
214
|
+
if (start_time) {
|
215
|
+
struct timespec current_time;
|
216
|
+
clock_gettime(CLOCK_MONOTONIC, ¤t_time);
|
217
|
+
|
218
|
+
float delta = current_time.tv_sec - start_time->tv_sec;
|
219
|
+
delta += (current_time.tv_nsec - start_time->tv_nsec) / 1e9;
|
220
|
+
|
221
|
+
return latency - delta;
|
222
|
+
} else {
|
223
|
+
return 0.0;
|
224
|
+
}
|
225
|
+
}
|
226
|
+
|
179
227
|
void IO_Watch_run(struct IO_Watch *watch) {
|
180
228
|
int fd = inotify_init1(IN_NONBLOCK);
|
181
229
|
if (fd == -1) {
|
@@ -193,16 +241,60 @@ void IO_Watch_run(struct IO_Watch *watch) {
|
|
193
241
|
IO_Watch_Watch_Array_scan(fd, &watch_array, path, i);
|
194
242
|
}
|
195
243
|
|
244
|
+
float latency = watch->latency;
|
245
|
+
|
246
|
+
// If start_time is non-null, it means we are now coallescing events, up to the specified latency:
|
247
|
+
struct timespec start_time_buffer, *start_time = NULL;
|
248
|
+
|
196
249
|
printf("{\"status\":\"started\"}\n");
|
197
250
|
fflush(stdout);
|
198
251
|
|
199
252
|
char buffer[BUFFER_SIZE] __attribute__ ((aligned(8)));
|
200
253
|
|
201
254
|
while (1) {
|
255
|
+
// Check for any events:
|
202
256
|
ssize_t result = read(fd, buffer, BUFFER_SIZE);
|
203
|
-
|
204
|
-
|
205
|
-
|
257
|
+
|
258
|
+
// Calculate the timeout, if any:
|
259
|
+
float timeout = IO_Watch_handle_timeout(latency, start_time);
|
260
|
+
|
261
|
+
// We need to check if the timeout has expired:
|
262
|
+
if (timeout < 0.0) {
|
263
|
+
if (DEBUG) fprintf(stderr, "io-watch:IO_Watch_run: Timeout expired\n");
|
264
|
+
|
265
|
+
start_time = NULL;
|
266
|
+
// Flush any pending events:
|
267
|
+
IO_Watch_INotify_flush_events(watch_array);
|
268
|
+
}
|
269
|
+
|
270
|
+
// If no events are available, we have to wait for the timeout:
|
271
|
+
if (result == -1) {
|
272
|
+
if (errno != EAGAIN && errno != EWOULDBLOCK) {
|
273
|
+
perror("(io-watch:IO_Watch_run:read)");
|
274
|
+
exit(EXIT_FAILURE);
|
275
|
+
}
|
276
|
+
|
277
|
+
if (DEBUG) fprintf(stderr, "io-watch:IO_Watch_run: No events available, waiting for %0.4f seconds\n", timeout);
|
278
|
+
|
279
|
+
// Wait until the file descriptor becomes readable:
|
280
|
+
struct pollfd poll_fd = {fd, POLLIN, 0};
|
281
|
+
int poll_timeout = start_time ? (int) (timeout * 1e3) : -1;
|
282
|
+
|
283
|
+
// If we have a timeout of 0.0, we have to poll for at least 1 ms:
|
284
|
+
if (poll_timeout == 0 && timeout > 0.0) {
|
285
|
+
poll_timeout = 1;
|
286
|
+
}
|
287
|
+
|
288
|
+
if (DEBUG) fprintf(stderr, "io-watch:IO_Watch_run:poll: Polling for %d ms\n", poll_timeout);
|
289
|
+
poll(&poll_fd, 1, poll_timeout);
|
290
|
+
continue;
|
291
|
+
}
|
292
|
+
|
293
|
+
// If we have received events, we have to set the start_time if it is not set:
|
294
|
+
if (!start_time) {
|
295
|
+
if (DEBUG) fprintf(stderr, "io-watch:IO_Watch_run: Setting start_time\n");
|
296
|
+
start_time = &start_time_buffer;
|
297
|
+
clock_gettime(CLOCK_MONOTONIC, start_time);
|
206
298
|
}
|
207
299
|
|
208
300
|
for (ssize_t offset = 0; offset < result;) {
|
@@ -225,7 +317,9 @@ void IO_Watch_run(struct IO_Watch *watch) {
|
|
225
317
|
ssize_t index = IO_Watch_Watch_Array_find(&watch_array, event->wd);
|
226
318
|
|
227
319
|
if (index != -1) {
|
228
|
-
|
320
|
+
if (DEBUG) fprintf(stderr, "io-watch:IO_Watch_run: Modified path %s mask=%d\n", watch_array.watches[index].path, event->mask);
|
321
|
+
watch_array.watches[index].modified |= event->mask;
|
322
|
+
watch_array.pending += 1;
|
229
323
|
|
230
324
|
// If a new directory is created, add a watch for it
|
231
325
|
if (event->mask & IN_CREATE && event->mask & IN_ISDIR) {
|
@@ -239,9 +333,8 @@ void IO_Watch_run(struct IO_Watch *watch) {
|
|
239
333
|
|
240
334
|
offset += sizeof(struct inotify_event) + event->len;
|
241
335
|
}
|
242
|
-
fflush(stdout);
|
243
336
|
}
|
244
|
-
|
337
|
+
|
245
338
|
for (size_t i = 0; i < watch_array.size; i++) {
|
246
339
|
inotify_rm_watch(fd, watch_array.watches[i].watch_descriptor);
|
247
340
|
free(watch_array.watches[i].path);
|
data/lib/io/watch/version.rb
CHANGED
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: io-watch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
@@ -37,7 +37,7 @@ cert_chain:
|
|
37
37
|
Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
|
38
38
|
voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
|
39
39
|
-----END CERTIFICATE-----
|
40
|
-
date: 2024-08-
|
40
|
+
date: 2024-08-12 00:00:00.000000000 Z
|
41
41
|
dependencies: []
|
42
42
|
description:
|
43
43
|
email:
|
metadata.gz.sig
CHANGED
Binary file
|