added logic for file list item exchange requests

This commit is contained in:
MrAlice 2016-08-23 21:23:58 +02:00
parent 76831348e6
commit 99ea8af015
5 changed files with 140 additions and 65 deletions

View File

@ -26,7 +26,9 @@ class DirectoryStorage
virtual int searchHash(const RsFileHash& hash, std::list<EntryIndex> &results) const ;
virtual int searchBoolExp(Expression * exp, std::list<EntryIndex> &results) const { NOT_IMPLEMENTED() ; return 0; }
bool getUpdateTS(EntryIndex index,time_t& recurs_max_modf_TS,time_t& last_update_TS) ;
bool getUpdateTS(EntryIndex index,time_t& recurs_max_modf_TS,time_t& local_update_TS) ;
bool setUpdateTS(EntryIndex index,time_t recurs_max_modf_TS,time_t local_update_TS) ;
uint32_t getEntryType(const EntryIndex& indx) ; // returns DIR_TYPE_*, not the internal directory storage stuff.
virtual bool extractData(const EntryIndex& indx,DirDetails& d);

View File

@ -555,6 +555,7 @@ bool p3FileDatabase::search(const RsFileHash &hash, FileSearchFlags hintflags, F
NOT_IMPLEMENTED();
return false;
}
return false;
}
int p3FileDatabase::filterResults(const std::list<EntryIndex>& firesults,std::list<DirDetails>& results,FileSearchFlags flags,const RsPeerId& peer_id) const
@ -628,9 +629,9 @@ void p3FileDatabase::tickRecv()
{
switch(item->PacketSubType())
{
case RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM: handleDirSyncRequest( dynamic_cast<RsFileListsSyncReqItem*>(item) ) ;
case RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM: handleDirSyncRequest( dynamic_cast<RsFileListsSyncRequestItem*>(item) ) ;
break ;
case RS_PKT_SUBTYPE_FILELISTS_SYNC_DIR_ITEM: handleDirSyncContent( dynamic_cast<RsFileListsSyncDirItem*>(item) ) ;
case RS_PKT_SUBTYPE_FILELISTS_SYNC_RSP_ITEM: handleDirSyncResponse( dynamic_cast<RsFileListsSyncResponseItem*>(item) ) ;
break ;
default:
std::cerr << "(EE) unhandled packet subtype " << item->PacketSubType() << " in " << __PRETTY_FUNCTION__ << std::endl;
@ -645,59 +646,119 @@ 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)
void p3FileDatabase::handleDirSyncRequest(RsFileListsSyncRequestItem *item)
{
RsFileListsSyncResponseItem *ritem = new RsFileListsSyncResponseItem;
// look at item TS. If local is newer, send the full directory content.
time_t recurs_max_modf_TS, last_update_TS;
P3FILELISTS_DEBUG() << "Received directory sync request. index=" << item->entry_index << ", flags=" << (void*)(intptr_t)item->flags << ", request id: " << std::hex << item->request_id << std::dec << ", last known TS: " << item->last_known_recurs_modf_TS << std::endl;
if(!mLocalSharedDirs->getUpdateTS(item->entry_index,recurs_max_modf_TS,last_update_TS))
{
std::cerr << "(EE) Cannot get update TS for entry " << item->entry_index << " in local dir, asked by " << item->PeerId() << std::endl;
return ;
RS_STACK_MUTEX(mFLSMtx) ;
P3FILELISTS_DEBUG() << "Received directory sync request. index=" << item->entry_index << ", flags=" << (void*)(intptr_t)item->flags << ", request id: " << std::hex << item->request_id << std::dec << ", last known TS: " << item->last_known_recurs_modf_TS << std::endl;
uint32_t entry_type = mLocalSharedDirs->getEntryType(item->entry_index) ;
ritem->PeerId(item->PeerId()) ;
ritem->request_id = item->request_id;
ritem->entry_index = item->entry_index ;
if(entry_type != DIR_TYPE_DIR)
{
P3FILELISTS_DEBUG() << " Directory does not exist anymore, or is not a directory. Answering with proper flags." << std::endl;
ritem->flags = RsFileListsItem::FLAGS_SYNC_RESPONSE | RsFileListsItem::FLAGS_ENTRY_WAS_REMOVED ;
}
else
{
time_t local_recurs_max_time,local_update_time;
mLocalSharedDirs->getUpdateTS(item->entry_index,local_recurs_max_time,local_update_time);
if(item->last_known_recurs_modf_TS < local_recurs_max_time)
{
P3FILELISTS_DEBUG() << " Directory is more recent than what the friend knows. Sending full dir content as response." << std::endl;
ritem->flags = RsFileListsItem::FLAGS_SYNC_RESPONSE | RsFileListsItem::FLAGS_SYNC_DIR_CONTENT;
ritem->last_known_recurs_modf_TS = local_recurs_max_time;
mLocalSharedDirs->serialiseDirEntry(item->entry_index,ritem->directory_content_data) ;
}
else
{
P3FILELISTS_DEBUG() << " Directory is up to date w.r.t. what the friend knows. Sending ACK." << std::endl;
ritem->flags = RsFileListsItem::FLAGS_SYNC_RESPONSE | RsFileListsItem::FLAGS_ENTRY_UP_TO_DATE ;
ritem->last_known_recurs_modf_TS = local_update_time ;
}
}
}
if(item->last_known_recurs_modf_TS < recurs_max_modf_TS)
{
// send full update of directory content
}
else
{
// send last recurs update TS.
}
// sends the response.
sendItem(ritem);
}
void p3FileDatabase::handleDirSyncContent(RsFileListsSyncDirItem *item)
void p3FileDatabase::handleDirSyncResponse(RsFileListsSyncResponseItem *item)
{
// update the directory content for the specified friend.
// find the correct friend entry
// set the update TS, and the remote modif TS accordingly
uint32_t fi = 0 ;
// notify the GUI if the hierarchy has changed
P3FILELISTS_DEBUG() << "Handling sync response for directory with index " << item->entry_index << std::endl;
{
RS_STACK_MUTEX(mFLSMtx) ;
fi = locked_getFriendIndex(item->PeerId());
// make sure we have a remote directory for that friend.
if(mRemoteDirectories.size() <= fi)
mRemoteDirectories.resize(fi+1,NULL) ;
if(mRemoteDirectories[fi] == NULL)
mRemoteDirectories[fi] = new RemoteDirectoryStorage(item->PeerId(),makeRemoteFileName(item->PeerId()));
}
if(item->flags & RsFileListsItem::FLAGS_ENTRY_WAS_REMOVED)
{
P3FILELISTS_DEBUG() << " removing directory with index " << item->entry_index << " because it does not exist." << std::endl;
mRemoteDirectories[fi]->removeDirectory(item->entry_index);
}
else if(item->flags & RsFileListsItem::FLAGS_ENTRY_UP_TO_DATE)
{
P3FILELISTS_DEBUG() << " Directory is up to date. Setting local TS." << std::endl;
mRemoteDirectories[fi]->setUpdateTS(item->entry_index,item->last_known_recurs_modf_TS,time(NULL));
}
else if(item->flags & RsFileListsItem::FLAGS_SYNC_DIR_CONTENT)
{
P3FILELISTS_DEBUG() << " Item contains directory data. Uptating." << std::endl;
mRemoteDirectories[fi]->deserialiseUpdateEntry(item->entry_index,item->directory_content_data) ;
mRemoteDirectories[fi]->setUpdateTS(item->entry_index,item->last_known_recurs_modf_TS,time(NULL));
#warning should notify the GUI here
// 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 ;
// get the info for this entry
if(!rds->getUpdateTS(e,recurs_max_modf_TS,last_update_TS))
time_t recurs_max_modf_TS_remote_time,local_update_TS;
if(!rds->getUpdateTS(e,recurs_max_modf_TS_remote_time,local_update_TS))
{
std::cerr << "(EE) Cannot get update TS for entry " << e << " in remote dir from " << rds->peerId() << std::endl;
return ;
std::cerr << "(EE) lockec_recursSweepRemoteDirectory(): cannot get update TS for directory with index " << e << ". This is a consistency bug." << std::endl;
return;
}
if(now > last_update_TS + DELAY_BETWEEN_REMOTE_DIRECTORY_SYNC_REQ)
// compare TS
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.
@ -707,11 +768,11 @@ void p3FileDatabase::locked_recursSweepRemoteDirectory(RemoteDirectoryStorage *r
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;
P3FILELISTS_DEBUG() << "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;
P3FILELISTS_DEBUG() << "Asking for sync of directory " << e << " because it's " << (now - local_update_TS) << " secs old since last check." << std::endl;
DirSyncRequestData data ;
@ -719,13 +780,24 @@ void p3FileDatabase::locked_recursSweepRemoteDirectory(RemoteDirectoryStorage *r
mPendingSyncRequests[sync_req_id] = data ;
RsFileListsSyncReqItem *item = new RsFileListsSyncReqItem ;
RsFileListsSyncRequestItem *item = new RsFileListsSyncRequestItem ;
item->entry_index = e ;
item->last_known_recurs_modf_TS = recurs_max_modf_TS ;
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()) ;
sendItem(item) ;
// Dont recurs into sub-directories, since we dont know yet were to go.
return ;
}
for(DirectoryStorage::DirIterator it(rds,e);it;++it)
locked_recursSweepRemoteDirectory(rds,*it);
}

View File

@ -37,8 +37,8 @@ class LocalDirectoryUpdater ;
class RemoteDirectoryStorage ;
class LocalDirectoryStorage ;
class RsFileListsSyncReqItem ;
class RsFileListsSyncDirItem ;
class RsFileListsSyncRequestItem ;
class RsFileListsSyncResponseItem ;
class HashStorage ;
@ -167,8 +167,8 @@ class p3FileDatabase: public p3Service, public p3Config, public ftSearch //, pub
uint32_t locked_getFriendIndex(const RsPeerId& pid);
const RsPeerId& locked_getFriendFromIndex(uint32_t indx) const;
void handleDirSyncRequest(RsFileListsSyncReqItem *) ;
void handleDirSyncContent(RsFileListsSyncDirItem *) ;
void handleDirSyncRequest (RsFileListsSyncRequestItem *) ;
void handleDirSyncResponse (RsFileListsSyncResponseItem *) ;
std::map<RsPeerId,uint32_t> mFriendIndexMap ;
std::vector<RsPeerId> mFriendIndexTab;

View File

@ -15,8 +15,8 @@ RsItem* RsFileListsSerialiser::deserialise(void *data, uint32_t *size)
switch(getRsItemSubType(rstype))
{
case RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM: return deserialFileListsSyncReqItem(data, size);
case RS_PKT_SUBTYPE_FILELISTS_SYNC_DIR_ITEM: return deserialFileListsSyncDirItem(data, size);
case RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM: return deserialFileListsSyncRequestItem(data, size);
case RS_PKT_SUBTYPE_FILELISTS_SYNC_RSP_ITEM: return deserialFileListsSyncResponseItem(data, size);
case RS_PKT_SUBTYPE_FILELISTS_CONFIG_ITEM: return deserialFileListsConfigItem (data, size);
default:
@ -77,7 +77,7 @@ bool RsFileListsItem::serialise_header(void *data,uint32_t& pktsize,uint32_t& tl
return true ;
}
bool RsFileListsSyncReqItem::serialise(void *data, uint32_t& size) const
bool RsFileListsSyncRequestItem::serialise(void *data, uint32_t& size) const
{
uint32_t tlvsize,offset=0;
bool ok = true;
@ -113,7 +113,7 @@ bool RsFileListsSyncReqItem::serialise(void *data, uint32_t& size) const
return ok;
}
bool RsFileListsSyncDirItem::serialise(void *data, uint32_t& size) const
bool RsFileListsSyncResponseItem::serialise(void *data, uint32_t& size) const
{
uint32_t tlvsize,offset=0;
bool ok = true;
@ -154,12 +154,12 @@ bool RsFileListsSyncDirItem::serialise(void *data, uint32_t& size) const
// Deserialisation //
//============================================================================================================================//
RsFileListsSyncReqItem* RsFileListsSerialiser::deserialFileListsSyncReqItem(void *data, uint32_t *size)
RsFileListsSyncRequestItem* RsFileListsSerialiser::deserialFileListsSyncRequestItem(void *data, uint32_t *size)
{
bool ok = checkItemHeader(data,size,RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM);
uint32_t offset = 8;
RsFileListsSyncReqItem* item = new RsFileListsSyncReqItem();
RsFileListsSyncRequestItem* item = new RsFileListsSyncRequestItem();
ok &= getRawUInt32(data, *size, &offset, &item->entry_index);
ok &= getRawUInt32(data, *size, &offset, &item->flags);
@ -187,12 +187,12 @@ RsFileListsSyncReqItem* RsFileListsSerialiser::deserialFileListsSyncReqItem(void
return item;
}
RsFileListsSyncDirItem* RsFileListsSerialiser::deserialFileListsSyncDirItem(void *data, uint32_t *size)
RsFileListsSyncResponseItem* RsFileListsSerialiser::deserialFileListsSyncResponseItem(void *data, uint32_t *size)
{
bool ok = checkItemHeader(data,size,RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM);
uint32_t offset = 8;
RsFileListsSyncDirItem* item = new RsFileListsSyncDirItem();
RsFileListsSyncResponseItem* item = new RsFileListsSyncResponseItem();
uint32_t entry_index ; // index of the directory to sync
uint32_t flags; // used to say that it's a request or a response, say that the directory has been removed, ask for further update, etc.
@ -262,7 +262,7 @@ bool RsFileListsSerialiser::checkItemHeader(void *data,uint32_t *size,uint8_t su
// Sizes //
//============================================================================================================================//
uint32_t RsFileListsSyncReqItem::serial_size()const
uint32_t RsFileListsSyncRequestItem::serial_size()const
{
uint32_t s = 8; //header size
@ -275,7 +275,7 @@ uint32_t RsFileListsSyncReqItem::serial_size()const
return s;
}
uint32_t RsFileListsSyncDirItem::serial_size()const
uint32_t RsFileListsSyncResponseItem::serial_size()const
{
uint32_t s = 8; //header size
@ -289,14 +289,14 @@ uint32_t RsFileListsSyncDirItem::serial_size()const
return s;
}
void RsFileListsSyncReqItem::clear()
void RsFileListsSyncRequestItem::clear()
{
}
void RsFileListsSyncDirItem::clear()
void RsFileListsSyncResponseItem::clear()
{
directory_content_data.TlvClear();
}
std::ostream& RsFileListsSyncReqItem::print(std::ostream &out, uint16_t indent)
std::ostream& RsFileListsSyncRequestItem::print(std::ostream &out, uint16_t indent)
{
printRsItemBase(out, "RsFileListsSyncReqItem", indent);
uint16_t int_Indent = indent + 2;
@ -311,7 +311,7 @@ std::ostream& RsFileListsSyncReqItem::print(std::ostream &out, uint16_t indent)
return out;
}
std::ostream& RsFileListsSyncDirItem::print(std::ostream &out, uint16_t indent)
std::ostream& RsFileListsSyncResponseItem::print(std::ostream &out, uint16_t indent)
{
printRsItemBase(out, "RsFileListsSyncDirItem", indent);
uint16_t int_Indent = indent + 2;

View File

@ -38,7 +38,7 @@
// These items have "flag type" numbers, but this is not used.
const uint8_t RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM = 0x01;
const uint8_t RS_PKT_SUBTYPE_FILELISTS_SYNC_DIR_ITEM = 0x02;
const uint8_t RS_PKT_SUBTYPE_FILELISTS_SYNC_RSP_ITEM = 0x02;
const uint8_t RS_PKT_SUBTYPE_FILELISTS_CONFIG_ITEM = 0x03;
/*!
@ -64,18 +64,19 @@ public:
static const uint32_t FLAGS_SYNC_REQUEST = 0x0001 ;
static const uint32_t FLAGS_SYNC_RESPONSE = 0x0002 ;
static const uint32_t FLAGS_ENTRY_UP_TO_DATE = 0x0004 ;
static const uint32_t FLAGS_ENTRY_WAS_REMOVED = 0x0008 ;
static const uint32_t FLAGS_SYNC_DIR_CONTENT = 0x0004 ;
static const uint32_t FLAGS_ENTRY_UP_TO_DATE = 0x0008 ;
static const uint32_t FLAGS_ENTRY_WAS_REMOVED = 0x0010 ;
};
/*!
* Use to request synchronization on a specific directory. Also used to respond that the directory is up to date.
*/
class RsFileListsSyncReqItem : public RsFileListsItem
class RsFileListsSyncRequestItem : public RsFileListsItem
{
public:
RsFileListsSyncReqItem() : RsFileListsItem(RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM) {}
RsFileListsSyncRequestItem() : RsFileListsItem(RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM) {}
virtual void clear();
virtual std::ostream &print(std::ostream &out, uint16_t indent);
@ -89,11 +90,11 @@ public:
uint64_t request_id; // use to determine if changes that have occured since last hash
};
class RsFileListsSyncDirItem : public RsFileListsItem
class RsFileListsSyncResponseItem : public RsFileListsItem
{
public:
RsFileListsSyncDirItem() : RsFileListsItem(RS_PKT_SUBTYPE_FILELISTS_SYNC_DIR_ITEM) {}
RsFileListsSyncResponseItem() : RsFileListsItem(RS_PKT_SUBTYPE_FILELISTS_SYNC_RSP_ITEM) {}
virtual void clear();
virtual std::ostream &print(std::ostream &out, uint16_t indent);
@ -122,9 +123,9 @@ public:
virtual RsItem* deserialise(void *data, uint32_t *size);
private:
RsFileListsSyncReqItem *deserialFileListsSyncReqItem(void *data, uint32_t *size); /* RS_PKT_SUBTYPE_SYNC_GRP */
RsFileListsSyncDirItem *deserialFileListsSyncDirItem(void *data, uint32_t *size); /* RS_PKT_SUBTYPE_SYNC_GRP */
RsFileListsSyncDirItem *deserialFileListsConfigItem (void *data, uint32_t *size); /* RS_PKT_SUBTYPE_SYNC_GRP */
RsFileListsSyncRequestItem *deserialFileListsSyncRequestItem(void *data, uint32_t *size); /* RS_PKT_SUBTYPE_SYNC_GRP */
RsFileListsSyncResponseItem *deserialFileListsSyncResponseItem(void *data, uint32_t *size); /* RS_PKT_SUBTYPE_SYNC_GRP */
RsFileListsSyncResponseItem *deserialFileListsConfigItem (void *data, uint32_t *size); /* RS_PKT_SUBTYPE_SYNC_GRP */
bool checkItemHeader(void *data, uint32_t *size, uint8_t subservice_type);
};