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