entangler 0.1.0
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 +7 -0
- data/.gitignore +11 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +28 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/entangler.gemspec +26 -0
- data/exe/entangler +21 -0
- data/lib/entangler/entangled_file.rb +139 -0
- data/lib/entangler/executor/base.rb +242 -0
- data/lib/entangler/executor/master.rb +45 -0
- data/lib/entangler/executor/slave.rb +17 -0
- data/lib/entangler/version.rb +3 -0
- data/lib/entangler.rb +23 -0
- data/lib/notifier/bin/darwin/notify +0 -0
- data/lib/notifier/bin/linux/notify +0 -0
- data/lib/notifier/src/darwin/BUILD +7 -0
- data/lib/notifier/src/darwin/README +12 -0
- data/lib/notifier/src/darwin/notify.c +63 -0
- data/lib/notifier/src/linux/BUILD +4 -0
- data/lib/notifier/src/linux/README +18 -0
- data/lib/notifier/src/linux/notify.c +296 -0
- data/lib/notifier/src/linux/old/BUILD +11 -0
- data/lib/notifier/src/linux/old/README +14 -0
- data/lib/notifier/src/linux/old/kernel-filesystem-monitor-daemon-cat.cpp +165 -0
- data/lib/notifier/src/linux/old/kernel-filesystem-monitor-daemon.cpp +727 -0
- data/lib/notifier/src/linux/old/kernel-filesystem-monitor-daemon.hh +212 -0
- metadata +132 -0
@@ -0,0 +1,727 @@
|
|
1
|
+
/******************************************************************************
|
2
|
+
*******************************************************************************
|
3
|
+
*******************************************************************************
|
4
|
+
|
5
|
+
|
6
|
+
kernel-filesystem-monitor-daemon
|
7
|
+
Copyright (C) 2005 Ben Martin
|
8
|
+
|
9
|
+
This program is free software; you can redistribute it and/or modify
|
10
|
+
it under the terms of the GNU General Public License as published by
|
11
|
+
the Free Software Foundation; either version 2 of the License, or
|
12
|
+
(at your option) any later version.
|
13
|
+
|
14
|
+
This program is distributed in the hope that it will be useful,
|
15
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
16
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
17
|
+
GNU General Public License for more details.
|
18
|
+
|
19
|
+
You should have received a copy of the GNU General Public License
|
20
|
+
along with this program; if not, write to the Free Software
|
21
|
+
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
22
|
+
|
23
|
+
For more details see the COPYING file in the root directory of this
|
24
|
+
distribution.
|
25
|
+
|
26
|
+
$Id: kernel-filesystem-monitor-daemon.cpp,v 1.4 2008/05/25 21:30:52 ben Exp $
|
27
|
+
|
28
|
+
*******************************************************************************
|
29
|
+
*******************************************************************************
|
30
|
+
******************************************************************************/
|
31
|
+
|
32
|
+
#include <sys/types.h>
|
33
|
+
#include <unistd.h>
|
34
|
+
#include <sys/stat.h>
|
35
|
+
#include <fcntl.h>
|
36
|
+
#include <sys/ioctl.h>
|
37
|
+
#include <dirent.h>
|
38
|
+
#include <sys/poll.h>
|
39
|
+
#include <signal.h>
|
40
|
+
#include <string.h>
|
41
|
+
#include <errno.h>
|
42
|
+
#include <syslog.h>
|
43
|
+
#include <stdlib.h>
|
44
|
+
#include <limits.h>
|
45
|
+
|
46
|
+
#include <sys/inotify.h>
|
47
|
+
//#include "inotify-syscalls.h"
|
48
|
+
|
49
|
+
#include <iostream>
|
50
|
+
#include <sstream>
|
51
|
+
|
52
|
+
#include <kernel-filesystem-monitor-daemon.hh>
|
53
|
+
|
54
|
+
static bool WantToQuit = false;
|
55
|
+
unsigned long Verbose = 0;
|
56
|
+
|
57
|
+
//#ifdef IN_CREATE_SUBDIR
|
58
|
+
//#define MY_CREATE_SUBDIR_MASK IN_CREATE_SUBDIR | IN_CREATE_FILE
|
59
|
+
//#else
|
60
|
+
#define MY_CREATE_SUBDIR_MASK IN_CREATE
|
61
|
+
//#endif
|
62
|
+
|
63
|
+
static void sig_term_cb(int sign)
|
64
|
+
{
|
65
|
+
syslog( LOG_INFO, "preparing to exit... pid:%d", getpid() );
|
66
|
+
WantToQuit = true;
|
67
|
+
}
|
68
|
+
|
69
|
+
static void sig_usr1_cb(int sign)
|
70
|
+
{
|
71
|
+
sig_term_cb(sign);
|
72
|
+
}
|
73
|
+
|
74
|
+
static void sig_usr2_cb(int sign)
|
75
|
+
{
|
76
|
+
/* ping */
|
77
|
+
if( Verbose )
|
78
|
+
{
|
79
|
+
syslog( LOG_INFO, "got a ping! pid:%d", getpid() );
|
80
|
+
}
|
81
|
+
}
|
82
|
+
|
83
|
+
struct tolowerstr : public std::unary_function< std::string , std::string >
|
84
|
+
{
|
85
|
+
/**
|
86
|
+
*/
|
87
|
+
inline std::string operator()(const std::string& x) const
|
88
|
+
{
|
89
|
+
std::string ret = x;
|
90
|
+
|
91
|
+
for( std::string::iterator p = ret.begin(); p != ret.end(); ++p )
|
92
|
+
{
|
93
|
+
*p = ::tolower( *p );
|
94
|
+
}
|
95
|
+
|
96
|
+
return ret;
|
97
|
+
}
|
98
|
+
};
|
99
|
+
|
100
|
+
static bool starts_with( const string& s, const string& starting )
|
101
|
+
{
|
102
|
+
int starting_len = starting.length();
|
103
|
+
int s_len = s.length();
|
104
|
+
|
105
|
+
if( s_len < starting_len )
|
106
|
+
return false;
|
107
|
+
|
108
|
+
return !s.compare( 0, starting_len, starting );
|
109
|
+
}
|
110
|
+
|
111
|
+
string getHomeDir( const char* homedir_CSTR )
|
112
|
+
{
|
113
|
+
if( homedir_CSTR )
|
114
|
+
return homedir_CSTR;
|
115
|
+
if( const char* en = getenv( "HOME" ) )
|
116
|
+
return en;
|
117
|
+
return "";
|
118
|
+
// cerr << "Can not work out your home directory! use the --homedir argument\n";
|
119
|
+
// exit(1);
|
120
|
+
}
|
121
|
+
|
122
|
+
|
123
|
+
|
124
|
+
/********************************************************************************/
|
125
|
+
/********************************************************************************/
|
126
|
+
/********************************************************************************/
|
127
|
+
|
128
|
+
KernelFileSystemMonitorDaemon::KernelFileSystemMonitorDaemon()
|
129
|
+
:
|
130
|
+
m_runInForground( 0 ),
|
131
|
+
watch_mask( IN_ATTRIB |
|
132
|
+
IN_MOVED_FROM |
|
133
|
+
IN_MOVED_TO |
|
134
|
+
MY_CREATE_SUBDIR_MASK |
|
135
|
+
|
136
|
+
#ifdef IN_DELETE_FILE
|
137
|
+
IN_DELETE_FILE |
|
138
|
+
#endif
|
139
|
+
#ifdef IN_DELETE
|
140
|
+
IN_DELETE |
|
141
|
+
#endif
|
142
|
+
IN_CLOSE_WRITE
|
143
|
+
),
|
144
|
+
dev_fd( 0 ),
|
145
|
+
m_inotify_queue_threshold_bytes( 8 * 1024 ),
|
146
|
+
m_nanosleep_ns( 50 * 1000 * 1000 ),
|
147
|
+
m_inotify_queue_sleep_threshold_ns( 200 * 1000 * 1000 )
|
148
|
+
{
|
149
|
+
// watch_mask = IN_ALL_EVENTS;
|
150
|
+
}
|
151
|
+
KernelFileSystemMonitorDaemon::~KernelFileSystemMonitorDaemon()
|
152
|
+
{
|
153
|
+
}
|
154
|
+
|
155
|
+
|
156
|
+
void
|
157
|
+
KernelFileSystemMonitorDaemon::background_into_daemon()
|
158
|
+
{
|
159
|
+
pid_t pid = 0;
|
160
|
+
|
161
|
+
if((pid = fork()) < 0 )
|
162
|
+
{
|
163
|
+
syslog( LOG_EMERG, "can't fork()", 0 );
|
164
|
+
exit( 1 );
|
165
|
+
}
|
166
|
+
else if( pid != 0 )
|
167
|
+
exit(0);
|
168
|
+
|
169
|
+
setsid();
|
170
|
+
chdir("/");
|
171
|
+
umask(0);
|
172
|
+
}
|
173
|
+
|
174
|
+
|
175
|
+
void
|
176
|
+
KernelFileSystemMonitorDaemon::priv_handle_event( struct inotify_event *pevent, time_t tt )
|
177
|
+
{
|
178
|
+
handle_event( pevent, tt );
|
179
|
+
}
|
180
|
+
|
181
|
+
void
|
182
|
+
KernelFileSystemMonitorDaemon::event_batch_start( time_t tt )
|
183
|
+
{
|
184
|
+
}
|
185
|
+
|
186
|
+
void
|
187
|
+
KernelFileSystemMonitorDaemon::event_batch_end( time_t tt )
|
188
|
+
{
|
189
|
+
}
|
190
|
+
|
191
|
+
|
192
|
+
void
|
193
|
+
KernelFileSystemMonitorDaemon::setupSignalHandlers()
|
194
|
+
{
|
195
|
+
struct sigaction newinth;
|
196
|
+
newinth.sa_handler = sig_term_cb;
|
197
|
+
sigemptyset(&newinth.sa_mask);
|
198
|
+
newinth.sa_flags = SA_RESTART;
|
199
|
+
if( -1 == sigaction( SIGTERM, &newinth, NULL))
|
200
|
+
{
|
201
|
+
syslog( LOG_ERR, "ERROR: can not setup signal handling. reason:%s", strerror(errno) );
|
202
|
+
exit(2);
|
203
|
+
}
|
204
|
+
if( -1 == sigaction( SIGQUIT, &newinth, NULL))
|
205
|
+
{
|
206
|
+
syslog( LOG_ERR, "ERROR: can not setup signal handling. reason:%s", strerror(errno) );
|
207
|
+
exit(2);
|
208
|
+
}
|
209
|
+
|
210
|
+
newinth.sa_handler = sig_usr1_cb;
|
211
|
+
sigemptyset(&newinth.sa_mask);
|
212
|
+
newinth.sa_flags = SA_RESTART;
|
213
|
+
if( -1 == sigaction( SIGUSR1, &newinth, NULL))
|
214
|
+
{
|
215
|
+
syslog( LOG_ERR, "ERROR: can not setup signal handling. reason:%s", strerror(errno) );
|
216
|
+
exit(2);
|
217
|
+
}
|
218
|
+
|
219
|
+
newinth.sa_handler = sig_usr2_cb;
|
220
|
+
sigemptyset(&newinth.sa_mask);
|
221
|
+
newinth.sa_flags = SA_RESTART;
|
222
|
+
if( -1 == sigaction( SIGUSR2, &newinth, NULL))
|
223
|
+
{
|
224
|
+
syslog( LOG_ERR, "ERROR: can not setup signal handling. reason:%s", strerror(errno) );
|
225
|
+
exit(2);
|
226
|
+
}
|
227
|
+
}
|
228
|
+
|
229
|
+
void
|
230
|
+
KernelFileSystemMonitorDaemon::priv_Closedown()
|
231
|
+
{
|
232
|
+
Closedown();
|
233
|
+
}
|
234
|
+
|
235
|
+
void
|
236
|
+
KernelFileSystemMonitorDaemon::print_event (struct inotify_event *event)
|
237
|
+
{
|
238
|
+
if( m_runInForground )
|
239
|
+
{
|
240
|
+
if (event->len)
|
241
|
+
{
|
242
|
+
cout << "M " << m_workingDirToURL[event->wd] << "/" << event->name << endl;
|
243
|
+
// cout << "-" << endl;
|
244
|
+
}
|
245
|
+
#if 0
|
246
|
+
cout << "event on wd:" << event->wd << " " << m_workingDirToURL[event->wd];
|
247
|
+
if (event->len)
|
248
|
+
{
|
249
|
+
cout << " filename:" << event->name;
|
250
|
+
}
|
251
|
+
cout << endl;
|
252
|
+
print_mask( cout, event->mask );
|
253
|
+
if (event->len)
|
254
|
+
{
|
255
|
+
cout << " URL:" << m_workingDirToURL[event->wd] << "/" << event->name
|
256
|
+
<< endl;
|
257
|
+
}
|
258
|
+
#endif
|
259
|
+
}
|
260
|
+
else
|
261
|
+
{
|
262
|
+
stringstream maskss;
|
263
|
+
print_mask( maskss, event->mask );
|
264
|
+
syslog( LOG_DEBUG, "event on wd:%s mask:%s file:%s\n",
|
265
|
+
m_workingDirToURL[event->wd].c_str(),
|
266
|
+
maskss.str().c_str(),
|
267
|
+
event->name );
|
268
|
+
}
|
269
|
+
}
|
270
|
+
|
271
|
+
|
272
|
+
bool
|
273
|
+
KernelFileSystemMonitorDaemon::shouldAddSubObject( int wd, const std::string& fn )
|
274
|
+
{
|
275
|
+
struct stat statbuf;
|
276
|
+
|
277
|
+
if( fn == "." || fn == ".." )
|
278
|
+
return false;
|
279
|
+
|
280
|
+
int rc = lstat( fn.c_str(), &statbuf );
|
281
|
+
if( !rc )
|
282
|
+
{
|
283
|
+
candidateObject( wd, fn, statbuf );
|
284
|
+
if( S_ISDIR( statbuf.st_mode) )
|
285
|
+
{
|
286
|
+
return true;
|
287
|
+
}
|
288
|
+
}
|
289
|
+
return false;
|
290
|
+
}
|
291
|
+
|
292
|
+
void
|
293
|
+
KernelFileSystemMonitorDaemon::candidateObject( int wd, const std::string& fn, struct stat& statbuf )
|
294
|
+
{
|
295
|
+
}
|
296
|
+
|
297
|
+
|
298
|
+
|
299
|
+
void
|
300
|
+
KernelFileSystemMonitorDaemon::Closedown()
|
301
|
+
{
|
302
|
+
}
|
303
|
+
|
304
|
+
|
305
|
+
void
|
306
|
+
KernelFileSystemMonitorDaemon::setRunInForground( bool v )
|
307
|
+
{
|
308
|
+
m_runInForground = v;
|
309
|
+
}
|
310
|
+
|
311
|
+
|
312
|
+
bool
|
313
|
+
KernelFileSystemMonitorDaemon::shouldWatch( const string& earl )
|
314
|
+
{
|
315
|
+
for( m_ignorePrefixes_t::iterator ci = m_ignorePrefixes.begin();
|
316
|
+
ci != m_ignorePrefixes.end(); ++ci )
|
317
|
+
{
|
318
|
+
if( starts_with( earl, *ci ) )
|
319
|
+
return false;
|
320
|
+
}
|
321
|
+
|
322
|
+
return true;
|
323
|
+
}
|
324
|
+
|
325
|
+
bool
|
326
|
+
KernelFileSystemMonitorDaemon::handle_create_subdir_event_by_maybe_watching(
|
327
|
+
struct inotify_event *pevent, time_t tt )
|
328
|
+
{
|
329
|
+
// cerr << "pevent->mask:" << hex << pevent->mask
|
330
|
+
// << " MY_CREATE_SUBDIR_MASK:" << hex << MY_CREATE_SUBDIR_MASK
|
331
|
+
// << dec
|
332
|
+
// << endl;
|
333
|
+
|
334
|
+
if ( pevent->mask & MY_CREATE_SUBDIR_MASK )
|
335
|
+
{
|
336
|
+
string dirName = m_workingDirToURL[ pevent->wd ];
|
337
|
+
chdir( dirName.c_str() );
|
338
|
+
// cerr << "have dirname:" << dirName << endl;
|
339
|
+
|
340
|
+
if( shouldAddSubObject( pevent->wd, pevent->name ) )
|
341
|
+
{
|
342
|
+
string earl = dirName + "/" + pevent->name;
|
343
|
+
m_watchRoots.push_back( earl );
|
344
|
+
return true;
|
345
|
+
}
|
346
|
+
}
|
347
|
+
return false;
|
348
|
+
}
|
349
|
+
|
350
|
+
|
351
|
+
|
352
|
+
|
353
|
+
void
|
354
|
+
KernelFileSystemMonitorDaemon::add_watches_recursive( const string& earl )
|
355
|
+
{
|
356
|
+
if( !shouldWatch( earl ) )
|
357
|
+
return;
|
358
|
+
|
359
|
+
// struct inotify_watch_request req;
|
360
|
+
|
361
|
+
int fd = open ( earl.c_str(), O_RDONLY);
|
362
|
+
|
363
|
+
if (fd < 0)
|
364
|
+
{
|
365
|
+
syslog( LOG_WARNING, "not monitoring:%s reason:%s", earl.c_str(), strerror(errno));
|
366
|
+
return;
|
367
|
+
}
|
368
|
+
|
369
|
+
fchdir(fd);
|
370
|
+
// req.fd = fd;
|
371
|
+
// req.mask = IN_CREATE_SUBDIR;
|
372
|
+
// long wd = ioctl( dev_fd, INOTIFY_WATCH, &req );
|
373
|
+
long wd = inotify_add_watch( dev_fd, earl.c_str(), MY_CREATE_SUBDIR_MASK );
|
374
|
+
m_workingDirToURL[ wd ] = earl;
|
375
|
+
setupWorkingDirToPersistentDirIDMapping( wd, earl );
|
376
|
+
|
377
|
+
//
|
378
|
+
// Gather up the subdirectory names into dirNames
|
379
|
+
//
|
380
|
+
typedef list< string > dirNames_t;
|
381
|
+
dirNames_t dirNames;
|
382
|
+
|
383
|
+
DIR *d;
|
384
|
+
struct dirent *e;
|
385
|
+
if ((d = opendir (earl.c_str())) == NULL)
|
386
|
+
{
|
387
|
+
syslog( LOG_WARNING, "not monitoring:%s reason:%s", earl.c_str(), strerror(errno));
|
388
|
+
}
|
389
|
+
else
|
390
|
+
{
|
391
|
+
while( e = readdir(d) )
|
392
|
+
{
|
393
|
+
if( shouldAddSubObject( wd, e->d_name ) )
|
394
|
+
{
|
395
|
+
dirNames.push_back( e->d_name );
|
396
|
+
if( Verbose )
|
397
|
+
cerr << "might add monitor for:" << e->d_name << endl;
|
398
|
+
}
|
399
|
+
}
|
400
|
+
closedir (d);
|
401
|
+
}
|
402
|
+
|
403
|
+
//
|
404
|
+
// Check to see if a new directory was created while
|
405
|
+
// we were readdir()ing
|
406
|
+
//
|
407
|
+
{
|
408
|
+
// cerr << "***** BEGIN ****** checking bg info url:" << earl << endl;
|
409
|
+
|
410
|
+
const int buf_sz = 16 * 1024;
|
411
|
+
char buf[ buf_sz + 1 ];
|
412
|
+
int event_count = 0;
|
413
|
+
|
414
|
+
unsigned int nfds = 1;
|
415
|
+
struct pollfd ufds;
|
416
|
+
ufds.fd = dev_fd;
|
417
|
+
ufds.events = POLLIN;
|
418
|
+
ufds.revents = 0;
|
419
|
+
|
420
|
+
int poll_rc = poll( &ufds, nfds, 0 );
|
421
|
+
for( ; poll_rc ; poll_rc = poll( &ufds, nfds, 0 ) )
|
422
|
+
{
|
423
|
+
size_t len = read( dev_fd, buf, buf_sz);
|
424
|
+
if( !len )
|
425
|
+
break;
|
426
|
+
|
427
|
+
size_t buf_iter = 0;
|
428
|
+
|
429
|
+
// cerr << "buf_iter:" << buf_iter << " len:" << len << endl;
|
430
|
+
// cerr << "dev_fd:" << dev_fd << endl;
|
431
|
+
|
432
|
+
while (buf_iter < len)
|
433
|
+
{
|
434
|
+
/* Parse events and queue them ! */
|
435
|
+
struct inotify_event * pevent
|
436
|
+
= (struct inotify_event *)&buf[buf_iter];
|
437
|
+
|
438
|
+
handle_create_subdir_event_by_maybe_watching( pevent, 0 );
|
439
|
+
|
440
|
+
int event_size = sizeof(struct inotify_event) + pevent->len;
|
441
|
+
buf_iter += event_size;
|
442
|
+
event_count++;
|
443
|
+
}
|
444
|
+
}
|
445
|
+
// cerr << "***** END ****** checking bg info url:" << earl << endl;
|
446
|
+
}
|
447
|
+
|
448
|
+
//
|
449
|
+
// switch to monitoring all interesting things for this directory.
|
450
|
+
//
|
451
|
+
// req.fd = fd;
|
452
|
+
// req.mask = watch_mask;
|
453
|
+
// wd = ioctl( dev_fd, INOTIFY_WATCH, &req );
|
454
|
+
wd = inotify_add_watch( dev_fd, earl.c_str(), watch_mask );
|
455
|
+
close (fd);
|
456
|
+
|
457
|
+
//
|
458
|
+
// Monitor the subdirectories
|
459
|
+
//
|
460
|
+
for( dirNames_t::const_iterator di = dirNames.begin();
|
461
|
+
di != dirNames.end(); ++di )
|
462
|
+
{
|
463
|
+
add_watches_recursive( earl + "/" + *di );
|
464
|
+
}
|
465
|
+
|
466
|
+
}
|
467
|
+
|
468
|
+
void
|
469
|
+
KernelFileSystemMonitorDaemon::addIgnorePrefix( const string& s )
|
470
|
+
{
|
471
|
+
m_ignorePrefixes.push_back( s );
|
472
|
+
}
|
473
|
+
|
474
|
+
void
|
475
|
+
KernelFileSystemMonitorDaemon::ParseWatchOptions( poptContext& optCon )
|
476
|
+
{
|
477
|
+
string opcode = "";
|
478
|
+
while( const char* tmpCSTR = poptGetArg(optCon) )
|
479
|
+
{
|
480
|
+
string s = tmpCSTR;
|
481
|
+
string ls = tolowerstr()(s);
|
482
|
+
|
483
|
+
// cerr << " s:" << s << endl;
|
484
|
+
|
485
|
+
if( ls == "ignorepfx" )
|
486
|
+
{
|
487
|
+
opcode = ls;
|
488
|
+
continue;
|
489
|
+
}
|
490
|
+
if( ls == "watch" )
|
491
|
+
{
|
492
|
+
opcode = ls;
|
493
|
+
continue;
|
494
|
+
}
|
495
|
+
|
496
|
+
if( opcode == "ignorepfx" )
|
497
|
+
{
|
498
|
+
m_ignorePrefixes.push_back( s );
|
499
|
+
}
|
500
|
+
else if( opcode == "watch" )
|
501
|
+
{
|
502
|
+
if( Verbose )
|
503
|
+
cerr << "setting up watch for:" << s << endl;
|
504
|
+
m_watchRoots.push_back( s );
|
505
|
+
}
|
506
|
+
}
|
507
|
+
|
508
|
+
}
|
509
|
+
|
510
|
+
|
511
|
+
void
|
512
|
+
KernelFileSystemMonitorDaemon::setupWatches()
|
513
|
+
{
|
514
|
+
if( !dev_fd )
|
515
|
+
{
|
516
|
+
// dev_fd = open ("/dev/inotify", O_RDONLY);
|
517
|
+
dev_fd = inotify_init();
|
518
|
+
if( dev_fd < 0 )
|
519
|
+
{
|
520
|
+
syslog( LOG_ERR, "Exiting due to failure to open inotify device reason:%s", strerror(errno));
|
521
|
+
cerr << "Exiting due to failure to open /dev/inotify device reason:" << strerror(errno)
|
522
|
+
<< endl;
|
523
|
+
exit( 1 );
|
524
|
+
}
|
525
|
+
}
|
526
|
+
|
527
|
+
if( m_watchRoots.empty() )
|
528
|
+
{
|
529
|
+
cerr << "No directories/files to watch have been specified!" << endl;
|
530
|
+
}
|
531
|
+
else
|
532
|
+
{
|
533
|
+
for( stringlist_t::const_iterator ci = m_watchRoots.begin();
|
534
|
+
ci != m_watchRoots.end(); ++ci )
|
535
|
+
{
|
536
|
+
add_watches_recursive( *ci );
|
537
|
+
}
|
538
|
+
}
|
539
|
+
}
|
540
|
+
|
541
|
+
void
|
542
|
+
KernelFileSystemMonitorDaemon::HandleSleepForQueueSize()
|
543
|
+
{
|
544
|
+
unsigned long long time_slept = 0;
|
545
|
+
|
546
|
+
while( !WantToQuit )
|
547
|
+
{
|
548
|
+
unsigned int bytesAvailable = 0;
|
549
|
+
int iorc = ioctl( dev_fd, FIONREAD, &bytesAvailable, 0 );
|
550
|
+
if( iorc < 0 )
|
551
|
+
{
|
552
|
+
// error
|
553
|
+
}
|
554
|
+
|
555
|
+
syslog( LOG_DEBUG,
|
556
|
+
"HandleQ() bytesAvailable:%d iorc:%d "
|
557
|
+
"queue_threshold_bytes:%d "
|
558
|
+
"queue_sleep_threshold_ns:%d time_slept:%d",
|
559
|
+
bytesAvailable, iorc,
|
560
|
+
m_inotify_queue_threshold_bytes,
|
561
|
+
m_inotify_queue_sleep_threshold_ns,
|
562
|
+
time_slept );
|
563
|
+
// cerr << "HandleQ() bytesAvailable:" << bytesAvailable
|
564
|
+
// << " iorc:" << iorc
|
565
|
+
// << " queue_threshold_bytes:" << m_inotify_queue_threshold_bytes
|
566
|
+
// << " queue_sleep_threshold_ns:" << m_inotify_queue_sleep_threshold_ns
|
567
|
+
// << " time_slept:" << time_slept
|
568
|
+
// << endl;
|
569
|
+
|
570
|
+
if( time_slept >= m_inotify_queue_sleep_threshold_ns )
|
571
|
+
{
|
572
|
+
if( !bytesAvailable )
|
573
|
+
{
|
574
|
+
time_slept = 0;
|
575
|
+
|
576
|
+
unsigned int nfds = 1;
|
577
|
+
struct pollfd ufds;
|
578
|
+
ufds.fd = dev_fd;
|
579
|
+
ufds.events = POLLIN;
|
580
|
+
ufds.revents = 0;
|
581
|
+
|
582
|
+
// if the system is idle we should really switch to
|
583
|
+
// poll() here so that we are not a burden
|
584
|
+
int poll_rc = poll( &ufds, nfds, -1 );
|
585
|
+
syslog( LOG_DEBUG, "after poll() rc:%d", poll_rc );
|
586
|
+
|
587
|
+
continue;
|
588
|
+
}
|
589
|
+
|
590
|
+
return;
|
591
|
+
}
|
592
|
+
|
593
|
+
if( bytesAvailable >= m_inotify_queue_threshold_bytes )
|
594
|
+
{
|
595
|
+
return;
|
596
|
+
}
|
597
|
+
|
598
|
+
//
|
599
|
+
// Time to go for a little kip
|
600
|
+
//
|
601
|
+
struct timespec nts;
|
602
|
+
nts.tv_sec = 0;
|
603
|
+
nts.tv_nsec = m_nanosleep_ns;
|
604
|
+
struct timespec rem;
|
605
|
+
bzero( &rem, sizeof(rem) );
|
606
|
+
|
607
|
+
while( nanosleep( &nts, &rem ) < 0 )
|
608
|
+
{
|
609
|
+
if( WantToQuit )
|
610
|
+
return;
|
611
|
+
|
612
|
+
if( errno == EINTR )
|
613
|
+
{
|
614
|
+
nts = rem;
|
615
|
+
bzero( &rem, sizeof(rem) );
|
616
|
+
continue;
|
617
|
+
}
|
618
|
+
else
|
619
|
+
{
|
620
|
+
// error
|
621
|
+
break;
|
622
|
+
}
|
623
|
+
}
|
624
|
+
time_slept += m_nanosleep_ns;
|
625
|
+
continue;
|
626
|
+
}
|
627
|
+
}
|
628
|
+
|
629
|
+
|
630
|
+
int
|
631
|
+
KernelFileSystemMonitorDaemon::run()
|
632
|
+
{
|
633
|
+
// cerr << "KernelFileSystemMonitorDaemon::run() starting" << endl;
|
634
|
+
|
635
|
+
chdir("/");
|
636
|
+
|
637
|
+
const int buf_sz = 32 * 1024;
|
638
|
+
char buf[ buf_sz + 1 ];
|
639
|
+
int event_count = 0;
|
640
|
+
|
641
|
+
while( true )
|
642
|
+
{
|
643
|
+
HandleSleepForQueueSize();
|
644
|
+
syslog( LOG_DEBUG, "After HandleSleepForQueueSize()", 0 );
|
645
|
+
|
646
|
+
if( WantToQuit )
|
647
|
+
{
|
648
|
+
Closedown();
|
649
|
+
return 0;
|
650
|
+
}
|
651
|
+
|
652
|
+
if( size_t len = read( dev_fd, buf, buf_sz) )
|
653
|
+
{
|
654
|
+
if( len > SSIZE_MAX )
|
655
|
+
continue;
|
656
|
+
|
657
|
+
time_t tt = time( 0 );
|
658
|
+
|
659
|
+
size_t buf_iter = 0;
|
660
|
+
bool have_new_subdirs_to_watch = false;
|
661
|
+
|
662
|
+
// cerr << "buf_iter:" << buf_iter << " len:" << len << endl;
|
663
|
+
// cerr << "dev_fd:" << dev_fd << endl;
|
664
|
+
|
665
|
+
event_batch_start( tt );
|
666
|
+
|
667
|
+
while (buf_iter < len)
|
668
|
+
{
|
669
|
+
/* Parse events and queue them ! */
|
670
|
+
struct inotify_event * pevent
|
671
|
+
= (struct inotify_event *)&buf[buf_iter];
|
672
|
+
|
673
|
+
have_new_subdirs_to_watch |=
|
674
|
+
handle_create_subdir_event_by_maybe_watching( pevent, tt );
|
675
|
+
handle_event( pevent, tt );
|
676
|
+
|
677
|
+
int event_size = sizeof(struct inotify_event) + pevent->len;
|
678
|
+
buf_iter += event_size;
|
679
|
+
event_count++;
|
680
|
+
}
|
681
|
+
|
682
|
+
event_batch_end( tt );
|
683
|
+
|
684
|
+
cout << "-" << endl;
|
685
|
+
|
686
|
+
if( have_new_subdirs_to_watch )
|
687
|
+
setupWatches();
|
688
|
+
}
|
689
|
+
}
|
690
|
+
|
691
|
+
// cerr << "KernelFileSystemMonitorDaemon::run() exiting" << endl;
|
692
|
+
return 0;
|
693
|
+
|
694
|
+
}
|
695
|
+
|
696
|
+
|
697
|
+
struct ::poptOption*
|
698
|
+
KernelFileSystemMonitorDaemon::getPopTable()
|
699
|
+
{
|
700
|
+
static struct poptOption optionsTable[] =
|
701
|
+
{
|
702
|
+
{ "inotify-queue-threshold-bytes", 0, POPT_ARG_INT, &m_inotify_queue_threshold_bytes, 0,
|
703
|
+
"number of bytes that should be available on /dev/inotify before reading", "" },
|
704
|
+
|
705
|
+
{ "inotify-queue-sleep-threshold-ns", 0, POPT_ARG_INT, &m_inotify_queue_sleep_threshold_ns, 0,
|
706
|
+
"after this time read the inotify queue anyway", "" },
|
707
|
+
|
708
|
+
{ "inotify-sleep-delay-ns", 0, POPT_ARG_INT, &m_nanosleep_ns, 0,
|
709
|
+
"nanoseconds to sleep if /dev/inotify is not full enough", "" },
|
710
|
+
|
711
|
+
POPT_TABLEEND
|
712
|
+
};
|
713
|
+
return optionsTable;
|
714
|
+
}
|
715
|
+
|
716
|
+
|
717
|
+
|
718
|
+
|
719
|
+
|
720
|
+
|
721
|
+
|
722
|
+
|
723
|
+
|
724
|
+
|
725
|
+
|
726
|
+
|
727
|
+
|