1 | /* |
---|
2 | * This file Copyright (C) 2015-2016 Mnemosyne LLC |
---|
3 | * |
---|
4 | * It may be used under the GNU GPL versions 2 or 3 |
---|
5 | * or any future license endorsed by Mnemosyne LLC. |
---|
6 | * |
---|
7 | * $Id: watchdir-generic.c 14651 2016-01-02 14:28:59Z mikedld $ |
---|
8 | */ |
---|
9 | |
---|
10 | #include <assert.h> |
---|
11 | #include <errno.h> |
---|
12 | |
---|
13 | #include <event2/event.h> |
---|
14 | |
---|
15 | #define __LIBTRANSMISSION_WATCHDIR_MODULE__ |
---|
16 | |
---|
17 | #include "transmission.h" |
---|
18 | #include "log.h" |
---|
19 | #include "ptrarray.h" |
---|
20 | #include "utils.h" |
---|
21 | #include "watchdir.h" |
---|
22 | #include "watchdir-common.h" |
---|
23 | |
---|
24 | /*** |
---|
25 | **** |
---|
26 | ***/ |
---|
27 | |
---|
28 | #define log_error(...) (!tr_logLevelIsActive (TR_LOG_ERROR) ? (void) 0 : \ |
---|
29 | tr_logAddMessage (__FILE__, __LINE__, TR_LOG_ERROR, "watchdir:generic", __VA_ARGS__)) |
---|
30 | |
---|
31 | /*** |
---|
32 | **** |
---|
33 | ***/ |
---|
34 | |
---|
35 | typedef struct tr_watchdir_generic |
---|
36 | { |
---|
37 | tr_watchdir_backend base; |
---|
38 | |
---|
39 | struct event * event; |
---|
40 | tr_ptrArray dir_entries; |
---|
41 | } |
---|
42 | tr_watchdir_generic; |
---|
43 | |
---|
44 | #define BACKEND_UPCAST(b) ((tr_watchdir_generic *) (b)) |
---|
45 | |
---|
46 | /* Non-static and mutable for unit tests */ |
---|
47 | struct timeval tr_watchdir_generic_interval = { 10, 0 }; |
---|
48 | |
---|
49 | /*** |
---|
50 | **** |
---|
51 | ***/ |
---|
52 | |
---|
53 | static void |
---|
54 | tr_watchdir_generic_on_event (evutil_socket_t fd UNUSED, |
---|
55 | short type UNUSED, |
---|
56 | void * context) |
---|
57 | { |
---|
58 | const tr_watchdir_t handle = context; |
---|
59 | tr_watchdir_generic * const backend = BACKEND_UPCAST (tr_watchdir_get_backend (handle)); |
---|
60 | |
---|
61 | tr_watchdir_scan (handle, &backend->dir_entries); |
---|
62 | } |
---|
63 | |
---|
64 | static void |
---|
65 | tr_watchdir_generic_free (tr_watchdir_backend * backend_base) |
---|
66 | { |
---|
67 | tr_watchdir_generic * const backend = BACKEND_UPCAST (backend_base); |
---|
68 | |
---|
69 | if (backend == NULL) |
---|
70 | return; |
---|
71 | |
---|
72 | assert (backend->base.free_func == &tr_watchdir_generic_free); |
---|
73 | |
---|
74 | if (backend->event != NULL) |
---|
75 | { |
---|
76 | event_del (backend->event); |
---|
77 | event_free (backend->event); |
---|
78 | } |
---|
79 | |
---|
80 | tr_ptrArrayDestruct (&backend->dir_entries, &tr_free); |
---|
81 | |
---|
82 | tr_free (backend); |
---|
83 | } |
---|
84 | |
---|
85 | tr_watchdir_backend * |
---|
86 | tr_watchdir_generic_new (tr_watchdir_t handle) |
---|
87 | { |
---|
88 | tr_watchdir_generic * backend; |
---|
89 | |
---|
90 | backend = tr_new0 (tr_watchdir_generic, 1); |
---|
91 | backend->base.free_func = &tr_watchdir_generic_free; |
---|
92 | |
---|
93 | if ((backend->event = event_new (tr_watchdir_get_event_base (handle), -1, EV_PERSIST, |
---|
94 | &tr_watchdir_generic_on_event, handle)) == NULL) |
---|
95 | { |
---|
96 | log_error ("Failed to create event: %s", tr_strerror (errno)); |
---|
97 | goto fail; |
---|
98 | } |
---|
99 | |
---|
100 | if (event_add (backend->event, &tr_watchdir_generic_interval) == -1) |
---|
101 | { |
---|
102 | log_error ("Failed to add event: %s", tr_strerror (errno)); |
---|
103 | goto fail; |
---|
104 | } |
---|
105 | |
---|
106 | /* Run initial scan on startup */ |
---|
107 | event_active (backend->event, EV_READ, 0); |
---|
108 | |
---|
109 | return BACKEND_DOWNCAST (backend); |
---|
110 | |
---|
111 | fail: |
---|
112 | tr_watchdir_generic_free (BACKEND_DOWNCAST (backend)); |
---|
113 | return NULL; |
---|
114 | } |
---|