added parent row and friend status to shared dirs

This commit is contained in:
mr-alice 2016-08-11 14:07:45 +02:00
parent 82c18bbb86
commit d8dfce4fff
5 changed files with 267 additions and 65 deletions

View File

@ -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<DirectoryStorage::EntryIndex> subdirs ;
std::vector<DirectoryStorage::EntryIndex> 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<std::string>::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<FileEntry*>(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<std::string>& 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;
}

View File

@ -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<EntryIndex> &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<std::string>& subdirs) ;
bool updateSubFilesList(const EntryIndex& indx, const std::map<std::string, FileTS> &subfiles, std::map<std::string, FileTS> &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<SharedDirInfo>& 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;

View File

@ -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;i<mRemoteDirectories.size();++i)
delete mRemoteDirectories[i];
for(uint32_t i=0;i<mDirectories.size();++i)
delete mDirectories[i];
mRemoteDirectories.clear(); // just a precaution, not to leave deleted pointers around.
mDirectories.clear(); // just a precaution, not to leave deleted pointers around.
delete mLocalSharedDirs ;
delete mLocalDirWatcher ;
@ -172,19 +174,19 @@ void p3FileDatabase::cleanup()
friend_set.insert(*it) ;
}
for(uint32_t i=0;i<mRemoteDirectories.size();++i)
if(friend_set.find(mRemoteDirectories[i]->peerId()) == friend_set.end())
for(uint32_t i=1;i<mDirectories.size();++i) // start at 1, so that we don't cleanup our own.
if(friend_set.find(mDirectories[i]->peerId()) == 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;i<mRemoteDirectories.size() && mRemoteDirectories[i] != NULL;++i);
for(i=0;i<mDirectories.size() && mDirectories[i] != NULL;++i);
if(i == mRemoteDirectories.size())
mRemoteDirectories.push_back(NULL) ;
if(i == mDirectories.size())
mDirectories.push_back(NULL) ;
mRemoteDirectories[i] = new RemoteDirectoryStorage(*it,makeRemoteFileName(*it));
mDirectories[i] = new RemoteDirectoryStorage(*it,makeRemoteFileName(*it));
mFriendIndexTab[i] = *it ;
mFriendIndexMap[*it] = i;
@ -264,7 +266,7 @@ const RsPeerId& p3FileDatabase::getFriendFromIndex(uint32_t indx) const
return mFriendIndexTab[indx];
}
bool p3FileDatabase::convertPointerToEntryIndex(void *p, EntryIndex& e, uint32_t& friend_index)
bool p3FileDatabase::convertPointerToEntryIndex(const void *p, EntryIndex& e, uint32_t& friend_index)
{
// trust me, I can do this ;-)
@ -273,7 +275,7 @@ bool p3FileDatabase::convertPointerToEntryIndex(void *p, EntryIndex& e, uint32_t
return true;
}
bool p3FileDatabase::convertEntryIndexToPointer(EntryIndex& e, uint32_t fi, void *& p)
bool p3FileDatabase::convertEntryIndexToPointer(const EntryIndex& e, uint32_t fi, void *& p)
{
// the pointer is formed the following way:
//
@ -295,16 +297,64 @@ bool p3FileDatabase::convertEntryIndexToPointer(EntryIndex& e, uint32_t fi, void
return true;
}
int p3FileDatabase::RequestDirDetails(void *ref, DirDetails&, FileSearchFlags) const
// This function converts a pointer into directory details, to be used by the AbstractItemModel for browsing the files.
int p3FileDatabase::RequestDirDetails(void *ref, DirDetails& d, FileSearchFlags flags) const
{
// Case where the pointer is NULL, which means we're at the top of the list of shared directories for all friends (including us)
if (ref == NULL)
{
for(uint32_t i=0;i<mDirectories.size();++i)
{
void *p;
convertEntryIndexToPointer(mDirectories[i]->root(),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<DirStub>::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();

View File

@ -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<RemoteDirectoryStorage *> mRemoteDirectories ;
std::vector<DirectoryStorage *> 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;

View File

@ -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<DirStub> children;
std::list<std::string> parent_groups; // parent groups for the shared directory
std::list<DirStub> children;
std::list<std::string> parent_groups; // parent groups for the shared directory
};
class FileDetail