@@ -609,27 +609,61 @@ class TLogManager::TImpl
609
609
return EmplaceOrCrash (KeyToCachedWriter_, cacheKey, writers)->second ;
610
610
}
611
611
612
- std::unique_ptr<TInotifyWatch> CreateNotificationWatch (
612
+ TInotifyHandle* TryGetNotificationHandle ()
613
+ {
614
+ if (!NotificationHandle_ && !NotificationHandleCreationFailed_) {
615
+ try {
616
+ NotificationHandle_ = std::make_unique<TInotifyHandle>();
617
+ } catch (const std::exception& ex) {
618
+ YT_LOG_ERROR (ex, " Error creating inotify handle, watching disabled" );
619
+ NotificationHandleCreationFailed_ = true ;
620
+ }
621
+ }
622
+ return NotificationHandle_.get ();
623
+ }
624
+
625
+ std::unique_ptr<TInotifyWatch> TryCreateNotificationWatch (
613
626
const TLogManagerConfigPtr& config,
614
627
const IFileLogWriterPtr& writer)
615
628
{
616
629
#ifdef _linux_
617
630
if (config->WatchPeriod ) {
618
- if (!NotificationHandle_) {
619
- NotificationHandle_ = std::make_unique<TInotifyHandle>();
631
+ auto * notifcationHandle = TryGetNotificationHandle ();
632
+ if (!notifcationHandle) {
633
+ return nullptr ;
634
+ }
635
+
636
+ try {
637
+ return std::make_unique<TInotifyWatch>(
638
+ notifcationHandle,
639
+ writer->GetFileName (),
640
+ EInotifyWatchEvents::DeleteSelf | EInotifyWatchEvents::MoveSelf);
641
+ } catch (const std::exception& ex) {
642
+ // Watch can fail to initialize if the writer is disabled
643
+ // e.g. due to the lack of space.
644
+ YT_LOG_ERROR (ex, " Error creating inotify watch (Path: %v)" ,
645
+ writer->GetFileName ());
646
+ return nullptr ;
620
647
}
621
- return std::make_unique<TInotifyWatch>(
622
- NotificationHandle_.get (),
623
- writer->GetFileName (),
624
- EInotifyWatchEvents::DeleteSelf | EInotifyWatchEvents::MoveSelf,
625
- BIND (&ILogWriter::Reload, writer));
626
648
}
627
649
#else
628
650
Y_UNUSED (config, writer);
629
651
#endif
630
652
return nullptr ;
631
653
}
632
654
655
+ void CreateNotificationWatchForWriter (
656
+ const TLogManagerConfigPtr& config,
657
+ const IFileLogWriterPtr& writer)
658
+ {
659
+ if (auto watch = TryCreateNotificationWatch (config, writer)) {
660
+ EmplaceOrCrash (NotificationWatchWDToWriter_, watch->GetWD (), writer);
661
+ EmplaceOrCrash (WriterToNotificationWatch_, writer, std::move (watch));
662
+ } else {
663
+ InsertOrCrash (WritersWithFailedNotificationWatches_, writer);
664
+ }
665
+ }
666
+
633
667
void UpdateConfig (const TConfigEvent& event)
634
668
{
635
669
YT_ASSERT_THREAD_AFFINITY (LoggingThread);
@@ -709,9 +743,10 @@ class TLogManager::TImpl
709
743
710
744
NameToWriter_.clear ();
711
745
KeyToCachedWriter_.clear ();
712
- WDToNotificationWatch_.clear ();
713
- NotificationWatches_.clear ();
714
- InvalidNotificationWatches_.clear ();
746
+
747
+ WriterToNotificationWatch_.clear ();
748
+ NotificationWatchWDToWriter_.clear ();
749
+ WritersWithFailedNotificationWatches_.clear ();
715
750
716
751
for (const auto & [name, writerConfig] : config->Writers ) {
717
752
auto typedWriterConfig = ConvertTo<TLogWriterConfigPtr>(writerConfig);
@@ -729,11 +764,7 @@ class TLogManager::TImpl
729
764
EmplaceOrCrash (NameToWriter_, name, writer);
730
765
731
766
if (auto fileWriter = DynamicPointerCast<IFileLogWriter>(writer)) {
732
- auto watch = CreateNotificationWatch (config, fileWriter);
733
- if (watch) {
734
- RegisterNotificatonWatch (watch.get ());
735
- NotificationWatches_.push_back (std::move (watch));
736
- }
767
+ CreateNotificationWatchForWriter (config, fileWriter);
737
768
}
738
769
}
739
770
@@ -827,56 +858,31 @@ class TLogManager::TImpl
827
858
}
828
859
}
829
860
830
- void RegisterNotificatonWatch (TInotifyWatch* watch)
831
- {
832
- YT_ASSERT_THREAD_AFFINITY (LoggingThread);
833
-
834
- if (watch->IsValid ()) {
835
- // Watch can fail to initialize if the writer is disabled
836
- // e.g. due to the lack of space.
837
- EmplaceOrCrash (WDToNotificationWatch_, watch->GetWD (), watch);
838
- } else {
839
- InvalidNotificationWatches_.push_back (watch);
840
- }
841
- }
842
-
843
861
void WatchWriters ()
844
862
{
845
863
YT_ASSERT_THREAD_AFFINITY (LoggingThread);
846
864
847
- if (!NotificationHandle_) {
865
+ auto * notificationHandle = TryGetNotificationHandle ();
866
+ if (!notificationHandle) {
848
867
return ;
849
868
}
850
869
851
- int previousWD = -1 ;
852
- while (auto pollResult = NotificationHandle_->Poll ()) {
853
- if (pollResult->WD == previousWD) {
854
- continue ;
855
- }
856
- auto it = WDToNotificationWatch_.find (pollResult->WD );
857
- auto jt = WDToNotificationWatch_.end ();
858
- if (it == jt) {
859
- continue ;
860
- }
870
+ auto config = Config_.Acquire ();
861
871
862
- auto * watch = it-> second ;
863
- watch-> Run ( );
872
+ // Always reload writers and retry registration for invalid watches.
873
+ auto writersToReconsider = std::exchange (WritersWithFailedNotificationWatches_, {} );
864
874
865
- if (watch->GetWD () != pollResult->WD ) {
866
- WDToNotificationWatch_.erase (it);
867
- RegisterNotificatonWatch (watch);
875
+ while (auto pollResult = notificationHandle->Poll ()) {
876
+ if (auto writer = GetOrDefault (NotificationWatchWDToWriter_, pollResult->WD )) {
877
+ EraseOrCrash (NotificationWatchWDToWriter_, pollResult->WD );
878
+ EraseOrCrash (WriterToNotificationWatch_, writer);
879
+ InsertOrCrash (writersToReconsider, writer);
868
880
}
869
-
870
- previousWD = pollResult->WD ;
871
881
}
872
- // Handle invalid watches, try to register they again.
873
- {
874
- std::vector<TInotifyWatch*> invalidNotificationWatches;
875
- invalidNotificationWatches.swap (InvalidNotificationWatches_);
876
- for (auto * watch : invalidNotificationWatches) {
877
- watch->Run ();
878
- RegisterNotificatonWatch (watch);
879
- }
882
+
883
+ for (const auto & writer : writersToReconsider) {
884
+ writer->Reload ();
885
+ CreateNotificationWatchForWriter (config, writer);
880
886
}
881
887
}
882
888
@@ -1358,9 +1364,11 @@ class TLogManager::TImpl
1358
1364
const IThreadPoolPtr CompressionThreadPool_;
1359
1365
1360
1366
std::unique_ptr<TInotifyHandle> NotificationHandle_;
1361
- std::vector<std::unique_ptr<TInotifyWatch>> NotificationWatches_;
1362
- THashMap<int , TInotifyWatch*> WDToNotificationWatch_;
1363
- std::vector<TInotifyWatch*> InvalidNotificationWatches_;
1367
+ bool NotificationHandleCreationFailed_ = false ;
1368
+
1369
+ THashMap<IFileLogWriterPtr, std::unique_ptr<TInotifyWatch>> WriterToNotificationWatch_;
1370
+ THashMap<int , IFileLogWriterPtr> NotificationWatchWDToWriter_;
1371
+ THashSet<IFileLogWriterPtr> WritersWithFailedNotificationWatches_;
1364
1372
1365
1373
THashMap<TString, TLoggingAnchor*> AnchorMap_;
1366
1374
std::atomic<TLoggingAnchor*> FirstAnchor_ = nullptr ;
0 commit comments