Switch to unified view

a/src/index/rclmonrcv.cpp b/src/index/rclmonrcv.cpp
...
...
100
        RclMonEvent ev;
100
        RclMonEvent ev;
101
        if (m_mon->getEvent(ev, 0)) {
101
        if (m_mon->getEvent(ev, 0)) {
102
            if (ev.m_etyp !=  RclMonEvent::RCLEVT_NONE)
102
            if (ev.m_etyp !=  RclMonEvent::RCLEVT_NONE)
103
            m_queue->pushEvent(ev);
103
            m_queue->pushEvent(ev);
104
        } else {
104
        } else {
105
            MONDEB(("rclMonRcvRun: no event pending\n"));
105
            MONDEB("rclMonRcvRun: no event pending\n");
106
            break;
106
            break;
107
        }
107
        }
108
        }
108
        }
109
        if (!m_mon || !m_mon->ok())
109
        if (!m_mon || !m_mon->ok())
110
        return FsTreeWalker::FtwError;
110
        return FsTreeWalker::FtwError;
...
...
208
        }
208
        }
209
    }
209
    }
210
    }
210
    }
211
211
212
    // Forever wait for monitoring events and add them to queue:
212
    // Forever wait for monitoring events and add them to queue:
213
    MONDEB(("rclMonRcvRun: waiting for events. q->ok() %d\n", queue->ok()));
213
    MONDEB("rclMonRcvRun: waiting for events. q->ok(): " << queue->ok() <<
214
           std::endl);
