2016-07-30 15:52:42 -04:00
|
|
|
#include "serialiser/rsserviceids.h"
|
|
|
|
|
2016-07-20 15:28:55 -04:00
|
|
|
#include "file_sharing/p3filelists.h"
|
2016-07-20 16:10:51 -04:00
|
|
|
#include "file_sharing/directory_storage.h"
|
2016-07-30 15:52:42 -04:00
|
|
|
#include "file_sharing/directory_updater.h"
|
2016-08-20 10:23:11 -04:00
|
|
|
#include "file_sharing/rsfilelistitems.h"
|
2016-07-30 15:52:42 -04:00
|
|
|
|
2016-07-20 15:28:55 -04:00
|
|
|
#include "retroshare/rsids.h"
|
2016-07-31 09:59:58 -04:00
|
|
|
#include "retroshare/rspeers.h"
|
2016-07-18 21:52:44 -04:00
|
|
|
|
2016-08-06 13:04:54 -04:00
|
|
|
#include "rsserver/p3face.h"
|
|
|
|
|
2016-07-20 16:10:51 -04:00
|
|
|
#define P3FILELISTS_DEBUG() std::cerr << "p3FileLists: "
|
2016-07-18 21:52:44 -04:00
|
|
|
|
|
|
|
static const uint32_t P3FILELISTS_UPDATE_FLAG_NOTHING_CHANGED = 0x0000 ;
|
|
|
|
static const uint32_t P3FILELISTS_UPDATE_FLAG_REMOTE_MAP_CHANGED = 0x0001 ;
|
|
|
|
static const uint32_t P3FILELISTS_UPDATE_FLAG_LOCAL_DIRS_CHANGED = 0x0002 ;
|
|
|
|
static const uint32_t P3FILELISTS_UPDATE_FLAG_REMOTE_DIRS_CHANGED = 0x0004 ;
|
|
|
|
|
2016-08-05 16:00:25 -04:00
|
|
|
static const uint32_t NB_FRIEND_INDEX_BITS = 10 ;
|
|
|
|
static const uint32_t NB_ENTRY_INDEX_BITS = 22 ;
|
|
|
|
static const uint32_t ENTRY_INDEX_BIT_MASK = 0x003fffff ; // used for storing (EntryIndex,Friend) couples into a 32bits pointer.
|
|
|
|
|
2016-07-30 15:52:42 -04:00
|
|
|
p3FileDatabase::p3FileDatabase(p3ServiceControl *mpeers)
|
|
|
|
: mServCtrl(mpeers), mFLSMtx("p3FileLists")
|
2016-07-18 21:52:44 -04:00
|
|
|
{
|
|
|
|
// loads existing indexes for friends. Some might be already present here.
|
|
|
|
//
|
2016-08-20 10:23:11 -04:00
|
|
|
mRemoteDirectories.clear() ; // we should load them!
|
|
|
|
mOwnId = mpeers->getOwnId() ;
|
2016-07-30 15:52:42 -04:00
|
|
|
|
2016-08-20 10:23:11 -04:00
|
|
|
mLocalSharedDirs = new LocalDirectoryStorage("local_file_store.bin",mOwnId);
|
2016-07-30 15:52:42 -04:00
|
|
|
mHashCache = new HashStorage("hash_cache.bin") ;
|
|
|
|
|
|
|
|
mLocalDirWatcher = new LocalDirectoryUpdater(mHashCache,mLocalSharedDirs) ;
|
|
|
|
|
2016-07-18 21:52:44 -04:00
|
|
|
mUpdateFlags = P3FILELISTS_UPDATE_FLAG_NOTHING_CHANGED ;
|
2016-08-20 10:23:11 -04:00
|
|
|
mLastRemoteDirSweepTS = 0 ;
|
2016-07-18 21:52:44 -04:00
|
|
|
}
|
2016-07-30 15:52:42 -04:00
|
|
|
|
|
|
|
void p3FileDatabase::setSharedDirectories(const std::list<SharedDirInfo>& shared_dirs)
|
|
|
|
{
|
2016-08-06 13:04:54 -04:00
|
|
|
RS_STACK_MUTEX(mFLSMtx) ;
|
|
|
|
|
2016-07-30 15:52:42 -04:00
|
|
|
mLocalSharedDirs->setSharedDirectoryList(shared_dirs) ;
|
2016-08-06 13:04:54 -04:00
|
|
|
mLocalDirWatcher->forceUpdate();
|
2016-07-30 15:52:42 -04:00
|
|
|
}
|
|
|
|
void p3FileDatabase::getSharedDirectories(std::list<SharedDirInfo>& shared_dirs)
|
|
|
|
{
|
2016-08-06 13:04:54 -04:00
|
|
|
RS_STACK_MUTEX(mFLSMtx) ;
|
2016-07-30 15:52:42 -04:00
|
|
|
mLocalSharedDirs->getSharedDirectoryList(shared_dirs) ;
|
|
|
|
}
|
2016-07-31 09:59:58 -04:00
|
|
|
void p3FileDatabase::updateShareFlags(const SharedDirInfo& info)
|
|
|
|
{
|
2016-08-06 13:04:54 -04:00
|
|
|
RS_STACK_MUTEX(mFLSMtx) ;
|
2016-07-31 09:59:58 -04:00
|
|
|
mLocalSharedDirs->updateShareFlags(info) ;
|
|
|
|
}
|
2016-07-30 15:52:42 -04:00
|
|
|
|
|
|
|
p3FileDatabase::~p3FileDatabase()
|
2016-07-18 21:52:44 -04:00
|
|
|
{
|
2016-07-20 16:10:51 -04:00
|
|
|
RS_STACK_MUTEX(mFLSMtx) ;
|
|
|
|
|
2016-08-20 10:23:11 -04:00
|
|
|
for(uint32_t i=0;i<mRemoteDirectories.size();++i)
|
|
|
|
delete mRemoteDirectories[i];
|
2016-07-20 16:10:51 -04:00
|
|
|
|
2016-08-20 10:23:11 -04:00
|
|
|
mRemoteDirectories.clear(); // just a precaution, not to leave deleted pointers around.
|
2016-07-20 16:10:51 -04:00
|
|
|
|
2016-07-30 15:52:42 -04:00
|
|
|
delete mLocalSharedDirs ;
|
|
|
|
delete mLocalDirWatcher ;
|
|
|
|
delete mHashCache ;
|
2016-07-18 21:52:44 -04:00
|
|
|
}
|
|
|
|
|
2016-07-30 15:52:42 -04:00
|
|
|
const std::string FILE_DB_APP_NAME = "file_database";
|
|
|
|
const uint16_t FILE_DB_APP_MAJOR_VERSION = 1;
|
|
|
|
const uint16_t FILE_DB_APP_MINOR_VERSION = 0;
|
|
|
|
const uint16_t FILE_DB_MIN_MAJOR_VERSION = 1;
|
|
|
|
const uint16_t FILE_DB_MIN_MINOR_VERSION = 0;
|
|
|
|
|
|
|
|
RsServiceInfo p3FileDatabase::getServiceInfo()
|
|
|
|
{
|
|
|
|
return RsServiceInfo(RS_SERVICE_TYPE_FILE_DATABASE,
|
|
|
|
FILE_DB_APP_NAME,
|
|
|
|
FILE_DB_APP_MAJOR_VERSION,
|
|
|
|
FILE_DB_APP_MINOR_VERSION,
|
|
|
|
FILE_DB_MIN_MAJOR_VERSION,
|
|
|
|
FILE_DB_MIN_MINOR_VERSION);
|
|
|
|
}
|
|
|
|
int p3FileDatabase::tick()
|
2016-07-18 21:52:44 -04:00
|
|
|
{
|
|
|
|
// tick the watchers, possibly create new ones if additional friends do connect.
|
|
|
|
//
|
|
|
|
tickWatchers();
|
|
|
|
|
|
|
|
// tick the input/output list of update items and process them
|
|
|
|
//
|
|
|
|
tickRecv() ;
|
|
|
|
tickSend() ;
|
|
|
|
|
|
|
|
// cleanup
|
|
|
|
// - remove/delete shared file lists for people who are not friend anymore
|
|
|
|
// -
|
|
|
|
cleanup();
|
2016-07-20 16:10:51 -04:00
|
|
|
|
2016-08-12 13:30:19 -04:00
|
|
|
static time_t last_print_time = 0;
|
|
|
|
time_t now = time(NULL) ;
|
|
|
|
|
2016-08-13 04:15:02 -04:00
|
|
|
if(last_print_time + 20 < now)
|
2016-08-12 13:30:19 -04:00
|
|
|
{
|
2016-08-17 08:48:54 -04:00
|
|
|
RS_STACK_MUTEX(mFLSMtx) ;
|
2016-08-19 12:49:42 -04:00
|
|
|
|
2016-08-12 13:30:19 -04:00
|
|
|
mLocalSharedDirs->print();
|
|
|
|
last_print_time = now ;
|
2016-08-17 08:48:54 -04:00
|
|
|
|
2016-08-19 12:49:42 -04:00
|
|
|
//#warning this should be removed, but it's necessary atm for updating the GUI
|
|
|
|
// RsServer::notify()->notifyListChange(NOTIFY_LIST_DIRLIST_FRIENDS, 0);
|
2016-08-12 13:30:19 -04:00
|
|
|
}
|
|
|
|
|
2016-08-17 08:48:54 -04:00
|
|
|
if(mUpdateFlags)
|
|
|
|
{
|
|
|
|
IndicateConfigChanged();
|
|
|
|
|
|
|
|
if(mUpdateFlags & P3FILELISTS_UPDATE_FLAG_LOCAL_DIRS_CHANGED)
|
|
|
|
RsServer::notify()->notifyListChange(NOTIFY_LIST_DIRLIST_LOCAL, 0);
|
|
|
|
|
|
|
|
if(mUpdateFlags & P3FILELISTS_UPDATE_FLAG_REMOTE_DIRS_CHANGED)
|
|
|
|
RsServer::notify()->notifyListChange(NOTIFY_LIST_DIRLIST_FRIENDS, 0);
|
|
|
|
|
|
|
|
mUpdateFlags = P3FILELISTS_UPDATE_FLAG_NOTHING_CHANGED ;
|
|
|
|
}
|
2016-08-20 10:23:11 -04:00
|
|
|
|
|
|
|
if(mLastRemoteDirSweepTS + 5 < now)
|
|
|
|
{
|
|
|
|
RS_STACK_MUTEX(mFLSMtx) ;
|
|
|
|
|
|
|
|
for(uint32_t i=0;i<mRemoteDirectories.size();++i)
|
|
|
|
locked_recursSweepRemoteDirectory(mRemoteDirectories[i],mRemoteDirectories[i]->root()) ;
|
|
|
|
|
|
|
|
mLastRemoteDirSweepTS = now;
|
|
|
|
}
|
|
|
|
|
2016-07-20 16:10:51 -04:00
|
|
|
return 0;
|
2016-07-18 21:52:44 -04:00
|
|
|
}
|
|
|
|
|
2016-07-31 09:59:58 -04:00
|
|
|
void p3FileDatabase::startThreads()
|
|
|
|
{
|
2016-08-17 08:48:54 -04:00
|
|
|
RS_STACK_MUTEX(mFLSMtx) ;
|
2016-08-05 16:37:40 -04:00
|
|
|
std::cerr << "Starting directory watcher thread..." ;
|
|
|
|
mLocalDirWatcher->start();
|
|
|
|
std::cerr << "Done." << std::endl;
|
2016-07-31 09:59:58 -04:00
|
|
|
}
|
|
|
|
void p3FileDatabase::stopThreads()
|
|
|
|
{
|
2016-08-17 08:48:54 -04:00
|
|
|
RS_STACK_MUTEX(mFLSMtx) ;
|
2016-07-31 09:59:58 -04:00
|
|
|
std::cerr << "Stopping hash cache thread..." ; std::cerr.flush() ;
|
|
|
|
mHashCache->fullstop();
|
2016-08-05 16:37:40 -04:00
|
|
|
std::cerr << "Done." << std::endl;
|
2016-07-31 09:59:58 -04:00
|
|
|
|
2016-08-05 16:37:40 -04:00
|
|
|
std::cerr << "Stopping directory watcher thread..." ; std::cerr.flush() ;
|
|
|
|
mLocalDirWatcher->fullstop();
|
2016-07-31 09:59:58 -04:00
|
|
|
std::cerr << "Done." << std::endl;
|
|
|
|
}
|
|
|
|
|
2016-07-30 15:52:42 -04:00
|
|
|
void p3FileDatabase::tickWatchers()
|
2016-07-18 21:52:44 -04:00
|
|
|
{
|
|
|
|
}
|
2016-07-30 15:52:42 -04:00
|
|
|
bool p3FileDatabase::loadList(std::list<RsItem *>& items)
|
2016-07-18 21:52:44 -04:00
|
|
|
{
|
|
|
|
// This loads
|
|
|
|
//
|
|
|
|
// - list of locally shared directories, and the permissions that go with them
|
2016-08-20 10:23:11 -04:00
|
|
|
|
2016-07-30 15:52:42 -04:00
|
|
|
NOT_IMPLEMENTED();
|
2016-07-20 16:10:51 -04:00
|
|
|
|
|
|
|
return true ;
|
2016-07-18 21:52:44 -04:00
|
|
|
}
|
|
|
|
|
2016-07-30 15:52:42 -04:00
|
|
|
bool p3FileDatabase::saveList(bool &cleanup, std::list<RsItem *>&)
|
2016-07-18 21:52:44 -04:00
|
|
|
{
|
2016-07-30 15:52:42 -04:00
|
|
|
NOT_IMPLEMENTED();
|
2016-07-20 16:10:51 -04:00
|
|
|
return true ;
|
2016-07-18 21:52:44 -04:00
|
|
|
}
|
|
|
|
|
2016-07-30 15:52:42 -04:00
|
|
|
void p3FileDatabase::cleanup()
|
2016-07-18 21:52:44 -04:00
|
|
|
{
|
2016-08-05 16:00:25 -04:00
|
|
|
{
|
2016-08-17 08:48:54 -04:00
|
|
|
RS_STACK_MUTEX(mFLSMtx) ;
|
2016-08-05 16:00:25 -04:00
|
|
|
|
2016-08-17 08:48:54 -04:00
|
|
|
// look through the list of friend directories. Remove those who are not our friends anymore.
|
|
|
|
//
|
|
|
|
std::set<RsPeerId> friend_set ;
|
|
|
|
{
|
|
|
|
std::list<RsPeerId> friend_lst ;
|
2016-07-18 21:52:44 -04:00
|
|
|
|
2016-08-17 08:48:54 -04:00
|
|
|
rsPeers->getFriendList(friend_lst);
|
2016-08-05 16:00:25 -04:00
|
|
|
|
2016-08-17 08:48:54 -04:00
|
|
|
for(std::list<RsPeerId>::const_iterator it(friend_lst.begin());it!=friend_lst.end();++it)
|
|
|
|
friend_set.insert(*it) ;
|
|
|
|
}
|
2016-07-18 21:52:44 -04:00
|
|
|
|
2016-08-20 10:23:11 -04:00
|
|
|
for(uint32_t i=0;i<mRemoteDirectories.size();++i)
|
|
|
|
if(friend_set.find(mRemoteDirectories[i]->peerId()) == friend_set.end())
|
2016-08-17 08:48:54 -04:00
|
|
|
{
|
2016-08-20 10:23:11 -04:00
|
|
|
P3FILELISTS_DEBUG() << " removing file list of non friend " << mRemoteDirectories[i]->peerId() << std::endl;
|
2016-07-18 21:52:44 -04:00
|
|
|
|
2016-08-20 10:23:11 -04:00
|
|
|
delete mRemoteDirectories[i];
|
|
|
|
mRemoteDirectories[i] = NULL ;
|
2016-07-18 21:52:44 -04:00
|
|
|
|
2016-08-17 08:48:54 -04:00
|
|
|
mUpdateFlags |= P3FILELISTS_UPDATE_FLAG_REMOTE_MAP_CHANGED ;
|
2016-08-05 16:00:25 -04:00
|
|
|
|
2016-08-20 10:23:11 -04:00
|
|
|
friend_set.erase(mRemoteDirectories[i]->peerId());
|
2016-08-05 16:00:25 -04:00
|
|
|
|
2016-08-20 10:23:11 -04:00
|
|
|
mFriendIndexMap.erase(mRemoteDirectories[i]->peerId());
|
2016-08-17 08:48:54 -04:00
|
|
|
mFriendIndexTab[i].clear();
|
|
|
|
}
|
2016-07-18 21:52:44 -04:00
|
|
|
|
2016-08-17 08:48:54 -04:00
|
|
|
// look through the remaining list of friends, which are the ones for which no remoteDirectoryStorage class has been allocated.
|
|
|
|
//
|
|
|
|
for(std::set<RsPeerId>::const_iterator it(friend_set.begin());it!=friend_set.end();++it)
|
|
|
|
{
|
|
|
|
// Check if a remote directory exists for that friend, possibly creating the index.
|
2016-07-18 21:52:44 -04:00
|
|
|
|
2016-08-17 08:48:54 -04:00
|
|
|
uint32_t friend_index = locked_getFriendIndex(*it) ;
|
2016-08-05 16:00:25 -04:00
|
|
|
|
2016-08-20 10:23:11 -04:00
|
|
|
if(mRemoteDirectories.size() > friend_index && mRemoteDirectories[friend_index] != NULL)
|
2016-08-17 08:48:54 -04:00
|
|
|
continue ;
|
2016-08-13 04:15:02 -04:00
|
|
|
|
2016-08-17 08:48:54 -04:00
|
|
|
P3FILELISTS_DEBUG() << " adding missing remote dir entry for friend " << *it << ", with index " << friend_index << std::endl;
|
2016-08-05 16:00:25 -04:00
|
|
|
|
2016-08-20 10:23:11 -04:00
|
|
|
mRemoteDirectories[friend_index] = new RemoteDirectoryStorage(*it,makeRemoteFileName(*it));
|
2016-07-18 21:52:44 -04:00
|
|
|
|
2016-08-17 08:48:54 -04:00
|
|
|
mUpdateFlags |= P3FILELISTS_UPDATE_FLAG_REMOTE_MAP_CHANGED ;
|
|
|
|
}
|
|
|
|
}
|
2016-07-18 21:52:44 -04:00
|
|
|
}
|
|
|
|
|
2016-07-31 09:59:58 -04:00
|
|
|
std::string p3FileDatabase::makeRemoteFileName(const RsPeerId& pid) const
|
|
|
|
{
|
|
|
|
#warning we should use the default paths here. Ask p3config
|
|
|
|
return "dirlist_"+pid.toStdString()+".txt" ;
|
|
|
|
}
|
|
|
|
|
2016-08-17 08:48:54 -04:00
|
|
|
uint32_t p3FileDatabase::locked_getFriendIndex(const RsPeerId& pid)
|
2016-08-05 16:00:25 -04:00
|
|
|
{
|
|
|
|
std::map<RsPeerId,uint32_t>::const_iterator it = mFriendIndexMap.find(pid) ;
|
|
|
|
|
|
|
|
if(it == mFriendIndexMap.end())
|
|
|
|
{
|
|
|
|
// allocate a new index for that friend, and tell that we should save.
|
|
|
|
uint32_t found = 0 ;
|
2016-08-20 10:23:11 -04:00
|
|
|
for(uint32_t i=0;i<mFriendIndexTab.size();++i)
|
2016-08-05 16:00:25 -04:00
|
|
|
if(mFriendIndexTab[i].isNull())
|
|
|
|
{
|
|
|
|
found = i ;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!found)
|
|
|
|
{
|
2016-08-16 07:46:55 -04:00
|
|
|
found = mFriendIndexTab.size();
|
|
|
|
mFriendIndexTab.push_back(pid);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(mFriendIndexTab.size() >= (1 << NB_FRIEND_INDEX_BITS) )
|
|
|
|
{
|
|
|
|
std::cerr << "(EE) FriendIndexTab is full. This is weird. Do you really have more than " << (1<<NB_FRIEND_INDEX_BITS) << " friends??" << std::endl;
|
|
|
|
return 1 << NB_FRIEND_INDEX_BITS ;
|
2016-08-05 16:00:25 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
mFriendIndexTab[found] = pid ;
|
|
|
|
mFriendIndexMap[pid] = found;
|
|
|
|
|
2016-08-20 10:23:11 -04:00
|
|
|
if(mRemoteDirectories.size() <= found)
|
|
|
|
mRemoteDirectories.resize(found,NULL) ;
|
2016-08-16 07:46:55 -04:00
|
|
|
|
2016-08-05 16:00:25 -04:00
|
|
|
IndicateConfigChanged();
|
|
|
|
|
|
|
|
return found ;
|
|
|
|
}
|
|
|
|
else
|
2016-08-16 07:46:55 -04:00
|
|
|
{
|
2016-08-20 10:23:11 -04:00
|
|
|
if(mRemoteDirectories.size() <= it->second)
|
|
|
|
mRemoteDirectories.resize(it->second,NULL) ;
|
2016-08-16 07:46:55 -04:00
|
|
|
|
2016-08-05 16:00:25 -04:00
|
|
|
return it->second;
|
2016-08-16 07:46:55 -04:00
|
|
|
}
|
2016-08-05 16:00:25 -04:00
|
|
|
}
|
|
|
|
|
2016-08-17 08:48:54 -04:00
|
|
|
const RsPeerId& p3FileDatabase::locked_getFriendFromIndex(uint32_t indx) const
|
2016-08-05 16:00:25 -04:00
|
|
|
{
|
|
|
|
static const RsPeerId null_id ;
|
|
|
|
|
|
|
|
if(indx >= mFriendIndexTab.size())
|
|
|
|
return null_id ;
|
|
|
|
|
|
|
|
if(mFriendIndexTab[indx].isNull())
|
|
|
|
{
|
|
|
|
std::cerr << "(EE) null friend id requested from index " << indx << ": this is a bug, most likely" << std::endl;
|
|
|
|
return null_id ;
|
|
|
|
}
|
|
|
|
|
|
|
|
return mFriendIndexTab[indx];
|
|
|
|
}
|
2016-08-11 08:07:45 -04:00
|
|
|
bool p3FileDatabase::convertPointerToEntryIndex(const void *p, EntryIndex& e, uint32_t& friend_index)
|
2016-08-05 16:00:25 -04:00
|
|
|
{
|
|
|
|
// trust me, I can do this ;-)
|
|
|
|
|
|
|
|
e = EntryIndex( *reinterpret_cast<uint32_t*>(&p) & ENTRY_INDEX_BIT_MASK ) ;
|
|
|
|
friend_index = (*reinterpret_cast<uint32_t*>(&p)) >> NB_ENTRY_INDEX_BITS ;
|
|
|
|
|
2016-08-16 17:44:48 -04:00
|
|
|
if(friend_index == 0)
|
|
|
|
{
|
|
|
|
std::cerr << "(EE) Cannot find friend index in pointer. Encoded value is zero!" << std::endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
friend_index--;
|
|
|
|
|
2016-08-05 16:00:25 -04:00
|
|
|
return true;
|
|
|
|
}
|
2016-08-11 08:07:45 -04:00
|
|
|
bool p3FileDatabase::convertEntryIndexToPointer(const EntryIndex& e, uint32_t fi, void *& p)
|
2016-08-05 16:00:25 -04:00
|
|
|
{
|
|
|
|
// the pointer is formed the following way:
|
|
|
|
//
|
|
|
|
// [ 10 bits | 22 bits ]
|
|
|
|
//
|
|
|
|
// This means that the whoel software has the following build-in limitation:
|
|
|
|
// * 1024 friends
|
|
|
|
// * 4M shared files.
|
|
|
|
|
|
|
|
uint32_t fe = (uint32_t)e ;
|
|
|
|
|
2016-08-16 17:44:48 -04:00
|
|
|
if(fi+1 >= (1<<NB_FRIEND_INDEX_BITS) || fe >= (1<< NB_ENTRY_INDEX_BITS))
|
2016-08-05 16:00:25 -04:00
|
|
|
{
|
|
|
|
std::cerr << "(EE) cannot convert entry index " << e << " of friend with index " << fi << " to pointer." << std::endl;
|
|
|
|
return false ;
|
|
|
|
}
|
|
|
|
|
2016-08-16 17:44:48 -04:00
|
|
|
p = reinterpret_cast<void*>( ( (1+fi) << NB_ENTRY_INDEX_BITS ) + (fe & ENTRY_INDEX_BIT_MASK)) ;
|
2016-08-05 16:00:25 -04:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2016-08-11 08:07:45 -04:00
|
|
|
|
|
|
|
// 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
|
2016-07-30 15:52:42 -04:00
|
|
|
{
|
2016-08-17 08:48:54 -04:00
|
|
|
RS_STACK_MUTEX(mFLSMtx) ;
|
|
|
|
|
2016-08-11 08:07:45 -04:00
|
|
|
// Case where the pointer is NULL, which means we're at the top of the list of shared directories for all friends (including us)
|
2016-08-16 17:44:48 -04:00
|
|
|
// or at the top of our own list of shred directories, depending on the flags.
|
2016-08-11 08:07:45 -04:00
|
|
|
|
|
|
|
if (ref == NULL)
|
|
|
|
{
|
2016-08-16 17:44:48 -04:00
|
|
|
d.ref = NULL ;
|
|
|
|
d.type = DIR_TYPE_ROOT;
|
|
|
|
d.count = 1;
|
|
|
|
d.parent = NULL;
|
|
|
|
d.prow = -1;
|
|
|
|
d.ref = NULL;
|
|
|
|
d.name = "root";
|
|
|
|
d.hash.clear() ;
|
|
|
|
d.path = "";
|
|
|
|
d.age = 0;
|
|
|
|
d.flags.clear() ;
|
|
|
|
d.min_age = 0 ;
|
|
|
|
d.children.clear();
|
|
|
|
|
|
|
|
if(flags & RS_FILE_HINTS_LOCAL)
|
|
|
|
{
|
|
|
|
void *p;
|
|
|
|
convertEntryIndexToPointer(0,0,p);
|
|
|
|
|
|
|
|
DirStub stub;
|
|
|
|
stub.type = DIR_TYPE_PERSON;
|
|
|
|
stub.name = mServCtrl->getOwnId().toStdString();
|
|
|
|
stub.ref = p;
|
|
|
|
d.children.push_back(stub);
|
|
|
|
}
|
2016-08-20 10:23:11 -04:00
|
|
|
else for(uint32_t i=0;i<mRemoteDirectories.size();++i)
|
2016-08-11 08:07:45 -04:00
|
|
|
{
|
|
|
|
void *p;
|
2016-08-20 10:23:11 -04:00
|
|
|
convertEntryIndexToPointer(mRemoteDirectories[i]->root(),i,p);
|
2016-08-11 08:07:45 -04:00
|
|
|
|
|
|
|
DirStub stub;
|
|
|
|
stub.type = DIR_TYPE_PERSON;
|
2016-08-20 10:23:11 -04:00
|
|
|
stub.name = mRemoteDirectories[i]->peerId().toStdString();
|
2016-08-11 08:07:45 -04:00
|
|
|
stub.ref = p;
|
|
|
|
d.children.push_back(stub);
|
|
|
|
}
|
|
|
|
|
2016-08-16 17:44:48 -04:00
|
|
|
d.count = d.children.size();
|
2016-08-11 08:07:45 -04:00
|
|
|
|
|
|
|
return true ;
|
|
|
|
}
|
|
|
|
|
2016-08-05 16:00:25 -04:00
|
|
|
uint32_t fi;
|
2016-08-16 17:44:48 -04:00
|
|
|
DirectoryStorage::EntryIndex e ;
|
2016-08-05 16:00:25 -04:00
|
|
|
|
2016-08-11 08:07:45 -04:00
|
|
|
convertPointerToEntryIndex(ref,e,fi);
|
2016-08-05 16:00:25 -04:00
|
|
|
|
2016-08-11 08:07:45 -04:00
|
|
|
// Case where the index is the top of a single person. Can be us, or a friend.
|
|
|
|
|
2016-08-20 10:23:11 -04:00
|
|
|
bool res = (flags & RS_FILE_HINTS_LOCAL)? (mLocalSharedDirs->extractData(e,d)) : (mRemoteDirectories[fi]->extractData(e,d)) ;
|
2016-08-11 08:07:45 -04:00
|
|
|
|
|
|
|
// 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) ;
|
|
|
|
|
2016-08-19 12:49:42 -04:00
|
|
|
for(uint32_t i=0;i<d.children.size();++i)
|
|
|
|
convertEntryIndexToPointer((intptr_t)d.children[i].ref,fi,d.children[i].ref);
|
2016-08-11 08:07:45 -04:00
|
|
|
|
2016-08-19 12:49:42 -04:00
|
|
|
#define Make sure this is right.
|
2016-08-17 08:48:54 -04:00
|
|
|
if(e == 0)
|
|
|
|
{
|
2016-08-19 12:49:42 -04:00
|
|
|
d.prow = 0;//fi-1 ;
|
2016-08-17 08:48:54 -04:00
|
|
|
d.parent = NULL ;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-08-20 10:23:11 -04:00
|
|
|
d.prow = mRemoteDirectories[fi]->parentRow(e) ;
|
2016-08-17 08:48:54 -04:00
|
|
|
convertEntryIndexToPointer((intptr_t)d.parent,fi,d.parent) ;
|
|
|
|
}
|
|
|
|
|
2016-08-20 10:23:11 -04:00
|
|
|
if(flags & RS_FILE_HINTS_LOCAL)
|
|
|
|
d.id = mOwnId ;
|
|
|
|
else
|
|
|
|
d.id = mRemoteDirectories[fi]->peerId();
|
2016-08-12 13:30:19 -04:00
|
|
|
|
2016-08-17 08:48:54 -04:00
|
|
|
std::cerr << "ExtractData: ref=" << ref << ", flags=" << flags << " : returning this: " << std::endl;
|
|
|
|
std::cerr << d << std::endl;
|
|
|
|
|
2016-08-12 13:30:19 -04:00
|
|
|
return true;
|
2016-07-30 15:52:42 -04:00
|
|
|
}
|
2016-08-11 08:07:45 -04:00
|
|
|
|
2016-08-05 16:00:25 -04:00
|
|
|
int p3FileDatabase::RequestDirDetails(const RsPeerId& uid,const std::string& path, DirDetails &details) const
|
2016-07-31 09:59:58 -04:00
|
|
|
{
|
|
|
|
NOT_IMPLEMENTED();
|
|
|
|
return 0;
|
|
|
|
}
|
2016-07-30 15:52:42 -04:00
|
|
|
int p3FileDatabase::RequestDirDetails(const std::string& path, DirDetails &details) const
|
|
|
|
{
|
|
|
|
NOT_IMPLEMENTED();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
uint32_t p3FileDatabase::getType(void *ref) const
|
|
|
|
{
|
2016-08-17 08:48:54 -04:00
|
|
|
RS_STACK_MUTEX(mFLSMtx) ;
|
|
|
|
|
2016-08-11 08:07:45 -04:00
|
|
|
EntryIndex e ;
|
|
|
|
uint32_t fi;
|
|
|
|
|
|
|
|
if(ref == NULL)
|
|
|
|
return DIR_TYPE_ROOT ;
|
|
|
|
|
|
|
|
convertPointerToEntryIndex(ref,e,fi);
|
|
|
|
|
|
|
|
if(e == 0)
|
|
|
|
return DIR_TYPE_PERSON ;
|
|
|
|
|
2016-08-20 10:23:11 -04:00
|
|
|
return mRemoteDirectories[fi]->getEntryType(e) ;
|
2016-07-30 15:52:42 -04:00
|
|
|
}
|
2016-08-11 08:07:45 -04:00
|
|
|
|
2016-07-30 15:52:42 -04:00
|
|
|
void p3FileDatabase::forceDirectoryCheck() // Force re-sweep the directories and see what's changed
|
|
|
|
{
|
|
|
|
NOT_IMPLEMENTED();
|
|
|
|
}
|
|
|
|
bool p3FileDatabase::inDirectoryCheck()
|
|
|
|
{
|
|
|
|
NOT_IMPLEMENTED();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
void p3FileDatabase::setWatchPeriod(uint32_t seconds)
|
|
|
|
{
|
|
|
|
NOT_IMPLEMENTED();
|
|
|
|
}
|
|
|
|
uint32_t p3FileDatabase::watchPeriod()
|
|
|
|
{
|
|
|
|
NOT_IMPLEMENTED();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
void p3FileDatabase::setRememberHashCacheDuration(uint32_t days)
|
|
|
|
{
|
|
|
|
NOT_IMPLEMENTED();
|
|
|
|
}
|
|
|
|
uint32_t p3FileDatabase::rememberHashCacheDuration()
|
|
|
|
{
|
|
|
|
NOT_IMPLEMENTED();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
void p3FileDatabase::clearHashCache()
|
|
|
|
{
|
|
|
|
NOT_IMPLEMENTED();
|
|
|
|
}
|
|
|
|
bool p3FileDatabase::rememberHashCache()
|
|
|
|
{
|
|
|
|
NOT_IMPLEMENTED();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
void p3FileDatabase::setRememberHashCache(bool)
|
|
|
|
{
|
|
|
|
NOT_IMPLEMENTED();
|
|
|
|
}
|
2016-07-31 09:59:58 -04:00
|
|
|
|
|
|
|
bool p3FileDatabase::findLocalFile(const RsFileHash& hash,FileSearchFlags flags,const RsPeerId& peer_id, std::string &fullpath, uint64_t &size,FileStorageFlags& storage_flags,std::list<std::string>& parent_groups) const
|
|
|
|
{
|
2016-08-17 08:48:54 -04:00
|
|
|
RS_STACK_MUTEX(mFLSMtx) ;
|
|
|
|
|
2016-07-31 09:59:58 -04:00
|
|
|
std::list<EntryIndex> firesults;
|
|
|
|
mLocalSharedDirs->searchHash(hash,firesults) ;
|
|
|
|
|
|
|
|
NOT_IMPLEMENTED();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int p3FileDatabase::SearchKeywords(const std::list<std::string>& keywords, std::list<DirDetails>& results,FileSearchFlags flags,const RsPeerId& client_peer_id)
|
|
|
|
{
|
2016-08-17 08:48:54 -04:00
|
|
|
RS_STACK_MUTEX(mFLSMtx) ;
|
|
|
|
|
2016-07-31 09:59:58 -04:00
|
|
|
std::list<EntryIndex> firesults;
|
|
|
|
mLocalSharedDirs->searchTerms(keywords,firesults) ;
|
|
|
|
|
|
|
|
return filterResults(firesults,results,flags,client_peer_id) ;
|
|
|
|
}
|
|
|
|
int p3FileDatabase::SearchBoolExp(Expression *exp, std::list<DirDetails>& results,FileSearchFlags flags,const RsPeerId& client_peer_id) const
|
|
|
|
{
|
2016-08-17 08:48:54 -04:00
|
|
|
RS_STACK_MUTEX(mFLSMtx) ;
|
|
|
|
|
2016-07-31 09:59:58 -04:00
|
|
|
std::list<EntryIndex> firesults;
|
|
|
|
mLocalSharedDirs->searchBoolExp(exp,firesults) ;
|
|
|
|
|
|
|
|
return filterResults(firesults,results,flags,client_peer_id) ;
|
|
|
|
}
|
|
|
|
bool p3FileDatabase::search(const RsFileHash &hash, FileSearchFlags hintflags, FileInfo &info) const
|
|
|
|
{
|
2016-08-17 08:48:54 -04:00
|
|
|
RS_STACK_MUTEX(mFLSMtx) ;
|
|
|
|
|
2016-07-31 09:59:58 -04:00
|
|
|
if(hintflags & RS_FILE_HINTS_LOCAL)
|
|
|
|
{
|
|
|
|
std::list<EntryIndex> res;
|
|
|
|
mLocalSharedDirs->searchHash(hash,res) ;
|
|
|
|
|
|
|
|
if(res.empty())
|
|
|
|
return false;
|
|
|
|
|
2016-08-20 10:23:11 -04:00
|
|
|
EntryIndex indx = *res.begin() ; // no need to report duplicates
|
2016-07-31 09:59:58 -04:00
|
|
|
|
|
|
|
mLocalSharedDirs->getFileInfo(indx,info) ;
|
2016-08-05 16:00:25 -04:00
|
|
|
|
|
|
|
return true;
|
2016-07-31 09:59:58 -04:00
|
|
|
}
|
2016-08-20 10:23:11 -04:00
|
|
|
|
|
|
|
if(hintflags & RS_FILE_HINTS_REMOTE)
|
2016-07-31 09:59:58 -04:00
|
|
|
{
|
|
|
|
NOT_IMPLEMENTED();
|
2016-08-05 16:00:25 -04:00
|
|
|
return false;
|
2016-07-31 09:59:58 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int p3FileDatabase::filterResults(const std::list<EntryIndex>& firesults,std::list<DirDetails>& results,FileSearchFlags flags,const RsPeerId& peer_id) const
|
|
|
|
{
|
|
|
|
results.clear();
|
|
|
|
|
|
|
|
#ifdef P3FILELISTS_DEBUG
|
|
|
|
if((flags & ~RS_FILE_HINTS_PERMISSION_MASK) > 0)
|
|
|
|
std::cerr << "(EE) ***** FileIndexMonitor:: Flags ERROR in filterResults!!" << std::endl;
|
|
|
|
#endif
|
|
|
|
/* translate/filter results */
|
|
|
|
|
|
|
|
for(std::list<EntryIndex>::const_iterator rit(firesults.begin()); rit != firesults.end(); ++rit)
|
|
|
|
{
|
|
|
|
DirDetails cdetails ;
|
2016-08-16 17:44:48 -04:00
|
|
|
RequestDirDetails ((void*)(intptr_t)*rit,cdetails,FileSearchFlags(0u));
|
2016-07-31 09:59:58 -04:00
|
|
|
#ifdef P3FILELISTS_DEBUG
|
|
|
|
std::cerr << "Filtering candidate " << (*rit) << ", flags=" << cdetails.flags << ", peer=" << peer_id ;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if(!peer_id.isNull())
|
|
|
|
{
|
|
|
|
FileSearchFlags permission_flags = rsPeers->computePeerPermissionFlags(peer_id,cdetails.flags,cdetails.parent_groups) ;
|
|
|
|
|
|
|
|
if (cdetails.type == DIR_TYPE_FILE && ( permission_flags & flags ))
|
|
|
|
{
|
|
|
|
cdetails.id.clear() ;
|
|
|
|
results.push_back(cdetails);
|
|
|
|
#ifdef P3FILELISTS_DEBUG
|
|
|
|
std::cerr << ": kept" << std::endl ;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#ifdef P3FILELISTS_DEBUG
|
|
|
|
else
|
|
|
|
std::cerr << ": discarded" << std::endl ;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else
|
|
|
|
results.push_back(cdetails);
|
|
|
|
}
|
|
|
|
|
|
|
|
return !results.empty() ;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool p3FileDatabase::convertSharedFilePath(const std::string& path,std::string& fullpath)
|
|
|
|
{
|
2016-08-17 08:48:54 -04:00
|
|
|
RS_STACK_MUTEX(mFLSMtx) ;
|
2016-07-31 09:59:58 -04:00
|
|
|
return mLocalSharedDirs->convertSharedFilePath(path,fullpath) ;
|
|
|
|
}
|
2016-08-20 10:23:11 -04:00
|
|
|
|
|
|
|
//==============================================================================================================================//
|
|
|
|
// Update of remote directories //
|
|
|
|
//==============================================================================================================================//
|
|
|
|
|
|
|
|
void p3FileDatabase::tickRecv()
|
|
|
|
{
|
|
|
|
RsItem *item ;
|
|
|
|
|
|
|
|
while( NULL != (item = recvItem()) )
|
|
|
|
{
|
|
|
|
switch(item->PacketSubType())
|
|
|
|
{
|
|
|
|
case RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM: handleDirSyncRequest( dynamic_cast<RsFileListsSyncReqItem*>(item) ) ;
|
|
|
|
break ;
|
|
|
|
case RS_PKT_SUBTYPE_FILELISTS_SYNC_DIR_ITEM: handleDirSyncContent( dynamic_cast<RsFileListsSyncDirItem*>(item) ) ;
|
|
|
|
break ;
|
|
|
|
default:
|
|
|
|
std::cerr << "(EE) unhandled packet subtype " << item->PacketSubType() << " in " << __PRETTY_FUNCTION__ << std::endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
delete item ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void p3FileDatabase::tickSend()
|
|
|
|
{
|
|
|
|
// go through the list of out requests and send them to the corresponding friends, if they are online.
|
|
|
|
}
|
|
|
|
|
|
|
|
void p3FileDatabase::handleDirSyncRequest(RsFileListsSyncReqItem *item)
|
|
|
|
{
|
|
|
|
// look at item TS. If local is newer, send the full directory content.
|
|
|
|
|
|
|
|
time_t recurs_max_modf_TS;
|
|
|
|
|
|
|
|
if(!mLocalSharedDirs->getUpdateTS(item->entry_index,recurs_max_modf_TS,last_update_TS))
|
|
|
|
{
|
|
|
|
std::cerr << "(EE) Cannot get update TS for entry " << index << " in local dir, asked by " << item->PeerId() << std::endl;
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(item->known_recurs_last_modf_TS < recurs_last_modf_TS)
|
|
|
|
{
|
|
|
|
// send full update of directory content
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// send last recurs update TS.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void p3FileDatabase::handleDirSyncContent(RsFileListsSyncContentItem *item)
|
|
|
|
{
|
|
|
|
// update the directory content for the specified friend.
|
|
|
|
|
|
|
|
// set the update TS, and the remote modif TS accordingly
|
|
|
|
|
|
|
|
// notify the GUI if the hierarchy has changed
|
|
|
|
}
|
|
|
|
|
|
|
|
void p3FileDatabase::locked_recursSweepRemoteDirectory(RemoteDirectoryStorage *rds,DirectoryStorage::EntryIndex e)
|
|
|
|
{
|
|
|
|
time_t now = time(NULL) ;
|
|
|
|
|
|
|
|
// get the info for this entry
|
|
|
|
|
|
|
|
// compare TS
|
|
|
|
|
|
|
|
// 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.
|
|
|
|
|
|
|
|
time_t recurs_max_modf_TS,last_update_TS ;
|
|
|
|
|
|
|
|
if(!rds->getUpdateTS(e,time_t& recurs_max_modf_TS,time_t& last_update_TS))
|
|
|
|
{
|
|
|
|
std::cerr << "(EE) Cannot get update TS for entry " << index << " in remote dir from " << rds->peerId() << std::endl;
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(now > last_update_TS + DELAY_BETWEEN_REMOTE_DIRECTORY_SYNC_REQ)
|
|
|
|
{
|
|
|
|
// check if a request already exists and is not too old either: no need to re-ask.
|
|
|
|
|
|
|
|
DirSyncRequestId sync_req_id = makeDirSyncReqId(rds->peerId(),e) ;
|
|
|
|
|
|
|
|
std::map<DirSyncRequestId,DirSyncRequestData>::iterator it = mPendingSyncRequests.find(sync_req_id) ;
|
|
|
|
|
|
|
|
if(it != mPendingSyncRequests.end())
|
|
|
|
{
|
|
|
|
std::cerr << "Not asking for sync of directory " << e << " to friend " << rds->peerId() << " because a recent pending request still exists." << std::endl;
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::cerr << "Asking for sync of directory " << e << " because it's " << (now - last_update_TS) << " secs old since last check." << std::endl;
|
|
|
|
|
|
|
|
DirSyncRequestData data ;
|
|
|
|
|
|
|
|
data.request_TS = now ;
|
|
|
|
|
|
|
|
mPendingSyncRequests[sync_req_id] = data ;
|
|
|
|
|
|
|
|
RsFileListsSyncRequestItem *item = new RsFileListsSyncRequestItem ;
|
|
|
|
item->entry_index = e ;
|
|
|
|
item->known_TS = recurs_max_modf_TS ;
|
|
|
|
|
|
|
|
sendItem(item) ;
|
|
|
|
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
}
|