mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-26 16:09:35 -05:00
added interactive update of dir entries when browsing files from an online friend
This commit is contained in:
parent
3718e7e3e8
commit
c1e538ff13
@ -192,7 +192,7 @@ int p3FileDatabase::tick()
|
||||
mRemoteDirectories[i]->print();
|
||||
#endif
|
||||
|
||||
locked_recursSweepRemoteDirectory(mRemoteDirectories[i],mRemoteDirectories[i]->root()) ;
|
||||
locked_recursSweepRemoteDirectory(mRemoteDirectories[i],mRemoteDirectories[i]->root(),0) ;
|
||||
}
|
||||
|
||||
mRemoteDirectories[i]->checkSave() ;
|
||||
@ -549,6 +549,30 @@ bool p3FileDatabase::convertEntryIndexToPointer(const EntryIndex& e, uint32_t fi
|
||||
return true;
|
||||
}
|
||||
|
||||
void p3FileDatabase::requestDirUpdate(void *ref)
|
||||
{
|
||||
uint32_t fi;
|
||||
DirectoryStorage::EntryIndex e ;
|
||||
|
||||
convertPointerToEntryIndex(ref,e,fi);
|
||||
|
||||
if(fi == 0)
|
||||
return ; // not updating current directory (should we?)
|
||||
|
||||
time_t recurs_max_modf_TS_remote_time,local_update_TS;
|
||||
|
||||
std::cerr << "Trying to force sync of entry ndex " << e << " to friend " << mRemoteDirectories[fi-1]->peerId() << std::endl;
|
||||
|
||||
if(!mRemoteDirectories[fi-1]->getDirUpdateTS(e,recurs_max_modf_TS_remote_time,local_update_TS))
|
||||
{
|
||||
std::cerr << " (EE) Cannot get max known recurs modf time!" << std::endl;
|
||||
return ;
|
||||
}
|
||||
|
||||
if(generateAndSendSyncRequest(mRemoteDirectories[fi-1],e,recurs_max_modf_TS_remote_time))
|
||||
P3FILELISTS_DEBUG() << " Succeed." << std::endl;
|
||||
}
|
||||
|
||||
// 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
|
||||
@ -1035,20 +1059,24 @@ void p3FileDatabase::handleDirSyncResponse(RsFileListsSyncResponseItem *item)
|
||||
}
|
||||
}
|
||||
|
||||
void p3FileDatabase::locked_recursSweepRemoteDirectory(RemoteDirectoryStorage *rds,DirectoryStorage::EntryIndex e)
|
||||
void p3FileDatabase::locked_recursSweepRemoteDirectory(RemoteDirectoryStorage *rds,DirectoryStorage::EntryIndex e,int depth)
|
||||
{
|
||||
time_t now = time(NULL) ;
|
||||
|
||||
std::string indent(2*depth,' ') ;
|
||||
|
||||
// if not up to date, request update, and return (content is not certified, so no need to recurs yet).
|
||||
// if up to date, return, because TS is about the last modif TS below, so no need to recurs either.
|
||||
|
||||
// get the info for this entry
|
||||
|
||||
P3FILELISTS_DEBUG() << "currently at entry index " << e << std::endl;
|
||||
|
||||
time_t recurs_max_modf_TS_remote_time,local_update_TS;
|
||||
|
||||
if(!rds->getDirUpdateTS(e,recurs_max_modf_TS_remote_time,local_update_TS))
|
||||
{
|
||||
std::cerr << "(EE) lockec_recursSweepRemoteDirectory(): cannot get update TS for directory with index " << e << ". This is a consistency bug." << std::endl;
|
||||
std::cerr << " (EE) lockec_recursSweepRemoteDirectory(): cannot get update TS for directory with index " << e << ". This is a consistency bug." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1056,73 +1084,89 @@ void p3FileDatabase::locked_recursSweepRemoteDirectory(RemoteDirectoryStorage *r
|
||||
|
||||
if(now > local_update_TS + DELAY_BETWEEN_REMOTE_DIRECTORY_SYNC_REQ) // we need to compare local times only. We cannot compare local (now) with remote time.
|
||||
{
|
||||
// check if a request already exists and is not too old either: no need to re-ask.
|
||||
if(generateAndSendSyncRequest(rds,e,recurs_max_modf_TS_remote_time))
|
||||
P3FILELISTS_DEBUG() << " Asking for sync of directory " << e << " to peer " << rds->peerId() << " because it's " << (now - local_update_TS) << " secs old since last check." << std::endl;
|
||||
|
||||
DirSyncRequestId sync_req_id = makeDirSyncReqId(rds->peerId(),e) ;
|
||||
// Dont recurs into sub-directories, since we dont know yet were to go.
|
||||
|
||||
std::map<DirSyncRequestId,DirSyncRequestData>::iterator it = mPendingSyncRequests.find(sync_req_id) ;
|
||||
|
||||
if(it != mPendingSyncRequests.end())
|
||||
{
|
||||
P3FILELISTS_DEBUG() << "Not asking for sync of directory " << e << " to friend " << rds->peerId() << " because a recent pending request still exists." << std::endl;
|
||||
return ;
|
||||
}
|
||||
|
||||
P3FILELISTS_DEBUG() << "Asking for sync of directory " << e << " to peer " << rds->peerId() << " because it's " << (now - local_update_TS) << " secs old since last check." << std::endl;
|
||||
|
||||
RsFileListsSyncRequestItem *item = new RsFileListsSyncRequestItem ;
|
||||
|
||||
if(!rds->getDirHashFromIndex(e,item->entry_hash) )
|
||||
{
|
||||
std::cerr << "(EE) cannot find hash for entry index " << e << ". This is very unexpected." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
item->flags = RsFileListsItem::FLAGS_SYNC_REQUEST ;
|
||||
item->request_id = sync_req_id ;
|
||||
item->last_known_recurs_modf_TS = recurs_max_modf_TS_remote_time ;
|
||||
item->PeerId(rds->peerId()) ;
|
||||
|
||||
DirSyncRequestData data ;
|
||||
|
||||
data.request_TS = now ;
|
||||
data.peer_id = item->PeerId();
|
||||
data.flags = item->flags;
|
||||
|
||||
std::cerr << "Pushing req in pending list with peer id " << data.peer_id << std::endl;
|
||||
|
||||
mPendingSyncRequests[sync_req_id] = data ;
|
||||
|
||||
sendItem(item) ; // at end! Because item is destroyed by the process.
|
||||
|
||||
// Dont recurs into sub-directories, since we dont know yet were to go.
|
||||
|
||||
//return ;
|
||||
//return ;
|
||||
}
|
||||
|
||||
for(DirectoryStorage::DirIterator it(rds,e);it;++it)
|
||||
locked_recursSweepRemoteDirectory(rds,*it);
|
||||
locked_recursSweepRemoteDirectory(rds,*it,depth+1);
|
||||
}
|
||||
|
||||
p3FileDatabase::DirSyncRequestId p3FileDatabase::makeDirSyncReqId(const RsPeerId& peer_id,DirectoryStorage::EntryIndex e)
|
||||
p3FileDatabase::DirSyncRequestId p3FileDatabase::makeDirSyncReqId(const RsPeerId& peer_id,const RsFileHash& hash)
|
||||
{
|
||||
#warning needs to be improved. It's quite likely that random_bias and then e can be bruteforced from the result of this function
|
||||
static uint64_t random_bias = RSRandom::random_u64();
|
||||
uint64_t r = e ;
|
||||
uint64_t r = 0 ;
|
||||
|
||||
// This is kind of arbitrary. The important thing is that the same ID needs to be generated every time for a given (peer_id,e) pair, in a way
|
||||
// that cannot be brute-forced or reverse-engineered, which explains the random bias.
|
||||
// This is kind of arbitrary. The important thing is that the same ID needs to be generated every time for a given (peer_id,entry index) pair, in a way
|
||||
// that cannot be brute-forced or reverse-engineered, which explains the random bias and the usage of the hash, that is itself random.
|
||||
|
||||
for(uint32_t i=0;i<RsPeerId::SIZE_IN_BYTES;++i)
|
||||
{
|
||||
r ^= (0x011933ff92892a94 * e + peer_id.toByteArray()[i] * 0x1001fff92ee640f9) ;
|
||||
r ^= (0x011933ff92892a94 + peer_id.toByteArray()[i] * 0x1001fff92ee640f9) ;
|
||||
r <<= 8 ;
|
||||
r ^= 0xf392843890321808;
|
||||
r += 0xf392843890321808;
|
||||
}
|
||||
for(uint32_t i=0;i<RsFileHash::SIZE_IN_BYTES;++i)
|
||||
{
|
||||
r ^= (0x011933ff92892a94 + hash.toByteArray()[i] * 0x1001fff92ee640f9) ;
|
||||
r <<= 8 ;
|
||||
r += 0xf392843890321808;
|
||||
}
|
||||
|
||||
return r ^ random_bias;
|
||||
}
|
||||
|
||||
bool p3FileDatabase::generateAndSendSyncRequest(RemoteDirectoryStorage *rds,const DirectoryStorage::EntryIndex& e,time_t max_known_recurs_modf_time)
|
||||
{
|
||||
RsFileHash entry_hash ;
|
||||
time_t now = time(NULL) ;
|
||||
|
||||
if(!rds->getDirHashFromIndex(e,entry_hash) )
|
||||
{
|
||||
std::cerr << " (EE) cannot find hash for entry index " << e << ". This is very unexpected." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if a request already exists and is not too old either: no need to re-ask.
|
||||
|
||||
DirSyncRequestId sync_req_id = makeDirSyncReqId(rds->peerId(),entry_hash) ;
|
||||
|
||||
std::map<DirSyncRequestId,DirSyncRequestData>::iterator it = mPendingSyncRequests.find(sync_req_id) ;
|
||||
|
||||
if(it != mPendingSyncRequests.end())
|
||||
{
|
||||
P3FILELISTS_DEBUG() << " Not asking for sync of directory " << e << " to friend " << rds->peerId() << " because a recent pending request still exists." << std::endl;
|
||||
return false ;
|
||||
}
|
||||
|
||||
RsFileListsSyncRequestItem *item = new RsFileListsSyncRequestItem ;
|
||||
|
||||
item->entry_hash = entry_hash ;
|
||||
item->flags = RsFileListsItem::FLAGS_SYNC_REQUEST ;
|
||||
item->request_id = sync_req_id ;
|
||||
item->last_known_recurs_modf_TS = max_known_recurs_modf_time ;
|
||||
item->PeerId(rds->peerId()) ;
|
||||
|
||||
DirSyncRequestData data ;
|
||||
|
||||
data.request_TS = now ;
|
||||
data.peer_id = item->PeerId();
|
||||
data.flags = item->flags;
|
||||
|
||||
std::cerr << " Pushing req in pending list with peer id " << data.peer_id << std::endl;
|
||||
|
||||
mPendingSyncRequests[sync_req_id] = data ;
|
||||
|
||||
sendItem(item) ; // at end! Because item is destroyed by the process.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -92,6 +92,7 @@ class p3FileDatabase: public p3Service, public p3Config, public ftSearch //, pub
|
||||
|
||||
// void * here is the type expected by the abstract model index from Qt. It gets turned into a DirectoryStorage::EntryIndex internally.
|
||||
|
||||
void requestDirUpdate(void *ref) ; // triggers an update. Used when browsing.
|
||||
int RequestDirDetails(void *, DirDetails&, FileSearchFlags) const ;
|
||||
uint32_t getType(void *) const ;
|
||||
|
||||
@ -142,7 +143,15 @@ class p3FileDatabase: public p3Service, public p3Config, public ftSearch //, pub
|
||||
|
||||
typedef uint64_t DirSyncRequestId ;
|
||||
|
||||
static DirSyncRequestId makeDirSyncReqId(const RsPeerId& peer_id,DirectoryStorage::EntryIndex e) ;
|
||||
static DirSyncRequestId makeDirSyncReqId(const RsPeerId& peer_id, const RsFileHash &hash) ;
|
||||
|
||||
/*!
|
||||
* \brief generateAndSendSyncRequest
|
||||
* \param rds Remote directory storage for the request
|
||||
* \param e Entry index to update
|
||||
* \return true if the request is correctly sent.
|
||||
*/
|
||||
bool generateAndSendSyncRequest(RemoteDirectoryStorage *rds,const DirectoryStorage::EntryIndex& e,time_t max_known_recurs_modf_time);
|
||||
|
||||
// File sync request queues. The fast one is used for online browsing when friends are connected.
|
||||
// The slow one is used for background update of file lists.
|
||||
@ -185,7 +194,7 @@ class p3FileDatabase: public p3Service, public p3Config, public ftSearch //, pub
|
||||
time_t mLastRemoteDirSweepTS ; // TS for friend list update
|
||||
std::map<DirSyncRequestId,DirSyncRequestData> mPendingSyncRequests ; // pending requests, waiting for an answer
|
||||
|
||||
void locked_recursSweepRemoteDirectory(RemoteDirectoryStorage *rds,DirectoryStorage::EntryIndex e);
|
||||
void locked_recursSweepRemoteDirectory(RemoteDirectoryStorage *rds, DirectoryStorage::EntryIndex e, int depth);
|
||||
|
||||
// We use a shared file cache as well, to avoid re-hashing files with known modification TS and equal name.
|
||||
//
|
||||
|
@ -345,7 +345,12 @@ bool ftServer::FileDownloadChunksDetails(const RsFileHash& hash,FileChunksInfo&
|
||||
return mFtController->getFileDownloadChunksDetails(hash,info);
|
||||
}
|
||||
|
||||
/* Directory Handling */
|
||||
void ftServer::requestDirUpdate(void *ref)
|
||||
{
|
||||
mFileDatabase->requestDirUpdate(ref) ;
|
||||
}
|
||||
|
||||
/* Directory Handling */
|
||||
void ftServer::setDownloadDirectory(std::string path)
|
||||
{
|
||||
mFtController->setDownloadDirectory(path);
|
||||
|
@ -199,6 +199,7 @@ public:
|
||||
/***
|
||||
* Directory Handling
|
||||
***/
|
||||
virtual void requestDirUpdate(void *ref) ; // triggers the update of the given reference. Used when browsing.
|
||||
virtual void setDownloadDirectory(std::string path);
|
||||
virtual void setPartialsDirectory(std::string path);
|
||||
virtual std::string getDownloadDirectory();
|
||||
|
@ -205,6 +205,8 @@ class RsFiles
|
||||
/***
|
||||
* Directory Control
|
||||
***/
|
||||
virtual void requestDirUpdate(void *ref) =0 ; // triggers the update of the given reference. Used when browsing.
|
||||
|
||||
virtual void setDownloadDirectory(std::string path) = 0;
|
||||
virtual void setPartialsDirectory(std::string path) = 0;
|
||||
virtual std::string getDownloadDirectory() = 0;
|
||||
|
@ -80,6 +80,11 @@ void RetroshareDirModel::treeStyle()
|
||||
peerIcon = QIcon(":/images/user/identity16.png");
|
||||
}
|
||||
|
||||
void TreeStyle_RDM::updateRef(const QModelIndex& indx) const
|
||||
{
|
||||
rsFiles->requestDirUpdate(indx.internalPointer()) ;
|
||||
}
|
||||
|
||||
bool TreeStyle_RDM::hasChildren(const QModelIndex &parent) const
|
||||
{
|
||||
|
||||
|
@ -78,6 +78,8 @@ class RetroshareDirModel : public QAbstractItemModel
|
||||
bool requestDirDetails(void *ref, bool remote,DirDetails& d) const;
|
||||
virtual void update() {}
|
||||
|
||||
virtual void updateRef(const QModelIndex&) const =0;
|
||||
|
||||
public:
|
||||
virtual QMimeData * mimeData ( const QModelIndexList & indexes ) const;
|
||||
virtual QStringList mimeTypes () const;
|
||||
@ -167,7 +169,9 @@ class TreeStyle_RDM: public RetroshareDirModel
|
||||
virtual ~TreeStyle_RDM() ;
|
||||
|
||||
protected:
|
||||
/* These are all overloaded Virtual Functions */
|
||||
virtual void updateRef(const QModelIndex&) const ;
|
||||
|
||||
/* These are all overloaded Virtual Functions */
|
||||
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
|
||||
@ -203,7 +207,8 @@ class FlatStyle_RDM: public RetroshareDirModel
|
||||
void updateRefs() ;
|
||||
|
||||
protected:
|
||||
virtual void postMods();
|
||||
virtual void updateRef(const QModelIndex&) const {}
|
||||
virtual void postMods();
|
||||
|
||||
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
|
@ -228,6 +228,7 @@ RemoteSharedFilesDialog::RemoteSharedFilesDialog(QWidget *parent)
|
||||
ui.checkButton->hide() ;
|
||||
|
||||
connect(ui.downloadButton, SIGNAL(clicked()), this, SLOT(downloadRemoteSelected()));
|
||||
connect(ui.dirTreeView, SIGNAL( expanded(const QModelIndex & ) ), this, SLOT( expanded(const QModelIndex & ) ) );
|
||||
|
||||
// load settings
|
||||
processSettings(true);
|
||||
@ -366,7 +367,6 @@ void SharedFilesDialog::changeCurrentViewModel(int viewTypeIndex)
|
||||
}
|
||||
|
||||
// connect( ui.dirTreeView, SIGNAL( collapsed(const QModelIndex & ) ), this, SLOT( collapsed(const QModelIndex & ) ) );
|
||||
// connect( ui.dirTreeView, SIGNAL( expanded(const QModelIndex & ) ), this, SLOT( expanded(const QModelIndex & ) ) );
|
||||
|
||||
ui.dirTreeView->setModel(proxyModel);
|
||||
ui.dirTreeView->update();
|
||||
@ -517,6 +517,13 @@ QModelIndexList SharedFilesDialog::getSelected()
|
||||
return proxyList ;
|
||||
}
|
||||
|
||||
void RemoteSharedFilesDialog::expanded(const QModelIndex& indx)
|
||||
{
|
||||
std::cerr << "Expanding at " << indx.row() << " and " << indx.column() << " ref=" << indx.internalPointer() << ", pointer at 1: " << proxyModel->mapToSource(indx).internalPointer() << std::endl;
|
||||
|
||||
model->updateRef(proxyModel->mapToSource(indx)) ;
|
||||
}
|
||||
|
||||
void RemoteSharedFilesDialog::downloadRemoteSelected()
|
||||
{
|
||||
/* call back to the model (which does all the interfacing? */
|
||||
|
@ -196,6 +196,7 @@ class RemoteSharedFilesDialog : public SharedFilesDialog
|
||||
|
||||
private slots:
|
||||
void downloadRemoteSelected();
|
||||
void expanded(const QModelIndex& indx);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user