214
    while (queue->ok() && mon->ok()) {
215
    while (queue->ok() && mon->ok()) {
215
    RclMonEvent ev;
216
    RclMonEvent ev;
216
    // Note: I could find no way to get the select
217
    // Note: I could find no way to get the select
217
    // call to return when a signal is delivered to the process
218
    // call to return when a signal is delivered to the process
218
    // (it goes to the main thread, from which I tried to close or
219
    // (it goes to the main thread, from which I tried to close or
...
...
262
// Utility routine used by both the fam/gamin and inotify versions to get 
263
// Utility routine used by both the fam/gamin and inotify versions to get 
263
// rid of the id-path translation for a moved dir
264
// rid of the id-path translation for a moved dir
264
bool eraseWatchSubTree(map<int, string>& idtopath, const string& top)
265
bool eraseWatchSubTree(map<int, string>& idtopath, const string& top)
265
{
266
{
266
    bool found = false;
267
    bool found = false;
267
    MONDEB(("Clearing map for [%s]\n", top.c_str()));
268
    MONDEB("Clearing map for [" << top << "]\n");
268
    map<int,string>::iterator it = idtopath.begin();
269
    map<int,string>::iterator it = idtopath.begin();
269
    while (it != idtopath.end()) {
270
    while (it != idtopath.end()) {
270
    if (it->second.find(top) == 0) {
271
    if (it->second.find(top) == 0) {
271
        found = true;
272
        found = true;
272
        idtopath.erase(it++);
273
        idtopath.erase(it++);
...
...
360
{
361
{
361
    if (!ok())
362
    if (!ok())
362
    return false;
363
    return false;
363
    bool ret = false;
364
    bool ret = false;
364
365
365
    MONDEB(("RclFAM::addWatch: adding %s\n", path.c_str()));
366
    MONDEB("RclFAM::addWatch: adding " << path << std::endl);
366
367
367
    // It happens that the following call block forever. 
368
    // It happens that the following call block forever. 
368
    // We'd like to be able to at least terminate on a signal here, but
369
    // We'd like to be able to at least terminate on a signal here, but
369
    // gamin forever retries its write call on EINTR, so it's not even useful
370
    // gamin forever retries its write call on EINTR, so it's not even useful
370
    // to unblock signals. SIGALRM is not used by the main thread, so at least
371
    // to unblock signals. SIGALRM is not used by the main thread, so at least
...
...
399
// Return EVT_NONE for bad event to keep queue processing going
400
// Return EVT_NONE for bad event to keep queue processing going
400
bool RclFAM::getEvent(RclMonEvent& ev, int msecs)
401
bool RclFAM::getEvent(RclMonEvent& ev, int msecs)
401
{
402
{
402
    if (!ok())
403
    if (!ok())
403
    return false;
404
    return false;
404
    MONDEB(("RclFAM::getEvent:\n"));
405
    MONDEB("RclFAM::getEvent:\n");
405
406
406
    fd_set readfds;
407
    fd_set readfds;
407
    int fam_fd = FAMCONNECTION_GETFD(&m_conn);
408
    int fam_fd = FAMCONNECTION_GETFD(&m_conn);
408
    FD_ZERO(&readfds);
409
    FD_ZERO(&readfds);
409
    FD_SET(fam_fd, &readfds);
410
    FD_SET(fam_fd, &readfds);
410
411
411
    MONDEB(("RclFAM::getEvent: select. fam_fd is %d\n", fam_fd));
412
    MONDEB("RclFAM::getEvent: select. fam_fd is " << fam_fd << std::endl);
412
    // Fam / gamin is sometimes a bit slow to send events. Always add
413
    // Fam / gamin is sometimes a bit slow to send events. Always add
413
    // a little timeout, because if we fail to retrieve enough events,
414
    // a little timeout, because if we fail to retrieve enough events,
414
    // we risk deadlocking in addwatch()
415
    // we risk deadlocking in addwatch()
415
    if (msecs == 0)
416
    if (msecs == 0)
416
    msecs = 2;
417
    msecs = 2;
...
...
424
    LOGERR("RclFAM::getEvent: select failed, errno "  << (errno) << "\n" );
425
    LOGERR("RclFAM::getEvent: select failed, errno "  << (errno) << "\n" );
425
    close();
426
    close();
426
    return false;
427
    return false;
427
    } else if (ret == 0) {
428
    } else if (ret == 0) {
428
    // timeout
429
    // timeout
429
    MONDEB(("RclFAM::getEvent: select timeout\n"));
430
    MONDEB("RclFAM::getEvent: select timeout\n");
430
    return false;
431
    return false;
431
    }
432
    }
432
433
433
    MONDEB(("RclFAM::getEvent: select returned %d\n", ret));
434
    MONDEB("RclFAM::getEvent: select returned " << ret << std::endl);
434
435
435
    if (!FD_ISSET(fam_fd, &readfds))
436
    if (!FD_ISSET(fam_fd, &readfds))
436
    return false;
437
    return false;
437
438
438
    // ?? 2011/03/15 gamin v0.1.10. There is initially a single null
439
    // ?? 2011/03/15 gamin v0.1.10. There is initially a single null
439
    // byte on the connection so the first select always succeeds. If
440
    // byte on the connection so the first select always succeeds. If
440
    // we then call FAMNextEvent we stall. Using FAMPending works
441
    // we then call FAMNextEvent we stall. Using FAMPending works
441
    // around the issue, but we did not need this in the past and this
442
    // around the issue, but we did not need this in the past and this
442
    // is most weird.
443
    // is most weird.
443
    if (FAMPending(&m_conn) <= 0) {
444
    if (FAMPending(&m_conn) <= 0) {
444
    MONDEB(("RclFAM::getEvent: FAMPending says no events\n"));
445
    MONDEB("RclFAM::getEvent: FAMPending says no events\n");
445
    return false;
446
    return false;
446
    }
447
    }
447
448
448
    MONDEB(("RclFAM::getEvent: call FAMNextEvent\n"));
449
    MONDEB("RclFAM::getEvent: call FAMNextEvent\n");
449
    FAMEvent fe;
450
    FAMEvent fe;
450
    if (FAMNextEvent(&m_conn, &fe) < 0) {
451
    if (FAMNextEvent(&m_conn, &fe) < 0) {
451
    LOGERR("RclFAM::getEvent: FAMNextEvent failed, errno "  << (errno) << "\n" );
452
    LOGERR("RclFAM::getEvent: FAMNextEvent failed, errno "  << (errno) << "\n" );
452
    close();
453
    close();
453
    return false;
454
    return false;
454
    }
455
    }
455
    MONDEB(("RclFAM::getEvent: FAMNextEvent returned\n"));
456
    MONDEB("RclFAM::getEvent: FAMNextEvent returned\n");
456
    
457
    
457
    map<int,string>::const_iterator it;
458
    map<int,string>::const_iterator it;
458
    if ((!path_isabsolute(fe.filename)) && 
459
    if ((!path_isabsolute(fe.filename)) && 
459
    (it = m_idtopath.find(fe.fr.reqnum)) != m_idtopath.end()) {
460
    (it = m_idtopath.find(fe.fr.reqnum)) != m_idtopath.end()) {
460
    ev.m_path = path_cat(it->second, fe.filename);
461
    ev.m_path = path_cat(it->second, fe.filename);
461
    } else {
462
    } else {
462
    ev.m_path = fe.filename;
463
    ev.m_path = fe.filename;
463
    }
464
    }
464
465
465
    MONDEB(("RclFAM::getEvent: %-12s %s\n", 
466
    MONDEB("RclFAM::getEvent: " << event_name(fe.code) < " " <<
466
      event_name(fe.code), ev.m_path.c_str()));
467
           ev.m_path << std::endl);
467
468
468
    switch (fe.code) {
469
    switch (fe.code) {
469
    case FAMCreated:
470
    case FAMCreated:
470
    if (path_isdir(ev.m_path)) {
471
    if (path_isdir(ev.m_path)) {
471
        ev.m_etyp = RclMonEvent::RCLEVT_DIRCREATE;
472
        ev.m_etyp = RclMonEvent::RCLEVT_DIRCREATE;
...
...
582
583
583
bool RclIntf::addWatch(const string& path, bool)
584
bool RclIntf::addWatch(const string& path, bool)
584
{
585
{
585
   if (!ok())
586
   if (!ok())
586
       return false;
587
       return false;
587
   MONDEB(("RclIntf::addWatch: adding %s\n", path.c_str()));
588
   MONDEB("RclIntf::addWatch: adding " << path << std::endl);
588
    // CLOSE_WRITE is covered through MODIFY. CREATE is needed for mkdirs
589
    // CLOSE_WRITE is covered through MODIFY. CREATE is needed for mkdirs
589
    uint32_t mask = IN_MODIFY | IN_CREATE
590
    uint32_t mask = IN_MODIFY | IN_CREATE
590
        | IN_MOVED_FROM | IN_MOVED_TO | IN_DELETE
591
        | IN_MOVED_FROM | IN_MOVED_TO | IN_DELETE
591
    // IN_ATTRIB used to be not needed to receive extattr
592
    // IN_ATTRIB used to be not needed to receive extattr
592
    // modification events, which was a bit weird because only ctime is
593
    // modification events, which was a bit weird because only ctime is
...
...
617
bool RclIntf::getEvent(RclMonEvent& ev, int msecs)
618
bool RclIntf::getEvent(RclMonEvent& ev, int msecs)
618
{
619
{
619
    if (!ok())
620
    if (!ok())
620
    return false;
621
    return false;
621
    ev.m_etyp = RclMonEvent::RCLEVT_NONE;
622
    ev.m_etyp = RclMonEvent::RCLEVT_NONE;
622
    MONDEB(("RclIntf::getEvent:\n"));
623
    MONDEB("RclIntf::getEvent:\n");
623
624
624
    if (m_evp == 0) {
625
    if (m_evp == 0) {
625
    fd_set readfds;
626
    fd_set readfds;
626
    FD_ZERO(&readfds);
627
    FD_ZERO(&readfds);
627
    FD_SET(m_fd, &readfds);
628
    FD_SET(m_fd, &readfds);
...
...
629
    if (msecs >= 0) {
630
    if (msecs >= 0) {
630
        timeout.tv_sec = msecs / 1000;
631
        timeout.tv_sec = msecs / 1000;
631
        timeout.tv_usec = (msecs % 1000) * 1000;
632
        timeout.tv_usec = (msecs % 1000) * 1000;
632
    }
633
    }
633
    int ret;
634
    int ret;
634
    MONDEB(("RclIntf::getEvent: select\n"));
635
    MONDEB("RclIntf::getEvent: select\n");
635
    if ((ret=select(m_fd + 1, &readfds, 0, 0, msecs >= 0 ? &timeout : 0)) < 0) {
636
    if ((ret=select(m_fd + 1, &readfds, 0, 0, msecs >= 0 ? &timeout : 0)) < 0) {
636
        LOGERR("RclIntf::getEvent: select failed, errno "  << (errno) << "\n" );
637
        LOGERR("RclIntf::getEvent: select failed, errno "  << (errno) << "\n" );
637
        close();
638
        close();
638
        return false;
639
        return false;
639
    } else if (ret == 0) {
640
    } else if (ret == 0) {
640
        MONDEB(("RclIntf::getEvent: select timeout\n"));
641
        MONDEB("RclIntf::getEvent: select timeout\n");
641
        // timeout
642
        // timeout
642
        return false;
643
        return false;
643
    }
644
    }
644
    MONDEB(("RclIntf::getEvent: select returned\n"));
645
    MONDEB("RclIntf::getEvent: select returned\n");
645
646
646
    if (!FD_ISSET(m_fd, &readfds))
647
    if (!FD_ISSET(m_fd, &readfds))
647
        return false;
648
        return false;
648
    int rret;
649
    int rret;
649
    if ((rret=read(m_fd, m_evbuf, sizeof(m_evbuf))) <= 0) {
650
    if ((rret=read(m_fd, m_evbuf, sizeof(m_evbuf))) <= 0) {
650
      LOGERR("RclIntf::getEvent: read failed, "  << (sizeof(m_evbuf)) << "->"  << (rret) << " errno "  << (errno) << "\n" );
651
      LOGERR("RclIntf::getEvent: read failed, "  << sizeof(m_evbuf) <<
652
                   "->"  << rret << " errno "  << errno << "\n");
651
        close();
653
        close();
652
        return false;
654
        return false;
653
    }
655
    }
654
    m_evp = m_evbuf;
656
    m_evp = m_evbuf;
655
    m_ep = m_evbuf + rret;
657
    m_ep = m_evbuf + rret;
...
...
671
673
672
    if (evp->len > 0) {
674
    if (evp->len > 0) {
673
    ev.m_path = path_cat(ev.m_path, evp->name);
675
    ev.m_path = path_cat(ev.m_path, evp->name);
674
    }
676
    }
675
677
676
    MONDEB(("RclIntf::getEvent: %-12s %s\n", 
678
    MONDEB("RclIntf::getEvent: " << event_name(evp->mask) << " " <<
677
      event_name(evp->mask), ev.m_path.c_str()));
679
           ev.m_path << std::endl);
678
680
679
    if ((evp->mask & IN_MOVED_FROM) && (evp->mask & IN_ISDIR)) {
681
    if ((evp->mask & IN_MOVED_FROM) && (evp->mask & IN_ISDIR)) {
680
    // We get this when a directory is renamed. Erase the subtree
682
    // We get this when a directory is renamed. Erase the subtree
681
    // entries in the map. The subsequent MOVED_TO will recreate
683
    // entries in the map. The subsequent MOVED_TO will recreate
682
    // them. This is probably not needed because the watches
684
    // them. This is probably not needed because the watches