|
a/src/index/rclmonrcv.cpp |
|
b/src/index/rclmonrcv.cpp |
1 |
#include "autoconfig.h"
|
1 |
#include "autoconfig.h"
|
2 |
#ifdef RCL_MONITOR
|
2 |
#ifdef RCL_MONITOR
|
3 |
#ifndef lint
|
3 |
#ifndef lint
|
4 |
static char rcsid[] = "@(#$Id: rclmonrcv.cpp,v 1.6 2006-10-24 09:09:36 dockes Exp $ (C) 2006 J.F.Dockes";
|
4 |
static char rcsid[] = "@(#$Id: rclmonrcv.cpp,v 1.7 2006-10-25 10:52:02 dockes Exp $ (C) 2006 J.F.Dockes";
|
5 |
#endif
|
5 |
#endif
|
6 |
/*
|
6 |
/*
|
7 |
* This program is free software; you can redistribute it and/or modify
|
7 |
* This program is free software; you can redistribute it and/or modify
|
8 |
* it under the terms of the GNU General Public License as published by
|
8 |
* it under the terms of the GNU General Public License as published by
|
9 |
* the Free Software Foundation; either version 2 of the License, or
|
9 |
* the Free Software Foundation; either version 2 of the License, or
|
|
... |
|
... |
66 |
virtual FsTreeWalker::Status
|
66 |
virtual FsTreeWalker::Status
|
67 |
processone(const string &fn, const struct stat *st, FsTreeWalker::CbFlag flg)
|
67 |
processone(const string &fn, const struct stat *st, FsTreeWalker::CbFlag flg)
|
68 |
{
|
68 |
{
|
69 |
LOGDEB2(("rclMonRcvRun: processone %s m_mon %p m_mon->ok %d\n",
|
69 |
LOGDEB2(("rclMonRcvRun: processone %s m_mon %p m_mon->ok %d\n",
|
70 |
fn.c_str(), m_mon, m_mon?m_mon->ok():0));
|
70 |
fn.c_str(), m_mon, m_mon?m_mon->ok():0));
|
71 |
// Create watch when entering directory
|
71 |
|
72 |
if (flg == FsTreeWalker::FtwDirEnter) {
|
72 |
if (flg == FsTreeWalker::FtwDirEnter) {
|
|
|
73 |
// Create watch when entering directory, but first empty
|
73 |
// Empty whatever events we may already have on queue
|
74 |
// whatever events we may already have on queue
|
74 |
while (m_queue->ok() && m_mon->ok()) {
|
75 |
while (m_queue->ok() && m_mon->ok()) {
|
75 |
RclMonEvent ev;
|
76 |
RclMonEvent ev;
|
76 |
if (m_mon->getEvent(ev, 0)) {
|
77 |
if (m_mon->getEvent(ev, 0)) {
|
|
|
78 |
if (ev.m_etyp != RclMonEvent::RCLEVT_NONE)
|
77 |
m_queue->pushEvent(ev);
|
79 |
m_queue->pushEvent(ev);
|
78 |
} else {
|
80 |
} else {
|
|
|
81 |
LOGDEB(("rclMonRcvRun: no event pending\n"));
|
79 |
break;
|
82 |
break;
|
80 |
}
|
83 |
}
|
81 |
}
|
84 |
}
|
82 |
if (!m_mon || !m_mon->ok() || !m_mon->addWatch(fn, true))
|
85 |
if (!m_mon || !m_mon->ok() || !m_mon->addWatch(fn, true))
|
83 |
return FsTreeWalker::FtwError;
|
86 |
return FsTreeWalker::FtwError;
|
|
... |
|
... |
133 |
LOGDEB(("rclMonRcvRun: walking %s\n", it->c_str()));
|
136 |
LOGDEB(("rclMonRcvRun: walking %s\n", it->c_str()));
|
134 |
walker.walk(*it, walkcb);
|
137 |
walker.walk(*it, walkcb);
|
135 |
}
|
138 |
}
|
136 |
|
139 |
|
137 |
// Forever wait for monitoring events and add them to queue:
|
140 |
// Forever wait for monitoring events and add them to queue:
|
138 |
LOGDEB2(("rclMonRcvRun: waiting for events. queue->ok() %d\n", queue->ok()));
|
141 |
LOGDEB2(("rclMonRcvRun: waiting for events. q->ok() %d\n", queue->ok()));
|
139 |
while (queue->ok() && mon->ok()) {
|
142 |
while (queue->ok() && mon->ok()) {
|
140 |
RclMonEvent ev;
|
143 |
RclMonEvent ev;
|
141 |
// Note: under Linux, I could find no way to get the select
|
144 |
// Note: I could find no way to get the select
|
142 |
// call to return when a signal is delivered to the process
|
145 |
// call to return when a signal is delivered to the process
|
143 |
// (it goes to the main thread, from which I tried to close or
|
146 |
// (it goes to the main thread, from which I tried to close or
|
144 |
// write to the select fd, with no effect. So set a
|
147 |
// write to the select fd, with no effect). So set a
|
145 |
// timeout so that an intr will be detected
|
148 |
// timeout so that an intr will be detected
|
146 |
if (mon->getEvent(ev,
|
149 |
if (mon->getEvent(ev, 2)) {
|
147 |
#ifdef linux
|
|
|
148 |
2
|
|
|
149 |
#else
|
|
|
150 |
-1
|
|
|
151 |
#endif
|
|
|
152 |
)) {
|
|
|
153 |
if (ev.m_etyp == RclMonEvent::RCLEVT_DIRCREATE) {
|
150 |
if (ev.m_etyp == RclMonEvent::RCLEVT_DIRCREATE) {
|
154 |
mon->addWatch(ev.m_path, true);
|
151 |
mon->addWatch(ev.m_path, true);
|
155 |
}
|
152 |
}
|
|
|
153 |
if (ev.m_etyp != RclMonEvent::RCLEVT_NONE)
|
156 |
queue->pushEvent(ev);
|
154 |
queue->pushEvent(ev);
|
157 |
}
|
155 |
}
|
158 |
}
|
156 |
}
|
159 |
|
157 |
|
160 |
LOGDEB(("rclMonRcvRun: exiting\n"));
|
158 |
LOGINFO(("rclMonRcvRun: exiting\n"));
|
161 |
queue->setTerminate();
|
159 |
queue->setTerminate();
|
162 |
return 0;
|
160 |
return 0;
|
163 |
}
|
161 |
}
|
164 |
|
162 |
|
165 |
#ifdef RCL_USE_FAM
|
163 |
#ifdef RCL_USE_FAM
|
|
... |
|
... |
250 |
}
|
248 |
}
|
251 |
m_reqtopath[req.reqnum] = path;
|
249 |
m_reqtopath[req.reqnum] = path;
|
252 |
return true;
|
250 |
return true;
|
253 |
}
|
251 |
}
|
254 |
|
252 |
|
|
|
253 |
// Note: return false only for queue empty or error
|
|
|
254 |
// Return EVT_NONE for bad event to keep queue processing going
|
255 |
bool RclFAM::getEvent(RclMonEvent& ev, int secs)
|
255 |
bool RclFAM::getEvent(RclMonEvent& ev, int secs)
|
256 |
{
|
256 |
{
|
257 |
if (!ok())
|
257 |
if (!ok())
|
258 |
return false;
|
258 |
return false;
|
259 |
LOGDEB2(("RclFAM::getEvent:\n"));
|
259 |
LOGDEB2(("RclFAM::getEvent:\n"));
|
|
... |
|
... |
261 |
fd_set readfds;
|
261 |
fd_set readfds;
|
262 |
int fam_fd = FAMCONNECTION_GETFD(&m_conn);
|
262 |
int fam_fd = FAMCONNECTION_GETFD(&m_conn);
|
263 |
FD_ZERO(&readfds);
|
263 |
FD_ZERO(&readfds);
|
264 |
FD_SET(fam_fd, &readfds);
|
264 |
FD_SET(fam_fd, &readfds);
|
265 |
|
265 |
|
266 |
LOGDEB2(("RclFAM::getEvent: select\n"));
|
266 |
LOGDEB(("RclFAM::getEvent: select\n"));
|
267 |
struct timeval timeout;
|
267 |
struct timeval timeout;
|
268 |
if (secs >= 0) {
|
268 |
if (secs >= 0) {
|
269 |
memset(&timeout, 0, sizeof(timeout));
|
269 |
memset(&timeout, 0, sizeof(timeout));
|
270 |
timeout.tv_sec = secs;
|
270 |
timeout.tv_sec = secs;
|
271 |
}
|
271 |
}
|
272 |
int ret;
|
272 |
int ret;
|
273 |
if ((ret=select(fam_fd + 1, &readfds, 0, 0, secs >= 0 ? &timeout : 0)) < 0) {
|
273 |
if ((ret=select(fam_fd+1, &readfds, 0, 0, secs >= 0 ? &timeout : 0)) < 0) {
|
274 |
LOGERR(("RclFAM::getEvent: select failed, errno %d\n", errno));
|
274 |
LOGERR(("RclFAM::getEvent: select failed, errno %d\n", errno));
|
275 |
close();
|
275 |
close();
|
276 |
return false;
|
276 |
return false;
|
277 |
} else if (ret == 0) {
|
277 |
} else if (ret == 0) {
|
278 |
// timeout
|
278 |
// timeout
|
|
|
279 |
LOGDEB(("RclFAM::getEvent: select timeout\n"));
|
279 |
return false;
|
280 |
return false;
|
280 |
}
|
281 |
}
|
|
|
282 |
|
|
|
283 |
LOGDEB(("RclFAM::getEvent: select return\n"));
|
281 |
|
284 |
|
282 |
if (!FD_ISSET(fam_fd, &readfds))
|
285 |
if (!FD_ISSET(fam_fd, &readfds))
|
283 |
return false;
|
286 |
return false;
|
284 |
|
287 |
|
|
|
288 |
LOGDEB(("RclFAM::getEvent: call FAMNextEvent\n"));
|
285 |
FAMEvent fe;
|
289 |
FAMEvent fe;
|
286 |
if (FAMNextEvent(&m_conn, &fe) < 0) {
|
290 |
if (FAMNextEvent(&m_conn, &fe) < 0) {
|
287 |
LOGERR(("RclFAM::getEvent: FAMNextEvent failed, errno %d\n", errno));
|
291 |
LOGERR(("RclFAM::getEvent: FAMNextEvent failed, errno %d\n", errno));
|
288 |
close();
|
292 |
close();
|
289 |
return false;
|
293 |
return false;
|
290 |
}
|
294 |
}
|
|
|
295 |
LOGDEB(("RclFAM::getEvent: FAMNextEvent returned\n"));
|
291 |
|
296 |
|
292 |
map<int,string>::const_iterator it;
|
297 |
map<int,string>::const_iterator it;
|
293 |
if ((fe.filename[0] != '/') &&
|
298 |
if ((fe.filename[0] != '/') &&
|
294 |
(it = m_reqtopath.find(fe.fr.reqnum)) != m_reqtopath.end()) {
|
299 |
(it = m_reqtopath.find(fe.fr.reqnum)) != m_reqtopath.end()) {
|
295 |
ev.m_path = path_cat(it->second, fe.filename);
|
300 |
ev.m_path = path_cat(it->second, fe.filename);
|
|
... |
|
... |
324 |
case FAMStartExecuting:
|
329 |
case FAMStartExecuting:
|
325 |
case FAMStopExecuting:
|
330 |
case FAMStopExecuting:
|
326 |
case FAMAcknowledge:
|
331 |
case FAMAcknowledge:
|
327 |
case FAMEndExist:
|
332 |
case FAMEndExist:
|
328 |
default:
|
333 |
default:
|
329 |
return false;
|
334 |
// Have to return something, this is different from an empty queue,
|
|
|
335 |
// esp if we are trying to empty it...
|
|
|
336 |
LOGDEB(("RclFAM::getEvent: got move event !\n"));
|
|
|
337 |
ev.m_etyp = RclMonEvent::RCLEVT_NONE;
|
|
|
338 |
break;
|
330 |
}
|
339 |
}
|
331 |
return true;
|
340 |
return true;
|
332 |
}
|
341 |
}
|
333 |
#endif // RCL_USE_FAM
|
342 |
#endif // RCL_USE_FAM
|
334 |
|
343 |
|
|
... |
|
... |
430 |
}
|
439 |
}
|
431 |
m_wdtopath[wd] = path;
|
440 |
m_wdtopath[wd] = path;
|
432 |
return true;
|
441 |
return true;
|
433 |
}
|
442 |
}
|
434 |
|
443 |
|
|
|
444 |
// Note: return false only for queue empty or error
|
|
|
445 |
// Return EVT_NONE for bad event to keep queue processing going
|
435 |
bool RclIntf::getEvent(RclMonEvent& ev, int secs)
|
446 |
bool RclIntf::getEvent(RclMonEvent& ev, int secs)
|
436 |
{
|
447 |
{
|
437 |
if (!ok())
|
448 |
if (!ok())
|
438 |
return false;
|
449 |
return false;
|
|
|
450 |
ev.m_etyp = RclMonEvent::RCLEVT_NONE;
|
439 |
LOGDEB2(("RclIntf::getEvent:\n"));
|
451 |
LOGDEB2(("RclIntf::getEvent:\n"));
|
440 |
|
452 |
|
441 |
if (m_evp == 0) {
|
453 |
if (m_evp == 0) {
|
442 |
fd_set readfds;
|
454 |
fd_set readfds;
|
443 |
FD_ZERO(&readfds);
|
455 |
FD_ZERO(&readfds);
|
|
... |
|
... |
481 |
m_evp = m_ep = 0;
|
493 |
m_evp = m_ep = 0;
|
482 |
|
494 |
|
483 |
map<int,string>::const_iterator it;
|
495 |
map<int,string>::const_iterator it;
|
484 |
if ((it = m_wdtopath.find(evp->wd)) == m_wdtopath.end()) {
|
496 |
if ((it = m_wdtopath.find(evp->wd)) == m_wdtopath.end()) {
|
485 |
LOGERR(("RclIntf::getEvent: unknown wd\n"));
|
497 |
LOGERR(("RclIntf::getEvent: unknown wd\n"));
|
486 |
return false;
|
498 |
return true;
|
487 |
}
|
499 |
}
|
488 |
ev.m_path = it->second;
|
500 |
ev.m_path = it->second;
|
489 |
|
501 |
|
490 |
if (evp->len > 0) {
|
502 |
if (evp->len > 0) {
|
491 |
ev.m_path = path_cat(ev.m_path, evp->name);
|
503 |
ev.m_path = path_cat(ev.m_path, evp->name);
|
|
... |
|
... |
500 |
ev.m_etyp = RclMonEvent::RCLEVT_DELETE;
|
512 |
ev.m_etyp = RclMonEvent::RCLEVT_DELETE;
|
501 |
} else if (evp->mask & (IN_CREATE)) {
|
513 |
} else if (evp->mask & (IN_CREATE)) {
|
502 |
if (path_isdir(ev.m_path)) {
|
514 |
if (path_isdir(ev.m_path)) {
|
503 |
ev.m_etyp = RclMonEvent::RCLEVT_DIRCREATE;
|
515 |
ev.m_etyp = RclMonEvent::RCLEVT_DIRCREATE;
|
504 |
} else {
|
516 |
} else {
|
505 |
// Will get modify event
|
517 |
// Return null event. Will get modify event later
|
506 |
return false;
|
518 |
return true;
|
507 |
}
|
519 |
}
|
508 |
} else {
|
520 |
} else {
|
509 |
LOGDEB(("RclIntf::getEvent: unhandled event %s 0x%x %s\n",
|
521 |
LOGDEB(("RclIntf::getEvent: unhandled event %s 0x%x %s\n",
|
510 |
event_name(evp->mask), evp->mask, ev.m_path.c_str()));
|
522 |
event_name(evp->mask), evp->mask, ev.m_path.c_str()));
|
511 |
return false;
|
523 |
return true;
|
512 |
}
|
524 |
}
|
513 |
return true;
|
525 |
return true;
|
514 |
}
|
526 |
}
|
515 |
|
527 |
|
516 |
#endif // RCL_USE_INOTIFY
|
528 |
#endif // RCL_USE_INOTIFY
|