mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-05-03 06:35:08 -04:00
improved FolderIterator class
This commit is contained in:
parent
3c976bb7ee
commit
3e48b0fd95
11 changed files with 183 additions and 62 deletions
|
@ -5,6 +5,9 @@ class InternalFileHierarchyStorage
|
|||
class FileStorageNode
|
||||
{
|
||||
public:
|
||||
static const uint32_t TYPE_FILE = 0x0001 ;
|
||||
static const uint32_t TYPE_DIR = 0x0002 ;
|
||||
|
||||
virtual uint32_t type() const =0;
|
||||
};
|
||||
class FileEntry: public FileStorageNode
|
||||
|
@ -19,12 +22,12 @@ class InternalFileHierarchyStorage
|
|||
public:
|
||||
virtual uint32_t type() const { return FileStorageNode::TYPE_DIR ; }
|
||||
|
||||
std::set<EntryIndex> subdirs ;
|
||||
std::set<EntryIndex> subfiles ;
|
||||
std::set<DirectoryStorage::EntryIndex> subdirs ;
|
||||
std::set<DirectoryStorage::EntryIndex> subfiles ;
|
||||
};
|
||||
|
||||
// file/dir access and modification
|
||||
bool findSubDirectory(EntryIndex e,const std::string& s) const ; // returns true when s is the name of a sub-directory in the given entry e
|
||||
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 root ;
|
||||
|
||||
|
|
|
@ -39,27 +39,44 @@ class DirectoryStorage
|
|||
{
|
||||
public:
|
||||
DirIterator(const DirIterator& d) ;
|
||||
DirIterator(const EntryIndex& d) ;
|
||||
|
||||
DirIterator& operator++() ;
|
||||
EntryIndex operator*() const ; // current directory entry
|
||||
|
||||
bool operator()() const ; // used in for loops. Returns true when the iterator is valid.
|
||||
};
|
||||
operator bool() const ; // used in for loops. Returns true when the iterator is valid.
|
||||
|
||||
// info about the directory that is pointed by the iterator
|
||||
|
||||
const std::string& name() const ;
|
||||
};
|
||||
class FileIterator
|
||||
{
|
||||
public:
|
||||
FileIterator(DirIterator& d); // crawls all files in specified directory
|
||||
FileIterator(EntryIndex& e); // crawls all files in specified directory
|
||||
|
||||
uint32_t size() const ; // number of files in this directory
|
||||
FileIterator& operator++() ;
|
||||
EntryIndex operator*() const ; // current file entry
|
||||
|
||||
bool operator()() const ; // used in for loops. Returns true when the iterator is valid.
|
||||
};
|
||||
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 ;
|
||||
std::string fullpath() const ;
|
||||
uint64_t size() const ;
|
||||
RsFileHash hash() const ;
|
||||
time_t modtime() const ;
|
||||
};
|
||||
|
||||
virtual DirIterator root() ; // returns the index of the root directory entry.
|
||||
|
||||
private:
|
||||
void updateSubDirectoryList(const EntryIndex& indx,const std::list<std::string>& subdirs) ;
|
||||
void updateSubFilesList(const EntryIndex& indx,const std::list<std::string>& subfiles) ;
|
||||
void removeDirectory(const EntryIndex& indx) ;
|
||||
|
||||
private:
|
||||
void load(const std::string& local_file_name) ;
|
||||
void save(const std::string& local_file_name) ;
|
||||
|
||||
|
|
|
@ -1,19 +1,24 @@
|
|||
#include "util/folderiterator.h"
|
||||
|
||||
#include "directory_storage.h"
|
||||
#include "directory_updater.h"
|
||||
|
||||
#define DEBUG_LOCAL_DIR_UPDATER 1
|
||||
|
||||
void RemoteDirectoryUpdater::tick()
|
||||
{
|
||||
// use the stored iterator
|
||||
}
|
||||
|
||||
LocalDirectoryUpdater::LocalDirectoryUpdater()
|
||||
LocalDirectoryUpdater::LocalDirectoryUpdater(HashCache *hc)
|
||||
: mHashCache(hc)
|
||||
{
|
||||
// tell the hash cache that we're the client
|
||||
mHashCache->setClient(this) ;
|
||||
}
|
||||
|
||||
void LocalDirectoryUpdater::tick()
|
||||
{
|
||||
std::cerr << "LocalDirectoryUpdater::tick()" << std::endl;
|
||||
|
||||
// recursive update algorithm works that way:
|
||||
// - the external loop starts on the shared directory list and goes through sub-directories
|
||||
// - at the same time, it updates the local list of shared directories. A single sweep is performed over the whole directory structure.
|
||||
|
@ -21,28 +26,29 @@ void LocalDirectoryUpdater::tick()
|
|||
// - doing so, changing directory names or moving files between directories does not cause a re-hash of the content.
|
||||
//
|
||||
std::list<SharedDirInfo> shared_directory_list ;
|
||||
std::list<std::string> sub_dir_list ;
|
||||
|
||||
for(std::list<SharedDirInfo>::const_iterator real_dir_it(shared_directory_list.begin());it!=shared_directory_list.end();++it)
|
||||
sub_dir_list.push_back( (*it).filename ) ;
|
||||
for(std::list<SharedDirInfo>::const_iterator real_dir_it(shared_directory_list.begin());real_dir_it!=shared_directory_list.end();++real_dir_it)
|
||||
sub_dir_list.push_back( (*real_dir_it).filename ) ;
|
||||
|
||||
// make sure that entries in stored_dir_it are the same than paths in real_dir_it, and in the same order.
|
||||
|
||||
mSharedDirectories->updateSubDirectoryList(mSharedDirectories->root(),sub_dir_list) ;
|
||||
mSharedDirectories->updateSubDirectoryList(*mSharedDirectories->root(),sub_dir_list) ;
|
||||
|
||||
// now for each of them, go recursively and match both files and dirs
|
||||
|
||||
DirectoryStorage::DirIterator stored_dir_it(mLocalSharedDirs.root()) ;
|
||||
DirectoryStorage::DirIterator stored_dir_it(mSharedDirectories->root()) ;
|
||||
|
||||
for(std::list<SharedDirInfo>::const_iterator real_dir_it(shared_directory_list.begin());it!=shared_directory_list.end();++it, ++stored_dir_it)
|
||||
recursUpdateSharedDir(*real_dir_it, *stored_dir_it) ;
|
||||
for(std::list<SharedDirInfo>::const_iterator real_dir_it(shared_directory_list.begin());real_dir_it!=shared_directory_list.end();++real_dir_it, ++stored_dir_it)
|
||||
recursUpdateSharedDir(real_dir_it->filename, *stored_dir_it) ;
|
||||
}
|
||||
|
||||
LocalDirectoryUpdater::recursUpdateSharedDir(const std::string& cumulated_path,const DirectoryStorage::EntryIndex indx)
|
||||
void LocalDirectoryUpdater::recursUpdateSharedDir(const std::string& cumulated_path, DirectoryStorage::EntryIndex indx)
|
||||
{
|
||||
std::cerr << " parsing directory " << cumulated_path << ", index=" << indx << std::endl;
|
||||
|
||||
// make sure list of subdirs is the same
|
||||
|
||||
// make sure list of subfiles is the same
|
||||
|
||||
// request all hashes to the hashcache
|
||||
|
||||
librs::util::FolderIterator dirIt(cumulated_path);
|
||||
|
@ -60,22 +66,18 @@ LocalDirectoryUpdater::recursUpdateSharedDir(const std::string& cumulated_path,c
|
|||
|
||||
while(dirIt.readdir())
|
||||
{
|
||||
std::string name ;
|
||||
uint64_t size ;
|
||||
uint8_t type ;
|
||||
time_t mod_time ;
|
||||
|
||||
dirIt.readEntryInformation(type,name,size,mod_time) ;
|
||||
|
||||
switch(type)
|
||||
switch(dirIt.file_type())
|
||||
{
|
||||
case librs::util::FolderIterator::TYPE_FILE: subfiles.push_back(name) ;
|
||||
break;
|
||||
case librs::util::FolderIterator::TYPE_DIR: subdirs.push_back(name) ;
|
||||
case librs::util::FolderIterator::TYPE_FILE: subfiles.push_back(dirIt.file_name()) ;
|
||||
std::cerr << " adding sub-file \"" << dirIt.file_name() << "\"" << std::endl;
|
||||
break;
|
||||
|
||||
case librs::util::FolderIterator::TYPE_DIR: subdirs.push_back(dirIt.file_name()) ;
|
||||
std::cerr << " adding sub-dir \"" << dirIt.file_name() << "\"" << std::endl;
|
||||
break;
|
||||
|
||||
default:
|
||||
std::cerr << "(EE) Dir entry of unknown type with path \"" << cumulated_path << "/" << name << "\"" << std::endl;
|
||||
std::cerr << "(EE) Dir entry of unknown type with path \"" << cumulated_path << "/" << dirIt.file_name() << "\"" << std::endl;
|
||||
}
|
||||
}
|
||||
// update file and dir lists for current directory.
|
||||
|
@ -87,18 +89,16 @@ LocalDirectoryUpdater::recursUpdateSharedDir(const std::string& cumulated_path,c
|
|||
|
||||
for(DirectoryStorage::FileIterator dit(indx);dit;++dit)
|
||||
{
|
||||
// ask about the hash. If not present, ask HashCache. If not present, the callback will update it.
|
||||
// ask about the hash. If not present, ask HashCache. If not present, or different, the callback will update it.
|
||||
|
||||
if()
|
||||
if(mHashCache.requestHash(realpath,name,size,modtime,hash),this)
|
||||
mSharedDirectories->updateFileHash(*dit,hash) ;
|
||||
mHashCache->requestHash(dit.fullpath(),dit.size(),dit.modtime(),dit.hash(),this) ;
|
||||
}
|
||||
|
||||
// go through the list of sub-dirs and recursively update
|
||||
|
||||
DirectoryStorage::DirIterator stored_dir_it(indx) ;
|
||||
|
||||
for(std::list<std::string>::const_iterator real_dir_it(subdirs.begin());it!=subdirs.end();++real_dir_it, ++stored_dir_it)
|
||||
for(std::list<std::string>::const_iterator real_dir_it(subdirs.begin());real_dir_it!=subdirs.end();++real_dir_it, ++stored_dir_it)
|
||||
recursUpdateSharedDir(*real_dir_it, *stored_dir_it) ;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
// - local: directories are crawled n disk and files are hashed / requested from a cache
|
||||
// - remote: directories are requested remotely to a providing client
|
||||
//
|
||||
class HashCache ;
|
||||
#include "file_sharing/hash_cache.h"
|
||||
|
||||
class LocalDirectoryStorage ;
|
||||
|
||||
class DirectoryUpdater
|
||||
|
@ -19,12 +20,16 @@ class DirectoryUpdater
|
|||
//
|
||||
};
|
||||
|
||||
class LocalDirectoryUpdater: public DirectoryUpdater
|
||||
class LocalDirectoryUpdater: public DirectoryUpdater, public HashCacheClient
|
||||
{
|
||||
public:
|
||||
LocalDirectoryUpdater(HashCache *hash_cache) ;
|
||||
virtual void tick() ;
|
||||
|
||||
protected:
|
||||
virtual void hash_callback(const std::string& full_name,const RsFileHash& hash) ;
|
||||
void recursUpdateSharedDir(const std::string& cumulated_path,DirectoryStorage::EntryIndex indx);
|
||||
|
||||
private:
|
||||
HashCache *mHashCache ;
|
||||
LocalDirectoryStorage *mSharedDirectories ;
|
||||
|
|
|
@ -2,14 +2,28 @@
|
|||
|
||||
#include <map>
|
||||
#include "util/rsthreads.h"
|
||||
#include "retroshare/rsfiles.h"
|
||||
|
||||
class HashCacheClient
|
||||
{
|
||||
public:
|
||||
virtual void hash_callback(const std::string& full_path,const RsFileHash& hash) ;
|
||||
};
|
||||
|
||||
class FileHashingThread: public RsTickingThread
|
||||
{
|
||||
public:
|
||||
FileHashingThread() {}
|
||||
|
||||
virtual void data_tick() ;
|
||||
};
|
||||
|
||||
class HashCache
|
||||
{
|
||||
public:
|
||||
HashCache(const std::string& save_file_name) ;
|
||||
|
||||
void insert(const std::string& full_path,uint64_t size,time_t time_stamp,const RsFileHash& hash) ;
|
||||
bool find(const std::string& full_path,uint64_t size,time_t time_stamp,RsFileHash& hash) ;
|
||||
bool requestHash(const std::string& full_path,uint64_t size,time_t mod_time,const RsFileHash& known_hash,HashCacheClient *c) ;
|
||||
|
||||
struct HashCacheInfo
|
||||
{
|
||||
|
@ -21,10 +35,10 @@ public:
|
|||
} ;
|
||||
|
||||
// interaction with GUI, called from p3FileLists
|
||||
void setRememberHashFilesDuration(uint32_t days) { _max_cache_duration_days = days ; }
|
||||
uint32_t rememberHashFilesDuration() const { return _max_cache_duration_days ; }
|
||||
void clear() { _files.clear(); }
|
||||
bool empty() const { return _files.empty() ; }
|
||||
void setRememberHashFilesDuration(uint32_t days) { mMaxCacheDurationDays = days ; }
|
||||
uint32_t rememberHashFilesDuration() const { return mMaxCacheDurationDays ; }
|
||||
void clear() { mFiles.clear(); }
|
||||
bool empty() const { return mFiles.empty() ; }
|
||||
|
||||
private:
|
||||
void clean() ;
|
||||
|
@ -33,7 +47,7 @@ private:
|
|||
void load() ;
|
||||
|
||||
// threaded stuff
|
||||
RsTickingThread mHashingThread ;
|
||||
FileHashingThread mHashingThread ;
|
||||
RsMutex mHashMtx ;
|
||||
|
||||
// Local configuration and storage
|
||||
|
@ -45,6 +59,6 @@ private:
|
|||
|
||||
// current work
|
||||
|
||||
std::map<std::string> mFilesToHash ;
|
||||
std::map<std::string,HashCacheClient *> mFilesToHash ;
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue