diff --git a/libretroshare/src/file_sharing/directory_storage.cc b/libretroshare/src/file_sharing/directory_storage.cc index b91bbe4cb..5230ec2fd 100644 --- a/libretroshare/src/file_sharing/directory_storage.cc +++ b/libretroshare/src/file_sharing/directory_storage.cc @@ -30,6 +30,9 @@ class InternalFileHierarchyStorage virtual ~FileStorageNode() {} virtual uint32_t type() const =0; + + DirectoryStorage::EntryIndex parent_index; + uint32_t row ; }; class FileEntry: public FileStorageNode { @@ -48,23 +51,35 @@ class InternalFileHierarchyStorage class DirEntry: public FileStorageNode { public: - DirEntry(const std::string& name,DirectoryStorage::EntryIndex parent) : dir_name(name),parent_index(parent) {} + DirEntry(const std::string& name) : dir_name(name) {} virtual ~DirEntry() {} virtual uint32_t type() const { return FileStorageNode::TYPE_DIR ; } // local stuff std::string dir_name ; - DirectoryStorage::EntryIndex parent_index; + std::string dir_parent_path ; std::vector subdirs ; std::vector subfiles ; + + time_t most_recent_time; }; // class stuff InternalFileHierarchyStorage() : mRoot(0) { - mNodes.push_back(new DirEntry("",0)) ; + mNodes.push_back(new DirEntry("")) ; + mNodes.back()->row=0; + mNodes.back()->parent_index=-1; + } + + int parentRow(DirectoryStorage::EntryIndex e) + { + if(!checkIndex(e,FileStorageNode::TYPE_DIR | FileStorageNode::TYPE_FILE) || e==0) + return -1 ; + + return mNodes[mNodes[e]->parent_index]->row; } // high level modification routines @@ -95,7 +110,9 @@ class InternalFileHierarchyStorage for(std::set::const_iterator it(should_create.begin());it!=should_create.end();++it) { d.subdirs.push_back(mNodes.size()) ; - mNodes.push_back(new DirEntry(*it,indx)); + mNodes.push_back(new DirEntry(*it)); + mNodes.back()->row = mNodes.size()-1; + mNodes.back()->parent_index = indx; } return true; @@ -127,7 +144,7 @@ class InternalFileHierarchyStorage 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) + if(! mNodes[indx]->type() & type) return nodeAccessError("checkIndex(): Node is of wrong type") ; return true; @@ -172,6 +189,8 @@ class InternalFileHierarchyStorage { d.subfiles.push_back(mNodes.size()) ; mNodes.push_back(new FileEntry(it->first,it->second.size,it->second.modtime)); + mNodes.back()->row = mNodes.size()-1; + mNodes.back()->parent_index = indx; } return true; } @@ -208,6 +227,7 @@ class InternalFileHierarchyStorage // 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. @@ -225,6 +245,16 @@ class InternalFileHierarchyStorage return static_cast(mNodes[indx]) ; } + uint32_t getType(DirectoryStorage::EntryIndex indx) const + { + if(checkIndex(indx,FileStorageNode::TYPE_FILE)) + return FileStorageNode::TYPE_FILE; + else if(checkIndex(indx,FileStorageNode::TYPE_DIR)) + return FileStorageNode::TYPE_DIR; + else + return FileStorageNode::TYPE_UNKNOWN; + } + DirectoryStorage::EntryIndex getSubFileIndex(DirectoryStorage::EntryIndex parent_index,uint32_t file_tab_index) { if(!checkIndex(parent_index,FileStorageNode::TYPE_DIR)) @@ -368,12 +398,14 @@ uint64_t DirectoryStorage::FileIterator::size() const { const InternalFil std::string DirectoryStorage::FileIterator::name() const { const InternalFileHierarchyStorage::FileEntry *f = mStorage->getFileEntry(**this) ; return f?(f->file_name):std::string(); } time_t DirectoryStorage::FileIterator::modtime() const { const InternalFileHierarchyStorage::FileEntry *f = mStorage->getFileEntry(**this) ; return f?(f->file_modtime):0; } +std::string DirectoryStorage::DirIterator::name() const { const InternalFileHierarchyStorage::DirEntry *d = mStorage->getDirEntry(**this) ; return d?(d->dir_name):std::string(); } + /******************************************************************************************************************/ /* Directory Storage */ /******************************************************************************************************************/ -DirectoryStorage::DirectoryStorage(const std::string& local_file_name) - : mFileName(local_file_name), mDirStorageMtx("Directory storage "+local_file_name) +DirectoryStorage::DirectoryStorage(const std::string& local_file_name, const RsPeerId &pid) + : mFileName(local_file_name),mPeerId(pid), mDirStorageMtx("Directory storage "+local_file_name) { RS_STACK_MUTEX(mDirStorageMtx) ; mFileHierarchy = new InternalFileHierarchyStorage(); @@ -383,6 +415,25 @@ DirectoryStorage::EntryIndex DirectoryStorage::root() const { return EntryIndex(0) ; } +int DirectoryStorage::parentRow(EntryIndex e) const +{ + RS_STACK_MUTEX(mDirStorageMtx) ; + + return mFileHierarchy->parentRow(e) ; +} + +uint32_t DirectoryStorage::getEntryType(const EntryIndex& indx) +{ + RS_STACK_MUTEX(mDirStorageMtx) ; + + switch(mFileHierarchy->getType(indx)) + { + case InternalFileHierarchyStorage::FileStorageNode::TYPE_DIR: return DIR_TYPE_DIR ; + case InternalFileHierarchyStorage::FileStorageNode::TYPE_FILE: return DIR_TYPE_FILE ; + default: + return DIR_TYPE_UNKNOWN; + } +} bool DirectoryStorage::updateSubDirectoryList(const EntryIndex& indx,const std::set& subdirs) { @@ -440,6 +491,15 @@ void DirectoryStorage::print() std::cerr << "LocalDirectoryStorage:" << std::endl; mFileHierarchy->print(); } + +bool LocalDirectoryStorage::getFileInfo(DirectoryStorage::EntryIndex i,FileInfo& info) +{ + RS_STACK_MUTEX(mDirStorageMtx) ; +#warning todo + + return true; +} + /******************************************************************************************************************/ /* Local Directory Storage */ /******************************************************************************************************************/ @@ -534,10 +594,80 @@ std::string LocalDirectoryStorage::locked_findRealRootFromVirtualFilename(const return cit->second.filename; } -bool LocalDirectoryStorage::getFileInfo(DirectoryStorage::EntryIndex i,FileInfo& info) +bool LocalDirectoryStorage::extractData(const EntryIndex& indx,DirDetails& d) { - RS_STACK_MUTEX(mDirStorageMtx) ; - NOT_IMPLEMENTED() ; - return false; -} + d.children.clear() ; + time_t now = time(NULL) ; + const InternalFileHierarchyStorage::DirEntry *dir_entry = mFileHierarchy->getDirEntry(indx) ; + + if (dir_entry != NULL) /* has children --- fill */ + { +#ifdef FI_DEBUG + std::cerr << "FileIndex::extractData() ref=dir" << std::endl; +#endif + /* extract all the entries */ + + for(DirectoryStorage::DirIterator it(this,indx);it;++it) + { + DirStub stub; + stub.type = DIR_TYPE_DIR; + stub.name = it.name(); + stub.ref = (void*)(intptr_t)*it; // this is updated by the caller, who knows which friend we're dealing with + + d.children.push_back(stub); + } + + for(DirectoryStorage::FileIterator it(this,indx);it;++it) + { + DirStub stub; + stub.type = DIR_TYPE_FILE; + stub.name = it.name(); + stub.ref = (void*)(intptr_t)*it; + + d.children.push_back(stub); + } + + if(dir_entry->parent_index == 0) + d.type = DIR_TYPE_PERSON ; + else + d.type = DIR_TYPE_DIR; + + d.hash.clear() ; + d.count = dir_entry->subdirs.size() + dir_entry->subfiles.size(); + d.min_age = now - dir_entry->most_recent_time ; + d.name = dir_entry->dir_name; + d.path = dir_entry->dir_parent_path + "/" + dir_entry->dir_name ; + d.parent = (void*)(intptr_t)dir_entry->parent_index ; + } + else + { + const InternalFileHierarchyStorage::FileEntry *file_entry = mFileHierarchy->getFileEntry(indx) ; +#ifdef FI_DEBUG + std::cerr << "FileIndexStore::extractData() ref=file" << std::endl; +#endif + d.type = DIR_TYPE_FILE; + d.count = file_entry->file_size; + d.min_age = now - file_entry->file_modtime ; + d.name = file_entry->file_name; + d.hash = file_entry->file_hash; + d.age = now - file_entry->file_modtime; + d.parent = (void*)(intptr_t)file_entry->parent_index ; + + const InternalFileHierarchyStorage::DirEntry *parent_dir_entry = mFileHierarchy->getDirEntry(file_entry->parent_index); + + if(parent_dir_entry != NULL) + d.path = parent_dir_entry->dir_parent_path + "/" + parent_dir_entry->dir_name + "/" ; + else + d.path = "" ; + } + +#ifdef FI_DEBUG + std::cerr << "FileIndexStore::extractData() name: " << file->name << std::endl; +#endif + d.flags.clear() ; + + /* find parent pointer, and row */ + + return true; +} diff --git a/libretroshare/src/file_sharing/directory_storage.h b/libretroshare/src/file_sharing/directory_storage.h index 9e7872611..0bdbb9dd6 100644 --- a/libretroshare/src/file_sharing/directory_storage.h +++ b/libretroshare/src/file_sharing/directory_storage.h @@ -14,10 +14,10 @@ class InternalFileHierarchyStorage ; class DirectoryStorage { public: - DirectoryStorage(const std::string& local_file_name) ; + DirectoryStorage(const std::string& local_file_name,const RsPeerId& pid) ; virtual ~DirectoryStorage() {} - typedef uint32_t EntryIndex ; + typedef int32_t EntryIndex ; static const EntryIndex NO_INDEX = 0xffffffff; void save() const ; @@ -27,6 +27,8 @@ class DirectoryStorage virtual int searchBoolExp(Expression * exp, std::list &results) const { NOT_IMPLEMENTED() ; return 0; } void getFileDetails(EntryIndex i) ; + uint32_t getEntryType(const EntryIndex& indx) ; // returns DIR_TYPE_*, not the internal directory storage stuff. + virtual bool extractData(const EntryIndex& indx,DirDetails& d) =0; // This class allows to abstractly browse the stored directory hierarchy in a depth-first manner. // It gives access to sub-files and sub-directories below. @@ -44,7 +46,7 @@ class DirectoryStorage // info about the directory that is pointed by the iterator - const std::string& name() const ; + std::string name() const ; private: EntryIndex mParentIndex ; // index of the parent dir. uint32_t mDirTabIndex ; // index in the vector of subdirs. @@ -83,6 +85,8 @@ class DirectoryStorage }; EntryIndex root() const ; // returns the index of the root directory entry. + const RsPeerId& peerId() const { return mPeerId ; } + int parentRow(EntryIndex e) const ; bool updateSubDirectoryList(const EntryIndex& indx,const std::set& subdirs) ; bool updateSubFilesList(const EntryIndex& indx, const std::map &subfiles, std::map &new_files) ; @@ -103,28 +107,31 @@ class DirectoryStorage // storage of internal structure. Totally hidden from the outside. EntryIndex is simply the index of the entry in the vector. - InternalFileHierarchyStorage *mFileHierarchy ; std::string mFileName; + RsPeerId mPeerId; + protected: - RsMutex mDirStorageMtx ; + mutable RsMutex mDirStorageMtx ; + + InternalFileHierarchyStorage *mFileHierarchy ; }; class RemoteDirectoryStorage: public DirectoryStorage { public: - RemoteDirectoryStorage(const RsPeerId& pid,const std::string& fname) : DirectoryStorage(fname),mPeerId(pid) {} + RemoteDirectoryStorage(const RsPeerId& pid,const std::string& fname) : DirectoryStorage(fname,pid) {} virtual ~RemoteDirectoryStorage() {} - const RsPeerId& peerId() const { return mPeerId ; } - -private: - RsPeerId mPeerId; + virtual bool extractData(const EntryIndex& indx,DirDetails& d) + { + NOT_IMPLEMENTED(); + } }; class LocalDirectoryStorage: public DirectoryStorage { public: - LocalDirectoryStorage(const std::string& fname) : DirectoryStorage(fname) {} + LocalDirectoryStorage(const std::string& fname,const RsPeerId& own_id) : DirectoryStorage(fname,own_id) {} virtual ~LocalDirectoryStorage() {} void setSharedDirectoryList(const std::list& lst) ; @@ -140,6 +147,9 @@ public: * \return false if the file does not exist, or is a directory,... */ bool getFileInfo(DirectoryStorage::EntryIndex i,FileInfo& info) ; + + virtual bool extractData(const EntryIndex& indx,DirDetails& d) ; + private: std::string locked_findRealRootFromVirtualFilename(const std::string& virtual_rootdir) const; diff --git a/libretroshare/src/file_sharing/p3filelists.cc b/libretroshare/src/file_sharing/p3filelists.cc index 299d90029..1c6f50802 100644 --- a/libretroshare/src/file_sharing/p3filelists.cc +++ b/libretroshare/src/file_sharing/p3filelists.cc @@ -25,9 +25,11 @@ p3FileDatabase::p3FileDatabase(p3ServiceControl *mpeers) { // loads existing indexes for friends. Some might be already present here. // - mRemoteDirectories.clear() ; // we should load them! + mDirectories.clear() ; // we should load them! + + mLocalSharedDirs = new LocalDirectoryStorage("local_file_store.bin",mpeers->getOwnId()) ; + mDirectories.push_back(mLocalSharedDirs) ; - mLocalSharedDirs = new LocalDirectoryStorage("local_file_store.bin") ; mHashCache = new HashStorage("hash_cache.bin") ; mLocalDirWatcher = new LocalDirectoryUpdater(mHashCache,mLocalSharedDirs) ; @@ -58,10 +60,10 @@ p3FileDatabase::~p3FileDatabase() { RS_STACK_MUTEX(mFLSMtx) ; - for(uint32_t i=0;ipeerId()) == friend_set.end()) + for(uint32_t i=1;ipeerId()) == friend_set.end()) { - P3FILELISTS_DEBUG() << " removing file list of non friend " << mRemoteDirectories[i]->peerId() << std::endl; + P3FILELISTS_DEBUG() << " removing file list of non friend " << mDirectories[i]->peerId() << std::endl; - delete mRemoteDirectories[i]; - mRemoteDirectories[i] = NULL ; + delete mDirectories[i]; + mDirectories[i] = NULL ; mUpdateFlags |= P3FILELISTS_UPDATE_FLAG_REMOTE_MAP_CHANGED ; - friend_set.erase(mRemoteDirectories[i]->peerId()); + friend_set.erase(mDirectories[i]->peerId()); - mFriendIndexMap.erase(mRemoteDirectories[i]->peerId()); + mFriendIndexMap.erase(mDirectories[i]->peerId()); mFriendIndexTab[i].clear(); } @@ -195,12 +197,12 @@ void p3FileDatabase::cleanup() P3FILELISTS_DEBUG() << " adding missing remote dir entry for friend " << *it << std::endl; uint32_t i; - for(i=0;iroot(),i,p); + + DirStub stub; + stub.type = DIR_TYPE_PERSON; + stub.name = mDirectories[i]->peerId().toStdString(); + stub.ref = p; + d.children.push_back(stub); + } + d.count = mDirectories.size(); + + d.parent = NULL; + d.prow = -1; + d.ref = NULL; + d.type = DIR_TYPE_ROOT; + d.name = "root"; + d.hash.clear() ; + d.path = "root"; + d.age = 0; + d.flags.clear() ; + d.min_age = 0 ; + + return true ; + } + uint32_t fi; EntryIndex e ; - convertPointerToEntryIndex(ref,e,fi) ; -#warning code needed here + convertPointerToEntryIndex(ref,e,fi); - return 0; + // Case where the index is the top of a single person. Can be us, or a friend. + + bool res = mDirectories[fi]->extractData(e,d) ; + + // 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) ; + convertEntryIndexToPointer((intptr_t)d.parent,fi,d.parent) ; + + for(std::list::iterator it(d.children.begin());it!=d.children.end();++it) + convertEntryIndexToPointer((intptr_t)it->ref,fi,it->ref); + + d.prow = mDirectories[fi]->parentRow(e) ; + d.id = mDirectories[fi]->peerId(); } + int p3FileDatabase::RequestDirDetails(const RsPeerId& uid,const std::string& path, DirDetails &details) const { NOT_IMPLEMENTED(); @@ -317,9 +367,20 @@ int p3FileDatabase::RequestDirDetails(const std::string& path, DirDetails &detai } uint32_t p3FileDatabase::getType(void *ref) const { - NOT_IMPLEMENTED(); - return 0; + EntryIndex e ; + uint32_t fi; + + if(ref == NULL) + return DIR_TYPE_ROOT ; + + convertPointerToEntryIndex(ref,e,fi); + + if(e == 0) + return DIR_TYPE_PERSON ; + + return mDirectories[fi]->getEntryType(e) ; } + void p3FileDatabase::forceDirectoryCheck() // Force re-sweep the directories and see what's changed { NOT_IMPLEMENTED(); diff --git a/libretroshare/src/file_sharing/p3filelists.h b/libretroshare/src/file_sharing/p3filelists.h index d7c8e2250..cd090af61 100644 --- a/libretroshare/src/file_sharing/p3filelists.h +++ b/libretroshare/src/file_sharing/p3filelists.h @@ -147,16 +147,16 @@ class p3FileDatabase: public p3Service, public p3Config, public ftSearch //, pub // The remote one is the reference for the PeerId index below: // RemoteDirectories[ getFriendIndex(pid) - 1] = RemoteDirectoryStorage(pid) - std::vector mRemoteDirectories ; + std::vector mDirectories ; // mDirectories[0]=mLocalSharedDirs LocalDirectoryStorage *mLocalSharedDirs ; - RemoteDirectoryUpdater *mRemoteDirWatcher ; + RemoteDirectoryUpdater *mRemoteDirWatcher ; // not used yet. LocalDirectoryUpdater *mLocalDirWatcher ; // utility functions to make/get a pointer out of an (EntryIndex,PeerId) pair. This is further documented in the .cc - static bool convertEntryIndexToPointer(EntryIndex& e,uint32_t friend_index,void *& p); - static bool convertPointerToEntryIndex(void *p, EntryIndex& e, uint32_t& friend_index) ; + static bool convertEntryIndexToPointer(const EntryIndex &e, uint32_t friend_index, void *& p); + static bool convertPointerToEntryIndex(const void *p, EntryIndex& e, uint32_t& friend_index) ; uint32_t getFriendIndex(const RsPeerId& pid); const RsPeerId& getFriendFromIndex(uint32_t indx) const; diff --git a/libretroshare/src/retroshare/rstypes.h b/libretroshare/src/retroshare/rstypes.h index 37975d605..d30b156eb 100644 --- a/libretroshare/src/retroshare/rstypes.h +++ b/libretroshare/src/retroshare/rstypes.h @@ -138,6 +138,7 @@ public: /********************** For FileCache Interface *****************/ +#define DIR_TYPE_UNKNOWN 0x00 #define DIR_TYPE_ROOT 0x01 #define DIR_TYPE_PERSON 0x02 #define DIR_TYPE_DIR 0x04 @@ -159,7 +160,7 @@ const FileStorageFlags DIR_FLAGS_BROWSABLE_OTHERS ( 0x0100 ); // one should const FileStorageFlags DIR_FLAGS_NETWORK_WIDE_GROUPS ( 0x0200 ); const FileStorageFlags DIR_FLAGS_BROWSABLE_GROUPS ( 0x0400 ); const FileStorageFlags DIR_FLAGS_PERMISSIONS_MASK ( DIR_FLAGS_NETWORK_WIDE_OTHERS | DIR_FLAGS_BROWSABLE_OTHERS - | DIR_FLAGS_NETWORK_WIDE_GROUPS | DIR_FLAGS_BROWSABLE_GROUPS ); + | DIR_FLAGS_NETWORK_WIDE_GROUPS | DIR_FLAGS_BROWSABLE_GROUPS ); const FileStorageFlags DIR_FLAGS_LOCAL ( 0x1000 ); const FileStorageFlags DIR_FLAGS_REMOTE ( 0x2000 ); @@ -227,23 +228,23 @@ class DirStub class DirDetails { - public: - void *parent; - int prow; /* parent row */ +public: + void *parent; + int prow; /* parent row */ - void *ref; - uint8_t type; + void *ref; + uint8_t type; RsPeerId id; - std::string name; + std::string name; RsFileHash hash; - std::string path; - uint64_t count; - uint32_t age; - FileStorageFlags flags; - uint32_t min_age ; // minimum age of files in this subtree + std::string path; + uint64_t count; + uint32_t age; + FileStorageFlags flags; + uint32_t min_age ; // minimum age of files in this subtree - std::list children; - std::list parent_groups; // parent groups for the shared directory + std::list children; + std::list parent_groups; // parent groups for the shared directory }; class FileDetail