|
42 | 42 | #include "Poco/Exception.h" |
43 | 43 | #include "Poco/Buffer.h" |
44 | 44 | #if defined(POCO_WIN32_UTF8) |
45 | | -#include "Poco/UnicodeConverter.h" |
| 45 | + #include "Poco/UnicodeConverter.h" |
46 | 46 | #endif |
47 | 47 | #if POCO_OS == POCO_OS_LINUX |
48 | | -#include <sys/inotify.h> |
49 | | -#include <sys/select.h> |
50 | | -#include <unistd.h> |
| 48 | + #include <sys/inotify.h> |
| 49 | + #include <sys/select.h> |
| 50 | + #include <unistd.h> |
| 51 | +#elif POCO_OS == POCO_OS_MAC_OS_X || POCO_OS == POCO_OS_FREE_BSD |
| 52 | + #include <fcntl.h> |
| 53 | + #include <sys/types.h> |
| 54 | + #include <sys/event.h> |
| 55 | + #include <sys/time.h> |
51 | 56 | #endif |
52 | 57 | #include <algorithm> |
53 | 58 | #include <map> |
@@ -391,6 +396,89 @@ class LinuxDirectoryWatcherStrategy: public DirectoryWatcherStrategy |
391 | 396 | }; |
392 | 397 |
|
393 | 398 |
|
| 399 | +#elif POCO_OS == POCO_OS_MAC_OS_X || POCO_OS == POCO_OS_FREE_BSD |
| 400 | + |
| 401 | + |
| 402 | +class BSDDirectoryWatcherStrategy: public DirectoryWatcherStrategy |
| 403 | +{ |
| 404 | +public: |
| 405 | + BSDDirectoryWatcherStrategy(DirectoryWatcher& owner): |
| 406 | + DirectoryWatcherStrategy(owner), |
| 407 | + _queueFD(-1), |
| 408 | + _dirFD(-1), |
| 409 | + _stopped(false) |
| 410 | + { |
| 411 | + _dirFD = open(owner.directory().path().c_str(), O_EVTONLY); |
| 412 | + if (_dirFD < 0) throw Poco::FileNotFoundException(owner.directory().path()); |
| 413 | + _queueFD = kqueue(); |
| 414 | + if (_queueFD < 0) |
| 415 | + { |
| 416 | + close(_dirFD); |
| 417 | + throw Poco::SystemException("Cannot create kqueue", errno); |
| 418 | + } |
| 419 | + } |
| 420 | + |
| 421 | + ~BSDDirectoryWatcherStrategy() |
| 422 | + { |
| 423 | + close(_dirFD); |
| 424 | + close(_queueFD); |
| 425 | + } |
| 426 | + |
| 427 | + void run() |
| 428 | + { |
| 429 | + Poco::Timestamp lastScan; |
| 430 | + ItemInfoMap entries; |
| 431 | + scan(entries); |
| 432 | + |
| 433 | + while (!_stopped) |
| 434 | + { |
| 435 | + struct timespec timeout; |
| 436 | + timeout.tv_sec = 0; |
| 437 | + timeout.tv_nsec = 200000000; |
| 438 | + unsigned eventFilter = NOTE_WRITE; |
| 439 | + struct kevent event; |
| 440 | + struct kevent eventData; |
| 441 | + EV_SET(&event, _dirFD, EVFILT_VNODE, EV_ADD | EV_CLEAR, eventFilter, 0, 0); |
| 442 | + int nEvents = kevent(_queueFD, &event, 1, &eventData, 1, &timeout); |
| 443 | + if (nEvents < 0 || eventData.flags == EV_ERROR) |
| 444 | + { |
| 445 | + try |
| 446 | + { |
| 447 | + FileImpl::handleLastErrorImpl(owner().directory().path()); |
| 448 | + } |
| 449 | + catch (Poco::Exception& exc) |
| 450 | + { |
| 451 | + owner().scanError(&owner(), exc); |
| 452 | + } |
| 453 | + } |
| 454 | + else if (nEvents > 0 || ((owner().eventMask() & DirectoryWatcher::DW_ITEM_MODIFIED) && lastScan.isElapsed(owner().scanInterval()*1000000))) |
| 455 | + { |
| 456 | + ItemInfoMap newEntries; |
| 457 | + scan(newEntries); |
| 458 | + compare(entries, newEntries); |
| 459 | + std::swap(entries, newEntries); |
| 460 | + lastScan.update(); |
| 461 | + } |
| 462 | + } |
| 463 | + } |
| 464 | + |
| 465 | + void stop() |
| 466 | + { |
| 467 | + _stopped = true; |
| 468 | + } |
| 469 | + |
| 470 | + bool supportsMoveEvents() const |
| 471 | + { |
| 472 | + return false; |
| 473 | + } |
| 474 | + |
| 475 | +private: |
| 476 | + int _queueFD; |
| 477 | + int _dirFD; |
| 478 | + bool _stopped; |
| 479 | +}; |
| 480 | + |
| 481 | + |
394 | 482 | #else |
395 | 483 |
|
396 | 484 |
|
@@ -495,6 +583,8 @@ void DirectoryWatcher::init() |
495 | 583 | _pStrategy = new WindowsDirectoryWatcherStrategy(*this); |
496 | 584 | #elif POCO_OS == POCO_OS_LINUX |
497 | 585 | _pStrategy = new LinuxDirectoryWatcherStrategy(*this); |
| 586 | +#elif POCO_OS == POCO_OS_MAC_OS_X || POCO_OS == POCO_OS_FREE_BSD |
| 587 | + _pStrategy = new BSDDirectoryWatcherStrategy(*this); |
498 | 588 | #else |
499 | 589 | _pStrategy = new DefaultDirectoryWatcherStrategy(*this); |
500 | 590 | #endif |
|
0 commit comments