2016-07-30 15:52:42 -04:00
# include "serialiser/rsserviceids.h"
2016-07-20 15:28:55 -04:00
# include "file_sharing/p3filelists.h"
2016-07-20 16:10:51 -04:00
# include "file_sharing/directory_storage.h"
2016-07-30 15:52:42 -04:00
# include "file_sharing/directory_updater.h"
2016-08-20 10:23:11 -04:00
# include "file_sharing/rsfilelistitems.h"
2016-07-30 15:52:42 -04:00
2016-07-20 15:28:55 -04:00
# include "retroshare/rsids.h"
2016-07-31 09:59:58 -04:00
# include "retroshare/rspeers.h"
2016-07-18 21:52:44 -04:00
2016-08-06 13:04:54 -04:00
# include "rsserver/p3face.h"
2016-07-20 16:10:51 -04:00
# define P3FILELISTS_DEBUG() std::cerr << "p3FileLists: "
2016-07-18 21:52:44 -04:00
static const uint32_t P3FILELISTS_UPDATE_FLAG_NOTHING_CHANGED = 0x0000 ;
static const uint32_t P3FILELISTS_UPDATE_FLAG_REMOTE_MAP_CHANGED = 0x0001 ;
static const uint32_t P3FILELISTS_UPDATE_FLAG_LOCAL_DIRS_CHANGED = 0x0002 ;
static const uint32_t P3FILELISTS_UPDATE_FLAG_REMOTE_DIRS_CHANGED = 0x0004 ;
2016-08-22 01:49:45 -04:00
static const uint32_t NB_FRIEND_INDEX_BITS = 10 ;
static const uint32_t NB_ENTRY_INDEX_BITS = 22 ;
static const uint32_t ENTRY_INDEX_BIT_MASK = 0x003fffff ; // used for storing (EntryIndex,Friend) couples into a 32bits pointer.
static const uint32_t DELAY_BETWEEN_REMOTE_DIRECTORY_SYNC_REQ = 60 ; // every minute, for debugging. Should be evey 10 minutes or so.
2016-08-05 16:00:25 -04:00
2016-07-30 15:52:42 -04:00
p3FileDatabase : : p3FileDatabase ( p3ServiceControl * mpeers )
: mServCtrl ( mpeers ) , mFLSMtx ( " p3FileLists " )
2016-07-18 21:52:44 -04:00
{
// loads existing indexes for friends. Some might be already present here.
//
2016-08-20 10:23:11 -04:00
mRemoteDirectories . clear ( ) ; // we should load them!
mOwnId = mpeers - > getOwnId ( ) ;
2016-07-30 15:52:42 -04:00
2016-08-20 10:23:11 -04:00
mLocalSharedDirs = new LocalDirectoryStorage ( " local_file_store.bin " , mOwnId ) ;
2016-07-30 15:52:42 -04:00
mHashCache = new HashStorage ( " hash_cache.bin " ) ;
mLocalDirWatcher = new LocalDirectoryUpdater ( mHashCache , mLocalSharedDirs ) ;
2016-07-18 21:52:44 -04:00
mUpdateFlags = P3FILELISTS_UPDATE_FLAG_NOTHING_CHANGED ;
2016-08-20 10:23:11 -04:00
mLastRemoteDirSweepTS = 0 ;
2016-07-18 21:52:44 -04:00
}
2016-07-30 15:52:42 -04:00
void p3FileDatabase : : setSharedDirectories ( const std : : list < SharedDirInfo > & shared_dirs )
{
2016-08-06 13:04:54 -04:00
RS_STACK_MUTEX ( mFLSMtx ) ;
2016-07-30 15:52:42 -04:00
mLocalSharedDirs - > setSharedDirectoryList ( shared_dirs ) ;
2016-08-06 13:04:54 -04:00
mLocalDirWatcher - > forceUpdate ( ) ;
2016-07-30 15:52:42 -04:00
}
void p3FileDatabase : : getSharedDirectories ( std : : list < SharedDirInfo > & shared_dirs )
{
2016-08-06 13:04:54 -04:00
RS_STACK_MUTEX ( mFLSMtx ) ;
2016-07-30 15:52:42 -04:00
mLocalSharedDirs - > getSharedDirectoryList ( shared_dirs ) ;
}
2016-07-31 09:59:58 -04:00
void p3FileDatabase : : updateShareFlags ( const SharedDirInfo & info )
{
2016-08-06 13:04:54 -04:00
RS_STACK_MUTEX ( mFLSMtx ) ;
2016-07-31 09:59:58 -04:00
mLocalSharedDirs - > updateShareFlags ( info ) ;
}
2016-07-30 15:52:42 -04:00
p3FileDatabase : : ~ p3FileDatabase ( )
2016-07-18 21:52:44 -04:00
{
2016-07-20 16:10:51 -04:00
RS_STACK_MUTEX ( mFLSMtx ) ;
2016-08-20 10:23:11 -04:00
for ( uint32_t i = 0 ; i < mRemoteDirectories . size ( ) ; + + i )
delete mRemoteDirectories [ i ] ;
2016-07-20 16:10:51 -04:00
2016-08-20 10:23:11 -04:00
mRemoteDirectories . clear ( ) ; // just a precaution, not to leave deleted pointers around.
2016-07-20 16:10:51 -04:00
2016-07-30 15:52:42 -04:00
delete mLocalSharedDirs ;
delete mLocalDirWatcher ;
delete mHashCache ;
2016-07-18 21:52:44 -04:00
}
2016-07-30 15:52:42 -04:00
const std : : string FILE_DB_APP_NAME = " file_database " ;
const uint16_t FILE_DB_APP_MAJOR_VERSION = 1 ;
const uint16_t FILE_DB_APP_MINOR_VERSION = 0 ;
const uint16_t FILE_DB_MIN_MAJOR_VERSION = 1 ;
const uint16_t FILE_DB_MIN_MINOR_VERSION = 0 ;
RsServiceInfo p3FileDatabase : : getServiceInfo ( )
{
return RsServiceInfo ( RS_SERVICE_TYPE_FILE_DATABASE ,
FILE_DB_APP_NAME ,
FILE_DB_APP_MAJOR_VERSION ,
FILE_DB_APP_MINOR_VERSION ,
FILE_DB_MIN_MAJOR_VERSION ,
FILE_DB_MIN_MINOR_VERSION ) ;
}
int p3FileDatabase : : tick ( )
2016-07-18 21:52:44 -04:00
{
// tick the watchers, possibly create new ones if additional friends do connect.
//
tickWatchers ( ) ;
// tick the input/output list of update items and process them
//
tickRecv ( ) ;
tickSend ( ) ;
// cleanup
// - remove/delete shared file lists for people who are not friend anymore
// -
cleanup ( ) ;
2016-07-20 16:10:51 -04:00
2016-08-12 13:30:19 -04:00
static time_t last_print_time = 0 ;
time_t now = time ( NULL ) ;
2016-08-13 04:15:02 -04:00
if ( last_print_time + 20 < now )
2016-08-12 13:30:19 -04:00
{
2016-08-17 08:48:54 -04:00
RS_STACK_MUTEX ( mFLSMtx ) ;
2016-08-19 12:49:42 -04:00
2016-08-12 13:30:19 -04:00
mLocalSharedDirs - > print ( ) ;
last_print_time = now ;
2016-08-17 08:48:54 -04:00
2016-08-19 12:49:42 -04:00
//#warning this should be removed, but it's necessary atm for updating the GUI
2016-08-26 10:29:02 -04:00
RsServer : : notify ( ) - > notifyListChange ( NOTIFY_LIST_DIRLIST_FRIENDS , 0 ) ;
2016-08-12 13:30:19 -04:00
}
2016-08-17 08:48:54 -04:00
if ( mUpdateFlags )
{
IndicateConfigChanged ( ) ;
if ( mUpdateFlags & P3FILELISTS_UPDATE_FLAG_LOCAL_DIRS_CHANGED )
RsServer : : notify ( ) - > notifyListChange ( NOTIFY_LIST_DIRLIST_LOCAL , 0 ) ;
if ( mUpdateFlags & P3FILELISTS_UPDATE_FLAG_REMOTE_DIRS_CHANGED )
RsServer : : notify ( ) - > notifyListChange ( NOTIFY_LIST_DIRLIST_FRIENDS , 0 ) ;
mUpdateFlags = P3FILELISTS_UPDATE_FLAG_NOTHING_CHANGED ;
}
2016-08-20 10:23:11 -04:00
2016-08-26 10:29:02 -04:00
if ( mLastRemoteDirSweepTS + 30 < now )
2016-08-20 10:23:11 -04:00
{
RS_STACK_MUTEX ( mFLSMtx ) ;
for ( uint32_t i = 0 ; i < mRemoteDirectories . size ( ) ; + + i )
locked_recursSweepRemoteDirectory ( mRemoteDirectories [ i ] , mRemoteDirectories [ i ] - > root ( ) ) ;
mLastRemoteDirSweepTS = now ;
}
2016-07-20 16:10:51 -04:00
return 0 ;
2016-07-18 21:52:44 -04:00
}
2016-07-31 09:59:58 -04:00
void p3FileDatabase : : startThreads ( )
{
2016-08-17 08:48:54 -04:00
RS_STACK_MUTEX ( mFLSMtx ) ;
2016-08-05 16:37:40 -04:00
std : : cerr < < " Starting directory watcher thread... " ;
mLocalDirWatcher - > start ( ) ;
std : : cerr < < " Done. " < < std : : endl ;
2016-07-31 09:59:58 -04:00
}
void p3FileDatabase : : stopThreads ( )
{
2016-08-17 08:48:54 -04:00
RS_STACK_MUTEX ( mFLSMtx ) ;
2016-07-31 09:59:58 -04:00
std : : cerr < < " Stopping hash cache thread... " ; std : : cerr . flush ( ) ;
mHashCache - > fullstop ( ) ;
2016-08-05 16:37:40 -04:00
std : : cerr < < " Done. " < < std : : endl ;
2016-07-31 09:59:58 -04:00
2016-08-05 16:37:40 -04:00
std : : cerr < < " Stopping directory watcher thread... " ; std : : cerr . flush ( ) ;
mLocalDirWatcher - > fullstop ( ) ;
2016-07-31 09:59:58 -04:00
std : : cerr < < " Done. " < < std : : endl ;
}
2016-07-30 15:52:42 -04:00
void p3FileDatabase : : tickWatchers ( )
2016-07-18 21:52:44 -04:00
{
}
2016-07-30 15:52:42 -04:00
bool p3FileDatabase : : loadList ( std : : list < RsItem * > & items )
2016-07-18 21:52:44 -04:00
{
// This loads
//
// - list of locally shared directories, and the permissions that go with them
2016-08-20 10:23:11 -04:00
2016-07-30 15:52:42 -04:00
NOT_IMPLEMENTED ( ) ;
2016-07-20 16:10:51 -04:00
return true ;
2016-07-18 21:52:44 -04:00
}
2016-07-30 15:52:42 -04:00
bool p3FileDatabase : : saveList ( bool & cleanup , std : : list < RsItem * > & )
2016-07-18 21:52:44 -04:00
{
2016-07-30 15:52:42 -04:00
NOT_IMPLEMENTED ( ) ;
2016-07-20 16:10:51 -04:00
return true ;
2016-07-18 21:52:44 -04:00
}
2016-07-30 15:52:42 -04:00
void p3FileDatabase : : cleanup ( )
2016-07-18 21:52:44 -04:00
{
2016-08-05 16:00:25 -04:00
{
2016-08-17 08:48:54 -04:00
RS_STACK_MUTEX ( mFLSMtx ) ;
2016-08-05 16:00:25 -04:00
2016-08-17 08:48:54 -04:00
// look through the list of friend directories. Remove those who are not our friends anymore.
//
std : : set < RsPeerId > friend_set ;
{
std : : list < RsPeerId > friend_lst ;
2016-07-18 21:52:44 -04:00
2016-08-17 08:48:54 -04:00
rsPeers - > getFriendList ( friend_lst ) ;
2016-08-05 16:00:25 -04:00
2016-08-17 08:48:54 -04:00
for ( std : : list < RsPeerId > : : const_iterator it ( friend_lst . begin ( ) ) ; it ! = friend_lst . end ( ) ; + + it )
friend_set . insert ( * it ) ;
}
2016-07-18 21:52:44 -04:00
2016-08-20 10:23:11 -04:00
for ( uint32_t i = 0 ; i < mRemoteDirectories . size ( ) ; + + i )
if ( friend_set . find ( mRemoteDirectories [ i ] - > peerId ( ) ) = = friend_set . end ( ) )
2016-08-17 08:48:54 -04:00
{
2016-08-20 10:23:11 -04:00
P3FILELISTS_DEBUG ( ) < < " removing file list of non friend " < < mRemoteDirectories [ i ] - > peerId ( ) < < std : : endl ;
2016-07-18 21:52:44 -04:00
2016-08-20 10:23:11 -04:00
delete mRemoteDirectories [ i ] ;
mRemoteDirectories [ i ] = NULL ;
2016-07-18 21:52:44 -04:00
2016-08-17 08:48:54 -04:00
mUpdateFlags | = P3FILELISTS_UPDATE_FLAG_REMOTE_MAP_CHANGED ;
2016-08-05 16:00:25 -04:00
2016-08-20 10:23:11 -04:00
friend_set . erase ( mRemoteDirectories [ i ] - > peerId ( ) ) ;
2016-08-05 16:00:25 -04:00
2016-08-20 10:23:11 -04:00
mFriendIndexMap . erase ( mRemoteDirectories [ i ] - > peerId ( ) ) ;
2016-08-17 08:48:54 -04:00
mFriendIndexTab [ i ] . clear ( ) ;
}
2016-07-18 21:52:44 -04:00
2016-08-17 08:48:54 -04:00
// look through the remaining list of friends, which are the ones for which no remoteDirectoryStorage class has been allocated.
//
for ( std : : set < RsPeerId > : : const_iterator it ( friend_set . begin ( ) ) ; it ! = friend_set . end ( ) ; + + it )
{
// Check if a remote directory exists for that friend, possibly creating the index.
2016-07-18 21:52:44 -04:00
2016-08-17 08:48:54 -04:00
uint32_t friend_index = locked_getFriendIndex ( * it ) ;
2016-08-05 16:00:25 -04:00
2016-08-20 10:23:11 -04:00
if ( mRemoteDirectories . size ( ) > friend_index & & mRemoteDirectories [ friend_index ] ! = NULL )
2016-08-17 08:48:54 -04:00
continue ;
2016-08-13 04:15:02 -04:00
2016-08-17 08:48:54 -04:00
P3FILELISTS_DEBUG ( ) < < " adding missing remote dir entry for friend " < < * it < < " , with index " < < friend_index < < std : : endl ;
2016-08-05 16:00:25 -04:00
2016-08-26 10:29:02 -04:00
if ( mRemoteDirectories . size ( ) < = friend_index )
mRemoteDirectories . resize ( friend_index + 1 , NULL ) ;
2016-08-20 10:23:11 -04:00
mRemoteDirectories [ friend_index ] = new RemoteDirectoryStorage ( * it , makeRemoteFileName ( * it ) ) ;
2016-07-18 21:52:44 -04:00
2016-08-17 08:48:54 -04:00
mUpdateFlags | = P3FILELISTS_UPDATE_FLAG_REMOTE_MAP_CHANGED ;
}
}
2016-07-18 21:52:44 -04:00
}
2016-07-31 09:59:58 -04:00
std : : string p3FileDatabase : : makeRemoteFileName ( const RsPeerId & pid ) const
{
# warning we should use the default paths here. Ask p3config
return " dirlist_ " + pid . toStdString ( ) + " .txt " ;
}
2016-08-17 08:48:54 -04:00
uint32_t p3FileDatabase : : locked_getFriendIndex ( const RsPeerId & pid )
2016-08-05 16:00:25 -04:00
{
std : : map < RsPeerId , uint32_t > : : const_iterator it = mFriendIndexMap . find ( pid ) ;
if ( it = = mFriendIndexMap . end ( ) )
{
// allocate a new index for that friend, and tell that we should save.
uint32_t found = 0 ;
2016-08-20 10:23:11 -04:00
for ( uint32_t i = 0 ; i < mFriendIndexTab . size ( ) ; + + i )
2016-08-05 16:00:25 -04:00
if ( mFriendIndexTab [ i ] . isNull ( ) )
{
found = i ;
break ;
}
if ( ! found )
{
2016-08-16 07:46:55 -04:00
found = mFriendIndexTab . size ( ) ;
mFriendIndexTab . push_back ( pid ) ;
}
if ( mFriendIndexTab . size ( ) > = ( 1 < < NB_FRIEND_INDEX_BITS ) )
{
std : : cerr < < " (EE) FriendIndexTab is full. This is weird. Do you really have more than " < < ( 1 < < NB_FRIEND_INDEX_BITS ) < < " friends?? " < < std : : endl ;
return 1 < < NB_FRIEND_INDEX_BITS ;
2016-08-05 16:00:25 -04:00
}
mFriendIndexTab [ found ] = pid ;
mFriendIndexMap [ pid ] = found ;
2016-08-20 10:23:11 -04:00
if ( mRemoteDirectories . size ( ) < = found )
mRemoteDirectories . resize ( found , NULL ) ;
2016-08-16 07:46:55 -04:00
2016-08-05 16:00:25 -04:00
IndicateConfigChanged ( ) ;
return found ;
}
else
2016-08-16 07:46:55 -04:00
{
2016-08-20 10:23:11 -04:00
if ( mRemoteDirectories . size ( ) < = it - > second )
mRemoteDirectories . resize ( it - > second , NULL ) ;
2016-08-16 07:46:55 -04:00
2016-08-05 16:00:25 -04:00
return it - > second ;
2016-08-16 07:46:55 -04:00
}
2016-08-05 16:00:25 -04:00
}
2016-08-17 08:48:54 -04:00
const RsPeerId & p3FileDatabase : : locked_getFriendFromIndex ( uint32_t indx ) const
2016-08-05 16:00:25 -04:00
{
static const RsPeerId null_id ;
if ( indx > = mFriendIndexTab . size ( ) )
return null_id ;
if ( mFriendIndexTab [ indx ] . isNull ( ) )
{
std : : cerr < < " (EE) null friend id requested from index " < < indx < < " : this is a bug, most likely " < < std : : endl ;
return null_id ;
}
return mFriendIndexTab [ indx ] ;
}
2016-08-11 08:07:45 -04:00
bool p3FileDatabase : : convertPointerToEntryIndex ( const void * p , EntryIndex & e , uint32_t & friend_index )
2016-08-05 16:00:25 -04:00
{
// trust me, I can do this ;-)
e = EntryIndex ( * reinterpret_cast < uint32_t * > ( & p ) & ENTRY_INDEX_BIT_MASK ) ;
friend_index = ( * reinterpret_cast < uint32_t * > ( & p ) ) > > NB_ENTRY_INDEX_BITS ;
2016-08-16 17:44:48 -04:00
if ( friend_index = = 0 )
{
std : : cerr < < " (EE) Cannot find friend index in pointer. Encoded value is zero! " < < std : : endl ;
return false ;
}
friend_index - - ;
2016-08-05 16:00:25 -04:00
return true ;
}
2016-08-11 08:07:45 -04:00
bool p3FileDatabase : : convertEntryIndexToPointer ( const EntryIndex & e , uint32_t fi , void * & p )
2016-08-05 16:00:25 -04:00
{
// the pointer is formed the following way:
//
// [ 10 bits | 22 bits ]
//
// This means that the whoel software has the following build-in limitation:
2016-08-26 10:29:02 -04:00
// * 1023 friends
2016-08-05 16:00:25 -04:00
// * 4M shared files.
uint32_t fe = ( uint32_t ) e ;
2016-08-16 17:44:48 -04:00
if ( fi + 1 > = ( 1 < < NB_FRIEND_INDEX_BITS ) | | fe > = ( 1 < < NB_ENTRY_INDEX_BITS ) )
2016-08-05 16:00:25 -04:00
{
std : : cerr < < " (EE) cannot convert entry index " < < e < < " of friend with index " < < fi < < " to pointer. " < < std : : endl ;
return false ;
}
2016-08-16 17:44:48 -04:00
p = reinterpret_cast < void * > ( ( ( 1 + fi ) < < NB_ENTRY_INDEX_BITS ) + ( fe & ENTRY_INDEX_BIT_MASK ) ) ;
2016-08-05 16:00:25 -04:00
return true ;
}
2016-08-11 08:07:45 -04:00
// This function converts a pointer into directory details, to be used by the AbstractItemModel for browsing the files.
int p3FileDatabase : : RequestDirDetails ( void * ref , DirDetails & d , FileSearchFlags flags ) const
2016-07-30 15:52:42 -04:00
{
2016-08-17 08:48:54 -04:00
RS_STACK_MUTEX ( mFLSMtx ) ;
2016-08-26 10:29:02 -04:00
d . children . clear ( ) ;
2016-08-11 08:07:45 -04:00
// Case where the pointer is NULL, which means we're at the top of the list of shared directories for all friends (including us)
2016-08-26 10:29:02 -04:00
// or at the top of our own list of shared directories, depending on the flags.
// Friend index is used as follows:
// 0 : own id
// 1...n : other friends
//
// entry_index: starts at 0.
//
// The point is: we cannot use (0,0) because it encodes to NULL. No existing combination should encode to NULL.
// So we need to properly convert the friend index into 0 or into a friend tab index in mRemoteDirectories.
//
// We should also check the consistency between flags and the content of ref.
2016-08-11 08:07:45 -04:00
if ( ref = = NULL )
{
2016-08-16 17:44:48 -04:00
d . ref = NULL ;
d . type = DIR_TYPE_ROOT ;
d . count = 1 ;
d . parent = NULL ;
d . prow = - 1 ;
d . ref = NULL ;
d . name = " root " ;
d . hash . clear ( ) ;
d . path = " " ;
d . age = 0 ;
d . flags . clear ( ) ;
d . min_age = 0 ;
if ( flags & RS_FILE_HINTS_LOCAL )
{
void * p ;
convertEntryIndexToPointer ( 0 , 0 , p ) ;
DirStub stub ;
stub . type = DIR_TYPE_PERSON ;
stub . name = mServCtrl - > getOwnId ( ) . toStdString ( ) ;
stub . ref = p ;
d . children . push_back ( stub ) ;
}
2016-08-20 10:23:11 -04:00
else for ( uint32_t i = 0 ; i < mRemoteDirectories . size ( ) ; + + i )
2016-08-11 08:07:45 -04:00
{
void * p ;
2016-08-26 10:29:02 -04:00
convertEntryIndexToPointer ( mRemoteDirectories [ i ] - > root ( ) , i + 1 , p ) ;
2016-08-11 08:07:45 -04:00
DirStub stub ;
stub . type = DIR_TYPE_PERSON ;
2016-08-20 10:23:11 -04:00
stub . name = mRemoteDirectories [ i ] - > peerId ( ) . toStdString ( ) ;
2016-08-11 08:07:45 -04:00
stub . ref = p ;
d . children . push_back ( stub ) ;
}
2016-08-16 17:44:48 -04:00
d . count = d . children . size ( ) ;
2016-08-11 08:07:45 -04:00
2016-08-26 10:29:02 -04:00
std : : cerr < < " ExtractData: ref= " < < ref < < " , flags= " < < flags < < " : returning this: " < < std : : endl ;
std : : cerr < < d < < std : : endl ;
2016-08-11 08:07:45 -04:00
return true ;
}
2016-08-05 16:00:25 -04:00
uint32_t fi ;
2016-08-16 17:44:48 -04:00
DirectoryStorage : : EntryIndex e ;
2016-08-05 16:00:25 -04:00
2016-08-11 08:07:45 -04:00
convertPointerToEntryIndex ( ref , e , fi ) ;
2016-08-05 16:00:25 -04:00
2016-08-26 10:29:02 -04:00
// check consistency
if ( ( fi = = 0 & & ! ( flags & RS_FILE_HINTS_LOCAL ) ) | | ( fi > 0 & & ( flags & RS_FILE_HINTS_LOCAL ) ) )
{
std : : cerr < < " remote request on local index or local request on remote index. This should not happen. " < < std : : endl ;
return false ;
}
DirectoryStorage * storage = ( fi = = 0 ) ? ( ( DirectoryStorage * ) mLocalSharedDirs ) : ( ( DirectoryStorage * ) mRemoteDirectories [ fi - 1 ] ) ;
2016-08-11 08:07:45 -04:00
// Case where the index is the top of a single person. Can be us, or a friend.
2016-08-26 10:29:02 -04:00
bool res = storage - > extractData ( e , d ) ;
2016-08-11 08:07:45 -04:00
// update indexes. This is a bit hacky, but does the job. The cast to intptr_t is the proper way to convert
// a pointer into an int.
convertEntryIndexToPointer ( ( intptr_t ) d . ref , fi , d . ref ) ;
2016-08-19 12:49:42 -04:00
for ( uint32_t i = 0 ; i < d . children . size ( ) ; + + i )
convertEntryIndexToPointer ( ( intptr_t ) d . children [ i ] . ref , fi , d . children [ i ] . ref ) ;
2016-08-11 08:07:45 -04:00
2016-08-26 10:29:02 -04:00
if ( e = = 0 ) // root
2016-08-17 08:48:54 -04:00
{
2016-08-19 12:49:42 -04:00
d . prow = 0 ; //fi-1 ;
2016-08-17 08:48:54 -04:00
d . parent = NULL ;
}
else
{
2016-08-27 07:22:29 -04:00
if ( d . parent = = 0 ) // child of root node
d . prow = ( flags & RS_FILE_HINTS_LOCAL ) ? 0 : ( fi - 1 ) ;
else
d . prow = storage - > parentRow ( e ) ;
2016-08-17 08:48:54 -04:00
convertEntryIndexToPointer ( ( intptr_t ) d . parent , fi , d . parent ) ;
}
2016-08-26 10:29:02 -04:00
d . id = storage - > peerId ( ) ;
2016-08-12 13:30:19 -04:00
2016-08-17 08:48:54 -04:00
std : : cerr < < " ExtractData: ref= " < < ref < < " , flags= " < < flags < < " : returning this: " < < std : : endl ;
std : : cerr < < d < < std : : endl ;
2016-08-12 13:30:19 -04:00
return true ;
2016-07-30 15:52:42 -04:00
}
2016-08-11 08:07:45 -04:00
2016-08-05 16:00:25 -04:00
int p3FileDatabase : : RequestDirDetails ( const RsPeerId & uid , const std : : string & path , DirDetails & details ) const
2016-07-31 09:59:58 -04:00
{
NOT_IMPLEMENTED ( ) ;
return 0 ;
}
2016-07-30 15:52:42 -04:00
int p3FileDatabase : : RequestDirDetails ( const std : : string & path , DirDetails & details ) const
{
NOT_IMPLEMENTED ( ) ;
return 0 ;
}
uint32_t p3FileDatabase : : getType ( void * ref ) const
{
2016-08-17 08:48:54 -04:00
RS_STACK_MUTEX ( mFLSMtx ) ;
2016-08-11 08:07:45 -04:00
EntryIndex e ;
uint32_t fi ;
if ( ref = = NULL )
return DIR_TYPE_ROOT ;
convertPointerToEntryIndex ( ref , e , fi ) ;
if ( e = = 0 )
return DIR_TYPE_PERSON ;
2016-08-27 07:22:29 -04:00
if ( fi = = 0 )
return mLocalSharedDirs - > getEntryType ( e ) ;
else
return mRemoteDirectories [ fi - 1 ] - > getEntryType ( e ) ;
2016-07-30 15:52:42 -04:00
}
2016-08-11 08:07:45 -04:00
2016-07-30 15:52:42 -04:00
void p3FileDatabase : : forceDirectoryCheck ( ) // Force re-sweep the directories and see what's changed
{
NOT_IMPLEMENTED ( ) ;
}
bool p3FileDatabase : : inDirectoryCheck ( )
{
NOT_IMPLEMENTED ( ) ;
return 0 ;
}
void p3FileDatabase : : setWatchPeriod ( uint32_t seconds )
{
NOT_IMPLEMENTED ( ) ;
}
uint32_t p3FileDatabase : : watchPeriod ( )
{
NOT_IMPLEMENTED ( ) ;
return 0 ;
}
void p3FileDatabase : : setRememberHashCacheDuration ( uint32_t days )
{
NOT_IMPLEMENTED ( ) ;
}
uint32_t p3FileDatabase : : rememberHashCacheDuration ( )
{
NOT_IMPLEMENTED ( ) ;
return 0 ;
}
void p3FileDatabase : : clearHashCache ( )
{
NOT_IMPLEMENTED ( ) ;
}
bool p3FileDatabase : : rememberHashCache ( )
{
NOT_IMPLEMENTED ( ) ;
return false ;
}
void p3FileDatabase : : setRememberHashCache ( bool )
{
NOT_IMPLEMENTED ( ) ;
}
2016-07-31 09:59:58 -04:00
bool p3FileDatabase : : findLocalFile ( const RsFileHash & hash , FileSearchFlags flags , const RsPeerId & peer_id , std : : string & fullpath , uint64_t & size , FileStorageFlags & storage_flags , std : : list < std : : string > & parent_groups ) const
{
2016-08-17 08:48:54 -04:00
RS_STACK_MUTEX ( mFLSMtx ) ;
2016-07-31 09:59:58 -04:00
std : : list < EntryIndex > firesults ;
mLocalSharedDirs - > searchHash ( hash , firesults ) ;
NOT_IMPLEMENTED ( ) ;
return false ;
}
int p3FileDatabase : : SearchKeywords ( const std : : list < std : : string > & keywords , std : : list < DirDetails > & results , FileSearchFlags flags , const RsPeerId & client_peer_id )
{
2016-08-17 08:48:54 -04:00
RS_STACK_MUTEX ( mFLSMtx ) ;
2016-07-31 09:59:58 -04:00
std : : list < EntryIndex > firesults ;
mLocalSharedDirs - > searchTerms ( keywords , firesults ) ;
return filterResults ( firesults , results , flags , client_peer_id ) ;
}
int p3FileDatabase : : SearchBoolExp ( Expression * exp , std : : list < DirDetails > & results , FileSearchFlags flags , const RsPeerId & client_peer_id ) const
{
2016-08-17 08:48:54 -04:00
RS_STACK_MUTEX ( mFLSMtx ) ;
2016-07-31 09:59:58 -04:00
std : : list < EntryIndex > firesults ;
mLocalSharedDirs - > searchBoolExp ( exp , firesults ) ;
return filterResults ( firesults , results , flags , client_peer_id ) ;
}
bool p3FileDatabase : : search ( const RsFileHash & hash , FileSearchFlags hintflags , FileInfo & info ) const
{
2016-08-17 08:48:54 -04:00
RS_STACK_MUTEX ( mFLSMtx ) ;
2016-07-31 09:59:58 -04:00
if ( hintflags & RS_FILE_HINTS_LOCAL )
{
std : : list < EntryIndex > res ;
mLocalSharedDirs - > searchHash ( hash , res ) ;
if ( res . empty ( ) )
return false ;
2016-08-20 10:23:11 -04:00
EntryIndex indx = * res . begin ( ) ; // no need to report duplicates
2016-07-31 09:59:58 -04:00
mLocalSharedDirs - > getFileInfo ( indx , info ) ;
2016-08-05 16:00:25 -04:00
return true ;
2016-07-31 09:59:58 -04:00
}
2016-08-20 10:23:11 -04:00
if ( hintflags & RS_FILE_HINTS_REMOTE )
2016-07-31 09:59:58 -04:00
{
NOT_IMPLEMENTED ( ) ;
2016-08-05 16:00:25 -04:00
return false ;
2016-07-31 09:59:58 -04:00
}
2016-08-23 15:23:58 -04:00
return false ;
2016-07-31 09:59:58 -04:00
}
int p3FileDatabase : : filterResults ( const std : : list < EntryIndex > & firesults , std : : list < DirDetails > & results , FileSearchFlags flags , const RsPeerId & peer_id ) const
{
results . clear ( ) ;
# ifdef P3FILELISTS_DEBUG
if ( ( flags & ~ RS_FILE_HINTS_PERMISSION_MASK ) > 0 )
std : : cerr < < " (EE) ***** FileIndexMonitor:: Flags ERROR in filterResults!! " < < std : : endl ;
# endif
/* translate/filter results */
for ( std : : list < EntryIndex > : : const_iterator rit ( firesults . begin ( ) ) ; rit ! = firesults . end ( ) ; + + rit )
{
DirDetails cdetails ;
2016-08-16 17:44:48 -04:00
RequestDirDetails ( ( void * ) ( intptr_t ) * rit , cdetails , FileSearchFlags ( 0u ) ) ;
2016-07-31 09:59:58 -04:00
# ifdef P3FILELISTS_DEBUG
std : : cerr < < " Filtering candidate " < < ( * rit ) < < " , flags= " < < cdetails . flags < < " , peer= " < < peer_id ;
# endif
if ( ! peer_id . isNull ( ) )
{
FileSearchFlags permission_flags = rsPeers - > computePeerPermissionFlags ( peer_id , cdetails . flags , cdetails . parent_groups ) ;
if ( cdetails . type = = DIR_TYPE_FILE & & ( permission_flags & flags ) )
{
cdetails . id . clear ( ) ;
results . push_back ( cdetails ) ;
# ifdef P3FILELISTS_DEBUG
std : : cerr < < " : kept " < < std : : endl ;
# endif
}
# ifdef P3FILELISTS_DEBUG
else
std : : cerr < < " : discarded " < < std : : endl ;
# endif
}
else
results . push_back ( cdetails ) ;
}
return ! results . empty ( ) ;
}
bool p3FileDatabase : : convertSharedFilePath ( const std : : string & path , std : : string & fullpath )
{
2016-08-17 08:48:54 -04:00
RS_STACK_MUTEX ( mFLSMtx ) ;
2016-07-31 09:59:58 -04:00
return mLocalSharedDirs - > convertSharedFilePath ( path , fullpath ) ;
}
2016-08-20 10:23:11 -04:00
//==============================================================================================================================//
// Update of remote directories //
//==============================================================================================================================//
2016-08-22 01:49:45 -04:00
// Algorithm:
//
// Local dirs store the last modif time of the file, in local time
// - the max time is computed upward until the root of the hierarchy
// - because the hash is performed late, the last modf time upward is updated only when the hash is obtained.
//
// Remote dirs store the last modif time of the files/dir in the friend's time
// - local node sends the last known modf time to friends,
// - friends respond with either a full directory content, or an acknowledge that the time is right
//
2016-08-20 10:23:11 -04:00
void p3FileDatabase : : tickRecv ( )
{
RsItem * item ;
while ( NULL ! = ( item = recvItem ( ) ) )
{
switch ( item - > PacketSubType ( ) )
{
2016-08-23 15:23:58 -04:00
case RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM : handleDirSyncRequest ( dynamic_cast < RsFileListsSyncRequestItem * > ( item ) ) ;
2016-08-20 10:23:11 -04:00
break ;
2016-08-23 15:23:58 -04:00
case RS_PKT_SUBTYPE_FILELISTS_SYNC_RSP_ITEM : handleDirSyncResponse ( dynamic_cast < RsFileListsSyncResponseItem * > ( item ) ) ;
2016-08-20 10:23:11 -04:00
break ;
default :
std : : cerr < < " (EE) unhandled packet subtype " < < item - > PacketSubType ( ) < < " in " < < __PRETTY_FUNCTION__ < < std : : endl ;
}
delete item ;
}
}
void p3FileDatabase : : tickSend ( )
{
// go through the list of out requests and send them to the corresponding friends, if they are online.
}
2016-08-23 15:23:58 -04:00
void p3FileDatabase : : handleDirSyncRequest ( RsFileListsSyncRequestItem * item )
2016-08-20 10:23:11 -04:00
{
2016-08-23 15:23:58 -04:00
RsFileListsSyncResponseItem * ritem = new RsFileListsSyncResponseItem ;
2016-08-20 10:23:11 -04:00
// look at item TS. If local is newer, send the full directory content.
2016-08-23 15:23:58 -04:00
{
RS_STACK_MUTEX ( mFLSMtx ) ;
2016-08-20 10:23:11 -04:00
2016-08-23 15:23:58 -04:00
P3FILELISTS_DEBUG ( ) < < " Received directory sync request. index= " < < item - > entry_index < < " , flags= " < < ( void * ) ( intptr_t ) item - > flags < < " , request id: " < < std : : hex < < item - > request_id < < std : : dec < < " , last known TS: " < < item - > last_known_recurs_modf_TS < < std : : endl ;
2016-08-20 10:23:11 -04:00
2016-08-23 15:23:58 -04:00
uint32_t entry_type = mLocalSharedDirs - > getEntryType ( item - > entry_index ) ;
ritem - > PeerId ( item - > PeerId ( ) ) ;
ritem - > request_id = item - > request_id ;
ritem - > entry_index = item - > entry_index ;
2016-08-22 01:49:45 -04:00
2016-08-23 15:23:58 -04:00
if ( entry_type ! = DIR_TYPE_DIR )
{
P3FILELISTS_DEBUG ( ) < < " Directory does not exist anymore, or is not a directory. Answering with proper flags. " < < std : : endl ;
ritem - > flags = RsFileListsItem : : FLAGS_SYNC_RESPONSE | RsFileListsItem : : FLAGS_ENTRY_WAS_REMOVED ;
}
else
{
time_t local_recurs_max_time , local_update_time ;
2016-08-26 10:29:02 -04:00
mLocalSharedDirs - > getDirUpdateTS ( item - > entry_index , local_recurs_max_time , local_update_time ) ;
2016-08-23 15:23:58 -04:00
if ( item - > last_known_recurs_modf_TS < local_recurs_max_time )
{
P3FILELISTS_DEBUG ( ) < < " Directory is more recent than what the friend knows. Sending full dir content as response. " < < std : : endl ;
ritem - > flags = RsFileListsItem : : FLAGS_SYNC_RESPONSE | RsFileListsItem : : FLAGS_SYNC_DIR_CONTENT ;
ritem - > last_known_recurs_modf_TS = local_recurs_max_time ;
mLocalSharedDirs - > serialiseDirEntry ( item - > entry_index , ritem - > directory_content_data ) ;
}
else
{
P3FILELISTS_DEBUG ( ) < < " Directory is up to date w.r.t. what the friend knows. Sending ACK. " < < std : : endl ;
ritem - > flags = RsFileListsItem : : FLAGS_SYNC_RESPONSE | RsFileListsItem : : FLAGS_ENTRY_UP_TO_DATE ;
2016-08-26 10:29:02 -04:00
ritem - > last_known_recurs_modf_TS = local_recurs_max_time ;
2016-08-23 15:23:58 -04:00
}
}
2016-08-22 01:49:45 -04:00
}
2016-08-20 10:23:11 -04:00
2016-08-23 15:23:58 -04:00
// sends the response.
sendItem ( ritem ) ;
}
void p3FileDatabase : : handleDirSyncResponse ( RsFileListsSyncResponseItem * item )
{
// find the correct friend entry
uint32_t fi = 0 ;
P3FILELISTS_DEBUG ( ) < < " Handling sync response for directory with index " < < item - > entry_index < < std : : endl ;
2016-08-20 10:23:11 -04:00
{
2016-08-23 15:23:58 -04:00
RS_STACK_MUTEX ( mFLSMtx ) ;
fi = locked_getFriendIndex ( item - > PeerId ( ) ) ;
// make sure we have a remote directory for that friend.
if ( mRemoteDirectories . size ( ) < = fi )
mRemoteDirectories . resize ( fi + 1 , NULL ) ;
if ( mRemoteDirectories [ fi ] = = NULL )
mRemoteDirectories [ fi ] = new RemoteDirectoryStorage ( item - > PeerId ( ) , makeRemoteFileName ( item - > PeerId ( ) ) ) ;
2016-08-20 10:23:11 -04:00
}
2016-08-23 15:23:58 -04:00
if ( item - > flags & RsFileListsItem : : FLAGS_ENTRY_WAS_REMOVED )
2016-08-20 10:23:11 -04:00
{
2016-08-23 15:23:58 -04:00
P3FILELISTS_DEBUG ( ) < < " removing directory with index " < < item - > entry_index < < " because it does not exist. " < < std : : endl ;
mRemoteDirectories [ fi ] - > removeDirectory ( item - > entry_index ) ;
2016-08-20 10:23:11 -04:00
}
2016-08-23 15:23:58 -04:00
else if ( item - > flags & RsFileListsItem : : FLAGS_ENTRY_UP_TO_DATE )
{
P3FILELISTS_DEBUG ( ) < < " Directory is up to date. Setting local TS. " < < std : : endl ;
2016-08-20 10:23:11 -04:00
2016-08-26 10:29:02 -04:00
mRemoteDirectories [ fi ] - > setDirUpdateTS ( item - > entry_index , item - > last_known_recurs_modf_TS , time ( NULL ) ) ;
2016-08-23 15:23:58 -04:00
}
else if ( item - > flags & RsFileListsItem : : FLAGS_SYNC_DIR_CONTENT )
{
2016-08-26 10:29:02 -04:00
P3FILELISTS_DEBUG ( ) < < " Item contains directory data. Updating. " < < std : : endl ;
2016-08-20 10:23:11 -04:00
2016-08-26 10:29:02 -04:00
mRemoteDirectories [ fi ] - > deserialiseDirEntry ( item - > entry_index , item - > directory_content_data ) ;
mRemoteDirectories [ fi ] - > setDirUpdateTS ( item - > entry_index , item - > last_known_recurs_modf_TS , time ( NULL ) ) ;
2016-08-20 10:23:11 -04:00
2016-08-23 15:23:58 -04:00
# warning should notify the GUI here
// notify the GUI if the hierarchy has changed
}
2016-08-20 10:23:11 -04:00
}
void p3FileDatabase : : locked_recursSweepRemoteDirectory ( RemoteDirectoryStorage * rds , DirectoryStorage : : EntryIndex e )
{
time_t now = time ( NULL ) ;
// if not up to date, request update, and return (content is not certified, so no need to recurs yet).
// if up to date, return, because TS is about the last modif TS below, so no need to recurs either.
2016-08-23 15:23:58 -04:00
// get the info for this entry
2016-08-20 10:23:11 -04:00
2016-08-23 15:23:58 -04:00
time_t recurs_max_modf_TS_remote_time , local_update_TS ;
2016-08-26 10:29:02 -04:00
if ( ! rds - > getDirUpdateTS ( e , recurs_max_modf_TS_remote_time , local_update_TS ) )
2016-08-20 10:23:11 -04:00
{
2016-08-23 15:23:58 -04:00
std : : cerr < < " (EE) lockec_recursSweepRemoteDirectory(): cannot get update TS for directory with index " < < e < < " . This is a consistency bug. " < < std : : endl ;
return ;
2016-08-20 10:23:11 -04:00
}
2016-08-23 15:23:58 -04:00
// compare TS
if ( now > local_update_TS + DELAY_BETWEEN_REMOTE_DIRECTORY_SYNC_REQ ) // we need to compare local times only. We cannot compare local (now) with remote time.
2016-08-20 10:23:11 -04:00
{
// check if a request already exists and is not too old either: no need to re-ask.
DirSyncRequestId sync_req_id = makeDirSyncReqId ( rds - > peerId ( ) , e ) ;
std : : map < DirSyncRequestId , DirSyncRequestData > : : iterator it = mPendingSyncRequests . find ( sync_req_id ) ;
if ( it ! = mPendingSyncRequests . end ( ) )
{
2016-08-23 15:23:58 -04:00
P3FILELISTS_DEBUG ( ) < < " Not asking for sync of directory " < < e < < " to friend " < < rds - > peerId ( ) < < " because a recent pending request still exists. " < < std : : endl ;
2016-08-20 10:23:11 -04:00
return ;
}
2016-08-23 15:23:58 -04:00
P3FILELISTS_DEBUG ( ) < < " Asking for sync of directory " < < e < < " because it's " < < ( now - local_update_TS ) < < " secs old since last check. " < < std : : endl ;
2016-08-20 10:23:11 -04:00
DirSyncRequestData data ;
data . request_TS = now ;
mPendingSyncRequests [ sync_req_id ] = data ;
2016-08-23 15:23:58 -04:00
RsFileListsSyncRequestItem * item = new RsFileListsSyncRequestItem ;
2016-08-20 10:23:11 -04:00
item - > entry_index = e ;
2016-08-23 15:23:58 -04:00
item - > flags = RsFileListsItem : : FLAGS_SYNC_REQUEST ;
item - > request_id = sync_req_id ;
item - > last_known_recurs_modf_TS = recurs_max_modf_TS_remote_time ;
2016-08-22 01:49:45 -04:00
item - > PeerId ( rds - > peerId ( ) ) ;
2016-08-20 10:23:11 -04:00
sendItem ( item ) ;
2016-08-23 15:23:58 -04:00
// Dont recurs into sub-directories, since we dont know yet were to go.
2016-08-20 10:23:11 -04:00
return ;
}
2016-08-23 15:23:58 -04:00
for ( DirectoryStorage : : DirIterator it ( rds , e ) ; it ; + + it )
locked_recursSweepRemoteDirectory ( rds , * it ) ;
2016-08-20 10:23:11 -04:00
}
2016-08-23 15:23:58 -04:00
2016-08-26 10:29:02 -04:00
p3FileDatabase : : DirSyncRequestId p3FileDatabase : : makeDirSyncReqId ( const RsPeerId & peer_id , DirectoryStorage : : EntryIndex e )
{
uint64_t r = e ;
// This is kind of arbitrary. The important thing is that the same ID needs to be generated for a given (peer_id,e) pair.
for ( uint32_t i = 0 ; i < RsPeerId : : SIZE_IN_BYTES ; + + i )
r + = ( 0x3ff92892a94 * peer_id . toByteArray ( ) [ i ] + r ) ^ 0x39e83784378aafe3 ;
return r ;
}
2016-08-23 15:23:58 -04:00