mirror of
https://github.com/uroni/urbackup_backend.git
synced 2025-10-26 11:36:50 +00:00
410 lines
9.4 KiB
C++
410 lines
9.4 KiB
C++
#include "ContinuousWatchEnqueue.h"
|
|
#include "../../Interface/Server.h"
|
|
#include <algorithm>
|
|
#include "../../stringtools.h"
|
|
#include "../ClientService.h"
|
|
#include <memory>
|
|
#include "../../Interface/SettingsReader.h"
|
|
#include "../../urbackupserver/database.h"
|
|
|
|
|
|
ContinuousWatchEnqueue::ContinuousWatchEnqueue()
|
|
: update_patterns(true)
|
|
{
|
|
|
|
}
|
|
|
|
void ContinuousWatchEnqueue::On_FileNameChanged( const std::string & strOldFileName, const std::string & strNewFileName, bool closed )
|
|
{
|
|
if(!closed)
|
|
return;
|
|
|
|
std::vector<std::pair<std::string, std::string> > dirs =
|
|
getWatchDirs(strOldFileName, strNewFileName);
|
|
|
|
for(size_t i=0;i<dirs.size();++i)
|
|
{
|
|
if(!dirs[i].first.empty()
|
|
&& !dirs[i].second.empty()
|
|
&& pathIncluded(strOldFileName, dirs[i].first)
|
|
&& pathIncluded(strNewFileName, dirs[i].second) )
|
|
{
|
|
On_FileNameChangedInt(dirs[i].first, dirs[i].second);
|
|
}
|
|
else if(!dirs[i].first.empty()
|
|
&& pathIncluded(strOldFileName, dirs[i].first) )
|
|
{
|
|
On_FileRemovedInt(dirs[i].first);
|
|
}
|
|
else if(!dirs[i].second.empty()
|
|
&& pathIncluded(strNewFileName, dirs[i].second) )
|
|
{
|
|
On_FileAddedInt(dirs[i].second);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void ContinuousWatchEnqueue::On_DirNameChanged( const std::string & strOldFileName, const std::string & strNewFileName, bool closed )
|
|
{
|
|
if(!closed)
|
|
return;
|
|
|
|
std::vector<std::pair<std::string, std::string> > dirs =
|
|
getWatchDirs(strOldFileName, strNewFileName);
|
|
|
|
for(size_t i=0;i<dirs.size();++i)
|
|
{
|
|
if(!dirs[i].first.empty()
|
|
&& !dirs[i].second.empty()
|
|
&& pathIncluded(strOldFileName, dirs[i].first)
|
|
&& pathIncluded(strNewFileName, dirs[i].second) )
|
|
{
|
|
On_DirNameChangedInt(dirs[i].first, dirs[i].second);
|
|
}
|
|
else if(!dirs[i].first.empty()
|
|
&& pathIncluded(strOldFileName, dirs[i].first) )
|
|
{
|
|
On_DirRemovedInt(dirs[i].first);
|
|
}
|
|
else if(!dirs[i].second.empty()
|
|
&& pathIncluded(strNewFileName, dirs[i].second) )
|
|
{
|
|
On_DirAddedInt(dirs[i].second);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void ContinuousWatchEnqueue::On_FileRemoved( const std::string & strFileName, bool closed )
|
|
{
|
|
if(!closed)
|
|
return;
|
|
|
|
std::vector<std::string> dirs =
|
|
getWatchDirs(strFileName);
|
|
|
|
for(size_t i=0;i<dirs.size();++i)
|
|
{
|
|
if(pathIncluded(strFileName, dirs[i]))
|
|
{
|
|
On_FileRemovedInt(dirs[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ContinuousWatchEnqueue::On_FileAdded( const std::string & strFileName, bool closed )
|
|
{
|
|
if(!closed)
|
|
return;
|
|
|
|
std::vector<std::string> dirs =
|
|
getWatchDirs(strFileName);
|
|
|
|
for(size_t i=0;i<dirs.size();++i)
|
|
{
|
|
if(pathIncluded(strFileName, dirs[i]))
|
|
{
|
|
On_FileAddedInt(dirs[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void ContinuousWatchEnqueue::On_DirAdded( const std::string & strFileName, bool closed )
|
|
{
|
|
if(!closed)
|
|
return;
|
|
|
|
std::vector<std::string> dirs =
|
|
getWatchDirs(strFileName);
|
|
|
|
for(size_t i=0;i<dirs.size();++i)
|
|
{
|
|
if(pathIncluded(strFileName, dirs[i]))
|
|
{
|
|
On_DirAddedInt(dirs[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void ContinuousWatchEnqueue::On_FileModified( const std::string & strFileName, bool closed )
|
|
{
|
|
if(!closed)
|
|
return;
|
|
|
|
std::vector<std::string> dirs =
|
|
getWatchDirs(strFileName);
|
|
|
|
for(size_t i=0;i<dirs.size();++i)
|
|
{
|
|
if(pathIncluded(strFileName, dirs[i]))
|
|
{
|
|
On_FileModifiedInt(dirs[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ContinuousWatchEnqueue::On_ResetAll( const std::string & vol )
|
|
{
|
|
On_ResetAllInt(vol);
|
|
}
|
|
|
|
void ContinuousWatchEnqueue::On_DirRemoved( const std::string & strDirName, bool closed )
|
|
{
|
|
if(!closed)
|
|
return;
|
|
|
|
std::vector<std::string> dirs =
|
|
getWatchDirs(strDirName);
|
|
|
|
for(size_t i=0;i<dirs.size();++i)
|
|
{
|
|
if(pathIncluded(strDirName, dirs[i]))
|
|
{
|
|
On_DirRemovedInt(dirs[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ContinuousWatchEnqueue::Commit(const std::vector<IChangeJournalListener::SSequence>& sequences)
|
|
{
|
|
if(queue.getDataSize()==0)
|
|
return;
|
|
|
|
std::string data(queue.getDataPtr(), queue.getDataPtr()+queue.getDataSize());
|
|
|
|
CWData header;
|
|
header.addChar(CHANGE_HEADER);
|
|
header.addUInt(static_cast<unsigned int>(sequences.size()));
|
|
for(size_t i=0;i<sequences.size();++i)
|
|
{
|
|
header.addInt64(sequences[i].id);
|
|
|
|
std::map<int64, int64>::iterator seq_start_it = sequences_start.find(sequences[i].id);
|
|
if(seq_start_it!=sequences_start.end())
|
|
{
|
|
header.addInt64(seq_start_it->second);
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
|
|
header.addInt64(sequences[i].stop);
|
|
|
|
sequences_start[sequences[i].id]=sequences[i].stop;
|
|
}
|
|
|
|
data.insert(data.begin(), header.getDataPtr(), header.getDataPtr()+header.getDataSize());
|
|
|
|
if(ClientConnector::tochannelSendChanges(data.data(), data.size()))
|
|
{
|
|
queue.clear();
|
|
}
|
|
}
|
|
|
|
void ContinuousWatchEnqueue::addWatchdir( SWatchItem item )
|
|
{
|
|
item.dir = strlower(item.dir);
|
|
std::vector<SWatchItem>::iterator iter=std::find(watchdirs.begin(),
|
|
watchdirs.end(), item);
|
|
|
|
if(iter==watchdirs.end())
|
|
{
|
|
watchdirs.push_back(item);
|
|
|
|
On_ResetAllInt(item.dir);
|
|
}
|
|
}
|
|
|
|
void ContinuousWatchEnqueue::removeWatchdir( SWatchItem item )
|
|
{
|
|
item.dir = strlower(item.dir);
|
|
std::vector<SWatchItem>::iterator iter=std::find(watchdirs.begin(),
|
|
watchdirs.end(), item);
|
|
|
|
if(iter!=watchdirs.end())
|
|
{
|
|
watchdirs.erase(iter);
|
|
On_ResetAllInt(item.dir);
|
|
}
|
|
}
|
|
|
|
std::vector<std::string> ContinuousWatchEnqueue::getWatchDirs( const std::string& fn )
|
|
{
|
|
std::string fn_lower = strlower(fn);
|
|
|
|
std::vector<std::string> dirs;
|
|
|
|
for(size_t i=0;i<watchdirs.size();++i)
|
|
{
|
|
if(next(fn_lower, 0, watchdirs[i].dir))
|
|
{
|
|
std::string fn_sub = fn.substr(watchdirs[i].dir.size());
|
|
dirs.push_back(watchdirs[i].name+fn_sub);
|
|
}
|
|
}
|
|
|
|
return dirs;
|
|
}
|
|
|
|
|
|
std::vector<std::pair<std::string, std::string> > ContinuousWatchEnqueue::getWatchDirs( const std::string& fn1, const std::string& fn2 )
|
|
{
|
|
std::string fn1_lower = strlower(fn1);
|
|
std::string fn2_lower = strlower(fn1);
|
|
|
|
std::vector<std::pair<std::string, std::string> > dirs;
|
|
|
|
for(size_t i=0;i<watchdirs.size();++i)
|
|
{
|
|
bool fn1_ins = next(fn1_lower, 0, watchdirs[i].dir);
|
|
bool fn2_ins = next(fn2_lower, 0, watchdirs[i].dir);
|
|
|
|
std::string fn1_sub;
|
|
if(fn1_ins)
|
|
{
|
|
fn1_sub = watchdirs[i].name+fn1.substr(watchdirs[i].dir.size());
|
|
}
|
|
std::string fn2_sub;
|
|
if(fn2_ins)
|
|
{
|
|
fn2_sub = watchdirs[i].name+fn2.substr(watchdirs[i].dir.size());
|
|
}
|
|
|
|
dirs.push_back(std::make_pair(fn1_sub, fn2_sub));
|
|
}
|
|
|
|
return dirs;
|
|
}
|
|
|
|
|
|
void ContinuousWatchEnqueue::On_FileNameChangedInt( const std::string & strOldFileName, const std::string & strNewFileName )
|
|
{
|
|
queue.addChar(CHANGE_REN_FILE);
|
|
queue.addString((strOldFileName));
|
|
queue.addString((strNewFileName));
|
|
}
|
|
|
|
void ContinuousWatchEnqueue::On_DirNameChangedInt( const std::string & strOldFileName, const std::string & strNewFileName )
|
|
{
|
|
queue.addChar(CHANGE_REN_DIR);
|
|
queue.addString((strOldFileName));
|
|
queue.addString((strNewFileName));
|
|
}
|
|
|
|
void ContinuousWatchEnqueue::On_FileRemovedInt( const std::string & strFileName )
|
|
{
|
|
queue.addChar(CHANGE_DEL_FILE);
|
|
queue.addString((strFileName));
|
|
}
|
|
|
|
void ContinuousWatchEnqueue::On_FileAddedInt( const std::string & strFileName )
|
|
{
|
|
queue.addChar(CHANGE_ADD_FILE);
|
|
queue.addString((strFileName));
|
|
}
|
|
|
|
void ContinuousWatchEnqueue::On_DirAddedInt( const std::string & strFileName )
|
|
{
|
|
queue.addChar(CHANGE_ADD_DIR);
|
|
queue.addString((strFileName));
|
|
}
|
|
|
|
void ContinuousWatchEnqueue::On_FileModifiedInt( const std::string & strFileName )
|
|
{
|
|
queue.addChar(CHANGE_MOD);
|
|
queue.addString((strFileName));
|
|
}
|
|
|
|
void ContinuousWatchEnqueue::On_ResetAllInt( const std::string & vol )
|
|
{
|
|
queue.addChar(CHANGE_MOD_ALL);
|
|
queue.addString((vol));
|
|
}
|
|
|
|
void ContinuousWatchEnqueue::On_DirRemovedInt( const std::string & strDirName )
|
|
{
|
|
readIncludeExcludePatterns();
|
|
|
|
queue.addChar(CHANGE_DEL_DIR);
|
|
queue.addString((strDirName));
|
|
}
|
|
|
|
void ContinuousWatchEnqueue::readIncludeExcludePatterns()
|
|
{
|
|
if(!update_patterns)
|
|
return;
|
|
|
|
update_patterns=false;
|
|
|
|
std::unique_ptr<ISettingsReader> curr_settings(Server->createFileSettingsReader("urbackup/data/settings.cfg"));
|
|
|
|
if(curr_settings.get())
|
|
{
|
|
std::string val;
|
|
if(curr_settings->getValue("continuous_exclude_files", &val)
|
|
|| curr_settings->getValue("continuous_exclude_files_def", &val) )
|
|
{
|
|
exclude_dirs = IndexThread::buildExcludeList(val);
|
|
}
|
|
else
|
|
{
|
|
exclude_dirs = IndexThread::buildExcludeList(std::string());
|
|
}
|
|
|
|
if(curr_settings->getValue("continuous_include_files", &val)
|
|
|| curr_settings->getValue("continuous_include_files_def", &val) )
|
|
{
|
|
include_dirs = IndexThread::parseIncludePatterns(val);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
IndexThread::buildExcludeList(std::string());
|
|
}
|
|
}
|
|
|
|
bool ContinuousWatchEnqueue::pathIncluded( const std::string& path, const std::string& named_path )
|
|
{
|
|
if( IndexThread::isExcluded(exclude_dirs, path)
|
|
|| IndexThread::isExcluded(exclude_dirs, named_path) )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if( !IndexThread::isIncluded(include_dirs, path, NULL)
|
|
&& !IndexThread::isIncluded(include_dirs, named_path, NULL) )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void ContinuousWatchEnqueue::setupDatabaseAccess()
|
|
{
|
|
if(journal_dao.get()==NULL)
|
|
{
|
|
journal_dao.reset(new JournalDAO(Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER)));
|
|
}
|
|
}
|
|
|
|
int64 ContinuousWatchEnqueue::getStartUsn( int64 sequence_id )
|
|
{
|
|
return sequences_start[sequence_id];
|
|
}
|
|
|
|
void ContinuousWatchEnqueue::setStartUsn( int64 sequence_id, int64 seq_start )
|
|
{
|
|
sequences_start[sequence_id]=seq_start;
|
|
}
|
|
|
|
void ContinuousWatchEnqueue::On_FileOpen( const std::string & strFileName )
|
|
{
|
|
|
|
}
|
|
|