-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathfluffy.h
292 lines (268 loc) · 10.7 KB
/
fluffy.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
#ifndef HUMBLE_FLUFFY_H
#define HUMBLE_FLUFFY_H
#include <stdint.h>
#include <sys/inotify.h>
/* The following are legal, implemented events that client can watch for */
#define FLUFFY_ACCESS IN_ACCESS /* File was accessed */
#define FLUFFY_MODIFY IN_MODIFY /* File was modified */
#define FLUFFY_ATTRIB IN_ATTRIB /* Metadata changed */
#define FLUFFY_CLOSE_WRITE IN_CLOSE_WRITE /* Writtable file was closed */
#define FLUFFY_CLOSE_NOWRITE IN_CLOSE_NOWRITE /* Unwrittable file closed */
#define FLUFFY_OPEN IN_OPEN /* File was opened */
#define FLUFFY_MOVED_FROM IN_MOVED_FROM /* File was moved from X */
#define FLUFFY_MOVED_TO IN_MOVED_TO /* File was moved to Y */
#define FLUFFY_CREATE IN_CREATE /* File was created */
#define FLUFFY_DELETE IN_DELETE /* File was deleted */
#define FLUFFY_ROOT_DELETE IN_DELETE_SELF /* Root file was deleted */
#define FLUFFY_ROOT_MOVE IN_MOVE_SELF /* Root file was moved */
/* All the above events */
#define FLUFFY_ALL_EVENTS IN_ALL_EVENTS
/* Helper events */
#define FLUFFY_CLOSE (FLUFFY_CLOSE_WRITE | FLUFFY_CLOSE_NOWRITE) /* close */
#define FLUFFY_MOVE (FLUFFY_MOVED_FROM | FLUFFY_MOVED_TO) /* moves */
#define FLUFFY_ISDIR IN_ISDIR /* Event occurred against dir */
/* The following are legal events. They are sent as needed to any watch */
#define FLUFFY_UNMOUNT IN_UNMOUNT /* Backing fs was unmounted */
#define FLUFFY_Q_OVERFLOW IN_Q_OVERFLOW /* Event queue overflowed */
#define FLUFFY_IGNORED IN_IGNORED /* File not watched anymore */
#define FLUFFY_ROOT_IGNORED 0x00010000 /* Root file was ignored */
#define FLUFFY_WATCH_EMPTY 0x00020000 /* All watches removed */
struct fluffy_event_info {
/*
* Any of the above FLUFFY_* macros are applicable. More than one event
* is possible on a watch path, in which case, the values are ORed.
*
* The checks must be made like,
* if (event_mask & FLUFFY_ACCESS) // RIGHT!
* rather than
* if (event_mask == FLUFFY_ACCESS) // WRONG!
*/
uint32_t event_mask;
/* Path where event occured. Absolute path. */
char *path;
};
/*
* Function: fluffy_init
*
* Initiates fluffy and returns a context handle. The returned context handle
* is a reference that's valid until the context is destroyed by the client or
* Fluffy terminates it for some reason.
*
* Multiple paths can be watched on a single context. Each call to
* fluffy_init() spawns a new context and returns its handle. Each context is
* run in a separate thread, a fluffy_wait_until_done() call may be required
* at some point to join the context.
*
* The user_event_fn() pointer passed as the first argument is defined by the
* user and this function will be called by Fluffy for every event on the
* context; sort of a callback. user_event_fn() receives the first argument
* *eventinfo from Fluffy along with user provided data as the second argument.
* Fluffy doesn't touch whatever *user_data is holding, stores the pointer and
* returns it. It's just for the convenience of not having to maintain global
* structures/variables so that user_data can be accessed from within
* user_event_fn() scope. user_event_fn() must return 0 for Fluffy to continue
* processing the next event. Any other integer value returned will cause
* Fluffy to destroy the associated context; A non zero return is equivalent to
* calling fluffy_destroy(). There's a helper function definition from Fluffy
* which comes handy for testing or for just printing the events on the
* standard output - fluffy_print_event().
*
* args:
* - int (*user_event_fn)( const struct fluffy_event_info *eventinfo,
* void *user_data): explained above
* - void *user_data: A pointer that's passed to user_event_fn on callback
* return:
* - int: 0 to continue with the next event processing,
* any other integer(preferably -1) to destroy the context
*/
extern int fluffy_init(int (*user_event_fn) (
const struct fluffy_event_info *eventinfo,
void *user_data), void *user_data);
/*
* Function: fluffy_add_watch_path
*
* Watch the path and its descendants recursively. If the provided path is not
* being watched already, this path will be considered as a root path.
*
* args:
* - const char *: a path to watch recursively
* return:
* - int: 0 on success, error value otherwise
*/
extern int fluffy_add_watch_path(int fluffy_handle,
const char *pathtoadd);
/*
* Function: fluffy_remove_watch_path
*
* Remove the watch on the path and its descendants recursively.
*
* args:
* - const char *: remove watches of the path recursively
* return:
* - int: 0 on success, error value otherwise
*/
extern int fluffy_remove_watch_path(int fluffy_handle,
const char *pathtoremove);
/*
* Function: fluffy_wait_until_done
*
* Each context returned by fluffy_init() runs as a separate thread. If the
* caller thread or main thread exits before the context thread terminates,
* the context thread becomes a zombie thread and continues to hog resources.
*
* A call to fluffy_wait_until_done() blocks(waits) until the associated
* context is destroyed or terminated.
*
* NOTE: fluffy_wait_until_done() and fluffy_no_wait() are mutually exclusive.
*
* args:
* - int: fluffy context handle
* return:
* - int: 0 on successful context exit, error value otherwise
*/
extern int fluffy_wait_until_done(int fluffy_handle);
/*
* Function: fluffy_no_wait
*
* Each context returned by fluffy_init() runs as a separate thread. If the
* caller thread or main thread exits before the context thread terminates,
* the context thread becomes a zombie thread and continues to hog resources.
*
* A call to fluffy_no_wait() detaches the associated context thread, ensuring
* that the resources are freed when the thread dies/exits;
* fluffy_wait_until_done() can't be used on that context.
*
* NOTE: fluffy_wait_until_done() and fluffy_no_wait() are mutually exclusive.
*
* args:
* - int: fluffy context handle
* return:
* - int: 0 on successful detach, error value otherwise
*/
extern int fluffy_no_wait(int fluffy_handle);
/*
* Function: fluffy_destroy
*
* Frees up resources and terminates the Fluffy context.
*
* args:
* - int: fluffy context handle
* return:
* - int: 0 on successful context exit, error value otherwise
*/
extern int fluffy_destroy(int fluffy_handle);
/* Helper functions */
/*
* Function: fluffy_reinitiate_context
*
* On a queue overflow, FLUFFY_Q_OVERFLOW event, fluffy inherently reinitiates
* the context. While reinitiation, all watches of the context is removed and
* then set from scratch. Fluffy reinitiates automatically only on a queue
* overflow.
*
* This function is exposed to the client and may be called when a reinitiation
* is required for any other situation/use case. It's a quite expensive call,
* avoid unless it's absolutely necessary.
*
* args:
* - int: The context handle received from fluffy_init()
* return:
* - int: 0 on successful reinitiation, error value otherwise
*/
extern int fluffy_reinitiate_context(int fluffy_handle);
/*
* Function: fluffy_reinitiate_all_contexts
*
* On a queue overflow, FLUFFY_Q_OVERFLOW event, fluffy inherently reinitiates
* the context. While reinitiation, all watches of the context is removed and
* then set from scratch. Fluffy reinitiates a context automatically only on a
* queue overflow event.
*
* This function is exposed to the client and may be called when a reinitiation
* of all contexts is required. It's a very expensive call, avoid unless it's
* absolutely necessary.
*
* args:
* - void
* return:
* - int: 0 on successful reinitiation, error value otherwise
*/
extern int fluffy_reinitiate_all_contexts();
/*
* Function: fluffy_set_max_queued_events
*
* The native inotify kernel implementation sends a IN_Q_OVERFLOW event when
* the queue overflows. The queue overflows when the limit set in
* /proc/sys/fs/inotify/max_queued_events is reached. man inotify for more
* info on the limits.
*
* This function is a helper to set/update this limit. This limit holds until
* the next restart. Note that the function doesn't validate the input
* argument, it simply writes the value to the file.
*
* Consider calling fluffy_reinitiate_context() or
* fluffy_reinitate_all_contexts() for the changes to be picked up because the
* kernel library sets this only at the time of initiation.
*
* args:
* - const char *: a character string representing numerical value.
* return:
* - int: 0 on successful update, error value otherwise
*/
extern int fluffy_set_max_queued_events(const char *max_size);
/*
* Function: fluffy_set_max_user_instances
*
* This specifies an upper limit on the number of inotify instances that can
* be created per real user ID. Initiation fails when the limit set in
* /proc/sys/fs/inotify/max_user_instances is reached. man inotify for more
* info on the limits. Fluffy initiation fails when inotify initiation fails.
*
* This function is a helper to set/update this limit. This limit holds until
* the next restart. Note that the function doesn't validate the input
* argument, it simply writes the value to the file.
*
* args:
* - const char *: a character string representing numerical value.
* return:
* - int: 0 on successful update, error value otherwise
*/
extern int fluffy_set_max_user_instances(const char *max_size);
/*
* Function: fluffy_set_max_user_watches
*
* This specifies an upper limit on the number of inotify watches that can
* be created per real user ID. Initiation fails when the limit set in
* /proc/sys/fs/inotify/max_user_watches is reached. man inotify for more
* info on the limits. Fluffy initiation fails when inotify initiation fails.
*
* This function is a helper to set/update this limit. This limit holds until
* the next restart. Note that the function doesn't validate the input
* argument, it simply writes the value to the file.
*
* args:
* - const char *: a character string representing numerical value.
* return:
* - int: 0 on successful update, error value otherwise
*/
extern int fluffy_set_max_user_watches(const char *max_size);
/*
* Function: fluffy_print_event
*
* A helper function to print the event path and event action to the standard
* output. This function must be passed as an argument only to the fluffy_init()
* call, not to be called separately. Fluffy calls the print function on every
* event as long as the watch list is not empty. Fluffy context is destroyed
* when the watch list becomes empty.
*
* args:
* - const struct fluffy_event_info *: This will be provided by fluffy.
* It carries event path & action.
* - void *: This will be provided by fluffy with context handle.
* return:
* - int: 0 to continue with the next event processing,
* any other integer(preferably -1) to destroy the context
*/
extern int fluffy_print_event(const struct fluffy_event_info *eventinfo,
void *user_data);
#endif