2016-09-13 00:01:26 +02:00
/*
* RetroShare C + + Internal directory hierarchy class .
*
* file_sharing / dir_hierarchy . 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-09-03 13:29:23 +02:00
# pragma once
# include <stdint.h>
# include <string.h>
# include <stdlib.h>
# include "directory_storage.h"
class InternalFileHierarchyStorage
{
public :
class FileStorageNode
{
public :
static const uint32_t TYPE_UNKNOWN = 0x0000 ;
static const uint32_t TYPE_FILE = 0x0001 ;
static const uint32_t TYPE_DIR = 0x0002 ;
virtual ~ FileStorageNode ( ) { }
virtual uint32_t type ( ) const = 0 ;
DirectoryStorage : : EntryIndex parent_index ;
uint32_t row ;
} ;
class FileEntry : public FileStorageNode
{
public :
2016-09-10 20:47:51 +02:00
FileEntry ( ) : file_size ( 0 ) , file_modtime ( 0 ) { }
2016-09-03 13:29:23 +02:00
FileEntry ( const std : : string & name , uint64_t size , time_t modtime ) : file_name ( name ) , file_size ( size ) , file_modtime ( modtime ) { }
2016-09-05 21:22:11 +02:00
FileEntry ( const std : : string & name , uint64_t size , time_t modtime , const RsFileHash & hash ) : file_name ( name ) , file_size ( size ) , file_modtime ( modtime ) , file_hash ( hash ) { }
2016-09-03 13:29:23 +02:00
virtual uint32_t type ( ) const { return FileStorageNode : : TYPE_FILE ; }
virtual ~ FileEntry ( ) { }
// local stuff
std : : string file_name ;
uint64_t file_size ;
time_t file_modtime ;
RsFileHash file_hash ;
} ;
class DirEntry : public FileStorageNode
{
public :
2016-09-05 21:22:11 +02:00
DirEntry ( const std : : string & name ) : dir_name ( name ) , dir_modtime ( 0 ) , dir_most_recent_time ( 0 ) , dir_update_time ( 0 ) { }
2016-09-03 13:29:23 +02:00
virtual ~ DirEntry ( ) { }
virtual uint32_t type ( ) const { return FileStorageNode : : TYPE_DIR ; }
// local stuff
std : : string dir_name ;
std : : string dir_parent_path ;
2016-09-10 13:57:05 +02:00
RsFileHash dir_hash ;
2016-09-03 13:29:23 +02:00
std : : vector < DirectoryStorage : : EntryIndex > subdirs ;
std : : vector < DirectoryStorage : : EntryIndex > subfiles ;
time_t dir_modtime ;
2016-11-11 20:25:11 +01:00
time_t dir_most_recent_time ; // recursive most recent modification time, including files and subdirs in the entire hierarchy below.
2016-09-03 13:29:23 +02:00
time_t dir_update_time ; // last time the information was updated for that directory. Includes subdirs indexes and subfile info.
} ;
// class stuff
InternalFileHierarchyStorage ( ) ;
bool load ( const std : : string & fname ) ;
bool save ( const std : : string & fname ) ;
int parentRow ( DirectoryStorage : : EntryIndex e ) ;
bool isIndexValid ( DirectoryStorage : : EntryIndex e ) const ;
2016-09-15 10:41:40 +02:00
bool getChildIndex ( DirectoryStorage : : EntryIndex e , int row , DirectoryStorage : : EntryIndex & c ) const ;
2016-10-12 23:20:38 +02:00
bool updateSubDirectoryList ( const DirectoryStorage : : EntryIndex & indx , const std : : map < std : : string , time_t > & subdirs , const RsFileHash & random_hash_seed ) ;
2016-09-03 13:29:23 +02:00
bool removeDirectory ( DirectoryStorage : : EntryIndex indx ) ;
bool checkIndex ( DirectoryStorage : : EntryIndex indx , uint8_t type ) const ;
bool updateSubFilesList ( const DirectoryStorage : : EntryIndex & indx , const std : : map < std : : string , DirectoryStorage : : FileTS > & subfiles , std : : map < std : : string , DirectoryStorage : : FileTS > & new_files ) ;
bool updateHash ( const DirectoryStorage : : EntryIndex & file_index , const RsFileHash & hash ) ;
bool updateFile ( const DirectoryStorage : : EntryIndex & file_index , const RsFileHash & hash , const std : : string & fname , uint64_t size , const time_t modf_time ) ;
2016-09-10 20:47:51 +02:00
bool updateDirEntry ( const DirectoryStorage : : EntryIndex & indx , const std : : string & dir_name , time_t most_recent_time , time_t dir_modtime , const std : : vector < RsFileHash > & subdirs_hash , const std : : vector < FileEntry > & subfiles_array ) ;
2016-09-15 21:45:00 +02:00
// TS get/set functions. Take one of the class members as argument.
bool getTS ( const DirectoryStorage : : EntryIndex & index , time_t & TS , time_t DirEntry : : * ) const ;
bool setTS ( const DirectoryStorage : : EntryIndex & index , time_t & TS , time_t DirEntry : : * ) ;
2016-09-03 13:29:23 +02:00
// Do a complete recursive sweep over sub-directories and files, and update the lst modf TS. This could be also performed by a cleanup method.
2016-11-11 20:25:11 +01:00
// Also keeps the high level statistics up to date.
2016-09-03 13:29:23 +02:00
2016-11-05 17:32:40 +01:00
time_t recursUpdateLastModfTime ( const DirectoryStorage : : EntryIndex & dir_index , bool & unfinished_files_present ) ;
2016-09-03 13:29:23 +02:00
2016-09-08 23:43:14 +02:00
// hash stuff
bool getDirHashFromIndex ( const DirectoryStorage : : EntryIndex & index , RsFileHash & hash ) const ;
2016-09-27 23:13:59 +02:00
bool getIndexFromDirHash ( const RsFileHash & hash , DirectoryStorage : : EntryIndex & index ) ;
bool getIndexFromFileHash ( const RsFileHash & hash , DirectoryStorage : : EntryIndex & index ) ;
2016-09-08 23:43:14 +02:00
2016-09-03 13:29:23 +02:00
// file/dir access and modification
bool findSubDirectory ( DirectoryStorage : : EntryIndex e , const std : : string & s ) const ; // returns true when s is the name of a sub-directory in the given entry e
uint32_t mRoot ;
2016-11-03 22:32:27 +01:00
std : : list < uint32_t > mFreeNodes ; // keeps a list of free nodes in order to make insert effcieint
2016-09-03 13:29:23 +02:00
std : : vector < FileStorageNode * > mNodes ; // uses pointers to keep information about valid/invalid objects.
void compress ( ) ; // use empty space in the vector, mostly due to deleted entries. This is a complicated operation, mostly due to
// all the indirections used. Nodes need to be moved, renamed, etc. The operation discards all file entries that
// are not referenced.
friend class DirectoryStorage ; // only class that can use this.
friend class LocalDirectoryStorage ; // only class that can use this.
// Low level stuff. Should normally not be used externally.
const FileStorageNode * getNode ( DirectoryStorage : : EntryIndex indx ) const ;
const DirEntry * getDirEntry ( DirectoryStorage : : EntryIndex indx ) const ;
const FileEntry * getFileEntry ( DirectoryStorage : : EntryIndex indx ) const ;
uint32_t getType ( DirectoryStorage : : EntryIndex indx ) const ;
DirectoryStorage : : EntryIndex getSubFileIndex ( DirectoryStorage : : EntryIndex parent_index , uint32_t file_tab_index ) ;
DirectoryStorage : : EntryIndex getSubDirIndex ( DirectoryStorage : : EntryIndex parent_index , uint32_t dir_tab_index ) ;
2016-09-12 23:37:19 +02:00
// search. SearchHash is logarithmic. The other two are linear.
2016-10-25 00:08:27 +02:00
bool searchHash ( const RsFileHash & hash , DirectoryStorage : : EntryIndex & result ) ;
2016-09-13 12:05:22 +02:00
int searchBoolExp ( RsRegularExpression : : Expression * exp , std : : list < DirectoryStorage : : EntryIndex > & results ) const ;
2016-09-25 23:42:20 +02:00
int searchTerms ( const std : : list < std : : string > & terms , std : : list < DirectoryStorage : : EntryIndex > & results ) const ; // does a logical OR between items of the list of terms
2016-09-03 13:29:23 +02:00
2016-09-27 23:13:59 +02:00
bool check ( std : : string & error_string ) ; // checks consistency of storage.
2016-09-03 13:29:23 +02:00
void print ( ) const ;
2016-11-11 20:25:11 +01:00
// gets statistics about share files
void getStatistics ( SharedDirStats & stats ) const ;
2016-09-03 13:29:23 +02:00
private :
void recursPrint ( int depth , DirectoryStorage : : EntryIndex node ) const ;
static bool nodeAccessError ( const std : : string & s ) ;
2016-10-12 23:20:38 +02:00
static RsFileHash createDirHash ( const std : : string & dir_name , const RsFileHash & dir_parent_hash , const RsFileHash & random_hash_salt ) ;
2016-09-03 13:29:23 +02:00
2016-09-10 20:47:51 +02:00
// Allocates a new entry in mNodes, possible re-using an empty slot and returns its index.
DirectoryStorage : : EntryIndex allocateNewIndex ( ) ;
2016-11-03 22:32:27 +01:00
// Deletes an existing entry in mNodes, and keeps record of the indices that get freed.
void deleteNode ( DirectoryStorage : : EntryIndex ) ;
2016-11-11 20:25:11 +01:00
void deleteFileNode ( DirectoryStorage : : EntryIndex ) ;
2016-11-03 22:32:27 +01:00
2016-09-03 13:29:23 +02:00
// Removes the given subdirectory from the parent node and all its pendign subdirs. Files are kept, and will go during the cleaning
// phase. That allows to keep file information when moving them around.
bool recursRemoveDirectory ( DirectoryStorage : : EntryIndex dir ) ;
2016-09-10 20:47:51 +02:00
// Map of the hash of all files. The file hashes are the sha1sum of the file data.
2016-09-07 22:31:12 +02:00
// is used for fast search access for FT.
// Note: We should try something faster than std::map. hash_map??
2016-09-10 20:47:51 +02:00
// Unlike directories, multiple files may have the same hash. So this cannot be used for anything else than FT.
2016-09-07 22:31:12 +02:00
std : : map < RsFileHash , DirectoryStorage : : EntryIndex > mFileHashes ;
// The directory hashes are the sha1sum of the
// full public path to the directory.
// The later is used by synchronisation items in order
// to avoid sending explicit EntryIndex values.
// This is kept separate from mFileHashes because the two are used
// in very different ways.
//
std : : map < RsFileHash , DirectoryStorage : : EntryIndex > mDirHashes ;
2016-11-11 20:25:11 +01:00
// high level statistics on the full hierarchy. Should be kept up to date.
uint32_t mTotalFiles ;
uint64_t mTotalSize ;
2016-09-03 13:29:23 +02:00
} ;
2016-09-07 22:31:12 +02:00