2016-09-12 18:01:26 -04:00
/*
* RetroShare C + + Directory Storage system .
*
* file_sharing / directory_storage . h
*
* Copyright 2016 by 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-24 23:48:22 -04:00
# pragma once
2016-07-18 21:52:44 -04:00
# include <string>
2016-07-20 16:10:51 -04:00
# include <stdint.h>
# include <list>
# include "retroshare/rsids.h"
# include "retroshare/rsfiles.h"
2016-07-18 21:52:44 -04:00
2016-07-31 09:59:58 -04:00
# define NOT_IMPLEMENTED() { std::cerr << __PRETTY_FUNCTION__ << ": not yet implemented." << std::endl; }
2016-08-26 10:29:02 -04:00
class RsTlvBinaryData ;
2016-07-21 00:16:12 -04:00
class InternalFileHierarchyStorage ;
2016-08-26 10:29:02 -04:00
class RsTlvBinaryData ;
2016-07-21 00:16:12 -04:00
2016-07-18 21:52:44 -04:00
class DirectoryStorage
{
public :
2016-09-03 07:29:23 -04:00
DirectoryStorage ( const RsPeerId & pid ) ;
2016-07-20 16:10:51 -04:00
virtual ~ DirectoryStorage ( ) { }
2016-09-03 07:29:23 -04:00
typedef uint32_t EntryIndex ;
2016-07-24 23:48:22 -04:00
static const EntryIndex NO_INDEX = 0xffffffff ;
2016-07-18 21:52:44 -04:00
void save ( ) const ;
2016-09-22 15:47:58 -04:00
// These functions are to be used by file transfer and file search.
2016-09-12 17:37:19 -04:00
virtual int searchTerms ( const std : : list < std : : string > & terms , std : : list < EntryIndex > & results ) const ;
2016-09-13 06:05:22 -04:00
virtual int searchBoolExp ( RsRegularExpression : : Expression * exp , std : : list < EntryIndex > & results ) const ;
2016-07-18 21:52:44 -04:00
2016-09-22 15:47:58 -04:00
// gets/sets the various time stamps:
//
bool getDirectoryRecursModTime ( EntryIndex index , time_t & recurs_max_modf_TS ) const ; // last modification time, computed recursively over all subfiles and directories
bool getDirectoryLocalModTime ( EntryIndex index , time_t & motime_TS ) const ; // last modification time for that index only
bool getDirectoryUpdateTime ( EntryIndex index , time_t & update_TS ) const ; // last time the entry was updated. This is only used on the RemoteDirectoryStorage side.
2016-09-15 15:45:00 -04:00
bool setDirectoryRecursModTime ( EntryIndex index , time_t recurs_max_modf_TS ) ;
bool setDirectoryLocalModTime ( EntryIndex index , time_t modtime_TS ) ;
bool setDirectoryUpdateTime ( EntryIndex index , time_t update_TS ) ;
2016-08-23 15:23:58 -04:00
2016-09-22 15:47:58 -04:00
uint32_t getEntryType ( const EntryIndex & indx ) ; // WARNING: returns DIR_TYPE_*, not the internal directory storage stuff.
2016-08-16 17:44:48 -04:00
virtual bool extractData ( const EntryIndex & indx , DirDetails & d ) ;
2016-07-18 21:52:44 -04:00
// This class allows to abstractly browse the stored directory hierarchy in a depth-first manner.
2016-09-22 15:47:58 -04:00
// It gives access to sub-files and sub-directories below. When using it, the client should make sure
// that the DirectoryStorage is properly locked, since the iterator cannot lock it.
2016-07-18 21:52:44 -04:00
//
class DirIterator
{
public :
2016-07-21 00:16:12 -04:00
DirIterator ( const DirIterator & d ) ;
2016-07-24 23:48:22 -04:00
DirIterator ( DirectoryStorage * d , EntryIndex i ) ;
2016-07-18 21:52:44 -04:00
DirIterator & operator + + ( ) ;
2016-07-24 23:48:22 -04:00
EntryIndex operator * ( ) const ;
2016-07-18 21:52:44 -04:00
2016-07-23 22:14:43 -04:00
operator bool ( ) const ; // used in for loops. Returns true when the iterator is valid.
// info about the directory that is pointed by the iterator
2016-08-11 08:07:45 -04:00
std : : string name ( ) const ;
2016-08-20 10:23:11 -04:00
time_t last_modif_time ( ) const ; // last time a file in this directory or in the directories below has been modified.
time_t last_update_time ( ) const ; // last time this directory was updated
2016-07-24 23:48:22 -04:00
private :
EntryIndex mParentIndex ; // index of the parent dir.
uint32_t mDirTabIndex ; // index in the vector of subdirs.
InternalFileHierarchyStorage * mStorage ;
friend class DirectoryStorage ;
2016-07-23 22:14:43 -04:00
} ;
2016-07-18 21:52:44 -04:00
class FileIterator
{
public :
2016-07-24 23:48:22 -04:00
FileIterator ( DirIterator & d ) ; // crawls all files in specified directory
FileIterator ( DirectoryStorage * d , EntryIndex e ) ; // crawls all files in specified directory
2016-07-18 21:52:44 -04:00
FileIterator & operator + + ( ) ;
2016-07-24 23:48:22 -04:00
EntryIndex operator * ( ) const ; // current file entry
2016-07-18 21:52:44 -04:00
2016-07-23 22:14:43 -04:00
operator bool ( ) const ; // used in for loops. Returns true when the iterator is valid.
// info about the file that is pointed by the iterator
std : : string name ( ) const ;
uint64_t size ( ) const ;
RsFileHash hash ( ) const ;
time_t modtime ( ) const ;
2016-07-24 23:48:22 -04:00
private :
EntryIndex mParentIndex ; // index of the parent dir.
uint32_t mFileTabIndex ; // index in the vector of subdirs.
InternalFileHierarchyStorage * mStorage ;
2016-07-23 22:14:43 -04:00
} ;
2016-07-18 21:52:44 -04:00
2016-07-28 03:29:15 -04:00
struct FileTS
{
uint64_t size ;
time_t modtime ;
} ;
2016-09-22 15:47:58 -04:00
EntryIndex root ( ) const ; // returns the index of the root directory entry. This is generally 0.
const RsPeerId & peerId ( ) const { return mPeerId ; } // peer ID of who owns that file list.
int parentRow ( EntryIndex e ) const ; // position of the current node, in the array of children at its parent node. Used by GUI for display.
bool getChildIndex ( EntryIndex e , int row , EntryIndex & c ) const ; // returns the index of the children node at position "row" in the children nodes. Used by GUI for display.
2016-07-21 00:16:12 -04:00
2016-09-22 15:47:58 -04:00
// Sets the subdirectory/subfiles list of entry indx the supplied one, possible adding and removing directories (resp.files). New directories are set empty with
// just a name and need to be updated later on. New files are returned in a list so that they can be sent to hash cache.
//
2016-09-07 16:31:12 -04:00
bool updateSubDirectoryList ( const EntryIndex & indx , const std : : map < std : : string , time_t > & subdirs ) ;
2016-07-28 03:29:15 -04:00
bool updateSubFilesList ( const EntryIndex & indx , const std : : map < std : : string , FileTS > & subfiles , std : : map < std : : string , FileTS > & new_files ) ;
2016-07-27 15:22:59 -04:00
bool removeDirectory ( const EntryIndex & indx ) ;
2016-07-23 22:14:43 -04:00
2016-09-22 15:47:58 -04:00
// Updates relevant information for the file at the given index.
2016-07-27 15:22:59 -04:00
bool updateFile ( const EntryIndex & index , const RsFileHash & hash , const std : : string & fname , uint64_t size , time_t modf_time ) ;
bool updateHash ( const EntryIndex & index , const RsFileHash & hash ) ;
2016-07-24 23:48:22 -04:00
2016-09-22 15:47:58 -04:00
// Returns the hash of the directory at the given index and reverse. This hash is set as random the first time it is used (when updating directories). It will be
// used by the sync system to designate the directory without referring to index (index could be used to figure out the existance of hidden directories)
bool getDirHashFromIndex ( const EntryIndex & index , RsFileHash & hash ) const ; // constant cost
bool getIndexFromDirHash ( const RsFileHash & hash , EntryIndex & index ) const ; // log cost.
2016-09-07 16:31:12 -04:00
2016-07-27 18:48:28 -04:00
void print ( ) ;
2016-07-24 23:48:22 -04:00
void cleanup ( ) ;
2016-09-03 07:29:23 -04:00
protected :
2016-07-18 21:52:44 -04:00
void load ( const std : : string & local_file_name ) ;
void save ( const std : : string & local_file_name ) ;
2016-09-03 07:29:23 -04:00
private :
2016-08-26 10:29:02 -04:00
// debug
void locked_check ( ) ;
2016-07-21 00:16:12 -04:00
// storage of internal structure. Totally hidden from the outside. EntryIndex is simply the index of the entry in the vector.
2016-08-11 08:07:45 -04:00
RsPeerId mPeerId ;
2016-07-27 15:22:59 -04:00
protected :
2016-08-11 08:07:45 -04:00
mutable RsMutex mDirStorageMtx ;
InternalFileHierarchyStorage * mFileHierarchy ;
2016-07-18 21:52:44 -04:00
} ;
class RemoteDirectoryStorage : public DirectoryStorage
{
2016-07-20 16:10:51 -04:00
public :
2016-09-03 07:29:23 -04:00
RemoteDirectoryStorage ( const RsPeerId & pid , const std : : string & fname ) ;
2016-07-20 16:10:51 -04:00
virtual ~ RemoteDirectoryStorage ( ) { }
2016-08-26 10:29:02 -04:00
/*!
* \ brief deserialiseDirEntry
* Loads a serialised directory content coming from a friend . The directory entry needs to exist already ,
* as it is created when updating the parent .
*
* \ param indx index of the directory to update
* \ param bindata binary data to deserialise from
* \ return false when the directory cannot be found .
*/
2016-09-03 07:29:23 -04:00
bool deserialiseUpdateDirEntry ( const EntryIndex & indx , const RsTlvBinaryData & data ) ;
/*!
* \ brief checkSave
* Checks the time of last saving , last modification time , and saves if needed .
*/
void checkSave ( ) ;
private :
time_t mLastSavedTime ;
bool mChanged ;
std : : string mFileName ;
2016-07-18 21:52:44 -04:00
} ;
class LocalDirectoryStorage : public DirectoryStorage
{
2016-07-20 16:10:51 -04:00
public :
2016-09-03 07:29:23 -04:00
LocalDirectoryStorage ( const std : : string & fname , const RsPeerId & own_id ) : DirectoryStorage ( own_id ) , mFileName ( fname ) { }
2016-07-20 16:10:51 -04:00
virtual ~ LocalDirectoryStorage ( ) { }
2016-07-21 00:16:12 -04:00
2016-09-22 15:47:58 -04:00
/*!
* \ brief [ gs ] etSharedDirectoryList
* Gets / sets the list of shared directories . Each directory is supplied with a virtual name ( the name the friends will see ) , and sharing flags / groups .
* \ param lst
*/
2016-07-21 00:16:12 -04:00
void setSharedDirectoryList ( const std : : list < SharedDirInfo > & lst ) ;
void getSharedDirectoryList ( std : : list < SharedDirInfo > & lst ) ;
2016-07-31 09:59:58 -04:00
void updateShareFlags ( const SharedDirInfo & info ) ;
bool convertSharedFilePath ( const std : : string & path_with_virtual_name , std : : string & fullpath ) ;
2016-10-29 11:59:03 -04:00
/*!
* \ brief searchHash
* Looks into local database of shared files for the given hash . Also looks for files such that the hash of the hash
* matches the given hash , and returns the real hash .
* \ param hash hash to look for
* \ param real_hash hash such that H ( real_hash ) = hash , or null hash if not found .
* \ param results Entry index of the file that is found
* \ return
* true is a file is found
* false otherwise .
*/
virtual int searchHash ( const RsFileHash & hash , RsFileHash & real_hash , EntryIndex & results ) const ;
2016-09-18 12:34:39 -04:00
/*!
* \ brief updateTimeStamps
* Checks recursive TS and update the if needed .
*/
2016-08-22 01:49:45 -04:00
void updateTimeStamps ( ) ;
2016-09-18 12:34:39 -04:00
/*!
* \ brief notifyTSChanged
* Use this to force an update of the recursive TS , when calling updateTimeStamps ( ) ;
*/
void notifyTSChanged ( ) ;
2016-07-31 09:59:58 -04:00
/*!
* \ brief getFileInfo Converts an index info a full file info structure .
* \ param i index in the directory structure
* \ param info structure to be filled in
* \ return false if the file does not exist , or is a directory , . . .
*/
bool getFileInfo ( DirectoryStorage : : EntryIndex i , FileInfo & info ) ;
2016-08-11 08:07:45 -04:00
2016-08-30 15:28:32 -04:00
/*!
* \ brief getFileSharingPermissions
* Computes the flags and parent groups for any index .
* \ param indx index of the entry to compute the flags for
* \ param flags computed flags
* \ param parent_groups computed parent groups
* \ return
* false if the index is not valid
* false otherwise
*/
2016-09-01 14:02:47 -04:00
bool getFileSharingPermissions ( const EntryIndex & indx , FileStorageFlags & flags , std : : list < RsNodeGroupId > & parent_groups ) ;
2016-08-30 15:28:32 -04:00
2016-08-11 08:07:45 -04:00
virtual bool extractData ( const EntryIndex & indx , DirDetails & d ) ;
2016-08-26 10:29:02 -04:00
/*!
* \ brief serialiseDirEntry
* Produced a serialised directory content listing suitable for export to friends .
*
2016-08-31 16:47:05 -04:00
* \ param indx index of the directory to serialise
* \ param bindata binary data created by serialisation
* \ param client_id Peer id to be serialised to . Depending on permissions , some subdirs can be removed .
* \ return false when the directory cannot be found .
2016-08-26 10:29:02 -04:00
*/
2016-08-31 16:47:05 -04:00
bool serialiseDirEntry ( const EntryIndex & indx , RsTlvBinaryData & bindata , const RsPeerId & client_id ) ;
2016-08-26 10:29:02 -04:00
2016-07-21 00:16:12 -04:00
private :
2016-10-29 11:59:03 -04:00
bool locked_findRealHash ( const RsFileHash & hash , RsFileHash & real_hash ) const ;
2016-09-10 07:57:05 -04:00
std : : string locked_getVirtualPath ( EntryIndex indx ) const ;
std : : string locked_getVirtualDirName ( EntryIndex indx ) const ;
2016-09-18 12:34:39 -04:00
bool locked_getFileSharingPermissions ( const EntryIndex & indx , FileStorageFlags & flags , std : : list < RsNodeGroupId > & parent_groups ) ;
std : : string locked_findRealRootFromVirtualFilename ( const std : : string & virtual_rootdir ) const ;
2016-07-21 00:16:12 -04:00
2016-09-18 12:34:39 -04:00
std : : map < std : : string , SharedDirInfo > mLocalDirs ; // map is better for search. it->first=it->second.filename
2016-10-29 11:59:03 -04:00
std : : map < RsFileHash , RsFileHash > mEncryptedHashes ; // map such that hash(it->second) = it->first
2016-09-18 12:34:39 -04:00
std : : string mFileName ;
bool mTSChanged ;
2016-07-18 21:52:44 -04:00
} ;
2016-07-21 00:16:12 -04:00