2016-09-12 18:01:26 -04:00
/*
* RetroShare Directory watching system .
*
* file_sharing / directory_updater . cc
*
* Copyright 2016 Mr . Alice
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Library General Public License for more details .
*
* You should have received a copy of the GNU Library General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307
* USA .
*
* Please report all bugs and problems to " retroshare.project@gmail.com " .
*
*/
2016-07-23 22:14:43 -04:00
# include "util/folderiterator.h"
2016-08-06 13:04:54 -04:00
# include "rsserver/p3face.h"
2016-07-23 22:14:43 -04:00
2016-07-20 16:11:26 -04:00
# include "directory_storage.h"
# include "directory_updater.h"
2016-09-01 15:04:48 -04:00
# include "file_sharing_defaults.h"
2016-07-20 16:11:26 -04:00
2016-07-23 22:14:43 -04:00
# define DEBUG_LOCAL_DIR_UPDATER 1
2016-08-20 10:23:11 -04:00
//=============================================================================================================//
// Local Directory Updater //
//=============================================================================================================//
2016-07-28 04:49:49 -04:00
2016-07-27 18:48:28 -04:00
LocalDirectoryUpdater : : LocalDirectoryUpdater ( HashStorage * hc , LocalDirectoryStorage * lds )
: mHashCache ( hc ) , mSharedDirectories ( lds )
2016-07-21 00:16:12 -04:00
{
2016-07-28 04:49:49 -04:00
mLastSweepTime = 0 ;
2016-08-22 01:49:45 -04:00
mLastTSUpdateTime = 0 ;
2016-09-01 15:04:48 -04:00
mDelayBetweenDirectoryUpdates = DELAY_BETWEEN_DIRECTORY_UPDATES ;
2016-07-28 04:49:49 -04:00
}
void LocalDirectoryUpdater : : data_tick ( )
{
time_t now = time ( NULL ) ;
if ( now > DELAY_BETWEEN_DIRECTORY_UPDATES + mLastSweepTime )
{
sweepSharedDirectories ( ) ;
mLastSweepTime = now ;
}
2016-08-22 01:49:45 -04:00
if ( now > DELAY_BETWEEN_LOCAL_DIRECTORIES_TS_UPDATE + mLastTSUpdateTime )
{
mSharedDirectories - > updateTimeStamps ( ) ;
mLastTSUpdateTime = now ;
}
usleep ( 10 * 1000 * 1000 ) ;
2016-07-21 00:16:12 -04:00
}
2016-08-06 13:04:54 -04:00
void LocalDirectoryUpdater : : forceUpdate ( )
{
mLastSweepTime = 0 ;
}
2016-07-28 04:49:49 -04:00
void LocalDirectoryUpdater : : sweepSharedDirectories ( )
2016-07-20 16:11:26 -04:00
{
2016-08-06 13:04:54 -04:00
RsServer : : notify ( ) - > notifyListPreChange ( NOTIFY_LIST_DIRLIST_LOCAL , 0 ) ;
2016-07-28 04:49:49 -04:00
std : : cerr < < " LocalDirectoryUpdater::sweep() " < < std : : endl ;
2016-07-23 22:14:43 -04:00
2016-07-20 16:11:26 -04:00
// recursive update algorithm works that way:
// - the external loop starts on the shared directory list and goes through sub-directories
2016-07-21 00:16:12 -04:00
// - at the same time, it updates the local list of shared directories. A single sweep is performed over the whole directory structure.
2016-07-20 16:11:26 -04:00
// - the information that is costly to compute (the hash) is store externally into a separate structure.
// - doing so, changing directory names or moving files between directories does not cause a re-hash of the content.
//
2016-07-21 00:16:12 -04:00
std : : list < SharedDirInfo > shared_directory_list ;
2016-07-27 18:48:28 -04:00
mSharedDirectories - > getSharedDirectoryList ( shared_directory_list ) ;
2016-07-24 23:48:22 -04:00
2016-08-28 12:42:52 -04:00
std : : map < std : : string , time_t > sub_dir_list ;
2016-07-21 00:16:12 -04:00
2016-07-23 22:14:43 -04:00
for ( std : : list < SharedDirInfo > : : const_iterator real_dir_it ( shared_directory_list . begin ( ) ) ; real_dir_it ! = shared_directory_list . end ( ) ; + + real_dir_it )
2016-08-28 12:42:52 -04:00
sub_dir_list [ ( * real_dir_it ) . filename ] = 0 ;
2016-07-21 00:16:12 -04:00
// make sure that entries in stored_dir_it are the same than paths in real_dir_it, and in the same order.
2016-07-27 15:22:59 -04:00
mSharedDirectories - > updateSubDirectoryList ( mSharedDirectories - > root ( ) , sub_dir_list ) ;
2016-07-21 00:16:12 -04:00
// now for each of them, go recursively and match both files and dirs
2016-08-17 08:48:54 -04:00
for ( DirectoryStorage : : DirIterator stored_dir_it ( mSharedDirectories , mSharedDirectories - > root ( ) ) ; stored_dir_it ; + + stored_dir_it )
2016-07-27 18:48:28 -04:00
{
2016-08-17 08:48:54 -04:00
std : : cerr < < " recursing into " < < stored_dir_it . name ( ) < < std : : endl ;
recursUpdateSharedDir ( stored_dir_it . name ( ) , * stored_dir_it ) ; // here we need to use the list that was stored, instead of the shared dir list, because the two
// are not necessarily in the same order.
2016-07-27 18:48:28 -04:00
}
2016-08-06 13:04:54 -04:00
RsServer : : notify ( ) - > notifyListChange ( NOTIFY_LIST_DIRLIST_LOCAL , 0 ) ;
2016-07-21 00:16:12 -04:00
}
2016-07-23 22:14:43 -04:00
void LocalDirectoryUpdater : : recursUpdateSharedDir ( const std : : string & cumulated_path , DirectoryStorage : : EntryIndex indx )
2016-07-21 00:16:12 -04:00
{
2016-07-23 22:14:43 -04:00
std : : cerr < < " parsing directory " < < cumulated_path < < " , index= " < < indx < < std : : endl ;
2016-07-21 00:16:12 -04:00
2016-07-23 22:14:43 -04:00
// make sure list of subdirs is the same
2016-07-21 00:16:12 -04:00
// make sure list of subfiles is the same
// request all hashes to the hashcache
librs : : util : : FolderIterator dirIt ( cumulated_path ) ;
// collect subdirs and subfiles
2016-07-28 03:29:15 -04:00
std : : map < std : : string , DirectoryStorage : : FileTS > subfiles ;
2016-08-28 12:42:52 -04:00
std : : map < std : : string , time_t > subdirs ;
2016-07-21 00:16:12 -04:00
2016-07-27 15:22:59 -04:00
for ( ; dirIt . isValid ( ) ; dirIt . next ( ) )
2016-07-21 00:16:12 -04:00
{
2016-07-23 22:14:43 -04:00
switch ( dirIt . file_type ( ) )
2016-07-21 00:16:12 -04:00
{
2016-07-28 03:29:15 -04:00
case librs : : util : : FolderIterator : : TYPE_FILE : subfiles [ dirIt . file_name ( ) ] . modtime = dirIt . file_modtime ( ) ;
2016-08-22 01:49:45 -04:00
subfiles [ dirIt . file_name ( ) ] . size = dirIt . file_size ( ) ;
std : : cerr < < " adding sub-file \" " < < dirIt . file_name ( ) < < " \" " < < std : : endl ;
2016-07-28 03:29:15 -04:00
break ;
2016-07-23 22:14:43 -04:00
2016-08-28 12:42:52 -04:00
case librs : : util : : FolderIterator : : TYPE_DIR : subdirs [ dirIt . file_name ( ) ] = dirIt . file_modtime ( ) ;
2016-08-22 01:49:45 -04:00
std : : cerr < < " adding sub-dir \" " < < dirIt . file_name ( ) < < " \" " < < std : : endl ;
break ;
2016-07-21 00:16:12 -04:00
default :
2016-07-23 22:14:43 -04:00
std : : cerr < < " (EE) Dir entry of unknown type with path \" " < < cumulated_path < < " / " < < dirIt . file_name ( ) < < " \" " < < std : : endl ;
2016-07-21 00:16:12 -04:00
}
}
2016-09-15 15:45:00 -04:00
// update folder modificatoin time, which is the only way to detect e.g. removed or renamed files.
mSharedDirectories - > setDirectoryLocalModTime ( indx , dirIt . dir_modtime ( ) ) ;
2016-07-21 00:16:12 -04:00
// update file and dir lists for current directory.
mSharedDirectories - > updateSubDirectoryList ( indx , subdirs ) ;
2016-07-24 23:48:22 -04:00
2016-07-28 03:29:15 -04:00
std : : map < std : : string , DirectoryStorage : : FileTS > new_files ;
2016-07-24 23:48:22 -04:00
mSharedDirectories - > updateSubFilesList ( indx , subfiles , new_files ) ;
2016-07-21 00:16:12 -04:00
// now go through list of subfiles and request the hash to hashcache
2016-07-27 15:22:59 -04:00
for ( DirectoryStorage : : FileIterator dit ( mSharedDirectories , indx ) ; dit ; + + dit )
2016-07-21 00:16:12 -04:00
{
2016-07-23 22:14:43 -04:00
// ask about the hash. If not present, ask HashCache. If not present, or different, the callback will update it.
2016-07-21 00:16:12 -04:00
2016-07-27 15:22:59 -04:00
RsFileHash hash ;
2016-07-27 18:48:28 -04:00
if ( mHashCache - > requestHash ( cumulated_path + " / " + dit . name ( ) , dit . size ( ) , dit . modtime ( ) , hash , this , * dit ) & & dit . hash ( ) ! = hash )
2016-07-27 15:22:59 -04:00
mSharedDirectories - > updateHash ( * dit , hash ) ;
2016-07-21 00:16:12 -04:00
}
// go through the list of sub-dirs and recursively update
2016-07-27 15:22:59 -04:00
DirectoryStorage : : DirIterator stored_dir_it ( mSharedDirectories , indx ) ;
2016-07-21 00:16:12 -04:00
2016-08-28 12:42:52 -04:00
for ( std : : map < std : : string , time_t > : : const_iterator real_dir_it ( subdirs . begin ( ) ) ; real_dir_it ! = subdirs . end ( ) ; + + real_dir_it , + + stored_dir_it )
2016-08-17 08:48:54 -04:00
{
std : : cerr < < " recursing into " < < stored_dir_it . name ( ) < < std : : endl ;
recursUpdateSharedDir ( cumulated_path + " / " + stored_dir_it . name ( ) , * stored_dir_it ) ;
}
2016-07-20 16:11:26 -04:00
}
2016-07-21 00:16:12 -04:00
2016-09-14 14:41:22 -04:00
bool LocalDirectoryUpdater : : inDirectoryCheck ( ) const
{
return mHashCache - > isRunning ( ) ;
}
2016-07-27 15:22:59 -04:00
void LocalDirectoryUpdater : : hash_callback ( uint32_t client_param , const std : : string & name , const RsFileHash & hash , uint64_t size )
{
if ( ! mSharedDirectories - > updateHash ( DirectoryStorage : : EntryIndex ( client_param ) , hash ) )
std : : cerr < < " (EE) Cannot update file. Something's wrong. " < < std : : endl ;
}
2016-08-22 01:49:45 -04:00