| 292 | |
| 293 | |
| 294 | void CSharedDirWatcher::OnFileSystemEvent(wxFileSystemWatcherEvent & event) |
| 295 | { |
| 296 | const int changeType = event.GetChangeType(); |
| 297 | const wxFileName & path = event.GetPath(); |
| 298 | |
| 299 | AddDebugLogLineN(logKnownFiles, |
| 300 | CFormat("Shared-dir watcher: event 0x%x on '%s'") |
| 301 | % changeType % path.GetFullPath()); |
| 302 | |
| 303 | // Watcher-backend overflow / drop signal. inotify reports |
| 304 | // IN_Q_OVERFLOW when its per-instance queue exhausts (typical |
| 305 | // cause: a multi-million-file `cp -r` into a watched tree), |
| 306 | // kqueue can drop on rapid rename storms, and Windows |
| 307 | // ReadDirectoryChangesW reports buffer exhaust the same way. In |
| 308 | // all three cases the watcher's incremental view of the tree is |
| 309 | // now stale, so we have to fall back to a full bulk Reload(). |
| 310 | // This is the only path that re-walks every shared dir on a |
| 311 | // huge shareset (#745); rare in normal operation. |
| 312 | if (changeType & (wxFSW_EVENT_WARNING | wxFSW_EVENT_ERROR)) { |
| 313 | AddLogLineC(CFormat( |
| 314 | _("Shared-dir watcher: backend overflow/error (%s); " |
| 315 | "falling back to full reload")) |
| 316 | % (event.GetErrorDescription().IsEmpty() |
| 317 | ? wxString("unspecified") |
| 318 | : event.GetErrorDescription())); |
| 319 | m_fallbackPending = true; |
| 320 | ScheduleProcessing(); |
| 321 | return; |
| 322 | } |
| 323 | |
| 324 | // Auto-share new subdirectories of any watched path. A user who has |
| 325 | // already shared /Music gets new subdirs of /Music auto-included |
| 326 | // without having to revisit the prefs dialog. Existing subdirs that |
| 327 | // were originally excluded (non-recursive share) are not |
| 328 | // retroactively scanned — only newly-created ones get added. |
| 329 | if ((changeType & wxFSW_EVENT_CREATE) && path.IsOk() && path.DirExists()) { |
| 330 | RegisterNewSubdirectory(path.GetFullPath()); |
| 331 | } |
| 332 | |
| 333 | // Per-path event accumulation. Coalesces a CREATE → MODIFY × N → |
| 334 | // CLOSE_WRITE burst on a single file into one dispatch entry. |
| 335 | const wxString rawPath = path.GetFullPath(); |
| 336 | if (rawPath.IsEmpty()) { |
| 337 | return; |
| 338 | } |
| 339 | |
| 340 | const int interesting = changeType & (wxFSW_EVENT_CREATE | wxFSW_EVENT_DELETE | |
| 341 | wxFSW_EVENT_RENAME | wxFSW_EVENT_MODIFY); |
| 342 | if (!interesting) { |
| 343 | return; |
| 344 | } |
| 345 | |
| 346 | PendingPathEvents & slot = m_pendingEvents[rawPath]; |
| 347 | slot.flags |= interesting; |
| 348 | if (changeType & wxFSW_EVENT_RENAME) { |
| 349 | slot.renamedTo = event.GetNewPath().GetFullPath(); |
| 350 | } |
| 351 | |