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