mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
fixed compilation/running of directory updater
This commit is contained in:
parent
25c824fd5f
commit
d86b89b15a
@ -22,6 +22,7 @@ class InternalFileHierarchyStorage
|
|||||||
class FileStorageNode
|
class FileStorageNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static const uint32_t TYPE_UNKNOWN = 0x0000 ;
|
||||||
static const uint32_t TYPE_FILE = 0x0001 ;
|
static const uint32_t TYPE_FILE = 0x0001 ;
|
||||||
static const uint32_t TYPE_DIR = 0x0002 ;
|
static const uint32_t TYPE_DIR = 0x0002 ;
|
||||||
|
|
||||||
@ -45,7 +46,7 @@ class InternalFileHierarchyStorage
|
|||||||
class DirEntry: public FileStorageNode
|
class DirEntry: public FileStorageNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DirEntry(const std::string& name,DirectoryStorage::EntryIndex parent) : dir_name(name),parent_index(parent) {}
|
DirEntry(const std::string& name,DirectoryStorage::EntryIndex parent) : dir_name(name),parent_index(DirectoryStorage::NO_INDEX) {}
|
||||||
virtual ~DirEntry() {}
|
virtual ~DirEntry() {}
|
||||||
|
|
||||||
virtual uint32_t type() const { return FileStorageNode::TYPE_DIR ; }
|
virtual uint32_t type() const { return FileStorageNode::TYPE_DIR ; }
|
||||||
@ -66,18 +67,15 @@ class InternalFileHierarchyStorage
|
|||||||
|
|
||||||
// high level modification routines
|
// high level modification routines
|
||||||
|
|
||||||
bool isIndexValid(DirectoryStorage::EntryIndex e)
|
bool isIndexValid(DirectoryStorage::EntryIndex e) const
|
||||||
{
|
{
|
||||||
return e < mNodes.size() && mNodes[e] != NULL ;
|
return e < mNodes.size() && mNodes[e] != NULL ;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool updateSubDirectoryList(const DirectoryStorage::EntryIndex& indx,const std::set<std::string>& subdirs)
|
bool updateSubDirectoryList(const DirectoryStorage::EntryIndex& indx,const std::set<std::string>& subdirs)
|
||||||
{
|
{
|
||||||
if(indx >= mNodes.size() || mNodes[indx] == NULL)
|
if(!checkIndex(indx,FileStorageNode::TYPE_DIR))
|
||||||
return nodeAccessError("updateSubDirectoryList(): Node does not exist") ;
|
return false;
|
||||||
|
|
||||||
if(mNodes[indx]->type() != FileStorageNode::TYPE_DIR)
|
|
||||||
return nodeAccessError("updateSubDirectoryList(): Node is not a directory") ;
|
|
||||||
|
|
||||||
DirEntry& d(*static_cast<DirEntry*>(mNodes[indx])) ;
|
DirEntry& d(*static_cast<DirEntry*>(mNodes[indx])) ;
|
||||||
|
|
||||||
@ -104,14 +102,11 @@ class InternalFileHierarchyStorage
|
|||||||
{
|
{
|
||||||
// check that it's a directory
|
// check that it's a directory
|
||||||
|
|
||||||
if(indx >= mNodes.size() || mNodes[indx] == NULL)
|
if(!checkIndex(indx,FileStorageNode::TYPE_DIR))
|
||||||
return nodeAccessError("removeDirectory(): Node does not exist") ;
|
return false;
|
||||||
|
|
||||||
if(mNodes[indx]->type() != FileStorageNode::TYPE_DIR)
|
|
||||||
return nodeAccessError("removeDirectory(): Node is not a directory") ;
|
|
||||||
|
|
||||||
if(indx == 0)
|
if(indx == 0)
|
||||||
return nodeAccessError("removeDirectory(): Cannot remove top level directory") ;
|
return nodeAccessError("checkIndex(): Cannot remove top level directory") ;
|
||||||
|
|
||||||
// remove from parent
|
// remove from parent
|
||||||
|
|
||||||
@ -125,13 +120,21 @@ class InternalFileHierarchyStorage
|
|||||||
return nodeAccessError("removeDirectory(): inconsistency!!") ;
|
return nodeAccessError("removeDirectory(): inconsistency!!") ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool checkIndex(DirectoryStorage::EntryIndex indx,uint8_t type) const
|
||||||
|
{
|
||||||
|
if(mNodes.empty() || indx==DirectoryStorage::NO_INDEX || indx >= mNodes.size() || mNodes[indx] == NULL)
|
||||||
|
return nodeAccessError("checkIndex(): Node does not exist") ;
|
||||||
|
|
||||||
|
if(mNodes[indx]->type() != type)
|
||||||
|
return nodeAccessError("checkIndex(): Node is of wrong type") ;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool updateSubFilesList(const DirectoryStorage::EntryIndex& indx,const std::set<std::string>& subfiles,std::set<std::string>& new_files)
|
bool updateSubFilesList(const DirectoryStorage::EntryIndex& indx,const std::set<std::string>& subfiles,std::set<std::string>& new_files)
|
||||||
{
|
{
|
||||||
if(indx >= mNodes.size() || mNodes[indx] == NULL)
|
if(!checkIndex(indx,FileStorageNode::TYPE_DIR))
|
||||||
return nodeAccessError("updateSubFilesList(): Node does not exist") ;
|
return false;
|
||||||
|
|
||||||
if(mNodes[indx]->type() != FileStorageNode::TYPE_DIR)
|
|
||||||
return nodeAccessError("updateSubFilesList(): Node is not a directory") ;
|
|
||||||
|
|
||||||
DirEntry& d(*static_cast<DirEntry*>(mNodes[indx])) ;
|
DirEntry& d(*static_cast<DirEntry*>(mNodes[indx])) ;
|
||||||
new_files = subfiles ;
|
new_files = subfiles ;
|
||||||
@ -155,14 +158,32 @@ class InternalFileHierarchyStorage
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
void updateFile(const DirectoryStorage::EntryIndex& parent_dir,const RsFileHash& hash, const std::string& fname, const uint32_t modf_time) ;
|
bool updateHash(const DirectoryStorage::EntryIndex& file_index,const RsFileHash& hash)
|
||||||
void updateDirectory(const DirectoryStorage::EntryIndex& parent_dir,const std::string& dname) ;
|
{
|
||||||
|
if(!checkIndex(file_index,FileStorageNode::TYPE_FILE))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
static_cast<FileEntry*>(mNodes[file_index])->file_hash = hash ;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool updateFile(const DirectoryStorage::EntryIndex& file_index,const RsFileHash& hash, const std::string& fname,uint64_t size, const uint32_t modf_time)
|
||||||
|
{
|
||||||
|
if(!checkIndex(file_index,FileStorageNode::TYPE_FILE))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
FileEntry& fe(*static_cast<FileEntry*>(mNodes[file_index])) ;
|
||||||
|
|
||||||
|
fe.file_hash = hash;
|
||||||
|
fe.file_size = size;
|
||||||
|
fe.file_modtime = modf_time;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// file/dir access and modification
|
// 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
|
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 ;
|
uint32_t mRoot ;
|
||||||
|
|
||||||
std::vector<FileStorageNode*> mNodes;// uses pointers to keep information about valid/invalid objects.
|
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
|
void compress() ; // use empty space in the vector, mostly due to deleted entries. This is a complicated operation, mostly due to
|
||||||
@ -171,11 +192,25 @@ class InternalFileHierarchyStorage
|
|||||||
|
|
||||||
friend class DirectoryStorage ; // only class that can use this.
|
friend class DirectoryStorage ; // only class that can use this.
|
||||||
|
|
||||||
// low level stuff. Should normally not be used externally.
|
// Low level stuff. Should normally not be used externally.
|
||||||
|
|
||||||
|
const DirEntry *getDirEntry(DirectoryStorage::EntryIndex indx) const
|
||||||
|
{
|
||||||
|
if(!checkIndex(indx,FileStorageNode::TYPE_DIR))
|
||||||
|
return NULL ;
|
||||||
|
|
||||||
|
return static_cast<DirEntry*>(mNodes[indx]) ;
|
||||||
|
}
|
||||||
|
const FileEntry *getFileEntry(DirectoryStorage::EntryIndex indx) const
|
||||||
|
{
|
||||||
|
if(!checkIndex(indx,FileStorageNode::TYPE_FILE))
|
||||||
|
return NULL ;
|
||||||
|
|
||||||
|
return static_cast<FileEntry*>(mNodes[indx]) ;
|
||||||
|
}
|
||||||
DirectoryStorage::EntryIndex getSubFileIndex(DirectoryStorage::EntryIndex parent_index,uint32_t file_tab_index)
|
DirectoryStorage::EntryIndex getSubFileIndex(DirectoryStorage::EntryIndex parent_index,uint32_t file_tab_index)
|
||||||
{
|
{
|
||||||
if(parent_index >= mNodes.size() || mNodes[parent_index] == NULL || mNodes[parent_index]->type() != FileStorageNode::TYPE_DIR)
|
if(!checkIndex(parent_index,FileStorageNode::TYPE_DIR))
|
||||||
return DirectoryStorage::NO_INDEX;
|
return DirectoryStorage::NO_INDEX;
|
||||||
|
|
||||||
if(static_cast<DirEntry*>(mNodes[parent_index])->subfiles.size() <= file_tab_index)
|
if(static_cast<DirEntry*>(mNodes[parent_index])->subfiles.size() <= file_tab_index)
|
||||||
@ -185,7 +220,7 @@ class InternalFileHierarchyStorage
|
|||||||
}
|
}
|
||||||
DirectoryStorage::EntryIndex getSubDirIndex(DirectoryStorage::EntryIndex parent_index,uint32_t dir_tab_index)
|
DirectoryStorage::EntryIndex getSubDirIndex(DirectoryStorage::EntryIndex parent_index,uint32_t dir_tab_index)
|
||||||
{
|
{
|
||||||
if(parent_index >= mNodes.size() || mNodes[parent_index] == NULL || mNodes[parent_index]->type() != FileStorageNode::TYPE_DIR)
|
if(!checkIndex(parent_index,FileStorageNode::TYPE_DIR))
|
||||||
return DirectoryStorage::NO_INDEX;
|
return DirectoryStorage::NO_INDEX;
|
||||||
|
|
||||||
if(static_cast<DirEntry*>(mNodes[parent_index])->subdirs.size() <= dir_tab_index)
|
if(static_cast<DirEntry*>(mNodes[parent_index])->subdirs.size() <= dir_tab_index)
|
||||||
@ -203,7 +238,7 @@ class InternalFileHierarchyStorage
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
bool nodeAccessError(const std::string& s)
|
static bool nodeAccessError(const std::string& s)
|
||||||
{
|
{
|
||||||
std::cerr << "(EE) InternalDirectoryStructure: ERROR: " << s << std::endl;
|
std::cerr << "(EE) InternalDirectoryStructure: ERROR: " << s << std::endl;
|
||||||
return false ;
|
return false ;
|
||||||
@ -256,46 +291,58 @@ DirectoryStorage::FileIterator& DirectoryStorage::FileIterator::operator++()
|
|||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
DirectoryStorage::EntryIndex DirectoryStorage::DirIterator::operator*() const
|
DirectoryStorage::EntryIndex DirectoryStorage::FileIterator::operator*() const { return mStorage->getSubFileIndex(mParentIndex,mFileTabIndex) ; }
|
||||||
{
|
DirectoryStorage::EntryIndex DirectoryStorage::DirIterator ::operator*() const { return mStorage->getSubDirIndex(mParentIndex,mDirTabIndex) ; }
|
||||||
return mStorage->getSubDirIndex(mParentIndex,mDirTabIndex) ;
|
|
||||||
}
|
DirectoryStorage::FileIterator::operator bool() const { return **this != DirectoryStorage::NO_INDEX; }
|
||||||
DirectoryStorage::EntryIndex DirectoryStorage::FileIterator::operator*() const
|
DirectoryStorage::DirIterator ::operator bool() const { return **this != DirectoryStorage::NO_INDEX; }
|
||||||
{
|
|
||||||
return mStorage->getSubFileIndex(mParentIndex,mFileTabIndex) ;
|
RsFileHash DirectoryStorage::FileIterator::hash() const { const InternalFileHierarchyStorage::FileEntry *f = mStorage->getFileEntry(**this) ; return f?(f->file_hash):RsFileHash(); }
|
||||||
}
|
uint64_t DirectoryStorage::FileIterator::size() const { const InternalFileHierarchyStorage::FileEntry *f = mStorage->getFileEntry(**this) ; return f?(f->file_size):0; }
|
||||||
DirectoryStorage::DirIterator::operator bool() const
|
std::string DirectoryStorage::FileIterator::name() const { const InternalFileHierarchyStorage::FileEntry *f = mStorage->getFileEntry(**this) ; return f?(f->file_name):std::string(); }
|
||||||
{
|
std::string DirectoryStorage::FileIterator::fullpath() const { const InternalFileHierarchyStorage::FileEntry *f = mStorage->getFileEntry(**this) ; return f?(f->file_name):std::string(); }
|
||||||
return **this != DirectoryStorage::NO_INDEX;
|
time_t DirectoryStorage::FileIterator::modtime() const { const InternalFileHierarchyStorage::FileEntry *f = mStorage->getFileEntry(**this) ; return f?(f->file_modtime):0; }
|
||||||
}
|
|
||||||
DirectoryStorage::FileIterator::operator bool() const
|
|
||||||
{
|
|
||||||
return **this != DirectoryStorage::NO_INDEX;
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************************************************/
|
/******************************************************************************************************************/
|
||||||
/* Directory Storage */
|
/* Directory Storage */
|
||||||
/******************************************************************************************************************/
|
/******************************************************************************************************************/
|
||||||
|
|
||||||
DirectoryStorage::DirIterator DirectoryStorage::root()
|
DirectoryStorage::DirectoryStorage(const std::string& local_file_name)
|
||||||
|
: mFileName(local_file_name), mDirStorageMtx("Directory storage "+local_file_name)
|
||||||
{
|
{
|
||||||
return DirIterator(this,EntryIndex(0)) ;
|
mFileHierarchy = new InternalFileHierarchyStorage();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DirectoryStorage::updateSubDirectoryList(const EntryIndex& indx,const std::set<std::string>& subdirs)
|
DirectoryStorage::EntryIndex DirectoryStorage::root() const
|
||||||
{
|
{
|
||||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
return EntryIndex(0) ;
|
||||||
mFileHierarchy->updateSubDirectoryList(indx,subdirs) ;
|
|
||||||
}
|
}
|
||||||
void DirectoryStorage::updateSubFilesList(const EntryIndex& indx,const std::set<std::string>& subfiles,std::set<std::string>& new_files)
|
|
||||||
|
bool DirectoryStorage::updateSubDirectoryList(const EntryIndex& indx,const std::set<std::string>& subdirs)
|
||||||
{
|
{
|
||||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||||
mFileHierarchy->updateSubFilesList(indx,subfiles,new_files) ;
|
return mFileHierarchy->updateSubDirectoryList(indx,subdirs) ;
|
||||||
}
|
}
|
||||||
void DirectoryStorage::removeDirectory(const EntryIndex& indx)
|
bool DirectoryStorage::updateSubFilesList(const EntryIndex& indx,const std::set<std::string>& subfiles,std::set<std::string>& new_files)
|
||||||
{
|
{
|
||||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||||
mFileHierarchy->removeDirectory(indx);
|
return mFileHierarchy->updateSubFilesList(indx,subfiles,new_files) ;
|
||||||
|
}
|
||||||
|
bool DirectoryStorage::removeDirectory(const EntryIndex& indx)
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||||
|
return mFileHierarchy->removeDirectory(indx);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DirectoryStorage::updateFile(const EntryIndex& index,const RsFileHash& hash,const std::string& fname, uint64_t size,time_t modf_time)
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||||
|
return mFileHierarchy->updateFile(index,hash,fname,size,modf_time);
|
||||||
|
}
|
||||||
|
bool DirectoryStorage::updateHash(const EntryIndex& index,const RsFileHash& hash)
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||||
|
return mFileHierarchy->updateHash(index,hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
// static const uint8_t DIRECTORY_STORAGE_TAG_FILE_HASH = 0x01 ;
|
// static const uint8_t DIRECTORY_STORAGE_TAG_FILE_HASH = 0x01 ;
|
||||||
@ -321,3 +368,18 @@ void DirectoryStorage::save(const std::string& local_file_name)
|
|||||||
{
|
{
|
||||||
// first write the header, than all fields.
|
// first write the header, than all fields.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************************************************************/
|
||||||
|
/* Local Directory Storage */
|
||||||
|
/******************************************************************************************************************/
|
||||||
|
|
||||||
|
void LocalDirectoryStorage::setSharedDirectoryList(const std::list<SharedDirInfo>& lst)
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||||
|
mLocalDirs = lst ;
|
||||||
|
}
|
||||||
|
void LocalDirectoryStorage::getSharedDirectoryList(std::list<SharedDirInfo>& lst)
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||||
|
lst = mLocalDirs ;
|
||||||
|
}
|
||||||
|
@ -84,14 +84,14 @@ class DirectoryStorage
|
|||||||
InternalFileHierarchyStorage *mStorage ;
|
InternalFileHierarchyStorage *mStorage ;
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual DirIterator root() ; // returns the index of the root directory entry.
|
EntryIndex root() const ; // returns the index of the root directory entry.
|
||||||
|
|
||||||
void updateSubDirectoryList(const EntryIndex& indx,const std::set<std::string>& subdirs) ;
|
bool updateSubDirectoryList(const EntryIndex& indx,const std::set<std::string>& subdirs) ;
|
||||||
void updateSubFilesList(const EntryIndex& indx,const std::set<std::string>& subfiles,std::set<std::string>& new_files) ;
|
bool updateSubFilesList(const EntryIndex& indx,const std::set<std::string>& subfiles,std::set<std::string>& new_files) ;
|
||||||
void removeDirectory(const EntryIndex& indx) ;
|
bool removeDirectory(const EntryIndex& indx) ;
|
||||||
|
|
||||||
void updateFile(const EntryIndex& parent_dir,const RsFileHash& hash, const std::string& fname, const uint32_t modf_time) ;
|
bool updateFile(const EntryIndex& index,const RsFileHash& hash, const std::string& fname, uint64_t size, time_t modf_time) ;
|
||||||
void updateDirectory(const EntryIndex& parent_dir,const std::string& dname) ;
|
bool updateHash(const EntryIndex& index,const RsFileHash& hash);
|
||||||
|
|
||||||
void cleanup();
|
void cleanup();
|
||||||
|
|
||||||
@ -105,7 +105,9 @@ class DirectoryStorage
|
|||||||
// storage of internal structure. Totally hidden from the outside. EntryIndex is simply the index of the entry in the vector.
|
// storage of internal structure. Totally hidden from the outside. EntryIndex is simply the index of the entry in the vector.
|
||||||
|
|
||||||
InternalFileHierarchyStorage *mFileHierarchy ;
|
InternalFileHierarchyStorage *mFileHierarchy ;
|
||||||
|
std::string mFileName;
|
||||||
|
|
||||||
|
protected:
|
||||||
RsMutex mDirStorageMtx ;
|
RsMutex mDirStorageMtx ;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -119,7 +121,7 @@ public:
|
|||||||
class LocalDirectoryStorage: public DirectoryStorage
|
class LocalDirectoryStorage: public DirectoryStorage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LocalDirectoryStorage() ;
|
LocalDirectoryStorage(const std::string& fname) : DirectoryStorage(fname) {}
|
||||||
virtual ~LocalDirectoryStorage() {}
|
virtual ~LocalDirectoryStorage() {}
|
||||||
|
|
||||||
void setSharedDirectoryList(const std::list<SharedDirInfo>& lst) ;
|
void setSharedDirectoryList(const std::list<SharedDirInfo>& lst) ;
|
||||||
|
@ -10,9 +10,10 @@ void RemoteDirectoryUpdater::tick()
|
|||||||
// use the stored iterator
|
// use the stored iterator
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalDirectoryUpdater::LocalDirectoryUpdater(HashCache *hc)
|
LocalDirectoryUpdater::LocalDirectoryUpdater(HashStorage *hc)
|
||||||
: mHashCache(hc)
|
: mHashCache(hc)
|
||||||
{
|
{
|
||||||
|
mSharedDirectories = new LocalDirectoryStorage("local_storage.txt");
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalDirectoryUpdater::tick()
|
void LocalDirectoryUpdater::tick()
|
||||||
@ -35,11 +36,11 @@ void LocalDirectoryUpdater::tick()
|
|||||||
|
|
||||||
// make sure that entries in stored_dir_it are the same than paths in real_dir_it, and in the same order.
|
// 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
|
// now for each of them, go recursively and match both files and dirs
|
||||||
|
|
||||||
DirectoryStorage::DirIterator stored_dir_it(mSharedDirectories->root()) ;
|
DirectoryStorage::DirIterator stored_dir_it(mSharedDirectories,mSharedDirectories->root()) ;
|
||||||
|
|
||||||
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)
|
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) ;
|
recursUpdateSharedDir(real_dir_it->filename, *stored_dir_it) ;
|
||||||
@ -66,7 +67,7 @@ void LocalDirectoryUpdater::recursUpdateSharedDir(const std::string& cumulated_p
|
|||||||
std::set<std::string> subfiles ;
|
std::set<std::string> subfiles ;
|
||||||
std::set<std::string> subdirs ;
|
std::set<std::string> subdirs ;
|
||||||
|
|
||||||
while(dirIt.readdir())
|
for(;dirIt.isValid();dirIt.next())
|
||||||
{
|
{
|
||||||
switch(dirIt.file_type())
|
switch(dirIt.file_type())
|
||||||
{
|
{
|
||||||
@ -91,18 +92,27 @@ void LocalDirectoryUpdater::recursUpdateSharedDir(const std::string& cumulated_p
|
|||||||
|
|
||||||
// now go through list of subfiles and request the hash to hashcache
|
// now go through list of subfiles and request the hash to hashcache
|
||||||
|
|
||||||
for(DirectoryStorage::FileIterator dit(indx);dit;++dit)
|
for(DirectoryStorage::FileIterator dit(mSharedDirectories,indx);dit;++dit)
|
||||||
{
|
{
|
||||||
// ask about the hash. If not present, ask HashCache. If not present, or different, the callback will update it.
|
// ask about the hash. If not present, ask HashCache. If not present, or different, the callback will update it.
|
||||||
|
|
||||||
mHashCache->requestHash(dit.fullpath(),dit.size(),dit.modtime(),dit.hash(),this) ;
|
RsFileHash hash ;
|
||||||
|
|
||||||
|
if(mHashCache->requestHash(dit.fullpath(),dit.size(),dit.modtime(),hash,this,*dit) && dit.hash() != hash)
|
||||||
|
mSharedDirectories->updateHash(*dit,hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
// go through the list of sub-dirs and recursively update
|
// go through the list of sub-dirs and recursively update
|
||||||
|
|
||||||
DirectoryStorage::DirIterator stored_dir_it(indx) ;
|
DirectoryStorage::DirIterator stored_dir_it(mSharedDirectories,indx) ;
|
||||||
|
|
||||||
for(std::set<std::string>::const_iterator real_dir_it(subdirs.begin());real_dir_it!=subdirs.end();++real_dir_it, ++stored_dir_it)
|
for(std::set<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) ;
|
recursUpdateSharedDir(*real_dir_it, *stored_dir_it) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -20,20 +20,20 @@ class DirectoryUpdater
|
|||||||
//
|
//
|
||||||
};
|
};
|
||||||
|
|
||||||
class LocalDirectoryUpdater: public DirectoryUpdater, public HashCacheClient
|
class LocalDirectoryUpdater: public DirectoryUpdater, public HashStorageClient
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LocalDirectoryUpdater(HashCache *hash_cache) ;
|
LocalDirectoryUpdater(HashStorage *hash_cache) ;
|
||||||
virtual ~LocalDirectoryUpdater() {}
|
virtual ~LocalDirectoryUpdater() {}
|
||||||
|
|
||||||
virtual void tick() ;
|
virtual void tick() ;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void hash_callback(const std::string& full_name,const RsFileHash& hash) ;
|
virtual void hash_callback(uint32_t client_param, const std::string& name, const RsFileHash& hash, uint64_t size);
|
||||||
void recursUpdateSharedDir(const std::string& cumulated_path,DirectoryStorage::EntryIndex indx);
|
void recursUpdateSharedDir(const std::string& cumulated_path,DirectoryStorage::EntryIndex indx);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HashCache *mHashCache ;
|
HashStorage *mHashCache ;
|
||||||
LocalDirectoryStorage *mSharedDirectories ;
|
LocalDirectoryStorage *mSharedDirectories ;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -0,0 +1,124 @@
|
|||||||
|
#include "util/rsdir.h"
|
||||||
|
#include "hash_cache.h"
|
||||||
|
|
||||||
|
#define HASHSTORAGE_DEBUG 1
|
||||||
|
|
||||||
|
HashStorage::HashStorage(const std::string& save_file_name)
|
||||||
|
: mFilePath(save_file_name), mHashMtx("Hash Storage mutex")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void HashStorage::data_tick()
|
||||||
|
{
|
||||||
|
std::cerr << "Ticking hash thread." << std::endl;
|
||||||
|
|
||||||
|
FileHashJob job;
|
||||||
|
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mHashMtx) ;
|
||||||
|
|
||||||
|
if(mFilesToHash.empty())
|
||||||
|
return ;
|
||||||
|
|
||||||
|
job = mFilesToHash.begin()->second ;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cerr << "Hashing file " << job.full_path << "..." ; std::cerr.flush();
|
||||||
|
|
||||||
|
RsFileHash hash;
|
||||||
|
uint64_t size ;
|
||||||
|
|
||||||
|
if(!RsDirUtil::getFileHash(job.full_path, hash,size, this))
|
||||||
|
{
|
||||||
|
std::cerr << "ERROR" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// update the hash storage
|
||||||
|
|
||||||
|
|
||||||
|
// call the client
|
||||||
|
|
||||||
|
job.client->hash_callback(job.client_param, job.full_path, hash, size);
|
||||||
|
|
||||||
|
std::cerr << "done."<< std::endl;
|
||||||
|
|
||||||
|
if(mFilesToHash.empty())
|
||||||
|
{
|
||||||
|
std::cerr << "Starting hashing thread." << std::endl;
|
||||||
|
fullstop();
|
||||||
|
std::cerr << "done." << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HashStorage::requestHash(const std::string& full_path,uint64_t size,time_t mod_time,RsFileHash& known_hash,HashStorageClient *c,uint32_t client_param)
|
||||||
|
{
|
||||||
|
// check if the hash is up to date w.r.t. cache.
|
||||||
|
|
||||||
|
RS_STACK_MUTEX(mHashMtx) ;
|
||||||
|
|
||||||
|
time_t now = time(NULL) ;
|
||||||
|
std::map<std::string,HashStorageInfo>::iterator it = mFiles.find(full_path) ;
|
||||||
|
|
||||||
|
if(it != mFiles.end() && (uint64_t)mod_time == it->second.modf_stamp && size == it->second.size)
|
||||||
|
{
|
||||||
|
it->second.time_stamp = now ;
|
||||||
|
#ifdef HASHCACHE_DEBUG
|
||||||
|
std::cerr << "Found in cache." << std::endl ;
|
||||||
|
#endif
|
||||||
|
return true ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we need to schedule a re-hashing
|
||||||
|
|
||||||
|
if(mFilesToHash.find(full_path) != mFilesToHash.end())
|
||||||
|
return false ;
|
||||||
|
|
||||||
|
FileHashJob job ;
|
||||||
|
|
||||||
|
job.client = c ;
|
||||||
|
job.client_param = client_param ;
|
||||||
|
job.full_path = full_path ;
|
||||||
|
|
||||||
|
mFilesToHash[full_path] = job;
|
||||||
|
|
||||||
|
if(!isRunning())
|
||||||
|
{
|
||||||
|
std::cerr << "Starting hashing thread." << std::endl;
|
||||||
|
start() ;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HashStorage::clean()
|
||||||
|
{
|
||||||
|
#ifdef HASHSTORAGE_DEBUG
|
||||||
|
std::cerr << "Cleaning HashStorage..." << std::endl ;
|
||||||
|
#endif
|
||||||
|
time_t now = time(NULL) ;
|
||||||
|
time_t duration = mMaxStorageDurationDays * 24 * 3600 ; // seconds
|
||||||
|
|
||||||
|
#ifdef HASHSTORAGE_DEBUG
|
||||||
|
std::cerr << "cleaning hash cache." << std::endl ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for(std::map<std::string,HashStorageInfo>::iterator it(mFiles.begin());it!=mFiles.end();)
|
||||||
|
if(it->second.time_stamp + duration < (uint64_t)now)
|
||||||
|
{
|
||||||
|
#ifdef HASHSTORAGE_DEBUG
|
||||||
|
std::cerr << " Entry too old: " << it->first << ", ts=" << it->second.time_stamp << std::endl ;
|
||||||
|
#endif
|
||||||
|
std::map<std::string,HashStorageInfo>::iterator tmp(it) ;
|
||||||
|
++tmp ;
|
||||||
|
mFiles.erase(it) ;
|
||||||
|
it=tmp ;
|
||||||
|
mChanged = true ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++it ;
|
||||||
|
|
||||||
|
#ifdef HASHSTORAGE_DEBUG
|
||||||
|
std::cerr << "Done." << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
@ -4,61 +4,78 @@
|
|||||||
#include "util/rsthreads.h"
|
#include "util/rsthreads.h"
|
||||||
#include "retroshare/rsfiles.h"
|
#include "retroshare/rsfiles.h"
|
||||||
|
|
||||||
class HashCacheClient
|
class HashStorageClient
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void hash_callback(const std::string& full_path,const RsFileHash& hash) ;
|
HashStorageClient() {}
|
||||||
|
virtual ~HashStorageClient() {}
|
||||||
|
|
||||||
|
virtual void hash_callback(uint32_t client_param, const std::string& name, const RsFileHash& hash, uint64_t size)=0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FileHashingThread: public RsTickingThread
|
class HashStorage: public RsTickingThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FileHashingThread() {}
|
HashStorage(const std::string& save_file_name) ;
|
||||||
|
|
||||||
virtual void data_tick() ;
|
/*!
|
||||||
};
|
* \brief requestHash Requests the hash for the given file, assuming size and mod_time are the same.
|
||||||
|
*
|
||||||
|
* \param full_path Full path to reach the file
|
||||||
|
* \param size Actual file size
|
||||||
|
* \param mod_time Actual file modification time
|
||||||
|
* \param known_hash Returned hash for the file.
|
||||||
|
* \param c Hash cache client to which the hash should be sent once calculated
|
||||||
|
* \param client_param Param to be passed to the client callback
|
||||||
|
*
|
||||||
|
* \return true if the supplied hash info is up to date.
|
||||||
|
*/
|
||||||
|
bool requestHash(const std::string& full_path, uint64_t size, time_t mod_time, RsFileHash& known_hash, HashStorageClient *c, uint32_t client_param) ;
|
||||||
|
|
||||||
class HashCache
|
struct HashStorageInfo
|
||||||
{
|
|
||||||
public:
|
|
||||||
HashCache(const std::string& save_file_name) ;
|
|
||||||
|
|
||||||
bool requestHash(const std::string& full_path,uint64_t size,time_t mod_time,const RsFileHash& known_hash,HashCacheClient *c) ;
|
|
||||||
|
|
||||||
struct HashCacheInfo
|
|
||||||
{
|
{
|
||||||
std::string filename ;
|
std::string filename ;
|
||||||
uint64_t size ;
|
uint64_t size ;
|
||||||
uint32_t time_stamp ;
|
uint32_t time_stamp ; // last time the hash was tested/requested
|
||||||
uint32_t modf_stamp ;
|
uint32_t modf_stamp ;
|
||||||
RsFileHash hash ;
|
RsFileHash hash ;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
// interaction with GUI, called from p3FileLists
|
// interaction with GUI, called from p3FileLists
|
||||||
void setRememberHashFilesDuration(uint32_t days) { mMaxCacheDurationDays = days ; }
|
void setRememberHashFilesDuration(uint32_t days) { mMaxStorageDurationDays = days ; }
|
||||||
uint32_t rememberHashFilesDuration() const { return mMaxCacheDurationDays ; }
|
uint32_t rememberHashFilesDuration() const { return mMaxStorageDurationDays ; }
|
||||||
void clear() { mFiles.clear(); }
|
void clear() { mFiles.clear(); }
|
||||||
bool empty() const { return mFiles.empty() ; }
|
bool empty() const { return mFiles.empty() ; }
|
||||||
|
|
||||||
|
// Functions called by the thread
|
||||||
|
|
||||||
|
virtual void data_tick() ;
|
||||||
private:
|
private:
|
||||||
void clean() ;
|
void clean() ;
|
||||||
|
|
||||||
void save() ;
|
void save() ;
|
||||||
void load() ;
|
void load() ;
|
||||||
|
|
||||||
// threaded stuff
|
|
||||||
FileHashingThread mHashingThread ;
|
|
||||||
RsMutex mHashMtx ;
|
|
||||||
|
|
||||||
// Local configuration and storage
|
// Local configuration and storage
|
||||||
|
|
||||||
uint32_t mMaxCacheDurationDays ; // maximum duration of un-requested cache entries
|
uint32_t mMaxStorageDurationDays ; // maximum duration of un-requested cache entries
|
||||||
std::map<std::string, HashCacheInfo> mFiles ;
|
std::map<std::string, HashStorageInfo> mFiles ; // stored as (full_path, hash_info)
|
||||||
std::string mFilePath ;
|
std::string mFilePath ;
|
||||||
bool mChanged ;
|
bool mChanged ;
|
||||||
|
|
||||||
// current work
|
struct FileHashJob
|
||||||
|
{
|
||||||
std::map<std::string,HashCacheClient *> mFilesToHash ;
|
std::string full_path;
|
||||||
|
HashStorageClient *client;
|
||||||
|
uint32_t client_param ;
|
||||||
|
};
|
||||||
|
|
||||||
|
// current work
|
||||||
|
|
||||||
|
std::map<std::string,FileHashJob> mFilesToHash ;
|
||||||
|
|
||||||
|
// thread/mutex stuff
|
||||||
|
|
||||||
|
RsMutex mHashMtx ;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user