xref: /glogg/src/watchtowerlist.cpp (revision c540156c41190af6e419dffb1b2c43c87fdd3cde)
1 #include "watchtowerlist.h"
2 
3 #include "log.h"
4 
5 namespace {
6     std::string directory_path( const std::string& path );
7 };
8 
9 // ObservedFileList class
10 ObservedFile* ObservedFileList::searchByName( const std::string& file_name )
11 {
12     // Look for an existing observer on this file
13     auto existing_observer = observed_files_.begin();
14     for ( ; existing_observer != observed_files_.end(); ++existing_observer )
15     {
16         if ( existing_observer->file_name_ == file_name )
17         {
18             LOG(logDEBUG) << "Found " << file_name;
19             break;
20         }
21     }
22 
23     if ( existing_observer != observed_files_.end() )
24         return &( *existing_observer );
25     else
26         return nullptr;
27 }
28 
29 ObservedFile* ObservedFileList::searchByFileOrSymlinkWd( int wd )
30 {
31     auto result = find_if( observed_files_.begin(), observed_files_.end(),
32             [wd] (ObservedFile file) -> bool {
33                 return ( wd == file.file_wd_ ) || ( wd == file.symlink_wd_ ); } );
34 
35     if ( result != observed_files_.end() )
36         return &( *result );
37     else
38         return nullptr;
39 }
40 
41 ObservedFile* ObservedFileList::searchByDirWdAndName( int wd, const char* name )
42 {
43     auto dir = find_if( observed_dirs_.begin(), observed_dirs_.end(),
44             [wd] (std::pair<std::string,std::weak_ptr<ObservedDir>> d) -> bool {
45             if ( auto dir = d.second.lock() ) {
46                 return ( wd == dir->dir_wd_ );
47             }
48             else {
49                 return false; } } );
50 
51     if ( dir != observed_dirs_.end() ) {
52         std::string path = dir->first + "/" + name;
53 
54         // LOG(logDEBUG) << "Testing path: " << path;
55 
56         // Looking for the path in the files we are watching
57         return searchByName( path );
58     }
59     else {
60         return nullptr;
61     }
62 }
63 
64 ObservedFile* ObservedFileList::addNewObservedFile( ObservedFile new_observed )
65 {
66     auto new_file = observed_files_.insert( std::begin( observed_files_ ), new_observed );
67 
68     return &( *new_file );
69 }
70 
71 std::shared_ptr<ObservedFile> ObservedFileList::removeCallback(
72             std::shared_ptr<void> callback )
73 {
74     std::shared_ptr<ObservedFile> returned_file = nullptr;
75 
76     for ( auto observer = begin( observed_files_ );
77             observer != end( observed_files_ ); )
78     {
79         LOG(logDEBUG) << "Examining entry for " << observer->file_name_;
80 
81         std::vector<std::shared_ptr<void>>& callbacks = observer->callbacks;
82         callbacks.erase( std::remove(
83                     std::begin( callbacks ), std::end( callbacks ), callback ),
84                 std::end( callbacks ) );
85 
86         /* See if all notifications have been deleted for this file */
87         if ( callbacks.empty() ) {
88             LOG(logDEBUG) << "Empty notification list, removing the watched file";
89             returned_file = std::make_shared<ObservedFile>( *observer );
90             observer = observed_files_.erase( observer );
91         }
92         else {
93             ++observer;
94         }
95     }
96 
97     return returned_file;
98 }
99 
100 std::shared_ptr<ObservedDir> ObservedFileList::watchedDirectory(
101         const std::string& dir_name )
102 {
103     std::shared_ptr<ObservedDir> dir = nullptr;
104 
105     if ( observed_dirs_.find( dir_name ) != std::end( observed_dirs_ ) )
106         dir = observed_dirs_[ dir_name ].lock();
107 
108     return dir;
109 }
110 
111 std::shared_ptr<ObservedDir> ObservedFileList::addWatchedDirectory(
112         const std::string& dir_name )
113 {
114     auto dir = std::make_shared<ObservedDir>( dir_name );
115 
116     observed_dirs_[ dir_name ] = std::weak_ptr<ObservedDir>( dir );
117 
118     return dir;
119 }
120 
121 std::shared_ptr<ObservedDir> ObservedFileList::watchedDirectoryForFile(
122         const std::string& file_name )
123 {
124     return watchedDirectory( directory_path( file_name ) );
125 }
126 
127 std::shared_ptr<ObservedDir> ObservedFileList::addWatchedDirectoryForFile(
128         const std::string& file_name )
129 {
130     return addWatchedDirectory( directory_path( file_name ) );
131 }
132 
133 namespace {
134     std::string directory_path( const std::string& path )
135     {
136         size_t slash_pos = path.rfind( '/' );
137 
138 #ifdef _WIN32
139         if ( slash_pos == std::string::npos ) {
140             slash_pos = path.rfind( '\\' );
141         }
142 
143         // We need to include the final slash on Windows
144         ++slash_pos;
145         LOG(logDEBUG) << "Pos = " << slash_pos;
146 #endif
147 
148         return std::string( path, 0, slash_pos );
149     }
150 };
151