mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
merged branch v0.6-FileLists locally into master
This commit is contained in:
commit
ee54c02101
3
.gitignore
vendored
3
.gitignore
vendored
@ -6,6 +6,7 @@
|
||||
moc_*.cpp
|
||||
qrc_*.cpp
|
||||
ui_*.h
|
||||
Makefile.*
|
||||
Makefile*
|
||||
*.sw?
|
||||
*~
|
||||
Thumbs.db
|
||||
|
@ -173,8 +173,8 @@ void FileSearchHandler::handleCreateSearch(Request &req, Response &resp)
|
||||
return;
|
||||
}
|
||||
|
||||
NameExpression exprs(ContainsAllStrings,words,true) ;
|
||||
LinearizedExpression lin_exp ;
|
||||
RsRegularExpression::NameExpression exprs(RsRegularExpression::ContainsAllStrings,words,true) ;
|
||||
RsRegularExpression::LinearizedExpression lin_exp ;
|
||||
exprs.linearize(lin_exp) ;
|
||||
|
||||
uint32_t search_id = RSRandom::random_u32();
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,475 +0,0 @@
|
||||
/*
|
||||
* RetroShare FileCache Module: cachestrapper.h
|
||||
*
|
||||
* Copyright 2004-2007 by Robert Fernie.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare@lunamutt.com".
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MRK_CACHE_STRAPPER_H
|
||||
#define MRK_CACHE_STRAPPER_H
|
||||
|
||||
#include "pqi/p3cfgmgr.h"
|
||||
#include "pqi/pqiservicemonitor.h"
|
||||
#include "util/rsthreads.h"
|
||||
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
/******************* CacheStrapper and Related Classes *******************
|
||||
* A generic Cache Update system.
|
||||
*
|
||||
* CacheStrapper: maintains a set of CacheSources, and CacheStores,
|
||||
* queries and updates as new information arrives.
|
||||
*
|
||||
* CacheTransfer: Interface for FileTransfer Class to support.
|
||||
*
|
||||
* CacheSource: Base Class for cache data provider. eg. FileIndexMonitor.
|
||||
* CacheStore: Base Class for data cache. eg. FileCache/Store.
|
||||
*
|
||||
* Still TODO:
|
||||
* (1) Design and Implement the Upload side of CacheTransfer/CacheStrapper.
|
||||
* (2) CacheStrapper:: Save / Load Cache lists....
|
||||
* (3) Clean up lists, maps on shutdown etc.
|
||||
* (4) Consider Mutexes for multithreaded operations.
|
||||
* (5) Test the MultiSource/Store capabilities.
|
||||
*
|
||||
******************* CacheStrapper and Related Classes *******************/
|
||||
|
||||
|
||||
class CacheTransfer; /* Interface for File Transfer */
|
||||
class CacheSource; /* Interface for local File Index/Monitor */
|
||||
class CacheStore; /* Interface for the actual Cache */
|
||||
class CacheStrapper; /* Controlling Class */
|
||||
|
||||
/******************************** CacheId ********************************/
|
||||
|
||||
/*!
|
||||
* Use this to identify the type of cache source, strapper,
|
||||
*/
|
||||
class CacheId
|
||||
{
|
||||
public:
|
||||
CacheId() :type(0), subid(0) { return; }
|
||||
CacheId(uint16_t a, uint16_t b) :type(a), subid(b) { return; }
|
||||
uint16_t type; /// cache types, this should be set to services type
|
||||
uint16_t subid; /// should be initialised when using multicache feature of cachestrapper
|
||||
};
|
||||
|
||||
|
||||
bool operator<(const CacheId &a, const CacheId &b);
|
||||
|
||||
/*!
|
||||
* Use for identifying physical files that have been chosen as cache data
|
||||
* note: this does not actual store the data but serves to locate on network (via hash attribute,
|
||||
* and on file via path)
|
||||
*/
|
||||
class RsCacheData
|
||||
{
|
||||
public:
|
||||
|
||||
RsPeerId pid; /// peer id
|
||||
/// REMOVED as a WASTE to look it up everywhere! std::string pname; /// peer name (can be used by cachestore)
|
||||
CacheId cid; /// cache id
|
||||
std::string path; /// file system path where physical cache data is located
|
||||
std::string name;
|
||||
RsFileHash hash;
|
||||
uint64_t size;
|
||||
time_t recvd; /// received timestamp
|
||||
};
|
||||
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const RsCacheData &d);
|
||||
|
||||
/***************************** CacheTransfer *****************************/
|
||||
|
||||
/**
|
||||
* Interface for FileTransfer Class to support cache
|
||||
*/
|
||||
class CacheTransfer
|
||||
{
|
||||
public:
|
||||
|
||||
CacheTransfer(CacheStrapper *cs) :strapper(cs) { return; }
|
||||
virtual ~CacheTransfer() {}
|
||||
|
||||
/*!
|
||||
* upload side of things .... searches through CacheStrapper.
|
||||
*/
|
||||
bool FindCacheFile(const RsFileHash& hash, std::string &path, uint64_t &size);
|
||||
|
||||
/*!
|
||||
* At the download side RequestCache() => overloaded RequestCacheFile()
|
||||
* the class should then call CompletedCache() or FailedCache()
|
||||
*/
|
||||
bool RequestCache(RsCacheData &data, CacheStore *cbStore); /* request from CacheStore */
|
||||
|
||||
protected:
|
||||
|
||||
/*!
|
||||
* to be overloaded
|
||||
*/
|
||||
virtual bool RequestCacheFile(const RsPeerId& id, std::string path, const RsFileHash& hash, uint64_t size);
|
||||
virtual bool CancelCacheFile(const RsPeerId& id, std::string path, const RsFileHash& hash, uint64_t size);
|
||||
|
||||
bool CompletedCache(const RsFileHash &hash); /* internal completion -> does cb */
|
||||
bool FailedCache(const RsFileHash &hash); /* internal completion -> does cb */
|
||||
|
||||
private:
|
||||
|
||||
CacheStrapper *strapper;
|
||||
|
||||
std::map<RsFileHash, RsCacheData> cbData;
|
||||
std::map<RsFileHash, CacheStore *> cbStores;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/************************ CacheSource/CacheStore *************************/
|
||||
|
||||
typedef std::map<uint16_t, RsCacheData> CacheSet;
|
||||
|
||||
/*!
|
||||
* Implements features needed for a service to act as a cachesource and allow pushing a of cache data from service to strapper
|
||||
* Service is able to use this class for refresh its cache (push cache data)
|
||||
* and interface to load and check cache availablility among peers (source of cache data)
|
||||
* Architecturally Cachestrapper maintains the cachesource (which is passed as a pointer handle) while the cachesource-inheriting
|
||||
* service can update cachesource as to new cache sources (cache data) created. Equivalently it enquiries through cache source for
|
||||
* new cache data from peers
|
||||
* @see p3Distrib
|
||||
*/
|
||||
class CacheSource
|
||||
{
|
||||
public:
|
||||
|
||||
CacheSource(uint16_t t, bool m, CacheStrapper *cs, std::string cachedir);
|
||||
virtual ~CacheSource() {}
|
||||
|
||||
/*!
|
||||
* called to determine available cache for peer -
|
||||
* default acceptable (returns all)
|
||||
*/
|
||||
virtual bool cachesAvailable(const RsPeerId& pid, std::map<CacheId, RsCacheData> &ids)=0;
|
||||
|
||||
/*!
|
||||
* function called at startup to load from
|
||||
* configuration file....
|
||||
* to be overloaded by inherited class
|
||||
*/
|
||||
virtual bool loadLocalCache(const RsCacheData &data);
|
||||
|
||||
/* control Caches available */
|
||||
bool refreshCache(const RsCacheData &data,const std::set<RsPeerId>& destination_peers);
|
||||
bool refreshCache(const RsCacheData &data);
|
||||
bool clearCache(CacheId id);
|
||||
|
||||
/* controls if peer is an accepted receiver for cache items. Default is yes. To be overloaded. */
|
||||
virtual bool isPeerAcceptedAsCacheReceiver(const RsPeerId& /*peer_id*/) { return true ; }
|
||||
|
||||
/* get private data */
|
||||
std::string getCacheDir() { return cacheDir; }
|
||||
bool isMultiCache() { return multiCache; }
|
||||
uint16_t getCacheType() { return cacheType; }
|
||||
|
||||
/* display */
|
||||
void listCaches(std::ostream &out);
|
||||
|
||||
/* search */
|
||||
bool findCache(const RsFileHash& hash, RsCacheData &data) const;
|
||||
|
||||
protected:
|
||||
|
||||
uint16_t cacheType; /// for checking of cache type (usually of child class of source)
|
||||
bool multiCache; /// whether multisource is in use or not.
|
||||
CacheStrapper *mStrapper;
|
||||
|
||||
/*** MUTEX LOCKING */
|
||||
void lockData() const;
|
||||
void unlockData() const;
|
||||
|
||||
CacheSet caches; /// all local cache data stored here
|
||||
std::map<RsFileHash, RsCacheData> mOldCaches; /// replaced/cleared caches are pushed here (in case requested)
|
||||
|
||||
private:
|
||||
|
||||
std::string cacheDir;
|
||||
mutable RsMutex cMutex;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
* Base Class for data cache. eg. FileCache/Store.
|
||||
* This is best used to deal with external caches from other peers
|
||||
* @see p3Distrib. pqiMonitor
|
||||
*/
|
||||
class CacheStore
|
||||
{
|
||||
public:
|
||||
|
||||
/*!
|
||||
*
|
||||
* @param t set to particular rs_service id. see rsserviceids.h
|
||||
* @param m whether this is multicache service (true) or not(false)
|
||||
* @param cs cache strapper instance responsible for maintaining the cache service
|
||||
* @param cft cache transfer instance responsible for rquestiing and tranfering caches
|
||||
* @param cachedir directory used to store cache related info for cachestore client
|
||||
* @return
|
||||
*/
|
||||
CacheStore(uint16_t t, bool m, CacheStrapper *cs, CacheTransfer *cft, std::string cachedir);
|
||||
virtual ~CacheStore() {}
|
||||
|
||||
/* current stored data */
|
||||
|
||||
/*!
|
||||
*
|
||||
* @param data returns cache data for pid/cid set in data itself
|
||||
* @return false is unsuccessful and vice versa
|
||||
*/
|
||||
bool getStoredCache(RsCacheData &data); /* use pid/cid in data */
|
||||
|
||||
/*!
|
||||
*
|
||||
* @param data all cache store by cachestore is store here
|
||||
* @return false not returned, only true at the moment
|
||||
*/
|
||||
bool getAllStoredCaches(std::list<RsCacheData> &data); /* use pid/cid in data */
|
||||
|
||||
/*!
|
||||
* input from CacheStrapper -> store can then download new data
|
||||
*/
|
||||
void availableCache(const RsCacheData &data);
|
||||
|
||||
/*!
|
||||
* should be called when the download is completed ... cache data is loaded
|
||||
*/
|
||||
void downloadedCache(const RsCacheData &data);
|
||||
|
||||
/*!
|
||||
* called if the download fails, TODO: nothing done yet
|
||||
*/
|
||||
void failedCache(const RsCacheData &data);
|
||||
|
||||
/* virtual functions overloaded by cache implementor */
|
||||
|
||||
/* controls if peer is an accepted provider for cache items. Default is yes. To be overloaded. */
|
||||
virtual bool isPeerAcceptedAsCacheProvider(const RsPeerId& /*peer_id*/) { return true ; }
|
||||
|
||||
/*!
|
||||
* @param data cache data is stored here
|
||||
* @return false is failed (cache does not exist), otherwise true
|
||||
*/
|
||||
virtual bool fetchCache(const RsCacheData &data); /* a question? */
|
||||
virtual int nameCache(RsCacheData &data); /* fill in the name/path */
|
||||
virtual int loadCache(const RsCacheData &data); /* actual load, once data available */
|
||||
|
||||
/* get private data */
|
||||
|
||||
std::string getCacheDir() { return cacheDir; }
|
||||
bool isMultiCache() { return multiCache; }
|
||||
uint16_t getCacheType() { return cacheType; }
|
||||
|
||||
/*!
|
||||
* display, e.g. can pass std::out, cerr, ofstream, etc
|
||||
*/
|
||||
void listCaches(std::ostream &out);
|
||||
|
||||
protected:
|
||||
|
||||
/*!
|
||||
* ** MUTEX LOCKING
|
||||
*/
|
||||
void lockData() const;
|
||||
|
||||
/*!
|
||||
* ** MUTEX LOCKING
|
||||
*/
|
||||
void unlockData() const;
|
||||
|
||||
/*! This function is called to store Cache Entry in the CacheStore Table.
|
||||
* it must be called from within a Mutex Lock....
|
||||
*
|
||||
* It doesn't lock itself -> to avoid race conditions
|
||||
*/
|
||||
void locked_storeCacheEntry(const RsCacheData &data);
|
||||
|
||||
/*! This function is called to store Cache Entry in the CacheStore Table.
|
||||
* it must be called from within a Mutex Lock....
|
||||
*
|
||||
* It doesn't lock itself -> to avoid race conditions
|
||||
*/
|
||||
bool locked_getStoredCache(RsCacheData &data);
|
||||
|
||||
private:
|
||||
|
||||
uint16_t cacheType; /* for checking */
|
||||
bool multiCache; /* do we care about subid's */
|
||||
|
||||
CacheStrapper *mStrapper;
|
||||
CacheTransfer *cacheTransfer;
|
||||
|
||||
std::string cacheDir;
|
||||
|
||||
mutable RsMutex cMutex;
|
||||
std::map<RsPeerId, CacheSet> caches;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/***************************** CacheStrapper *****************************/
|
||||
|
||||
|
||||
/*!
|
||||
* a convenient to pass cache handles to cachestrapper to maintain the cache service
|
||||
* Make Sure you get the Ids right! see rsservicesids.h.
|
||||
* When creating a cache service this data structure is
|
||||
* source, usually the child class of store and source also serves as both handles
|
||||
* @see CacheStrapper
|
||||
*/
|
||||
class CachePair
|
||||
{
|
||||
public:
|
||||
|
||||
/*!
|
||||
* Default constructor, all variables set to NULL
|
||||
*/
|
||||
CachePair()
|
||||
:source(NULL), store(NULL), id(0, 0) { return; }
|
||||
|
||||
/*!
|
||||
*
|
||||
* @param a cache source for service
|
||||
* @param b cache store for service
|
||||
* @param c the cache service id, c.type should be set to service id service-child class of store and source
|
||||
*/
|
||||
CachePair(CacheSource *a, CacheStore *b, CacheId c)
|
||||
:source(a), store(b), id(c) { return; }
|
||||
|
||||
CacheSource *source;
|
||||
CacheStore *store;
|
||||
CacheId id; /// should be set id type to service types of store and source service-child class, and subid for multicache use
|
||||
};
|
||||
|
||||
|
||||
bool operator<(const CachePair &a, const CachePair &b);
|
||||
|
||||
/*!
|
||||
* CacheStrapper: maintains a set of CacheSources, and CacheStores,
|
||||
* queries and updates as new information arrives.
|
||||
*/
|
||||
|
||||
class p3ServiceControl;
|
||||
|
||||
class CacheStrapper: public pqiServiceMonitor, public p3Config
|
||||
{
|
||||
public:
|
||||
|
||||
/*!
|
||||
* @param cm handle used by strapper for getting peer connection information (online peers, sslids...)
|
||||
* @return
|
||||
*/
|
||||
CacheStrapper(p3ServiceControl *sc, uint32_t ftServiceId);
|
||||
virtual ~CacheStrapper() { return; }
|
||||
|
||||
/************* from pqiMonitor *******************/
|
||||
virtual void statusChange(const std::list<pqiServicePeer> &plist);
|
||||
/************* from pqiMonitor *******************/
|
||||
|
||||
/* Feedback from CacheSources */
|
||||
|
||||
/*!
|
||||
* send data to peers online and self
|
||||
* @param data
|
||||
*
|
||||
*/
|
||||
void refreshCache(const RsCacheData &data);
|
||||
void refreshCache(const RsCacheData &data,const std::set<RsPeerId>& destination_peers); // specify a particular list of destination peers (self not added!)
|
||||
|
||||
/*!
|
||||
* forces config savelist
|
||||
* @param data
|
||||
* @see saveList()
|
||||
*/
|
||||
void refreshCacheStore(const RsCacheData &data);
|
||||
|
||||
/*!
|
||||
* list of Caches to send out
|
||||
*/
|
||||
bool getCacheUpdates(std::list<std::pair<RsPeerId, RsCacheData> > &updates);
|
||||
|
||||
/*!
|
||||
* add to strapper's cachepair set so a related service's store and source can be maintained
|
||||
* @param pair the source and store handle for a service
|
||||
*/
|
||||
void addCachePair(CachePair pair);
|
||||
|
||||
/*** I/O (2) ***/
|
||||
void recvCacheResponse(RsCacheData &data, time_t ts);
|
||||
void handleCacheQuery(const RsPeerId& id, std::map<CacheId, RsCacheData> &data);
|
||||
|
||||
|
||||
/*!
|
||||
* search through CacheSources.
|
||||
* @return false if cachedate mapping to hash not found
|
||||
*/
|
||||
bool findCache(const RsFileHash &hash, RsCacheData &data) const;
|
||||
|
||||
/* display */
|
||||
void listCaches(std::ostream &out);
|
||||
|
||||
/*!
|
||||
* does not do anything
|
||||
* @param out
|
||||
* @deprecated
|
||||
*/
|
||||
void listPeerStatus(std::ostream &out);
|
||||
|
||||
/**
|
||||
* Checks if the cache physically exist at path given
|
||||
* @param data
|
||||
* @return whether it exists or not
|
||||
*/
|
||||
bool CacheExist(RsCacheData& data);
|
||||
|
||||
/* Config */
|
||||
protected:
|
||||
|
||||
/* Key Functions to be overloaded for Full Configuration */
|
||||
virtual RsSerialiser *setupSerialiser();
|
||||
virtual bool saveList(bool &cleanup, std::list<RsItem *>&);
|
||||
virtual bool loadList(std::list<RsItem *>& load);
|
||||
|
||||
private:
|
||||
|
||||
/* these are static - so shouldn't need mutex */
|
||||
p3ServiceControl *mServiceCtrl;
|
||||
uint32_t mFtServiceId;
|
||||
|
||||
std::map<uint16_t, CachePair> caches;
|
||||
|
||||
RsMutex csMtx; /* protect below */
|
||||
|
||||
std::list<std::pair<RsPeerId, RsCacheData> > mCacheUpdates;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
@ -1,63 +0,0 @@
|
||||
/*
|
||||
* RetroShare FileCache Module: cachetest.h
|
||||
*
|
||||
* Copyright 2004-2007 by Robert Fernie.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare@lunamutt.com".
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MRK_TEST_CACHE_H
|
||||
#define MRK_TEST_CACHE_H
|
||||
|
||||
#include "cachestrapper.h"
|
||||
|
||||
#define TESTID 0xffff
|
||||
#define TESTID2 0xffee
|
||||
|
||||
class CacheTestSource: public CacheSource
|
||||
{
|
||||
public:
|
||||
CacheTestSource(CacheStrapper *cs, std::string dir)
|
||||
:CacheSource(cs, TESTID, false, dir) { return; }
|
||||
};
|
||||
|
||||
class CacheTestStore: public CacheStore
|
||||
{
|
||||
public:
|
||||
CacheTestStore(CacheTransfer *cft, std::string dir)
|
||||
:CacheStore(TESTID, false, cft, dir) { return; }
|
||||
};
|
||||
|
||||
|
||||
class CacheTestMultiSource: public CacheSource
|
||||
{
|
||||
public:
|
||||
CacheTestMultiSource(CacheStrapper *cs, std::string dir)
|
||||
:CacheSource(cs, TESTID2, true, dir) { return; }
|
||||
};
|
||||
|
||||
class CacheTestMultiStore: public CacheStore
|
||||
{
|
||||
public:
|
||||
CacheTestMultiStore(CacheTransfer *cft, std::string dir)
|
||||
:CacheStore(TESTID2, true, cft, dir) { return; }
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,220 +0,0 @@
|
||||
/*
|
||||
* RetroShare FileCache Module: fimonitor.h
|
||||
*
|
||||
* Copyright 2004-2007 by Robert Fernie.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare@lunamutt.com".
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FILE_INDEX_MONITOR_H
|
||||
#define FILE_INDEX_MONITOR_H
|
||||
|
||||
#include "dbase/cachestrapper.h"
|
||||
#include "dbase/findex.h"
|
||||
#include "util/rsthreads.h"
|
||||
#include "retroshare/rsfiles.h"
|
||||
|
||||
/******************************************************************************************
|
||||
* The Local Monitoring Class: FileIndexMonitor.
|
||||
*
|
||||
* This periodically scans the directory tree, and updates any modified directories/files.
|
||||
*
|
||||
*****************************************************************************************/
|
||||
|
||||
/******************************************************************************************
|
||||
STILL TODO:
|
||||
|
||||
(1) Implement Hash function.
|
||||
|
||||
bool FileIndexMonitor::hashFile(std::string path, FileEntry &fi);
|
||||
|
||||
(2) Add Shared directory controls to Monitor.
|
||||
|
||||
int FileIndexMonitor::addSharedDirectory(std::path);
|
||||
int FileIndexMonitor::removeSharedDirectory(std::path);
|
||||
std::string FileIndexMonitor::findRealRoot(std::string base);
|
||||
|
||||
These must be split into <base>/<top> and the mapping saved.
|
||||
eg: addSharedDirectory("c:/home/stuff/dir1") --> "c:/home/stuff" <-> "dir1"
|
||||
This code has been written already, and can just be moved over.
|
||||
|
||||
FOR LATER:
|
||||
(2) Port File/Directory lookup code to windoze. (or compile dirent.c under windoze)
|
||||
(3) Add Load/Store interface to FileIndexMonitor. (later)
|
||||
(4) Integrate with real Thread/Mutex code (last thing to do)
|
||||
|
||||
******************************************************************************************/
|
||||
|
||||
|
||||
class DirContentToHash
|
||||
{
|
||||
public:
|
||||
std::vector<FileEntry> fentries ;
|
||||
|
||||
std::string realpath ;
|
||||
std::string dirpath ;
|
||||
};
|
||||
|
||||
class HashCache
|
||||
{
|
||||
public:
|
||||
HashCache(const std::string& save_file_name) ;
|
||||
|
||||
void save() ;
|
||||
void insert(const std::string& full_path,uint64_t size,time_t time_stamp,const RsFileHash& hash) ;
|
||||
bool find(const std::string& full_path,uint64_t size,time_t time_stamp,RsFileHash& hash) ;
|
||||
void clean() ;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t size ;
|
||||
uint64_t time_stamp ;
|
||||
uint64_t modf_stamp ;
|
||||
RsFileHash hash ;
|
||||
} HashCacheInfo ;
|
||||
|
||||
void setRememberHashFilesDuration(uint32_t days) { _max_cache_duration_days = days ; }
|
||||
uint32_t rememberHashFilesDuration() const { return _max_cache_duration_days ; }
|
||||
void clear() { _files.clear(); }
|
||||
bool empty() const { return _files.empty() ; }
|
||||
private:
|
||||
uint32_t _max_cache_duration_days ; // maximum duration of un-requested cache entries
|
||||
std::map<std::string, HashCacheInfo> _files ;
|
||||
std::string _path ;
|
||||
bool _changed ;
|
||||
};
|
||||
|
||||
/******************************************************************************************
|
||||
* FileIndexMonitor
|
||||
*****************************************************************************************/
|
||||
|
||||
class FileIndexMonitor: public CacheSource, public RsTickingThread
|
||||
{
|
||||
public:
|
||||
FileIndexMonitor(CacheStrapper *cs, std::string cachedir, const RsPeerId& pid, const std::string& config_dir);
|
||||
virtual ~FileIndexMonitor();
|
||||
|
||||
/* external interface for filetransfer */
|
||||
bool findLocalFile(const RsFileHash& hash,FileSearchFlags flags,const RsPeerId& peer_id, std::string &fullpath, uint64_t &size,FileStorageFlags& storage_flags,std::list<RsNodeGroupId>& parent_groups) const;
|
||||
|
||||
int SearchKeywords(std::list<std::string> keywords, std::list<DirDetails> &results,FileSearchFlags flags,const RsPeerId& peer_id) ;
|
||||
int SearchBoolExp(Expression *exp, std::list<DirDetails> &results,FileSearchFlags flags,const RsPeerId& peer_id) const ;
|
||||
|
||||
int filterResults(std::list<FileEntry*>& firesults,std::list<DirDetails>& results,FileSearchFlags flags,const RsPeerId& peer_id) const ;
|
||||
|
||||
|
||||
/* external interface for local access to files */
|
||||
bool convertSharedFilePath(std::string path, std::string &fullpath);
|
||||
|
||||
|
||||
/* Interacting with CacheSource */
|
||||
/* overloaded from CacheSource */
|
||||
virtual bool loadLocalCache(const RsCacheData &data); /* called with stored data */
|
||||
bool updateCache(const RsCacheData &data,const std::set<RsPeerId>& dest_peers); /* we call when we have a new cache for others */
|
||||
|
||||
|
||||
/* the FileIndexMonitor inner workings */
|
||||
//virtual void run(std::string& currentJob); /* overloaded from RsThread */
|
||||
//void updateCycle(std::string& currentJob);
|
||||
virtual void data_tick(); /* overloaded from RsThread */
|
||||
void updateCycle();
|
||||
|
||||
// Interface for browsing dir hirarchy
|
||||
int RequestDirDetails(void*, DirDetails&, FileSearchFlags) const ;
|
||||
uint32_t getType(void*) const ;
|
||||
int RequestDirDetails(const std::string& path, DirDetails &details) const ;
|
||||
|
||||
// set/update shared directories
|
||||
virtual void setSharedDirectories(const std::list<SharedDirInfo>& dirs);
|
||||
void getSharedDirectories(std::list<SharedDirInfo>& dirs);
|
||||
void updateShareFlags(const SharedDirInfo& info) ;
|
||||
|
||||
void forceDirectoryCheck(); // Force re-sweep the directories and see what's changed
|
||||
void forceDirListsRebuildAndSend() ; // Force re-build dir lists because groups have changed. Does not re-check files.
|
||||
bool inDirectoryCheck();
|
||||
|
||||
/* util fns */
|
||||
|
||||
// from CacheSource
|
||||
virtual bool cachesAvailable(const RsPeerId& pid, std::map<CacheId, RsCacheData> &ids) ;
|
||||
|
||||
protected:
|
||||
// Sets/gets the duration period within which already hashed files are remembered.
|
||||
//
|
||||
void setRememberHashFilesDuration(uint32_t days) ;
|
||||
uint32_t rememberHashFilesDuration() const ;
|
||||
void setRememberHashFiles(bool) ;
|
||||
bool rememberHashFiles() ;
|
||||
// Remove any memory of formerly hashed files that are not shared anymore
|
||||
void clearHashFiles() ;
|
||||
void setPeriod(int insecs);
|
||||
int getPeriod() const;
|
||||
|
||||
bool autoCheckEnabled() const ;
|
||||
|
||||
private:
|
||||
/* the mutex should be locked before calling these 3. */
|
||||
|
||||
// Saves file indexs and update the cache. Returns the name of the main
|
||||
// file index, which becomes the new reference file for mod times.
|
||||
//
|
||||
time_t locked_saveFileIndexes(bool update_cache) ;
|
||||
|
||||
// Finds the share flags associated with this file entry.
|
||||
void locked_findShareFlagsAndParentGroups(FileEntry *fe, FileStorageFlags& shareflags, std::list<RsNodeGroupId> &parent_groups) const ;
|
||||
|
||||
std::string locked_findRealRoot(std::string base) const;
|
||||
|
||||
void hashFiles(const std::vector<DirContentToHash>& to_hash) ;
|
||||
bool hashFile(std::string path, FileEntry &fi); /* To Implement */
|
||||
|
||||
/* data */
|
||||
|
||||
mutable RsMutex fiMutex;
|
||||
|
||||
FileIndex fi;
|
||||
|
||||
int updatePeriod;
|
||||
std::map<std::string, SharedDirInfo> directoryMap; /* used by findRealRoot */
|
||||
|
||||
/* flags to kick - if we were busy or sleeping */
|
||||
bool pendingDirs;
|
||||
bool pendingForceCacheWrite;
|
||||
|
||||
/* flags to force Check, to tell if we're in check */
|
||||
bool mForceCheck;
|
||||
bool mInCheck;
|
||||
|
||||
std::list<SharedDirInfo> pendingDirList;
|
||||
bool internal_setSharedDirectories();
|
||||
|
||||
HashCache hashCache ;
|
||||
bool useHashCache ;
|
||||
|
||||
std::map<RsPeerId,RsCacheData> _cache_items_per_peer ; // stored the cache items to be sent to each peer.
|
||||
|
||||
// This file is the location of the current index file. When checking for new files, we compare the modification time
|
||||
// of this file to the mod time of the files on the disk. This allows to now account for time-shift in the computer.
|
||||
//
|
||||
time_t reference_time ;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,278 +0,0 @@
|
||||
/*
|
||||
* RetroShare FileCache Module: findex.h
|
||||
*
|
||||
* Copyright 2004-2007 by Robert Fernie.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare@lunamutt.com".
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FILE_INDEX_H
|
||||
#define FILE_INDEX_H
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#if __MACH__
|
||||
#include <unordered_set>
|
||||
#else
|
||||
#include <tr1/unordered_set>
|
||||
#endif
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#include "retroshare/rstypes.h"
|
||||
|
||||
/******************************************************************************************
|
||||
* The Key Data Types for the File Index:
|
||||
|
||||
FileEntry : Information about a single file.
|
||||
DirEntry : Information about a directory and its children
|
||||
PersonEntry : Information the root of a FileIndex.
|
||||
|
||||
FileIndex : A Collection of root directories, with a set of functions to manipulate them.
|
||||
In terms of retroshare, There will be a single 'Local' FileIndex used to store
|
||||
the shared files, and a set of 'Remote' FileIndices which are used to store
|
||||
the available files of all the peers.
|
||||
|
||||
******************************************************************************************/
|
||||
/******************************************************************************************
|
||||
STILL TODO:
|
||||
|
||||
(1) Load/Store a FileIndex to file...
|
||||
int FileIndex::loadIndex(FILE *input);
|
||||
int FileIndex::saveIndex(FILE *input);
|
||||
|
||||
This can be done in a recursive manner, or handled completely within FileIndex.
|
||||
|
||||
(2) Search Functions for Partial File Names and Hashes.
|
||||
|
||||
int FileIndex::searchHash(std::string hash, std::list<FileEntry> &results);
|
||||
int FileIndex::searchTerms(std::list<string> terms, std::list<FileEntry> &results);
|
||||
|
||||
This is probably best done in a recursive manner.
|
||||
|
||||
The search could also be extended to handle complex Boolean searches such as :
|
||||
match (size > 100K) && (name contains 'Blue') .... if anyone is interested.
|
||||
But this can get quite complicated, and can be left to a later date.
|
||||
|
||||
******************************************************************************************/
|
||||
|
||||
|
||||
/******************************************************************************************
|
||||
* FileEntry
|
||||
*****************************************************************************************/
|
||||
|
||||
#include <util/smallobject.h>
|
||||
|
||||
class DirEntry;
|
||||
|
||||
class FileEntry: public RsMemoryManagement::SmallObject
|
||||
{
|
||||
public:
|
||||
FileEntry()
|
||||
: size(0), modtime(0), pop(0), updtime(0), parent(NULL), row(0)
|
||||
{ return; }
|
||||
|
||||
virtual ~FileEntry() { return; }
|
||||
virtual uint32_t type() const { return DIR_TYPE_FILE ; }
|
||||
|
||||
virtual int print(std::string &out);
|
||||
|
||||
/* Data */
|
||||
std::string name;
|
||||
RsFileHash hash;
|
||||
uint64_t size; /* file size */
|
||||
time_t modtime; /* modification time - most recent mod time for a sub entry for dirs */
|
||||
int pop; /* popularity rating */
|
||||
|
||||
time_t updtime; /* last updated */
|
||||
|
||||
/* References for easy manipulation */
|
||||
DirEntry *parent;
|
||||
int row;
|
||||
std::list<std::string> parent_groups ;
|
||||
};
|
||||
|
||||
/******************************************************************************************
|
||||
* DirEntry
|
||||
*****************************************************************************************/
|
||||
|
||||
class DirEntry: public FileEntry
|
||||
{
|
||||
public:
|
||||
|
||||
DirEntry() : most_recent_time(0) {}
|
||||
/* cleanup */
|
||||
virtual ~DirEntry();
|
||||
|
||||
/* update local entries */
|
||||
DirEntry * updateDir(const FileEntry& fe, time_t updtime);
|
||||
FileEntry * updateFile(const FileEntry& fe, time_t updtime);
|
||||
|
||||
|
||||
virtual uint32_t type() const { return DIR_TYPE_DIR ; }
|
||||
int checkParentPointers();
|
||||
int updateChildRows();
|
||||
|
||||
/* remove local entries */
|
||||
int removeFile(const std::string& name);
|
||||
int removeDir(const std::string& name);
|
||||
int removeOldDir(const std::string& name, time_t old); /* checks ts first */
|
||||
|
||||
/* recursive cleanup */
|
||||
int removeOldEntries(time_t old, bool recursive);
|
||||
|
||||
/* recursive searches */
|
||||
DirEntry * findOldDirectory(time_t old);
|
||||
DirEntry * findDirectory(const std::string& path);
|
||||
|
||||
/* recursive update directory mod/pop values */
|
||||
int updateDirectories(const std::string& path, int pop, int modtime);
|
||||
|
||||
/* output */
|
||||
int print(std::string &out);
|
||||
|
||||
int saveEntry(std::string &out);
|
||||
void writeDirInfo(std::string&);
|
||||
void writeFileInfo(std::string&);
|
||||
|
||||
/* Data */
|
||||
std::string path; /* full path (includes name) */
|
||||
std::map<std::string, DirEntry *> subdirs;
|
||||
std::map<std::string, FileEntry *> files;
|
||||
|
||||
time_t most_recent_time; /* last updated */
|
||||
|
||||
/* Inherited members from FileEntry:
|
||||
int size - count for dirs
|
||||
std::string name; - directory name
|
||||
std::string hash; - not used
|
||||
int size; - not used
|
||||
int modtime; - most recent modication time of any child file (recursive)
|
||||
int pop; - most popular child file (recursive)
|
||||
int updtime; - last updated
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
/******************************************************************************************
|
||||
* PersonEntry
|
||||
*****************************************************************************************/
|
||||
|
||||
class PersonEntry: public DirEntry
|
||||
{
|
||||
public:
|
||||
/* cleanup */
|
||||
PersonEntry(const RsPeerId& pid) : id(pid) { return; }
|
||||
virtual ~PersonEntry() { return; }
|
||||
|
||||
DirEntry &operator=(DirEntry &src)
|
||||
{
|
||||
DirEntry *pdest = this;
|
||||
(*pdest) = src;
|
||||
return *this;
|
||||
}
|
||||
virtual uint32_t type() const { return DIR_TYPE_PERSON ; }
|
||||
|
||||
/* Data */
|
||||
RsPeerId id;
|
||||
|
||||
/* Inherited members from FileEntry:
|
||||
int size - count for dirs
|
||||
std::string name; - directory name
|
||||
std::string hash; - not used
|
||||
int size; - not used
|
||||
int modtime; - most recent modication time of any child file (recursive)
|
||||
int pop; - most popular child file (recursive)
|
||||
int updtime; - last updated
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
/******************************************************************************************
|
||||
* FileIndex
|
||||
*****************************************************************************************/
|
||||
|
||||
class Expression;
|
||||
|
||||
class FileIndex
|
||||
{
|
||||
public:
|
||||
FileIndex(const RsPeerId& pid);
|
||||
~FileIndex();
|
||||
|
||||
/* control root entries */
|
||||
int setRootDirectories(const std::list<std::string> &inlist, time_t utime);
|
||||
int getRootDirectories(std::list<std::string> &outlist);
|
||||
|
||||
/* update (index building) */
|
||||
DirEntry * updateDirEntry(const std::string& path, const FileEntry& fe, time_t utime);
|
||||
FileEntry * updateFileEntry(const std::string& path, const FileEntry& fe, time_t utime);
|
||||
|
||||
DirEntry * findOldDirectory(time_t old); /* finds directories older than old */
|
||||
int removeOldDirectory(const std::string& fpath, const std::string& name, time_t old);
|
||||
|
||||
int cleanOldEntries(time_t old); /* removes entries older than old */
|
||||
|
||||
/* debug */
|
||||
int printFileIndex(std::string &out);
|
||||
int printFileIndex(std::ostream &out);
|
||||
|
||||
/* load/save to file */
|
||||
int loadIndex(const std::string& filename, const RsFileHash &expectedHash, uint64_t size);
|
||||
int saveIndex(const std::string& filename, RsFileHash &fileHash, uint64_t &size, const std::set<std::string>& forbidden_roots);
|
||||
|
||||
/* search through this index */
|
||||
int searchTerms(const std::list<std::string>& terms, std::list<FileEntry *> &results) const;
|
||||
int searchHash(const RsFileHash& hash, std::list<FileEntry *> &results) const;
|
||||
int searchBoolExp(Expression * exp, std::list<FileEntry *> &results) const;
|
||||
|
||||
/// Recursively compute the maximum modification time of children.
|
||||
/// Used to easily retrieve mose recent files.
|
||||
//
|
||||
void updateMaxModTime() ;
|
||||
void RecursUpdateMaxModTime(DirEntry *) ;
|
||||
|
||||
PersonEntry *root;
|
||||
|
||||
#ifdef __MACH__
|
||||
static std::unordered_set<void*> _pointers ;
|
||||
#else
|
||||
static std::tr1::unordered_set<void*> _pointers ;
|
||||
#endif
|
||||
static void registerEntry(void*p) ;
|
||||
static void unregisterEntry(void*p) ;
|
||||
static bool isValid(void*p) ;
|
||||
|
||||
/// Fills up details from the data contained in ref.
|
||||
//
|
||||
static bool extractData(void *ref,DirDetails& details) ;
|
||||
static uint32_t getType(void *ref) ;
|
||||
|
||||
void *findRef(const std::string& path) const ;
|
||||
bool extractData(const std::string& path,DirDetails& details) const ;
|
||||
|
||||
void updateHashIndex() ;
|
||||
void recursUpdateHashIndex(DirEntry *) ;
|
||||
|
||||
std::map<RsFileHash,FileEntry*> _file_hashes ;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -1,459 +0,0 @@
|
||||
/*
|
||||
* RetroShare FileCache Module: fistore.cc
|
||||
*
|
||||
* Copyright 2004-2007 by Robert Fernie.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare@lunamutt.com".
|
||||
*
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "rsserver/p3face.h"
|
||||
#include "dbase/fistore.h"
|
||||
#include "retroshare/rsexpr.h"
|
||||
#include "retroshare/rsfiles.h"
|
||||
#include "serialiser/rsserviceids.h"
|
||||
#include "pqi/p3peermgr.h"
|
||||
#include "pqi/p3notify.h"
|
||||
|
||||
FileIndexStore::FileIndexStore(CacheStrapper *cs, CacheTransfer *cft,
|
||||
p3PeerMgr *cnmgr, RsPeerId ownid, std::string cachedir)
|
||||
:CacheStore(RS_SERVICE_TYPE_FILE_INDEX, false, cs, cft, cachedir),
|
||||
localId(ownid), localindex(NULL), mPeerMgr(cnmgr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FileIndexStore::~FileIndexStore()
|
||||
{
|
||||
/* clean up the Index */
|
||||
return;
|
||||
}
|
||||
|
||||
/***
|
||||
* #define FIS_DEBUG2 1
|
||||
* #define FIS_DEBUG 1
|
||||
**/
|
||||
|
||||
/* actual load, once data available */
|
||||
int FileIndexStore::loadCache(const RsCacheData &data)
|
||||
{
|
||||
|
||||
#ifdef FIS_DEBUG2
|
||||
std::cerr << "FileIndexStore::loadCache() hash: " << data.hash << std::endl;
|
||||
std::cerr << "FileIndexStore::loadCache() path: " << data.path << std::endl;
|
||||
std::cerr << "FileIndexStore::loadCache() name: " << data.name << std::endl;
|
||||
std::cerr << "FileIndexStore::loadCache() size: " << data.size << std::endl;
|
||||
#endif
|
||||
|
||||
/* do Callback */
|
||||
AboutToModify();
|
||||
|
||||
/* lock it up */
|
||||
lockData();
|
||||
|
||||
FileIndex *fiold = NULL;
|
||||
bool local = (data.pid == localId);
|
||||
|
||||
std::map<RsPeerId, FileIndex *>::iterator it;
|
||||
/* remove old cache */
|
||||
if (local)
|
||||
{
|
||||
fiold = localindex;
|
||||
localindex = NULL;
|
||||
}
|
||||
else if (indices.end() != (it = indices.find(data.pid)))
|
||||
{
|
||||
fiold = it->second;
|
||||
indices.erase(it);
|
||||
//delete fi;
|
||||
}
|
||||
|
||||
if(mPeerMgr->isFriend(data.pid))
|
||||
{
|
||||
// We discard file lists from non friends. This is the place to remove file lists of deleted friends
|
||||
// from the cache. Doing this, the file list still shows in a session where we deleted a friend, but will be removed
|
||||
// at next restart.
|
||||
//
|
||||
|
||||
/* load Cache */
|
||||
FileIndex *finew = new FileIndex(data.pid);
|
||||
|
||||
if (finew->loadIndex(data.path + '/' + data.name, data.hash, data.size))
|
||||
{
|
||||
#ifdef FIS_DEBUG2
|
||||
std::cerr << "FileIndexStore::loadCache() Succeeded!" << std::endl;
|
||||
#endif
|
||||
/* This is not the place to set the peername.
|
||||
* It is a hack, which makes it programmatically impossible
|
||||
* to get the file data out....
|
||||
*
|
||||
* peername should not be used in dbase.
|
||||
*/
|
||||
finew->root->name = data.pid.toStdString();
|
||||
|
||||
if (local)
|
||||
{
|
||||
localindex = finew;
|
||||
}
|
||||
else
|
||||
{
|
||||
indices[data.pid] = finew;
|
||||
}
|
||||
delete fiold;
|
||||
|
||||
/* store in tale */
|
||||
locked_storeCacheEntry(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef FIS_DEBUG2
|
||||
std::cerr << "FileIndexStore::loadCache() Failed!" << std::endl;
|
||||
#endif
|
||||
/* reinstall the old one! */
|
||||
delete finew;
|
||||
if (fiold)
|
||||
{
|
||||
if (local)
|
||||
{
|
||||
localindex = fiold;
|
||||
}
|
||||
else
|
||||
{
|
||||
indices[data.pid] = fiold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef FIS_DEBUG
|
||||
else
|
||||
std::cerr << "Discarding file list from deleted peer " << data.pid << std::endl ;
|
||||
#endif
|
||||
|
||||
/* need to correct indices(row) for the roots of the FileIndex */
|
||||
int i = 0;
|
||||
for(it = indices.begin(); it != indices.end(); ++it)
|
||||
{
|
||||
(it->second)->root->row = i++;
|
||||
it->second->FileIndex::updateMaxModTime() ;
|
||||
}
|
||||
if (localindex)
|
||||
{
|
||||
localindex->root->row = 0;
|
||||
localindex->updateMaxModTime() ;
|
||||
}
|
||||
|
||||
unlockData();
|
||||
|
||||
ModCompleted();
|
||||
bool ret = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Search Interface - For Directory Access */
|
||||
int FileIndexStore::RequestDirDetails(const RsPeerId& uid, const std::string& path, DirDetails& details) const
|
||||
{
|
||||
lockData();
|
||||
|
||||
std::map<RsPeerId, FileIndex *>::const_iterator it = indices.find(uid);
|
||||
bool found = true;
|
||||
|
||||
if (it != indices.end())
|
||||
found = it->second->extractData(path,details) ;
|
||||
|
||||
unlockData();
|
||||
|
||||
return found ;
|
||||
|
||||
#ifdef OLD_STUFF_TO_REMOVE
|
||||
/* lock it up */
|
||||
lockData();
|
||||
|
||||
std::map<RsPeerId, FileIndex *>::const_iterator it;
|
||||
it = indices.find(uid);
|
||||
bool found = true;
|
||||
|
||||
if (it != indices.end())
|
||||
{
|
||||
//DirEntry *fdir = (it->second).lookupDirectory(path);
|
||||
/* translate it
|
||||
*/
|
||||
bool b = FileIndex::extractData((it->second)->root,details) ;
|
||||
|
||||
found = found && b ;
|
||||
}
|
||||
else
|
||||
found = false;
|
||||
|
||||
unlockData();
|
||||
return found;
|
||||
#endif
|
||||
}
|
||||
|
||||
int FileIndexStore::RequestDirDetails(void *ref, DirDetails &details, FileSearchFlags flags) const
|
||||
{
|
||||
/* remove unused parameter warnings */
|
||||
(void) flags;
|
||||
|
||||
#ifdef FIS_DEBUG
|
||||
std::cerr << "FileIndexStore::RequestDirDetails() ref=" << ref << " flags: " << flags << std::endl;
|
||||
#endif
|
||||
|
||||
std::map<RsPeerId, FileIndex *>::const_iterator pit;
|
||||
|
||||
lockData();
|
||||
|
||||
// checked by FileIndex::extractData
|
||||
// if(ref != NULL && !FileIndex::isValid(ref))
|
||||
// {
|
||||
// unlockData() ;
|
||||
// return false ;
|
||||
// }
|
||||
|
||||
/* so cast *ref to a DirEntry */
|
||||
/* root case */
|
||||
|
||||
#ifdef FIS_DEBUG
|
||||
std::cerr << "FileIndexStore::RequestDirDetails() CHKS" << std::endl;
|
||||
for(pit = indices.begin(); pit != indices.end(); ++pit)
|
||||
{
|
||||
(pit->second)->root->checkParentPointers();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ref == NULL)
|
||||
{
|
||||
#ifdef FIS_DEBUG
|
||||
std::cerr << "FileIndexStore::RequestDirDetails() ref=NULL (root)" << std::endl;
|
||||
#endif
|
||||
|
||||
/* get remote root entries */
|
||||
for(pit = indices.begin(); pit != indices.end(); ++pit)
|
||||
{
|
||||
/*
|
||||
*/
|
||||
FileIndex *fileIndex = pit->second;
|
||||
|
||||
DirStub stub;
|
||||
stub.type = DIR_TYPE_PERSON;
|
||||
stub.name = fileIndex->root->name;
|
||||
stub.ref = fileIndex->root;
|
||||
|
||||
details.children.push_back(stub);
|
||||
}
|
||||
details.parent = NULL;
|
||||
details.prow = -1;
|
||||
details.ref = NULL;
|
||||
details.type = DIR_TYPE_ROOT;
|
||||
details.name = "";
|
||||
details.hash.clear() ;
|
||||
details.path = "";
|
||||
details.count = indices.size();
|
||||
details.age = 0;
|
||||
details.flags.clear() ;
|
||||
details.min_age = 0;
|
||||
|
||||
unlockData();
|
||||
return true ;
|
||||
}
|
||||
|
||||
bool b = FileIndex::extractData(ref,details) ;
|
||||
|
||||
unlockData();
|
||||
return b;
|
||||
}
|
||||
uint32_t FileIndexStore::getType(void *ref) const
|
||||
{
|
||||
lockData() ;
|
||||
uint32_t b = FileIndex::getType(ref) ;
|
||||
unlockData();
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
int FileIndexStore::SearchHash(const RsFileHash& hash, std::list<FileDetail> &results) const
|
||||
{
|
||||
lockData();
|
||||
results.clear() ;
|
||||
std::map<RsPeerId, FileIndex *>::const_iterator pit;
|
||||
std::list<FileEntry *>::iterator rit;
|
||||
std::list<FileEntry *> firesults;
|
||||
|
||||
time_t now = time(NULL);
|
||||
|
||||
#ifdef FIS_DEBUG
|
||||
std::cerr << "FileIndexStore::SearchHash()" << std::endl;
|
||||
#endif
|
||||
for(pit = indices.begin(); pit != indices.end(); ++pit)
|
||||
{
|
||||
#ifdef FIS_DEBUG
|
||||
std::cerr << "FileIndexStore::SearchHash() Searching: Peer ";
|
||||
std::cerr << pit->first << std::endl;
|
||||
#endif
|
||||
firesults.clear();
|
||||
|
||||
(pit->second)->searchHash(hash, firesults);
|
||||
/* translate results */
|
||||
for(rit = firesults.begin(); rit != firesults.end(); ++rit)
|
||||
{
|
||||
FileDetail fd;
|
||||
fd.id = pit->first;
|
||||
fd.name = (*rit)->name;
|
||||
fd.hash = (*rit)->hash;
|
||||
fd.path = ""; /* TODO */
|
||||
fd.size = (*rit)->size;
|
||||
fd.age = now - (*rit)->modtime;
|
||||
fd.rank = (*rit)->pop;
|
||||
|
||||
results.push_back(fd);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#ifdef FIS_DEBUG
|
||||
std::cerr << "FileIndexStore::SearchHash() Found " << results.size();
|
||||
std::cerr << " Results from " << indices.size() << " Peers" << std::endl;
|
||||
#endif
|
||||
|
||||
unlockData();
|
||||
return results.size();
|
||||
}
|
||||
|
||||
|
||||
int FileIndexStore::SearchKeywords(std::list<std::string> keywords, std::list<DirDetails> &results,FileSearchFlags flags) const
|
||||
{
|
||||
lockData();
|
||||
std::map<RsPeerId, FileIndex *>::const_iterator pit;
|
||||
std::list<FileEntry *>::iterator rit;
|
||||
std::list<FileEntry *> firesults;
|
||||
|
||||
results.clear() ;
|
||||
|
||||
#ifdef FIS_DEBUG
|
||||
std::cerr << "FileIndexStore::SearchKeywords()" << std::endl;
|
||||
#endif
|
||||
if(flags & RS_FILE_HINTS_REMOTE)
|
||||
for(pit = indices.begin(); pit != indices.end(); ++pit)
|
||||
{
|
||||
firesults.clear();
|
||||
|
||||
(pit->second)->searchTerms(keywords, firesults);
|
||||
/* translate results */
|
||||
for(rit = firesults.begin(); rit != firesults.end(); ++rit)
|
||||
{
|
||||
DirDetails dd;
|
||||
|
||||
if(!FileIndex::extractData(*rit, dd))
|
||||
continue ;
|
||||
|
||||
results.push_back(dd);
|
||||
}
|
||||
}
|
||||
|
||||
if(flags & RS_FILE_HINTS_LOCAL)
|
||||
if (localindex)
|
||||
{
|
||||
firesults.clear();
|
||||
|
||||
localindex->searchTerms(keywords, firesults);
|
||||
/* translate results */
|
||||
for(rit = firesults.begin(); rit != firesults.end(); ++rit)
|
||||
{
|
||||
DirDetails dd;
|
||||
|
||||
if(!FileIndex::extractData(*rit, dd))
|
||||
continue ;
|
||||
|
||||
dd.id.clear() ;
|
||||
results.push_back(dd);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
unlockData();
|
||||
return results.size();
|
||||
}
|
||||
|
||||
|
||||
int FileIndexStore::searchBoolExp(Expression * exp, std::list<DirDetails> &results) const
|
||||
{
|
||||
lockData();
|
||||
std::map<RsPeerId, FileIndex *>::const_iterator pit;
|
||||
std::list<FileEntry *>::iterator rit;
|
||||
std::list<FileEntry *> firesults;
|
||||
|
||||
#ifdef FIS_DEBUG
|
||||
std::cerr << "FileIndexStore::searchBoolExp()" << std::endl;
|
||||
#endif
|
||||
for(pit = indices.begin(); pit != indices.end(); ++pit)
|
||||
{
|
||||
firesults.clear();
|
||||
|
||||
(pit->second)->searchBoolExp(exp, firesults);
|
||||
|
||||
/* translate results */
|
||||
for(rit = firesults.begin(); rit != firesults.end(); ++rit)
|
||||
{
|
||||
DirDetails dd;
|
||||
FileIndex::extractData(*rit, dd);
|
||||
results.push_back(dd);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* finally search local files */
|
||||
if (localindex)
|
||||
{
|
||||
firesults.clear();
|
||||
|
||||
localindex->searchBoolExp(exp, firesults);
|
||||
|
||||
/* translate results */
|
||||
for(rit = firesults.begin(); rit != firesults.end(); ++rit)
|
||||
{
|
||||
DirDetails dd;
|
||||
FileIndex::extractData(*rit, dd);
|
||||
dd.id.clear() ;
|
||||
results.push_back(dd);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
unlockData();
|
||||
return results.size();
|
||||
}
|
||||
|
||||
int FileIndexStore::AboutToModify()
|
||||
{
|
||||
RsServer::notify()->notifyListPreChange(NOTIFY_LIST_DIRLIST_FRIENDS, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int FileIndexStore::ModCompleted()
|
||||
{
|
||||
RsServer::notify()->notifyListChange(NOTIFY_LIST_DIRLIST_FRIENDS, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1,102 +0,0 @@
|
||||
/*
|
||||
* RetroShare FileCache Module: fistore.h
|
||||
*
|
||||
* Copyright 2004-2007 by Robert Fernie.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare@lunamutt.com".
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MRK_FILE_INDEX_STORE_H
|
||||
#define MRK_FILE_INDEX_STORE_H
|
||||
|
||||
|
||||
/**********
|
||||
* Stores the FileCaches of the Peers
|
||||
* must implement 'loadCache' to
|
||||
*
|
||||
* This class is also accessed by the GUI....
|
||||
* and the FileTransfer class.
|
||||
*
|
||||
*/
|
||||
|
||||
class p3PeerMgr ;
|
||||
|
||||
#include "dbase/findex.h"
|
||||
#include "dbase/cachestrapper.h"
|
||||
#include "retroshare/rsiface.h"
|
||||
|
||||
class FileStoreResult
|
||||
{
|
||||
public:
|
||||
std::string id;
|
||||
std::string path;
|
||||
std::string hash;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
class NotifyCallback
|
||||
{
|
||||
public:
|
||||
NotifyCallback() { return; }
|
||||
virtual ~NotifyCallback() { return; }
|
||||
virtual void AboutToModify() { return; }
|
||||
virtual void ModCompleted() { return; }
|
||||
};
|
||||
|
||||
|
||||
class Expression;
|
||||
|
||||
class FileIndexStore: public CacheStore
|
||||
{
|
||||
public:
|
||||
|
||||
FileIndexStore(CacheStrapper *cs, CacheTransfer *cft, p3PeerMgr *pmgr, RsPeerId ownid, std::string cachedir);
|
||||
virtual ~FileIndexStore();
|
||||
|
||||
/* virtual functions overloaded by cache implementor */
|
||||
virtual int loadCache(const RsCacheData &data); /* actual load, once data available */
|
||||
|
||||
/* Search Interface - For FileTransfer Lookup */
|
||||
int SearchHash(const RsFileHash &hash, std::list<FileDetail> &results) const;
|
||||
|
||||
/* Search Interface - For Search Interface */
|
||||
int SearchKeywords(std::list<std::string> terms, std::list<DirDetails> &results,FileSearchFlags flags) const;
|
||||
|
||||
/* Search Interface - for Adv Search Interface */
|
||||
int searchBoolExp(Expression * exp, std::list<DirDetails> &results) const;
|
||||
|
||||
|
||||
/* Search Interface - For Directory Access */
|
||||
int RequestDirDetails(const RsPeerId& uid, const std::string& path, DirDetails &details) const;
|
||||
int RequestDirDetails(void *ref, DirDetails &details, FileSearchFlags flags) const;
|
||||
uint32_t getType(void *ref) const ;
|
||||
|
||||
private:
|
||||
int AboutToModify();
|
||||
int ModCompleted();
|
||||
|
||||
std::map<RsPeerId, FileIndex *> indices;
|
||||
|
||||
RsPeerId localId;
|
||||
FileIndex *localindex;
|
||||
|
||||
p3PeerMgr *mPeerMgr ;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
@ -1,289 +0,0 @@
|
||||
/*
|
||||
* rs-core/src/dbase: rsexpr.cc
|
||||
*
|
||||
* RetroShare C++ Interface.
|
||||
*
|
||||
* Copyright 2007-2008 by Kashif Kaleem.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare@lunamutt.com".
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "dbase/findex.h"
|
||||
#include "retroshare/rsexpr.h"
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
/******************************************************************************************
|
||||
eval functions of relational expressions.
|
||||
|
||||
******************************************************************************************/
|
||||
|
||||
template<>
|
||||
void RelExpression<int>::linearize(LinearizedExpression& e) const
|
||||
{
|
||||
e._ints.push_back(Op) ;
|
||||
e._ints.push_back(LowerValue) ;
|
||||
e._ints.push_back(HigherValue) ;
|
||||
}
|
||||
|
||||
|
||||
bool DateExpression::eval(FileEntry *file)
|
||||
{
|
||||
return evalRel(file->modtime);
|
||||
}
|
||||
|
||||
bool SizeExpressionMB::eval(FileEntry *file)
|
||||
{
|
||||
return evalRel((int)(file->size/(uint64_t)(1024*1024)));
|
||||
}
|
||||
|
||||
bool SizeExpression::eval(FileEntry *file)
|
||||
{
|
||||
return evalRel(file->size);
|
||||
}
|
||||
|
||||
bool PopExpression::eval(FileEntry *file)
|
||||
{
|
||||
return evalRel(file->pop);
|
||||
}
|
||||
|
||||
/******************************************************************************************
|
||||
Code for evaluating string expressions
|
||||
|
||||
******************************************************************************************/
|
||||
|
||||
bool NameExpression::eval(FileEntry *file)
|
||||
{
|
||||
return evalStr(file->name);
|
||||
}
|
||||
|
||||
bool PathExpression::eval(FileEntry *file){
|
||||
std::string path;
|
||||
/*Construct the path of this file*/
|
||||
DirEntry * curr = file->parent;
|
||||
while ( curr != NULL ){
|
||||
path = curr->name+"/"+ path;
|
||||
curr = curr->parent;
|
||||
}
|
||||
return evalStr(path);
|
||||
}
|
||||
|
||||
bool ExtExpression::eval(FileEntry *file){
|
||||
std::string ext;
|
||||
/*Get the part of the string after the last instance of . in the filename */
|
||||
size_t index = file->name.find_last_of('.');
|
||||
if (index != std::string::npos) {
|
||||
ext = file->name.substr(index+1);
|
||||
if (ext != "" ){
|
||||
return evalStr(ext);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HashExpression::eval(FileEntry *file){
|
||||
return evalStr(file->hash.toStdString());
|
||||
}
|
||||
|
||||
/*Check whether two strings are 'equal' to each other*/
|
||||
static bool StrEquals(const std::string & str1, const std::string & str2,
|
||||
bool IgnoreCase ){
|
||||
if ( str1.size() != str2.size() ){
|
||||
return false;
|
||||
} else if (IgnoreCase) {
|
||||
std::equal( str1.begin(), str1.end(),
|
||||
str2.begin(), CompareCharIC() );
|
||||
}
|
||||
return std::equal( str1.begin(), str1.end(),
|
||||
str2.begin());
|
||||
}
|
||||
|
||||
/*Check whether one string contains the other*/
|
||||
static bool StrContains( const std::string & str1, const std::string & str2,
|
||||
bool IgnoreCase){
|
||||
|
||||
std::string::const_iterator iter ;
|
||||
if (IgnoreCase) {
|
||||
iter = std::search( str1.begin(), str1.end(),
|
||||
str2.begin(), str2.end(), CompareCharIC() );
|
||||
} else {
|
||||
iter = std::search( str1.begin(), str1.end(),
|
||||
str2.begin(), str2.end());
|
||||
}
|
||||
|
||||
return ( iter != str1.end() );
|
||||
}
|
||||
|
||||
|
||||
bool StringExpression :: evalStr ( const std::string &str ){
|
||||
std::list<std::string>::iterator iter;
|
||||
switch (Op) {
|
||||
case ContainsAllStrings:
|
||||
for ( iter = terms.begin(); iter != terms.end(); ++iter ) {
|
||||
if ( StrContains (str, *iter, IgnoreCase) == false ){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
case ContainsAnyStrings:
|
||||
for ( iter = terms.begin(); iter != terms.end(); ++iter ) {
|
||||
if ( StrContains (str,*iter, IgnoreCase) == true ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EqualsString:
|
||||
for ( iter = terms.begin(); iter != terms.end(); ++iter ) {
|
||||
if ( StrEquals (str,*iter, IgnoreCase) == true ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* linearization code
|
||||
*************************************************************************/
|
||||
|
||||
void CompoundExpression::linearize(LinearizedExpression& e) const
|
||||
{
|
||||
e._tokens.push_back(LinearizedExpression::EXPR_COMP) ;
|
||||
e._ints.push_back(Op) ;
|
||||
|
||||
Lexp->linearize(e) ;
|
||||
Rexp->linearize(e) ;
|
||||
}
|
||||
|
||||
void StringExpression::linearize(LinearizedExpression& e) const
|
||||
{
|
||||
e._ints.push_back(Op) ;
|
||||
e._ints.push_back(IgnoreCase) ;
|
||||
e._ints.push_back(terms.size()) ;
|
||||
|
||||
for(std::list<std::string>::const_iterator it(terms.begin());it!=terms.end();++it)
|
||||
e._strings.push_back(*it) ;
|
||||
}
|
||||
|
||||
Expression *LinearizedExpression::toExpr(const LinearizedExpression& e)
|
||||
{
|
||||
int i=0,j=0,k=0 ;
|
||||
return toExpr(e,i,j,k) ;
|
||||
}
|
||||
|
||||
void LinearizedExpression::readStringExpr(const LinearizedExpression& e,int& n_ints,int& n_strings,std::list<std::string>& strings,bool& b,StringOperator& op)
|
||||
{
|
||||
op = static_cast<StringOperator>(e._ints[n_ints++]) ;
|
||||
b = e._ints[n_ints++] ;
|
||||
int n = e._ints[n_ints++] ;
|
||||
|
||||
strings.clear() ;
|
||||
for(int i=0;i<n;++i)
|
||||
strings.push_back(e._strings[n_strings++]) ;
|
||||
}
|
||||
|
||||
Expression *LinearizedExpression::toExpr(const LinearizedExpression& e,int& n_tok,int& n_ints,int& n_strings)
|
||||
{
|
||||
LinearizedExpression::token tok = static_cast<LinearizedExpression::token>(e._tokens[n_tok++]) ;
|
||||
|
||||
switch(tok)
|
||||
{
|
||||
case EXPR_DATE: {
|
||||
RelOperator op = static_cast<RelOperator>(e._ints[n_ints++]) ;
|
||||
int lv = e._ints[n_ints++] ;
|
||||
int hv = e._ints[n_ints++] ;
|
||||
|
||||
return new DateExpression(op,lv,hv) ;
|
||||
}
|
||||
|
||||
case EXPR_POP: {
|
||||
RelOperator op = static_cast<RelOperator>(e._ints[n_ints++]) ;
|
||||
int lv = e._ints[n_ints++] ;
|
||||
int hv = e._ints[n_ints++] ;
|
||||
|
||||
return new PopExpression(op,lv,hv) ;
|
||||
}
|
||||
case EXPR_SIZE: {
|
||||
RelOperator op = static_cast<RelOperator>(e._ints[n_ints++]) ;
|
||||
int lv = e._ints[n_ints++] ;
|
||||
int hv = e._ints[n_ints++] ;
|
||||
|
||||
return new SizeExpression(op,lv,hv) ;
|
||||
}
|
||||
case EXPR_HASH: {
|
||||
std::list<std::string> strings ;
|
||||
StringOperator op ;
|
||||
bool b ;
|
||||
|
||||
readStringExpr(e,n_ints,n_strings,strings,b,op) ;
|
||||
return new HashExpression(op,strings) ;
|
||||
}
|
||||
case EXPR_NAME: {
|
||||
std::list<std::string> strings ;
|
||||
StringOperator op ;
|
||||
bool b ;
|
||||
|
||||
readStringExpr(e,n_ints,n_strings,strings,b,op) ;
|
||||
|
||||
return new NameExpression(op,strings,b) ;
|
||||
}
|
||||
case EXPR_PATH: {
|
||||
std::list<std::string> strings ;
|
||||
StringOperator op ;
|
||||
bool b ;
|
||||
|
||||
readStringExpr(e,n_ints,n_strings,strings,b,op) ;
|
||||
|
||||
return new ExtExpression(op,strings,b) ;
|
||||
}
|
||||
case EXPR_EXT: {
|
||||
std::list<std::string> strings ;
|
||||
StringOperator op ;
|
||||
bool b ;
|
||||
|
||||
readStringExpr(e,n_ints,n_strings,strings,b,op) ;
|
||||
|
||||
return new ExtExpression(op,strings,b) ;
|
||||
}
|
||||
case EXPR_COMP: {
|
||||
LogicalOperator op = static_cast<LogicalOperator>(e._ints[n_ints++]) ;
|
||||
|
||||
Expression *e1 = toExpr(e,n_tok,n_ints,n_strings) ;
|
||||
Expression *e2 = toExpr(e,n_tok,n_ints,n_strings) ;
|
||||
|
||||
return new CompoundExpression(op,e1,e2) ;
|
||||
}
|
||||
case EXPR_SIZE_MB: {
|
||||
RelOperator op = static_cast<RelOperator>(e._ints[n_ints++]) ;
|
||||
int lv = e._ints[n_ints++] ;
|
||||
int hv = e._ints[n_ints++] ;
|
||||
|
||||
return new SizeExpressionMB(op,lv,hv) ;
|
||||
}
|
||||
default:
|
||||
std::cerr << "No expression match the current value " << tok << std::endl ;
|
||||
return NULL ;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,9 +40,35 @@ Big picture
|
||||
- the same file should be able to be held by two different directories. Hash search will return a single hit.
|
||||
- the previously existing PersonEntry had no field and was overloading DirEntry, with overwritten file names, hashes etc. Super bad!
|
||||
|
||||
Directory storage file format
|
||||
-----------------------------
|
||||
* should be extensible (xml or binary format? Binary, because it's going to be encrypted anyway)
|
||||
=> works with binary fields
|
||||
=>
|
||||
|
||||
[= version =]
|
||||
[= peer id =]
|
||||
[= num entries =]
|
||||
[= some information =]
|
||||
|
||||
[entry tag] [entry size] [Field ID 01] [field size v 01] [Field data 01] [Field ID 02] [field size v 02] [Field data 02] ...
|
||||
[entry tag] [entry size] [Field ID 01] [field size v 01] [Field data 01] [Field ID 02] [field size v 02] [Field data 02] ...
|
||||
[entry tag] [entry size] [Field ID 01] [field size v 01] [Field data 01] [Field ID 02] [field size v 02] [Field data 02] ...
|
||||
...
|
||||
2 1-5 v 2 1-5 v
|
||||
* entry content
|
||||
Tag | Content | Size
|
||||
----------------+--------------------------------------+------
|
||||
01 | sha1 hash | 20
|
||||
01 | sha1^2 hash | 20
|
||||
02 | file name | < 512
|
||||
03 | file size | 8
|
||||
04 | dir name | < 512
|
||||
05 | last modif time local | 4
|
||||
06 | last modif time including sub-dirs | 4
|
||||
|
||||
Classes
|
||||
-------
|
||||
Rs
|
||||
|
||||
p3ShareManager
|
||||
- tick()
|
||||
@ -75,6 +101,29 @@ Classes
|
||||
- parent groups
|
||||
- group flags
|
||||
|
||||
Best data structure for file index
|
||||
----------------------------------
|
||||
|
||||
| Hash map map list
|
||||
----------------+-----------------+------------+--------------
|
||||
Adding | Constant | log(n) | O(n)
|
||||
Hash search | Constant | log(n) | O(n)
|
||||
Name/exp search | O(n) | O(n) | O(n)
|
||||
Recursive browse| Constant | log(n) | O(n)
|
||||
|
||||
Should we use the same struct for files and directories?
|
||||
|
||||
Sol 1:
|
||||
DirClass + PersonClass + FileEntry class
|
||||
- each has pointers to elements list of the same type
|
||||
- lists are handled for Files (all file entries),
|
||||
|
||||
Directories are represented by the hash of the full path
|
||||
|
||||
Sol 2:
|
||||
Same class for all elements, in a single hash map. Each element is
|
||||
defined by its type (Dir, Person, File) which all have a hash.
|
||||
|
||||
Syncing between peers
|
||||
---------------------
|
||||
|
||||
@ -83,19 +132,84 @@ Generating sync events
|
||||
- for each directory, in breadth first order
|
||||
- if directory has changed, or last update is old
|
||||
=> push a sync request
|
||||
- store the peer's last up time. Compare with peer uptimes recursively.
|
||||
|
||||
* Server side
|
||||
- after a change, broadcast a "directory changed" packet to all connected friends
|
||||
|
||||
* directoy updater
|
||||
- crawl through directories
|
||||
- compare TS of files, missing files, new files
|
||||
- feed a queue of files to hash
|
||||
- directory whatcher gets notified when files are hashed
|
||||
|
||||
- a separate component hashes files (FileHashingProcess)
|
||||
|
||||
DirectoryWatcher (watches a hierarchy) File List (stores a directory hierarchy)
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
+-----------------------+------------------+
|
||||
| |
|
||||
Shared File Service |
|
||||
| |
|
||||
| |
|
||||
+----------- own file list -------+---------- Encrypted/compressed save to disk
|
||||
| | |
|
||||
+----------- friend file lists ---+
|
||||
Roadmap
|
||||
-------
|
||||
|
||||
- complete this file until a proper description of the whole thing is achieved.
|
||||
- create a new directory and implement the .h for the basic functionality
|
||||
- look into existing code in ftServer for the integration, but don't change anything yet
|
||||
- setup class hierarchy
|
||||
- merge hash cache into file lists.
|
||||
[X] complete this file until a proper description of the whole thing is achieved.
|
||||
[X] create a new directory and implement the .h for the basic functionality
|
||||
[ ] look into existing code in ftServer for the integration, but don't change anything yet
|
||||
[X] setup class hierarchy
|
||||
[ ] merge hash cache into file lists.
|
||||
[ ] new format for saving of FileIndex to make it locally encrypted, compact and extensible
|
||||
[ ] create basic directory functionality with own files: re-hash, and store
|
||||
[ ] display own files in GUI, with proper update and working sort
|
||||
|
||||
TODO
|
||||
====
|
||||
|
||||
[ ] directory handler
|
||||
[ ] abstract functions to keep a directory and get updates to it.
|
||||
[ ] hierarchical storage representation.
|
||||
[ ] allow add/delete entries
|
||||
[ ] auto-cleanup
|
||||
|
||||
[ ] directory updater
|
||||
[ ] abstract layer
|
||||
[ ] crawls the directory and ask updates
|
||||
|
||||
[ ] derive local directory updater
|
||||
[ ] crawl local files, and asks updates to storage class
|
||||
[ ] derive remote directory updater
|
||||
[ ] crawl stored files, and request updates to storage class
|
||||
|
||||
[ ] load/save of directory content. Should be extensible
|
||||
[ ] p3FileLists with minimal functonality: no exchange. Only storage of own file lists
|
||||
[ ] service (items) for p3FileLists
|
||||
[ ] connect RemoteDirModel to new system
|
||||
[ ] test GUI functions
|
||||
[ ] test update between peers
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- optionally
|
||||
- change the saving system of FileIndex to make it locally encrypted and compact
|
||||
|
||||
|
1099
libretroshare/src/file_sharing/dir_hierarchy.cc
Normal file
1099
libretroshare/src/file_sharing/dir_hierarchy.cc
Normal file
File diff suppressed because it is too large
Load Diff
183
libretroshare/src/file_sharing/dir_hierarchy.h
Normal file
183
libretroshare/src/file_sharing/dir_hierarchy.h
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* RetroShare C++ Internal directory hierarchy class.
|
||||
*
|
||||
* file_sharing/dir_hierarchy.h
|
||||
*
|
||||
* Copyright 2016 by Mr.Alice
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare.project@gmail.com".
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "directory_storage.h"
|
||||
|
||||
class InternalFileHierarchyStorage
|
||||
{
|
||||
public:
|
||||
class FileStorageNode
|
||||
{
|
||||
public:
|
||||
static const uint32_t TYPE_UNKNOWN = 0x0000 ;
|
||||
static const uint32_t TYPE_FILE = 0x0001 ;
|
||||
static const uint32_t TYPE_DIR = 0x0002 ;
|
||||
|
||||
virtual ~FileStorageNode() {}
|
||||
virtual uint32_t type() const =0;
|
||||
|
||||
DirectoryStorage::EntryIndex parent_index;
|
||||
uint32_t row ;
|
||||
};
|
||||
class FileEntry: public FileStorageNode
|
||||
{
|
||||
public:
|
||||
FileEntry() : file_size(0), file_modtime(0) {}
|
||||
FileEntry(const std::string& name,uint64_t size,time_t modtime) : file_name(name),file_size(size),file_modtime(modtime) {}
|
||||
FileEntry(const std::string& name,uint64_t size,time_t modtime,const RsFileHash& hash) : file_name(name),file_size(size),file_modtime(modtime),file_hash(hash) {}
|
||||
|
||||
virtual uint32_t type() const { return FileStorageNode::TYPE_FILE ; }
|
||||
virtual ~FileEntry() {}
|
||||
|
||||
// local stuff
|
||||
std::string file_name ;
|
||||
uint64_t file_size ;
|
||||
time_t file_modtime;
|
||||
RsFileHash file_hash ;
|
||||
};
|
||||
|
||||
class DirEntry: public FileStorageNode
|
||||
{
|
||||
public:
|
||||
DirEntry(const std::string& name) : dir_name(name), dir_modtime(0),dir_most_recent_time(0),dir_update_time(0) {}
|
||||
virtual ~DirEntry() {}
|
||||
|
||||
virtual uint32_t type() const { return FileStorageNode::TYPE_DIR ; }
|
||||
|
||||
// local stuff
|
||||
std::string dir_name ;
|
||||
std::string dir_parent_path ;
|
||||
RsFileHash dir_hash ;
|
||||
|
||||
std::vector<DirectoryStorage::EntryIndex> subdirs ;
|
||||
std::vector<DirectoryStorage::EntryIndex> subfiles ;
|
||||
|
||||
time_t dir_modtime;
|
||||
time_t dir_most_recent_time; // recursive most recent modification time, including files and subdirs in the entire hierarchy below.
|
||||
time_t dir_update_time; // last time the information was updated for that directory. Includes subdirs indexes and subfile info.
|
||||
};
|
||||
|
||||
// class stuff
|
||||
InternalFileHierarchyStorage() ;
|
||||
|
||||
bool load(const std::string& fname) ;
|
||||
bool save(const std::string& fname) ;
|
||||
|
||||
int parentRow(DirectoryStorage::EntryIndex e);
|
||||
bool isIndexValid(DirectoryStorage::EntryIndex e) const;
|
||||
bool getChildIndex(DirectoryStorage::EntryIndex e,int row,DirectoryStorage::EntryIndex& c) const;
|
||||
bool updateSubDirectoryList(const DirectoryStorage::EntryIndex& indx,const std::map<std::string,time_t>& subdirs);
|
||||
bool removeDirectory(DirectoryStorage::EntryIndex indx) ;
|
||||
bool checkIndex(DirectoryStorage::EntryIndex indx,uint8_t type) const;
|
||||
bool updateSubFilesList(const DirectoryStorage::EntryIndex& indx,const std::map<std::string,DirectoryStorage::FileTS>& subfiles,std::map<std::string,DirectoryStorage::FileTS>& new_files);
|
||||
bool updateHash(const DirectoryStorage::EntryIndex& file_index,const RsFileHash& hash);
|
||||
bool updateFile(const DirectoryStorage::EntryIndex& file_index,const RsFileHash& hash, const std::string& fname,uint64_t size, const time_t modf_time);
|
||||
bool updateDirEntry(const DirectoryStorage::EntryIndex& indx, const std::string& dir_name, time_t most_recent_time, time_t dir_modtime, const std::vector<RsFileHash> &subdirs_hash, const std::vector<FileEntry> &subfiles_array);
|
||||
|
||||
// TS get/set functions. Take one of the class members as argument.
|
||||
|
||||
bool getTS(const DirectoryStorage::EntryIndex& index,time_t& TS,time_t DirEntry::* ) const;
|
||||
bool setTS(const DirectoryStorage::EntryIndex& index,time_t& TS,time_t DirEntry::* ) ;
|
||||
|
||||
// Do a complete recursive sweep over sub-directories and files, and update the lst modf TS. This could be also performed by a cleanup method.
|
||||
|
||||
time_t recursUpdateLastModfTime(const DirectoryStorage::EntryIndex& dir_index);
|
||||
|
||||
// hash stuff
|
||||
|
||||
bool getDirHashFromIndex(const DirectoryStorage::EntryIndex& index,RsFileHash& hash) const ;
|
||||
bool getIndexFromDirHash(const RsFileHash& hash,DirectoryStorage::EntryIndex& index) const ;
|
||||
bool getIndexFromFileHash(const RsFileHash& hash,DirectoryStorage::EntryIndex& index) const ;
|
||||
|
||||
// file/dir access and modification
|
||||
bool findSubDirectory(DirectoryStorage::EntryIndex e,const std::string& s) const ; // returns true when s is the name of a sub-directory in the given entry e
|
||||
|
||||
uint32_t mRoot ;
|
||||
std::vector<FileStorageNode*> mNodes;// uses pointers to keep information about valid/invalid objects.
|
||||
|
||||
void compress() ; // use empty space in the vector, mostly due to deleted entries. This is a complicated operation, mostly due to
|
||||
// all the indirections used. Nodes need to be moved, renamed, etc. The operation discards all file entries that
|
||||
// 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.
|
||||
|
||||
const FileStorageNode *getNode(DirectoryStorage::EntryIndex indx) const;
|
||||
const DirEntry *getDirEntry(DirectoryStorage::EntryIndex indx) const;
|
||||
const FileEntry *getFileEntry(DirectoryStorage::EntryIndex indx) const;
|
||||
uint32_t getType(DirectoryStorage::EntryIndex indx) const;
|
||||
DirectoryStorage::EntryIndex getSubFileIndex(DirectoryStorage::EntryIndex parent_index,uint32_t file_tab_index);
|
||||
DirectoryStorage::EntryIndex getSubDirIndex(DirectoryStorage::EntryIndex parent_index,uint32_t dir_tab_index);
|
||||
|
||||
// search. SearchHash is logarithmic. The other two are linear.
|
||||
|
||||
bool searchHash(const RsFileHash& hash,std::list<DirectoryStorage::EntryIndex>& results);
|
||||
int searchBoolExp(RsRegularExpression::Expression * exp, std::list<DirectoryStorage::EntryIndex> &results) const ;
|
||||
int searchTerms(const std::list<std::string>& terms, std::list<DirectoryStorage::EntryIndex> &results) const ;
|
||||
|
||||
bool check(std::string& error_string) const ;// checks consistency of storage.
|
||||
|
||||
void print() const;
|
||||
|
||||
private:
|
||||
void recursPrint(int depth,DirectoryStorage::EntryIndex node) const;
|
||||
static bool nodeAccessError(const std::string& s);
|
||||
static RsFileHash createDirHash(const std::string& dir_name,const std::string& dir_parent_path) ;
|
||||
|
||||
// Allocates a new entry in mNodes, possible re-using an empty slot and returns its index.
|
||||
|
||||
DirectoryStorage::EntryIndex allocateNewIndex();
|
||||
|
||||
// Removes the given subdirectory from the parent node and all its pendign subdirs. Files are kept, and will go during the cleaning
|
||||
// phase. That allows to keep file information when moving them around.
|
||||
|
||||
bool recursRemoveDirectory(DirectoryStorage::EntryIndex dir);
|
||||
|
||||
// Map of the hash of all files. The file hashes are the sha1sum of the file data.
|
||||
// is used for fast search access for FT.
|
||||
// Note: We should try something faster than std::map. hash_map??
|
||||
// Unlike directories, multiple files may have the same hash. So this cannot be used for anything else than FT.
|
||||
|
||||
std::map<RsFileHash,DirectoryStorage::EntryIndex> mFileHashes ;
|
||||
|
||||
// The directory hashes are the sha1sum of the
|
||||
// full public path to the directory.
|
||||
// The later is used by synchronisation items in order
|
||||
// to avoid sending explicit EntryIndex values.
|
||||
// This is kept separate from mFileHashes because the two are used
|
||||
// in very different ways.
|
||||
//
|
||||
std::map<RsFileHash,DirectoryStorage::EntryIndex> mDirHashes ;
|
||||
};
|
||||
|
13
libretroshare/src/file_sharing/directory_list.h
Normal file
13
libretroshare/src/file_sharing/directory_list.h
Normal file
@ -0,0 +1,13 @@
|
||||
// This class keeps a shared directory. It's quite the equivalent of the old "FileIndex" class
|
||||
// The main difference is that it is
|
||||
// - extensible
|
||||
// - fast to search (at least for hashes). Should provide possibly multiple search handles for
|
||||
// the same file, e.g. if connexion is encrypted.
|
||||
// - abstracts the browsing in a same manner.
|
||||
//
|
||||
class SharedDirectoryList
|
||||
{
|
||||
public:
|
||||
|
||||
DirEntry mRoot ;
|
||||
};
|
806
libretroshare/src/file_sharing/directory_storage.cc
Normal file
806
libretroshare/src/file_sharing/directory_storage.cc
Normal file
@ -0,0 +1,806 @@
|
||||
/*
|
||||
* RetroShare File list storage system.
|
||||
*
|
||||
* file_sharing/directory_storage.cc
|
||||
*
|
||||
* Copyright 2016 Mr.Alice
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare.project@gmail.com".
|
||||
*
|
||||
*/
|
||||
#include <set>
|
||||
#include <time.h>
|
||||
#include "serialiser/rstlvbinary.h"
|
||||
#include "retroshare/rspeers.h"
|
||||
#include "util/rsdir.h"
|
||||
#include "util/rsstring.h"
|
||||
#include "file_sharing_defaults.h"
|
||||
#include "directory_storage.h"
|
||||
#include "dir_hierarchy.h"
|
||||
#include "filelist_io.h"
|
||||
|
||||
//#define DEBUG_REMOTE_DIRECTORY_STORAGE 1
|
||||
|
||||
/******************************************************************************************************************/
|
||||
/* Iterators */
|
||||
/******************************************************************************************************************/
|
||||
|
||||
DirectoryStorage::DirIterator::DirIterator(DirectoryStorage *s,DirectoryStorage::EntryIndex i)
|
||||
{
|
||||
mStorage = s->mFileHierarchy ;
|
||||
mParentIndex = i;
|
||||
mDirTabIndex = 0;
|
||||
}
|
||||
|
||||
DirectoryStorage::FileIterator::FileIterator(DirectoryStorage *s,DirectoryStorage::EntryIndex i)
|
||||
{
|
||||
mStorage = s->mFileHierarchy ;
|
||||
mParentIndex = i;
|
||||
mFileTabIndex = 0;
|
||||
}
|
||||
|
||||
DirectoryStorage::DirIterator& DirectoryStorage::DirIterator::operator++()
|
||||
{
|
||||
++mDirTabIndex ;
|
||||
|
||||
return *this;
|
||||
}
|
||||
DirectoryStorage::FileIterator& DirectoryStorage::FileIterator::operator++()
|
||||
{
|
||||
++mFileTabIndex ;
|
||||
|
||||
return *this;
|
||||
}
|
||||
DirectoryStorage::EntryIndex DirectoryStorage::FileIterator::operator*() const { return mStorage->getSubFileIndex(mParentIndex,mFileTabIndex) ; }
|
||||
DirectoryStorage::EntryIndex DirectoryStorage::DirIterator ::operator*() const { return mStorage->getSubDirIndex(mParentIndex,mDirTabIndex) ; }
|
||||
|
||||
DirectoryStorage::FileIterator::operator bool() const { return **this != DirectoryStorage::NO_INDEX; }
|
||||
DirectoryStorage::DirIterator ::operator bool() const { return **this != DirectoryStorage::NO_INDEX; }
|
||||
|
||||
RsFileHash DirectoryStorage::FileIterator::hash() const { const InternalFileHierarchyStorage::FileEntry *f = mStorage->getFileEntry(**this) ; return f?(f->file_hash):RsFileHash(); }
|
||||
uint64_t DirectoryStorage::FileIterator::size() const { const InternalFileHierarchyStorage::FileEntry *f = mStorage->getFileEntry(**this) ; return f?(f->file_size):0; }
|
||||
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 RsPeerId &pid)
|
||||
: mPeerId(pid), mDirStorageMtx("Directory storage "+pid.toStdString())
|
||||
{
|
||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||
mFileHierarchy = new InternalFileHierarchyStorage();
|
||||
}
|
||||
|
||||
DirectoryStorage::EntryIndex DirectoryStorage::root() const
|
||||
{
|
||||
return EntryIndex(0) ;
|
||||
}
|
||||
int DirectoryStorage::parentRow(EntryIndex e) const
|
||||
{
|
||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||
|
||||
return mFileHierarchy->parentRow(e) ;
|
||||
}
|
||||
bool DirectoryStorage::getChildIndex(EntryIndex e,int row,EntryIndex& c) const
|
||||
{
|
||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||
|
||||
return mFileHierarchy->getChildIndex(e,row,c) ;
|
||||
}
|
||||
|
||||
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::getDirectoryUpdateTime (EntryIndex index,time_t& update_TS) const { RS_STACK_MUTEX(mDirStorageMtx) ; return mFileHierarchy->getTS(index,update_TS,&InternalFileHierarchyStorage::DirEntry::dir_update_time ); }
|
||||
bool DirectoryStorage::getDirectoryRecursModTime(EntryIndex index,time_t& rec_md_TS) const { RS_STACK_MUTEX(mDirStorageMtx) ; return mFileHierarchy->getTS(index,rec_md_TS,&InternalFileHierarchyStorage::DirEntry::dir_most_recent_time); }
|
||||
bool DirectoryStorage::getDirectoryLocalModTime (EntryIndex index,time_t& loc_md_TS) const { RS_STACK_MUTEX(mDirStorageMtx) ; return mFileHierarchy->getTS(index,loc_md_TS,&InternalFileHierarchyStorage::DirEntry::dir_modtime ); }
|
||||
|
||||
bool DirectoryStorage::setDirectoryUpdateTime (EntryIndex index,time_t update_TS) { RS_STACK_MUTEX(mDirStorageMtx) ; return mFileHierarchy->setTS(index,update_TS,&InternalFileHierarchyStorage::DirEntry::dir_update_time ); }
|
||||
bool DirectoryStorage::setDirectoryRecursModTime(EntryIndex index,time_t rec_md_TS) { RS_STACK_MUTEX(mDirStorageMtx) ; return mFileHierarchy->setTS(index,rec_md_TS,&InternalFileHierarchyStorage::DirEntry::dir_most_recent_time); }
|
||||
bool DirectoryStorage::setDirectoryLocalModTime (EntryIndex index,time_t loc_md_TS) { RS_STACK_MUTEX(mDirStorageMtx) ; return mFileHierarchy->setTS(index,loc_md_TS,&InternalFileHierarchyStorage::DirEntry::dir_modtime ); }
|
||||
|
||||
bool DirectoryStorage::updateSubDirectoryList(const EntryIndex& indx,const std::map<std::string,time_t>& subdirs)
|
||||
{
|
||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||
bool res = mFileHierarchy->updateSubDirectoryList(indx,subdirs) ;
|
||||
locked_check() ;
|
||||
return res ;
|
||||
}
|
||||
bool DirectoryStorage::updateSubFilesList(const EntryIndex& indx,const std::map<std::string,FileTS>& subfiles,std::map<std::string,FileTS>& new_files)
|
||||
{
|
||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||
bool res = mFileHierarchy->updateSubFilesList(indx,subfiles,new_files) ;
|
||||
locked_check() ;
|
||||
return res ;
|
||||
}
|
||||
bool DirectoryStorage::removeDirectory(const EntryIndex& indx)
|
||||
{
|
||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||
bool res = mFileHierarchy->removeDirectory(indx);
|
||||
|
||||
locked_check();
|
||||
return res ;
|
||||
}
|
||||
|
||||
void DirectoryStorage::locked_check()
|
||||
{
|
||||
std::string error ;
|
||||
if(!mFileHierarchy->check(error))
|
||||
std::cerr << "Check error: " << error << std::endl;
|
||||
}
|
||||
|
||||
bool DirectoryStorage::updateFile(const EntryIndex& index,const RsFileHash& hash,const std::string& fname, uint64_t size,time_t modf_time)
|
||||
{
|
||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||
return mFileHierarchy->updateFile(index,hash,fname,size,modf_time);
|
||||
}
|
||||
bool DirectoryStorage::updateHash(const EntryIndex& index,const RsFileHash& hash)
|
||||
{
|
||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||
return mFileHierarchy->updateHash(index,hash);
|
||||
}
|
||||
|
||||
int DirectoryStorage::searchHash(const RsFileHash& hash, std::list<EntryIndex> &results) const
|
||||
{
|
||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||
return mFileHierarchy->searchHash(hash,results);
|
||||
}
|
||||
|
||||
void DirectoryStorage::load(const std::string& local_file_name)
|
||||
{
|
||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||
mFileHierarchy->load(local_file_name);
|
||||
}
|
||||
void DirectoryStorage::save(const std::string& local_file_name)
|
||||
{
|
||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||
mFileHierarchy->save(local_file_name);
|
||||
}
|
||||
void DirectoryStorage::print()
|
||||
{
|
||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||
mFileHierarchy->print();
|
||||
}
|
||||
|
||||
int DirectoryStorage::searchTerms(const std::list<std::string>& terms, std::list<EntryIndex> &results) const
|
||||
{
|
||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||
return mFileHierarchy->searchTerms(terms,results);
|
||||
}
|
||||
int DirectoryStorage::searchBoolExp(RsRegularExpression::Expression * exp, std::list<EntryIndex> &results) const
|
||||
{
|
||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||
return mFileHierarchy->searchBoolExp(exp,results);
|
||||
}
|
||||
|
||||
bool DirectoryStorage::extractData(const EntryIndex& indx,DirDetails& d)
|
||||
{
|
||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||
|
||||
d.children.clear() ;
|
||||
time_t now = time(NULL) ;
|
||||
|
||||
uint32_t type = mFileHierarchy->getType(indx) ;
|
||||
|
||||
d.ref = (void*)(intptr_t)indx ;
|
||||
|
||||
if (type == InternalFileHierarchyStorage::FileStorageNode::TYPE_DIR) /* has children --- fill */
|
||||
{
|
||||
const InternalFileHierarchyStorage::DirEntry *dir_entry = mFileHierarchy->getDirEntry(indx) ;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
d.type = DIR_TYPE_DIR;
|
||||
d.hash.clear() ;
|
||||
d.count = dir_entry->subdirs.size() + dir_entry->subfiles.size();
|
||||
d.min_age = now - dir_entry->dir_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 ;
|
||||
|
||||
if(indx == 0)
|
||||
{
|
||||
d.type = DIR_TYPE_PERSON ;
|
||||
d.name = mPeerId.toStdString();
|
||||
}
|
||||
}
|
||||
else if(type == InternalFileHierarchyStorage::FileStorageNode::TYPE_FILE)
|
||||
{
|
||||
const InternalFileHierarchyStorage::FileEntry *file_entry = mFileHierarchy->getFileEntry(indx) ;
|
||||
|
||||
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 = "" ;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
d.flags.clear() ;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DirectoryStorage::getDirHashFromIndex(const EntryIndex& index,RsFileHash& hash) const
|
||||
{
|
||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||
return mFileHierarchy->getDirHashFromIndex(index,hash) ;
|
||||
}
|
||||
bool DirectoryStorage::getIndexFromDirHash(const RsFileHash& hash,EntryIndex& index) const
|
||||
{
|
||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||
return mFileHierarchy->getIndexFromDirHash(hash,index) ;
|
||||
}
|
||||
|
||||
/******************************************************************************************************************/
|
||||
/* Local Directory Storage */
|
||||
/******************************************************************************************************************/
|
||||
|
||||
void LocalDirectoryStorage::setSharedDirectoryList(const std::list<SharedDirInfo>& lst)
|
||||
{
|
||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||
|
||||
// Chose virtual name if not supplied, and remove duplicates.
|
||||
|
||||
std::set<std::string> virtual_names ; // maps virtual to real name
|
||||
std::list<SharedDirInfo> processed_list ;
|
||||
|
||||
for(std::list<SharedDirInfo>::const_iterator it(lst.begin());it!= lst.end();++it)
|
||||
{
|
||||
int i=0;
|
||||
std::string candidate_virtual_name = it->virtualname ;
|
||||
|
||||
if(candidate_virtual_name.empty())
|
||||
candidate_virtual_name = RsDirUtil::getTopDir(it->filename);
|
||||
|
||||
while(virtual_names.find(candidate_virtual_name) != virtual_names.end())
|
||||
rs_sprintf_append(candidate_virtual_name, "-%d", ++i);
|
||||
|
||||
SharedDirInfo d(*it);
|
||||
d.virtualname = candidate_virtual_name ;
|
||||
processed_list.push_back(d) ;
|
||||
|
||||
virtual_names.insert(candidate_virtual_name) ;
|
||||
}
|
||||
|
||||
mLocalDirs.clear();
|
||||
|
||||
for(std::list<SharedDirInfo>::const_iterator it(processed_list.begin());it!=processed_list.end();++it)
|
||||
mLocalDirs[it->filename] = *it;
|
||||
|
||||
mTSChanged = true ;
|
||||
}
|
||||
void LocalDirectoryStorage::getSharedDirectoryList(std::list<SharedDirInfo>& lst)
|
||||
{
|
||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||
|
||||
lst.clear();
|
||||
|
||||
for(std::map<std::string,SharedDirInfo>::iterator it(mLocalDirs.begin());it!=mLocalDirs.end();++it)
|
||||
lst.push_back(it->second) ;
|
||||
}
|
||||
|
||||
static bool sameLists(const std::list<RsNodeGroupId>& l1,const std::list<RsNodeGroupId>& l2)
|
||||
{
|
||||
std::list<RsNodeGroupId>::const_iterator it1(l1.begin()) ;
|
||||
std::list<RsNodeGroupId>::const_iterator it2(l2.begin()) ;
|
||||
|
||||
for(; (it1!=l1.end() && it2!=l2.end());++it1,++it2)
|
||||
if(*it1 != *it2)
|
||||
return false ;
|
||||
|
||||
return it1 == l1.end() && it2 == l2.end() ;
|
||||
}
|
||||
|
||||
void LocalDirectoryStorage::updateShareFlags(const SharedDirInfo& info)
|
||||
{
|
||||
bool changed = false ;
|
||||
|
||||
{
|
||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||
|
||||
std::map<std::string,SharedDirInfo>::iterator it = mLocalDirs.find(info.filename) ;
|
||||
|
||||
if(it == mLocalDirs.end())
|
||||
{
|
||||
std::cerr << "(EE) LocalDirectoryStorage::updateShareFlags: directory \"" << info.filename << "\" not found" << std::endl;
|
||||
return ;
|
||||
}
|
||||
|
||||
// we compare the new info with the old one. If the two group lists have a different order, they will be seen as different. Not a big deal. We just
|
||||
// want to make sure that if they are different, flags get updated.
|
||||
|
||||
if(!sameLists(it->second.parent_groups,info.parent_groups) || it->second.filename != info.filename || it->second.shareflags != info.shareflags || it->second.virtualname != info.virtualname)
|
||||
{
|
||||
it->second = info;
|
||||
|
||||
#ifdef DEBUG_LOCAL_DIRECTORY_STORAGE
|
||||
std::cerr << "Updating dir mod time because flags at level 0 have changed." << std::endl;
|
||||
#endif
|
||||
changed = true ;
|
||||
}
|
||||
}
|
||||
|
||||
if(changed)
|
||||
{
|
||||
setDirectoryLocalModTime(0,time(NULL)) ;
|
||||
mTSChanged = true ;
|
||||
}
|
||||
}
|
||||
|
||||
bool LocalDirectoryStorage::convertSharedFilePath(const std::string& path, std::string& fullpath)
|
||||
{
|
||||
std::string shpath = RsDirUtil::removeRootDir(path);
|
||||
std::string basedir = RsDirUtil::getRootDir(path);
|
||||
std::string realroot ;
|
||||
{
|
||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||
realroot = locked_findRealRootFromVirtualFilename(basedir);
|
||||
}
|
||||
|
||||
if (realroot.empty())
|
||||
return false;
|
||||
|
||||
/* construct full name */
|
||||
fullpath = realroot + "/";
|
||||
fullpath += shpath;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LocalDirectoryStorage::notifyTSChanged()
|
||||
{
|
||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||
mTSChanged = true ;
|
||||
}
|
||||
void LocalDirectoryStorage::updateTimeStamps()
|
||||
{
|
||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||
|
||||
if(mTSChanged)
|
||||
{
|
||||
#ifdef DEBUG_LOCAL_DIRECTORY_STORAGE
|
||||
std::cerr << "Updating recursive TS for local shared dirs..." << std::endl;
|
||||
#endif
|
||||
|
||||
time_t last_modf_time = mFileHierarchy->recursUpdateLastModfTime(EntryIndex(0)) ;
|
||||
mTSChanged = false ;
|
||||
|
||||
#ifdef DEBUG_LOCAL_DIRECTORY_STORAGE
|
||||
std::cerr << "LocalDirectoryStorage: global last modf time is " << last_modf_time << " (which is " << time(NULL) - last_modf_time << " secs ago)" << std::endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
std::string LocalDirectoryStorage::locked_findRealRootFromVirtualFilename(const std::string& virtual_rootdir) const
|
||||
{
|
||||
/**** MUST ALREADY BE LOCKED ****/
|
||||
|
||||
std::map<std::string, SharedDirInfo>::const_iterator cit = mLocalDirs.find(virtual_rootdir) ;
|
||||
|
||||
if (cit == mLocalDirs.end())
|
||||
{
|
||||
std::cerr << "(EE) locked_findRealRootFromVirtualFilename() Invalid RootDir: " << virtual_rootdir << std::endl;
|
||||
return std::string();
|
||||
}
|
||||
return cit->second.filename;
|
||||
}
|
||||
|
||||
bool LocalDirectoryStorage::extractData(const EntryIndex& indx,DirDetails& d)
|
||||
{
|
||||
bool res = DirectoryStorage::extractData(indx,d) ;
|
||||
|
||||
if(!res)
|
||||
return false;
|
||||
|
||||
// here we should update the file sharing flags
|
||||
|
||||
return getFileSharingPermissions(indx,d.flags,d.parent_groups) ;
|
||||
}
|
||||
|
||||
bool LocalDirectoryStorage::getFileInfo(DirectoryStorage::EntryIndex i,FileInfo& info)
|
||||
{
|
||||
DirDetails d;
|
||||
extractData(i,d) ;
|
||||
|
||||
if(d.type != DIR_TYPE_FILE)
|
||||
{
|
||||
std::cerr << "(EE) LocalDirectoryStorage: asked for file info for index " << i << " which is not a file." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
info.storage_permission_flags = d.flags; // Combination of the four RS_DIR_FLAGS_*. Updated when the file is a local stored file.
|
||||
info.parent_groups = d.parent_groups;
|
||||
info.transfer_info_flags = TransferRequestFlags(); // various flags from RS_FILE_HINTS_*
|
||||
info.path = d.path + "/" + d.name;
|
||||
info.fname = d.name;
|
||||
info.hash = d.hash;
|
||||
info.size = d.count;
|
||||
|
||||
// all this stuff below is not useful in this case.
|
||||
|
||||
info.mId = 0; /* (GUI) Model Id -> unique number */
|
||||
info.ext.clear();
|
||||
info.avail = 0; /* how much we have */
|
||||
info.rank = 0;
|
||||
info.age = 0;
|
||||
info.queue_position =0;
|
||||
info.searchId = 0; /* 0 if none */
|
||||
|
||||
/* Transfer Stuff */
|
||||
info.transfered = 0;
|
||||
info.tfRate = 0; /* in kbytes */
|
||||
info.downloadStatus = FT_STATE_COMPLETE ;
|
||||
std::list<TransferInfo> peers;
|
||||
|
||||
info.priority = SPEED_NORMAL;
|
||||
info.lastTS = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LocalDirectoryStorage::getFileSharingPermissions(const EntryIndex& indx,FileStorageFlags& flags,std::list<RsNodeGroupId>& parent_groups)
|
||||
{
|
||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||
return locked_getFileSharingPermissions(indx,flags,parent_groups) ;
|
||||
}
|
||||
|
||||
bool LocalDirectoryStorage::locked_getFileSharingPermissions(const EntryIndex& indx, FileStorageFlags& flags, std::list<RsNodeGroupId> &parent_groups)
|
||||
{
|
||||
flags.clear() ;
|
||||
parent_groups.clear();
|
||||
|
||||
std::string base_dir;
|
||||
|
||||
const InternalFileHierarchyStorage::FileStorageNode *n = mFileHierarchy->getNode(indx) ;
|
||||
|
||||
if(n == NULL)
|
||||
return false ;
|
||||
|
||||
for(DirectoryStorage::EntryIndex i=((n->type()==InternalFileHierarchyStorage::FileStorageNode::TYPE_FILE)?((intptr_t)n->parent_index):indx);;)
|
||||
{
|
||||
const InternalFileHierarchyStorage::DirEntry *e = mFileHierarchy->getDirEntry(i) ;
|
||||
|
||||
if(e == NULL)
|
||||
break ;
|
||||
|
||||
if(e->parent_index == 0)
|
||||
{
|
||||
base_dir = e->dir_name ;
|
||||
break ;
|
||||
}
|
||||
i = e->parent_index ;
|
||||
}
|
||||
|
||||
if(!base_dir.empty())
|
||||
{
|
||||
std::map<std::string,SharedDirInfo>::const_iterator it = mLocalDirs.find(base_dir) ;
|
||||
|
||||
if(it == mLocalDirs.end())
|
||||
{
|
||||
std::cerr << "(EE) very weird bug: base directory \"" << base_dir << "\" not found in shared dir list." << std::endl;
|
||||
return false ;
|
||||
}
|
||||
|
||||
flags = it->second.shareflags;
|
||||
parent_groups = it->second.parent_groups;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string LocalDirectoryStorage::locked_getVirtualDirName(EntryIndex indx) const
|
||||
{
|
||||
if(indx == 0)
|
||||
return std::string() ;
|
||||
|
||||
const InternalFileHierarchyStorage::DirEntry *dir = mFileHierarchy->getDirEntry(indx);
|
||||
|
||||
if(dir->parent_index != 0)
|
||||
return dir->dir_name ;
|
||||
|
||||
std::map<std::string,SharedDirInfo>::const_iterator it = mLocalDirs.find(dir->dir_name) ;
|
||||
|
||||
if(it == mLocalDirs.end())
|
||||
{
|
||||
std::cerr << "(EE) Cannot find real name " << dir->dir_name << " at level 1 among shared dirs. Bug?" << std::endl;
|
||||
return std::string() ;
|
||||
}
|
||||
|
||||
return it->second.virtualname ;
|
||||
}
|
||||
std::string LocalDirectoryStorage::locked_getVirtualPath(EntryIndex indx) const
|
||||
{
|
||||
if(indx == 0)
|
||||
return std::string() ;
|
||||
|
||||
std::string res ;
|
||||
const InternalFileHierarchyStorage::DirEntry *dir = mFileHierarchy->getDirEntry(indx);
|
||||
|
||||
while(dir->parent_index != 0)
|
||||
{
|
||||
dir = mFileHierarchy->getDirEntry(dir->parent_index) ;
|
||||
res += dir->dir_name + "/"+ res ;
|
||||
}
|
||||
|
||||
std::map<std::string,SharedDirInfo>::const_iterator it = mLocalDirs.find(dir->dir_name) ;
|
||||
|
||||
if(it == mLocalDirs.end())
|
||||
{
|
||||
std::cerr << "(EE) Cannot find real name " << dir->dir_name << " at level 1 among shared dirs. Bug?" << std::endl;
|
||||
return std::string() ;
|
||||
}
|
||||
return it->second.virtualname + "/" + res;
|
||||
}
|
||||
|
||||
bool LocalDirectoryStorage::serialiseDirEntry(const EntryIndex& indx,RsTlvBinaryData& bindata,const RsPeerId& client_id)
|
||||
{
|
||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||
|
||||
const InternalFileHierarchyStorage::DirEntry *dir = mFileHierarchy->getDirEntry(indx);
|
||||
|
||||
if(dir == NULL)
|
||||
{
|
||||
std::cerr << "(EE) serialiseDirEntry: ERROR. Cannot find entry " << (void*)(intptr_t)indx << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// compute list of allowed subdirs
|
||||
std::vector<RsFileHash> allowed_subdirs ;
|
||||
FileStorageFlags node_flags ;
|
||||
std::list<RsNodeGroupId> node_groups ;
|
||||
|
||||
// for each subdir, compute the node flags and groups, then ask rsPeers to compute the mask that result from these flags for the particular peer supplied in parameter
|
||||
|
||||
for(uint32_t i=0;i<dir->subdirs.size();++i)
|
||||
if(indx != 0 || (locked_getFileSharingPermissions(dir->subdirs[i],node_flags,node_groups) && (rsPeers->computePeerPermissionFlags(client_id,node_flags,node_groups) & RS_FILE_HINTS_BROWSABLE)))
|
||||
{
|
||||
RsFileHash hash ;
|
||||
if(!mFileHierarchy->getDirHashFromIndex(dir->subdirs[i],hash))
|
||||
{
|
||||
std::cerr << "(EE) Cannot get hash from subdir index " << dir->subdirs[i] << ". Weird bug." << std::endl ;
|
||||
return false;
|
||||
}
|
||||
allowed_subdirs.push_back(hash) ;
|
||||
}
|
||||
|
||||
unsigned char *section_data = NULL;
|
||||
uint32_t section_size = 0;
|
||||
uint32_t section_offset = 0;
|
||||
|
||||
// we need to send:
|
||||
// - the name of the directory, its TS
|
||||
// - the index entry for each subdir (the updte TS are exchanged at a higher level)
|
||||
// - the file info for each subfile
|
||||
//
|
||||
std::string virtual_dir_name = locked_getVirtualDirName(indx) ;
|
||||
|
||||
if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_DIR_NAME ,virtual_dir_name )) return false ;
|
||||
if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_RECURS_MODIF_TS,(uint32_t)dir->dir_most_recent_time)) return false ;
|
||||
if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_MODIF_TS ,(uint32_t)dir->dir_modtime )) return false ;
|
||||
|
||||
// serialise number of subdirs and number of subfiles
|
||||
|
||||
if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,(uint32_t)allowed_subdirs.size() )) return false ;
|
||||
if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,(uint32_t)dir->subfiles.size() )) return false ;
|
||||
|
||||
// serialise subdirs entry indexes
|
||||
|
||||
for(uint32_t i=0;i<allowed_subdirs.size();++i)
|
||||
if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_ENTRY_INDEX ,allowed_subdirs[i] )) return false ;
|
||||
|
||||
// serialise directory subfiles, with info for each of them
|
||||
|
||||
for(uint32_t i=0;i<dir->subfiles.size();++i)
|
||||
{
|
||||
unsigned char *file_section_data = NULL ;
|
||||
uint32_t file_section_offset = 0 ;
|
||||
uint32_t file_section_size = 0;
|
||||
|
||||
const InternalFileHierarchyStorage::FileEntry *file = mFileHierarchy->getFileEntry(dir->subfiles[i]) ;
|
||||
|
||||
if(file == NULL)
|
||||
{
|
||||
std::cerr << "(EE) cannot reach file entry " << dir->subfiles[i] << " to get/send file info." << std::endl;
|
||||
continue ;
|
||||
}
|
||||
|
||||
if(!FileListIO::writeField(file_section_data,file_section_size,file_section_offset,FILE_LIST_IO_TAG_FILE_NAME ,file->file_name )) return false ;
|
||||
if(!FileListIO::writeField(file_section_data,file_section_size,file_section_offset,FILE_LIST_IO_TAG_FILE_SIZE ,file->file_size )) return false ;
|
||||
if(!FileListIO::writeField(file_section_data,file_section_size,file_section_offset,FILE_LIST_IO_TAG_FILE_SHA1_HASH,file->file_hash )) return false ;
|
||||
if(!FileListIO::writeField(file_section_data,file_section_size,file_section_offset,FILE_LIST_IO_TAG_MODIF_TS ,(uint32_t)file->file_modtime)) return false ;
|
||||
|
||||
// now write the whole string into a single section in the file
|
||||
|
||||
if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_REMOTE_FILE_ENTRY,file_section_data,file_section_offset)) return false ;
|
||||
|
||||
free(file_section_data) ;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOCAL_DIRECTORY_STORAGE
|
||||
std::cerr << "Serialised dir entry to send for entry index " << (void*)(intptr_t)indx << ". Data size is " << section_size << " bytes" << std::endl;
|
||||
#endif
|
||||
|
||||
bindata.bin_data = section_data ;
|
||||
bindata.bin_len = section_offset ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
/******************************************************************************************************************/
|
||||
/* Remote Directory Storage */
|
||||
/******************************************************************************************************************/
|
||||
|
||||
RemoteDirectoryStorage::RemoteDirectoryStorage(const RsPeerId& pid,const std::string& fname)
|
||||
: DirectoryStorage(pid),mLastSavedTime(0),mChanged(false),mFileName(fname)
|
||||
{
|
||||
load(fname) ;
|
||||
|
||||
std::cerr << "Loaded remote directory for peer " << pid << std::endl;
|
||||
#ifdef DEBUG_REMOTE_DIRECTORY_STORAGE
|
||||
mFileHierarchy->print();
|
||||
#endif
|
||||
}
|
||||
|
||||
void RemoteDirectoryStorage::checkSave()
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
|
||||
if(mChanged && mLastSavedTime + MIN_INTERVAL_BETWEEN_REMOTE_DIRECTORY_SAVE < now)
|
||||
{
|
||||
save(mFileName);
|
||||
mLastSavedTime = now ;
|
||||
}
|
||||
}
|
||||
|
||||
bool RemoteDirectoryStorage::deserialiseUpdateDirEntry(const EntryIndex& indx,const RsTlvBinaryData& bindata)
|
||||
{
|
||||
const unsigned char *section_data = (unsigned char*)bindata.bin_data ;
|
||||
uint32_t section_size = bindata.bin_len ;
|
||||
uint32_t section_offset=0 ;
|
||||
|
||||
#ifdef DEBUG_REMOTE_DIRECTORY_STORAGE
|
||||
std::cerr << "RemoteDirectoryStorage::deserialiseDirEntry(): deserialising directory content for friend " << peerId() << ", and directory " << indx << std::endl;
|
||||
#endif
|
||||
|
||||
std::string dir_name ;
|
||||
uint32_t most_recent_time ,dir_modtime ;
|
||||
|
||||
if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_DIR_NAME ,dir_name )) return false ;
|
||||
if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_RECURS_MODIF_TS,most_recent_time)) return false ;
|
||||
if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_MODIF_TS ,dir_modtime )) return false ;
|
||||
|
||||
std::cerr << " dir name : \"" << dir_name << "\"" << std::endl;
|
||||
std::cerr << " most recent time : " << most_recent_time << std::endl;
|
||||
std::cerr << " modification time : " << dir_modtime << std::endl;
|
||||
|
||||
// serialise number of subdirs and number of subfiles
|
||||
|
||||
uint32_t n_subdirs,n_subfiles ;
|
||||
|
||||
if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,n_subdirs )) return false ;
|
||||
if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,n_subfiles )) return false ;
|
||||
|
||||
std::cerr << " number of subdirs : " << n_subdirs << std::endl;
|
||||
std::cerr << " number of files : " << n_subfiles << std::endl;
|
||||
|
||||
// serialise subdirs entry indexes
|
||||
|
||||
std::vector<RsFileHash> subdirs_hashes ;
|
||||
RsFileHash subdir_hash ;
|
||||
|
||||
for(uint32_t i=0;i<n_subdirs;++i)
|
||||
{
|
||||
if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_ENTRY_INDEX ,subdir_hash)) return false ;
|
||||
|
||||
subdirs_hashes.push_back(subdir_hash) ;
|
||||
}
|
||||
|
||||
// deserialise directory subfiles, with info for each of them
|
||||
|
||||
std::vector<InternalFileHierarchyStorage::FileEntry> subfiles_array ;
|
||||
|
||||
for(uint32_t i=0;i<n_subfiles;++i)
|
||||
{
|
||||
// Read the full data section for the file
|
||||
|
||||
unsigned char *file_section_data = NULL ;
|
||||
uint32_t file_section_size = 0;
|
||||
|
||||
if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_REMOTE_FILE_ENTRY,file_section_data,file_section_size)) return false ;
|
||||
|
||||
uint32_t file_section_offset = 0 ;
|
||||
|
||||
InternalFileHierarchyStorage::FileEntry f;
|
||||
uint32_t modtime =0;
|
||||
|
||||
if(!FileListIO::readField(file_section_data,file_section_size,file_section_offset,FILE_LIST_IO_TAG_FILE_NAME ,f.file_name )) return false ;
|
||||
if(!FileListIO::readField(file_section_data,file_section_size,file_section_offset,FILE_LIST_IO_TAG_FILE_SIZE ,f.file_size )) return false ;
|
||||
if(!FileListIO::readField(file_section_data,file_section_size,file_section_offset,FILE_LIST_IO_TAG_FILE_SHA1_HASH,f.file_hash )) return false ;
|
||||
if(!FileListIO::readField(file_section_data,file_section_size,file_section_offset,FILE_LIST_IO_TAG_MODIF_TS ,modtime )) return false ;
|
||||
|
||||
f.file_modtime = modtime ;
|
||||
|
||||
free(file_section_data) ;
|
||||
|
||||
subfiles_array.push_back(f) ;
|
||||
}
|
||||
|
||||
RS_STACK_MUTEX(mDirStorageMtx) ;
|
||||
|
||||
std::cerr << " updating dir entry..." << std::endl;
|
||||
|
||||
// First create the entries for each subdir and each subfile, if needed.
|
||||
if(!mFileHierarchy->updateDirEntry(indx,dir_name,most_recent_time,dir_modtime,subdirs_hashes,subfiles_array))
|
||||
{
|
||||
std::cerr << "(EE) Cannot update dir entry with index " << indx << ": entry does not exist." << std::endl;
|
||||
return false ;
|
||||
}
|
||||
|
||||
mChanged = true ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
285
libretroshare/src/file_sharing/directory_storage.h
Normal file
285
libretroshare/src/file_sharing/directory_storage.h
Normal file
@ -0,0 +1,285 @@
|
||||
/*
|
||||
* RetroShare C++ Directory Storage system.
|
||||
*
|
||||
* file_sharing/directory_storage.h
|
||||
*
|
||||
* Copyright 2016 by Mr.Alice
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare.project@gmail.com".
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <list>
|
||||
|
||||
#include "retroshare/rsids.h"
|
||||
#include "retroshare/rsfiles.h"
|
||||
|
||||
#define NOT_IMPLEMENTED() { std::cerr << __PRETTY_FUNCTION__ << ": not yet implemented." << std::endl; }
|
||||
|
||||
class RsTlvBinaryData ;
|
||||
class InternalFileHierarchyStorage ;
|
||||
class RsTlvBinaryData ;
|
||||
|
||||
class DirectoryStorage
|
||||
{
|
||||
public:
|
||||
DirectoryStorage(const RsPeerId& pid) ;
|
||||
virtual ~DirectoryStorage() {}
|
||||
|
||||
typedef uint32_t EntryIndex ;
|
||||
static const EntryIndex NO_INDEX = 0xffffffff;
|
||||
|
||||
void save() const ;
|
||||
|
||||
// These functions are to be used by file transfer and file search.
|
||||
|
||||
virtual int searchTerms(const std::list<std::string>& terms, std::list<EntryIndex> &results) const ;
|
||||
virtual int searchBoolExp(RsRegularExpression::Expression * exp, std::list<EntryIndex> &results) const ;
|
||||
virtual int searchHash(const RsFileHash& hash, std::list<EntryIndex> &results) const ;
|
||||
|
||||
// gets/sets the various time stamps:
|
||||
//
|
||||
bool getDirectoryRecursModTime(EntryIndex index,time_t& recurs_max_modf_TS) const ; // last modification time, computed recursively over all subfiles and directories
|
||||
bool getDirectoryLocalModTime (EntryIndex index,time_t& motime_TS) const ; // last modification time for that index only
|
||||
bool getDirectoryUpdateTime (EntryIndex index,time_t& update_TS) const ; // last time the entry was updated. This is only used on the RemoteDirectoryStorage side.
|
||||
|
||||
bool setDirectoryRecursModTime(EntryIndex index,time_t recurs_max_modf_TS) ;
|
||||
bool setDirectoryLocalModTime (EntryIndex index,time_t modtime_TS) ;
|
||||
bool setDirectoryUpdateTime (EntryIndex index,time_t update_TS) ;
|
||||
|
||||
uint32_t getEntryType(const EntryIndex& indx) ; // WARNING: returns DIR_TYPE_*, not the internal directory storage stuff.
|
||||
virtual bool extractData(const EntryIndex& indx,DirDetails& d);
|
||||
|
||||
// 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. When using it, the client should make sure
|
||||
// that the DirectoryStorage is properly locked, since the iterator cannot lock it.
|
||||
//
|
||||
class DirIterator
|
||||
{
|
||||
public:
|
||||
DirIterator(const DirIterator& d) ;
|
||||
DirIterator(DirectoryStorage *d,EntryIndex i) ;
|
||||
|
||||
DirIterator& operator++() ;
|
||||
EntryIndex operator*() const ;
|
||||
|
||||
operator bool() const ; // used in for loops. Returns true when the iterator is valid.
|
||||
|
||||
// info about the directory that is pointed by the iterator
|
||||
|
||||
std::string name() const ;
|
||||
time_t last_modif_time() const ; // last time a file in this directory or in the directories below has been modified.
|
||||
time_t last_update_time() const ; // last time this directory was updated
|
||||
private:
|
||||
EntryIndex mParentIndex ; // index of the parent dir.
|
||||
uint32_t mDirTabIndex ; // index in the vector of subdirs.
|
||||
InternalFileHierarchyStorage *mStorage ;
|
||||
|
||||
friend class DirectoryStorage ;
|
||||
};
|
||||
class FileIterator
|
||||
{
|
||||
public:
|
||||
FileIterator(DirIterator& d); // crawls all files in specified directory
|
||||
FileIterator(DirectoryStorage *d,EntryIndex e); // crawls all files in specified directory
|
||||
|
||||
FileIterator& operator++() ;
|
||||
EntryIndex operator*() const ; // current file entry
|
||||
|
||||
operator bool() const ; // used in for loops. Returns true when the iterator is valid.
|
||||
|
||||
// info about the file that is pointed by the iterator
|
||||
|
||||
std::string name() const ;
|
||||
uint64_t size() const ;
|
||||
RsFileHash hash() const ;
|
||||
time_t modtime() const ;
|
||||
|
||||
private:
|
||||
EntryIndex mParentIndex ; // index of the parent dir.
|
||||
uint32_t mFileTabIndex ; // index in the vector of subdirs.
|
||||
InternalFileHierarchyStorage *mStorage ;
|
||||
};
|
||||
|
||||
struct FileTS
|
||||
{
|
||||
uint64_t size ;
|
||||
time_t modtime;
|
||||
};
|
||||
|
||||
EntryIndex root() const ; // returns the index of the root directory entry. This is generally 0.
|
||||
const RsPeerId& peerId() const { return mPeerId ; } // peer ID of who owns that file list.
|
||||
int parentRow(EntryIndex e) const ; // position of the current node, in the array of children at its parent node. Used by GUI for display.
|
||||
bool getChildIndex(EntryIndex e,int row,EntryIndex& c) const; // returns the index of the children node at position "row" in the children nodes. Used by GUI for display.
|
||||
|
||||
// Sets the subdirectory/subfiles list of entry indx the supplied one, possible adding and removing directories (resp.files). New directories are set empty with
|
||||
// just a name and need to be updated later on. New files are returned in a list so that they can be sent to hash cache.
|
||||
//
|
||||
bool updateSubDirectoryList(const EntryIndex& indx, const std::map<std::string, time_t> &subdirs) ;
|
||||
bool updateSubFilesList(const EntryIndex& indx, const std::map<std::string, FileTS> &subfiles, std::map<std::string, FileTS> &new_files) ;
|
||||
bool removeDirectory(const EntryIndex& indx) ;
|
||||
|
||||
// Updates relevant information for the file at the given index.
|
||||
|
||||
bool updateFile(const EntryIndex& index,const RsFileHash& hash, const std::string& fname, uint64_t size, time_t modf_time) ;
|
||||
bool updateHash(const EntryIndex& index,const RsFileHash& hash);
|
||||
|
||||
// Returns the hash of the directory at the given index and reverse. This hash is set as random the first time it is used (when updating directories). It will be
|
||||
// used by the sync system to designate the directory without referring to index (index could be used to figure out the existance of hidden directories)
|
||||
|
||||
bool getDirHashFromIndex(const EntryIndex& index,RsFileHash& hash) const ; // constant cost
|
||||
bool getIndexFromDirHash(const RsFileHash& hash,EntryIndex& index) const ; // log cost.
|
||||
|
||||
void print();
|
||||
void cleanup();
|
||||
|
||||
protected:
|
||||
void load(const std::string& local_file_name) ;
|
||||
void save(const std::string& local_file_name) ;
|
||||
|
||||
private:
|
||||
|
||||
// debug
|
||||
void locked_check();
|
||||
|
||||
// storage of internal structure. Totally hidden from the outside. EntryIndex is simply the index of the entry in the vector.
|
||||
|
||||
RsPeerId mPeerId;
|
||||
|
||||
protected:
|
||||
mutable RsMutex mDirStorageMtx ;
|
||||
|
||||
InternalFileHierarchyStorage *mFileHierarchy ;
|
||||
};
|
||||
|
||||
class RemoteDirectoryStorage: public DirectoryStorage
|
||||
{
|
||||
public:
|
||||
RemoteDirectoryStorage(const RsPeerId& pid,const std::string& fname) ;
|
||||
virtual ~RemoteDirectoryStorage() {}
|
||||
|
||||
/*!
|
||||
* \brief deserialiseDirEntry
|
||||
* Loads a serialised directory content coming from a friend. The directory entry needs to exist already,
|
||||
* as it is created when updating the parent.
|
||||
*
|
||||
* \param indx index of the directory to update
|
||||
* \param bindata binary data to deserialise from
|
||||
* \return false when the directory cannot be found.
|
||||
*/
|
||||
bool deserialiseUpdateDirEntry(const EntryIndex& indx,const RsTlvBinaryData& data) ;
|
||||
|
||||
/*!
|
||||
* \brief checkSave
|
||||
* Checks the time of last saving, last modification time, and saves if needed.
|
||||
*/
|
||||
void checkSave() ;
|
||||
|
||||
private:
|
||||
time_t mLastSavedTime ;
|
||||
bool mChanged ;
|
||||
std::string mFileName;
|
||||
};
|
||||
|
||||
class LocalDirectoryStorage: public DirectoryStorage
|
||||
{
|
||||
public:
|
||||
LocalDirectoryStorage(const std::string& fname,const RsPeerId& own_id) : DirectoryStorage(own_id),mFileName(fname) {}
|
||||
virtual ~LocalDirectoryStorage() {}
|
||||
|
||||
/*!
|
||||
* \brief [gs]etSharedDirectoryList
|
||||
* Gets/sets the list of shared directories. Each directory is supplied with a virtual name (the name the friends will see), and sharing flags/groups.
|
||||
* \param lst
|
||||
*/
|
||||
void setSharedDirectoryList(const std::list<SharedDirInfo>& lst) ;
|
||||
void getSharedDirectoryList(std::list<SharedDirInfo>& lst) ;
|
||||
|
||||
void updateShareFlags(const SharedDirInfo& info) ;
|
||||
bool convertSharedFilePath(const std::string& path_with_virtual_name,std::string& fullpath) ;
|
||||
|
||||
/*!
|
||||
* \brief updateTimeStamps
|
||||
* Checks recursive TS and update the if needed.
|
||||
*/
|
||||
void updateTimeStamps();
|
||||
|
||||
/*!
|
||||
* \brief notifyTSChanged
|
||||
* Use this to force an update of the recursive TS, when calling updateTimeStamps();
|
||||
*/
|
||||
void notifyTSChanged();
|
||||
/*!
|
||||
* \brief getFileInfo Converts an index info a full file info structure.
|
||||
* \param i index in the directory structure
|
||||
* \param info structure to be filled in
|
||||
* \return false if the file does not exist, or is a directory,...
|
||||
*/
|
||||
bool getFileInfo(DirectoryStorage::EntryIndex i,FileInfo& info) ;
|
||||
|
||||
/*!
|
||||
* \brief getFileSharingPermissions
|
||||
* Computes the flags and parent groups for any index.
|
||||
* \param indx index of the entry to compute the flags for
|
||||
* \param flags computed flags
|
||||
* \param parent_groups computed parent groups
|
||||
* \return
|
||||
* false if the index is not valid
|
||||
* false otherwise
|
||||
*/
|
||||
bool getFileSharingPermissions(const EntryIndex& indx, FileStorageFlags &flags, std::list<RsNodeGroupId> &parent_groups);
|
||||
|
||||
virtual bool extractData(const EntryIndex& indx,DirDetails& d) ;
|
||||
|
||||
/*!
|
||||
* \brief serialiseDirEntry
|
||||
* Produced a serialised directory content listing suitable for export to friends.
|
||||
*
|
||||
* \param indx index of the directory to serialise
|
||||
* \param bindata binary data created by serialisation
|
||||
* \param client_id Peer id to be serialised to. Depending on permissions, some subdirs can be removed.
|
||||
* \return false when the directory cannot be found.
|
||||
*/
|
||||
bool serialiseDirEntry(const EntryIndex& indx, RsTlvBinaryData& bindata, const RsPeerId &client_id) ;
|
||||
|
||||
private:
|
||||
std::string locked_getVirtualPath(EntryIndex indx) const ;
|
||||
std::string locked_getVirtualDirName(EntryIndex indx) const ;
|
||||
|
||||
bool locked_getFileSharingPermissions(const EntryIndex& indx, FileStorageFlags &flags, std::list<RsNodeGroupId>& parent_groups);
|
||||
std::string locked_findRealRootFromVirtualFilename(const std::string& virtual_rootdir) const;
|
||||
|
||||
std::map<std::string,SharedDirInfo> mLocalDirs ; // map is better for search. it->first=it->second.filename
|
||||
std::string mFileName;
|
||||
|
||||
bool mTSChanged ;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
230
libretroshare/src/file_sharing/directory_updater.cc
Normal file
230
libretroshare/src/file_sharing/directory_updater.cc
Normal file
@ -0,0 +1,230 @@
|
||||
/*
|
||||
* RetroShare Directory watching system.
|
||||
*
|
||||
* file_sharing/directory_updater.cc
|
||||
*
|
||||
* Copyright 2016 Mr.Alice
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare.project@gmail.com".
|
||||
*
|
||||
*/
|
||||
#include "util/folderiterator.h"
|
||||
#include "rsserver/p3face.h"
|
||||
|
||||
#include "directory_storage.h"
|
||||
#include "directory_updater.h"
|
||||
#include "file_sharing_defaults.h"
|
||||
|
||||
//#define DEBUG_LOCAL_DIR_UPDATER 1
|
||||
|
||||
//=============================================================================================================//
|
||||
// Local Directory Updater //
|
||||
//=============================================================================================================//
|
||||
|
||||
LocalDirectoryUpdater::LocalDirectoryUpdater(HashStorage *hc,LocalDirectoryStorage *lds)
|
||||
: mHashCache(hc),mSharedDirectories(lds)
|
||||
{
|
||||
mLastSweepTime = 0;
|
||||
mLastTSUpdateTime = 0;
|
||||
|
||||
mDelayBetweenDirectoryUpdates = DELAY_BETWEEN_DIRECTORY_UPDATES;
|
||||
mIsEnabled = false ;
|
||||
}
|
||||
|
||||
bool LocalDirectoryUpdater::isEnabled() const
|
||||
{
|
||||
return mIsEnabled ;
|
||||
}
|
||||
void LocalDirectoryUpdater::setEnabled(bool b)
|
||||
{
|
||||
if(mIsEnabled == b)
|
||||
return ;
|
||||
|
||||
if(b)
|
||||
start() ;
|
||||
else
|
||||
shutdown();
|
||||
|
||||
mIsEnabled = b ;
|
||||
}
|
||||
|
||||
void LocalDirectoryUpdater::data_tick()
|
||||
{
|
||||
time_t now = time(NULL) ;
|
||||
|
||||
if(now > mDelayBetweenDirectoryUpdates + mLastSweepTime)
|
||||
{
|
||||
sweepSharedDirectories() ;
|
||||
mLastSweepTime = now;
|
||||
mSharedDirectories->notifyTSChanged() ;
|
||||
}
|
||||
|
||||
if(now > DELAY_BETWEEN_LOCAL_DIRECTORIES_TS_UPDATE + mLastTSUpdateTime)
|
||||
{
|
||||
mSharedDirectories->updateTimeStamps() ;
|
||||
mLastTSUpdateTime = now ;
|
||||
}
|
||||
usleep(10*1000*1000);
|
||||
}
|
||||
|
||||
void LocalDirectoryUpdater::forceUpdate()
|
||||
{
|
||||
mLastSweepTime = 0;
|
||||
}
|
||||
|
||||
void LocalDirectoryUpdater::sweepSharedDirectories()
|
||||
{
|
||||
RsServer::notify()->notifyListPreChange(NOTIFY_LIST_DIRLIST_LOCAL, 0);
|
||||
#ifdef DEBUG_LOCAL_DIR_UPDATER
|
||||
std::cerr << "[directory storage] LocalDirectoryUpdater::sweep()" << std::endl;
|
||||
#endif
|
||||
|
||||
// recursive update algorithm works that way:
|
||||
// - the external loop starts on the shared directory list and goes through sub-directories
|
||||
// - at the same time, it updates the local list of shared directories. A single sweep is performed over the whole directory structure.
|
||||
// - the information that is costly to compute (the hash) is store externally into a separate structure.
|
||||
// - doing so, changing directory names or moving files between directories does not cause a re-hash of the content.
|
||||
//
|
||||
std::list<SharedDirInfo> shared_directory_list ;
|
||||
mSharedDirectories->getSharedDirectoryList(shared_directory_list);
|
||||
|
||||
std::map<std::string,time_t> sub_dir_list ;
|
||||
|
||||
for(std::list<SharedDirInfo>::const_iterator real_dir_it(shared_directory_list.begin());real_dir_it!=shared_directory_list.end();++real_dir_it)
|
||||
sub_dir_list[(*real_dir_it).filename] = 0 ;
|
||||
|
||||
// make sure that entries in stored_dir_it are the same than paths in real_dir_it, and in the same order.
|
||||
|
||||
mSharedDirectories->updateSubDirectoryList(mSharedDirectories->root(),sub_dir_list) ;
|
||||
|
||||
// now for each of them, go recursively and match both files and dirs
|
||||
|
||||
for(DirectoryStorage::DirIterator stored_dir_it(mSharedDirectories,mSharedDirectories->root()) ; stored_dir_it;++stored_dir_it)
|
||||
{
|
||||
#ifdef DEBUG_LOCAL_DIR_UPDATER
|
||||
std::cerr << "[directory storage] recursing into " << stored_dir_it.name() << std::endl;
|
||||
#endif
|
||||
|
||||
recursUpdateSharedDir(stored_dir_it.name(), *stored_dir_it) ; // here we need to use the list that was stored, instead of the shared dir list, because the two
|
||||
// are not necessarily in the same order.
|
||||
}
|
||||
RsServer::notify()->notifyListChange(NOTIFY_LIST_DIRLIST_LOCAL, 0);
|
||||
}
|
||||
|
||||
void LocalDirectoryUpdater::recursUpdateSharedDir(const std::string& cumulated_path, DirectoryStorage::EntryIndex indx)
|
||||
{
|
||||
#ifdef DEBUG_LOCAL_DIR_UPDATER
|
||||
std::cerr << "[directory storage] parsing directory " << cumulated_path << ", index=" << indx << std::endl;
|
||||
#endif
|
||||
|
||||
// make sure list of subdirs is the same
|
||||
// make sure list of subfiles is the same
|
||||
// request all hashes to the hashcache
|
||||
|
||||
librs::util::FolderIterator dirIt(cumulated_path);
|
||||
|
||||
// collect subdirs and subfiles
|
||||
|
||||
std::map<std::string,DirectoryStorage::FileTS> subfiles ;
|
||||
std::map<std::string,time_t> subdirs ;
|
||||
|
||||
for(;dirIt.isValid();dirIt.next())
|
||||
{
|
||||
switch(dirIt.file_type())
|
||||
{
|
||||
case librs::util::FolderIterator::TYPE_FILE: subfiles[dirIt.file_name()].modtime = dirIt.file_modtime() ;
|
||||
subfiles[dirIt.file_name()].size = dirIt.file_size();
|
||||
#ifdef DEBUG_LOCAL_DIR_UPDATER
|
||||
std::cerr << " adding sub-file \"" << dirIt.file_name() << "\"" << std::endl;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case librs::util::FolderIterator::TYPE_DIR: subdirs[dirIt.file_name()] = dirIt.file_modtime();
|
||||
#ifdef DEBUG_LOCAL_DIR_UPDATER
|
||||
std::cerr << " adding sub-dir \"" << dirIt.file_name() << "\"" << std::endl;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
std::cerr << "(EE) Dir entry of unknown type with path \"" << cumulated_path << "/" << dirIt.file_name() << "\"" << std::endl;
|
||||
}
|
||||
}
|
||||
// update folder modificatoin time, which is the only way to detect e.g. removed or renamed files.
|
||||
|
||||
mSharedDirectories->setDirectoryLocalModTime(indx,dirIt.dir_modtime()) ;
|
||||
|
||||
// update file and dir lists for current directory.
|
||||
|
||||
mSharedDirectories->updateSubDirectoryList(indx,subdirs) ;
|
||||
|
||||
std::map<std::string,DirectoryStorage::FileTS> new_files ;
|
||||
mSharedDirectories->updateSubFilesList(indx,subfiles,new_files) ;
|
||||
|
||||
// now go through list of subfiles and request the hash to hashcache
|
||||
|
||||
for(DirectoryStorage::FileIterator dit(mSharedDirectories,indx);dit;++dit)
|
||||
{
|
||||
// ask about the hash. If not present, ask HashCache. If not present, or different, the callback will update it.
|
||||
|
||||
RsFileHash hash ;
|
||||
|
||||
if(mHashCache->requestHash(cumulated_path + "/" + dit.name(),dit.size(),dit.modtime(),hash,this,*dit) && dit.hash() != hash)
|
||||
mSharedDirectories->updateHash(*dit,hash);
|
||||
}
|
||||
|
||||
// go through the list of sub-dirs and recursively update
|
||||
|
||||
DirectoryStorage::DirIterator stored_dir_it(mSharedDirectories,indx) ;
|
||||
|
||||
for(std::map<std::string,time_t>::const_iterator real_dir_it(subdirs.begin());real_dir_it!=subdirs.end();++real_dir_it, ++stored_dir_it)
|
||||
{
|
||||
#ifdef DEBUG_LOCAL_DIR_UPDATER
|
||||
std::cerr << " recursing into " << stored_dir_it.name() << std::endl;
|
||||
#endif
|
||||
recursUpdateSharedDir(cumulated_path + "/" + stored_dir_it.name(), *stored_dir_it) ;
|
||||
}
|
||||
}
|
||||
|
||||
bool LocalDirectoryUpdater::inDirectoryCheck() const
|
||||
{
|
||||
return mHashCache->isRunning();
|
||||
}
|
||||
|
||||
void LocalDirectoryUpdater::hash_callback(uint32_t client_param, const std::string& name, const RsFileHash& hash, uint64_t size)
|
||||
{
|
||||
if(!mSharedDirectories->updateHash(DirectoryStorage::EntryIndex(client_param),hash))
|
||||
std::cerr << "(EE) Cannot update file. Something's wrong." << std::endl;
|
||||
|
||||
mSharedDirectories->notifyTSChanged() ;
|
||||
}
|
||||
|
||||
bool LocalDirectoryUpdater::hash_confirm(uint32_t client_param)
|
||||
{
|
||||
return mSharedDirectories->getEntryType(DirectoryStorage::EntryIndex(client_param)) == DIR_TYPE_FILE ;
|
||||
}
|
||||
|
||||
void LocalDirectoryUpdater::setFileWatchPeriod(int seconds)
|
||||
{
|
||||
mDelayBetweenDirectoryUpdates = seconds ;
|
||||
}
|
||||
uint32_t LocalDirectoryUpdater::fileWatchPeriod() const
|
||||
{
|
||||
return mDelayBetweenDirectoryUpdates ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
69
libretroshare/src/file_sharing/directory_updater.h
Normal file
69
libretroshare/src/file_sharing/directory_updater.h
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* RetroShare C++ Directory parsing code.
|
||||
*
|
||||
* file_sharing/directory_updater.h
|
||||
*
|
||||
* Copyright 2016 by Mr.Alice
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare.project@gmail.com".
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// This class crawls the given directry hierarchy and updates it. It does so by calling the
|
||||
// shared file list source. This source may be of two types:
|
||||
// - local: directories are crawled n disk and files are hashed / requested from a cache
|
||||
// - remote: directories are requested remotely to a providing client
|
||||
//
|
||||
#include "file_sharing/hash_cache.h"
|
||||
#include "file_sharing/directory_storage.h"
|
||||
|
||||
class LocalDirectoryUpdater: public HashStorageClient, public RsTickingThread
|
||||
{
|
||||
public:
|
||||
LocalDirectoryUpdater(HashStorage *hash_cache,LocalDirectoryStorage *lds) ;
|
||||
virtual ~LocalDirectoryUpdater() {}
|
||||
|
||||
void forceUpdate();
|
||||
bool inDirectoryCheck() const ;
|
||||
|
||||
void setFileWatchPeriod(int seconds) ;
|
||||
uint32_t fileWatchPeriod() const ;
|
||||
|
||||
void setEnabled(bool b) ;
|
||||
bool isEnabled() const ;
|
||||
|
||||
protected:
|
||||
virtual void data_tick() ;
|
||||
|
||||
virtual void hash_callback(uint32_t client_param, const std::string& name, const RsFileHash& hash, uint64_t size);
|
||||
virtual bool hash_confirm(uint32_t client_param) ;
|
||||
|
||||
void recursUpdateSharedDir(const std::string& cumulated_path,DirectoryStorage::EntryIndex indx);
|
||||
void sweepSharedDirectories();
|
||||
|
||||
private:
|
||||
HashStorage *mHashCache ;
|
||||
LocalDirectoryStorage *mSharedDirectories ;
|
||||
|
||||
time_t mLastSweepTime;
|
||||
time_t mLastTSUpdateTime;
|
||||
|
||||
uint32_t mDelayBetweenDirectoryUpdates;
|
||||
bool mIsEnabled ;
|
||||
};
|
||||
|
44
libretroshare/src/file_sharing/file_sharing_defaults.h
Normal file
44
libretroshare/src/file_sharing/file_sharing_defaults.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* RetroShare C++ File sharing default variables
|
||||
*
|
||||
* file_sharing/file_sharing_defaults.h
|
||||
*
|
||||
* Copyright 2016 by Mr.Alice
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare.project@gmail.com".
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
static const uint32_t DELAY_BETWEEN_DIRECTORY_UPDATES = 600 ; // 10 minutes
|
||||
static const uint32_t DELAY_BETWEEN_REMOTE_DIRECTORY_SYNC_REQ = 120 ; // 2 minutes
|
||||
static const uint32_t DELAY_BETWEEN_LOCAL_DIRECTORIES_TS_UPDATE = 20 ; // 20 sec. Buy we only update for real if something has changed.
|
||||
|
||||
static const std::string HASH_CACHE_DURATION_SS = "HASH_CACHE_DURATION" ; // key string to store hash remembering time
|
||||
static const std::string WATCH_FILE_DURATION_SS = "WATCH_FILES_DELAY" ; // key to store delay before re-checking for new files
|
||||
static const std::string WATCH_FILE_ENABLED_SS = "WATCH_FILES_ENABLED"; // key to store ON/OFF flags for file whatch
|
||||
|
||||
static const std::string FILE_SHARING_DIR_NAME = "file_sharing" ; // hard-coded directory name to store friend file lists, hash cache, etc.
|
||||
static const std::string HASH_CACHE_FILE_NAME = "hash_cache.bin" ; // hard-coded directory name to store encrypted hash cache.
|
||||
|
||||
static const uint32_t MIN_INTERVAL_BETWEEN_HASH_CACHE_SAVE = 20 ; // never save hash cache more often than every 20 secs.
|
||||
static const uint32_t MIN_INTERVAL_BETWEEN_REMOTE_DIRECTORY_SAVE = 23 ; // never save remote directories more often than this
|
||||
|
||||
static const uint32_t MAX_DIR_SYNC_RESPONSE_DATA_SIZE = 20000 ; // Maximum RsItem data size in bytes for serialised directory transmission
|
||||
static const uint32_t DEFAULT_HASH_STORAGE_DURATION_DAYS = 30 ; // remember deleted/inaccessible files for 30 days
|
232
libretroshare/src/file_sharing/filelist_io.cc
Normal file
232
libretroshare/src/file_sharing/filelist_io.cc
Normal file
@ -0,0 +1,232 @@
|
||||
/*
|
||||
* RetroShare File lists IO methods.
|
||||
*
|
||||
* file_sharing/filelist_io.h
|
||||
*
|
||||
* Copyright 2016 Mr.Alice
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare.project@gmail.com".
|
||||
*
|
||||
*/
|
||||
#include "retroshare/rsids.h"
|
||||
#include "pqi/authssl.h"
|
||||
#include "util/rsdir.h"
|
||||
#include "serialiser/rsbaseserial.h"
|
||||
#include "filelist_io.h"
|
||||
|
||||
template<> bool FileListIO::serialise(unsigned char *buff,uint32_t size,uint32_t& offset,const uint32_t & val) { return setRawUInt32(buff,size,&offset,val) ; }
|
||||
template<> bool FileListIO::serialise(unsigned char *buff,uint32_t size,uint32_t& offset,const uint64_t & val) { return setRawUInt64(buff,size,&offset,val) ; }
|
||||
template<> bool FileListIO::serialise(unsigned char *buff,uint32_t size,uint32_t& offset,const std::string & val) { return setRawString(buff,size,&offset,val) ; }
|
||||
template<> bool FileListIO::serialise(unsigned char *buff,uint32_t size,uint32_t& offset,const Sha1CheckSum & val) { return val.serialise(buff,size,offset) ; }
|
||||
|
||||
template<> bool FileListIO::deserialise(const unsigned char *buff,uint32_t size,uint32_t& offset,uint32_t & val) { return getRawUInt32(const_cast<uint8_t*>(buff),size,&offset,&val) ; }
|
||||
template<> bool FileListIO::deserialise(const unsigned char *buff,uint32_t size,uint32_t& offset,uint64_t & val) { return getRawUInt64(const_cast<uint8_t*>(buff),size,&offset,&val) ; }
|
||||
template<> bool FileListIO::deserialise(const unsigned char *buff,uint32_t size,uint32_t& offset,std::string & val) { return getRawString(const_cast<uint8_t*>(buff),size,&offset,val) ; }
|
||||
template<> bool FileListIO::deserialise(const unsigned char *buff,uint32_t size,uint32_t& offset,Sha1CheckSum & val) { return val.deserialise(const_cast<uint8_t*>(buff),size,offset) ; }
|
||||
|
||||
template<> uint32_t FileListIO::serial_size(const uint32_t & ) { return 4 ; }
|
||||
template<> uint32_t FileListIO::serial_size(const uint64_t & ) { return 8 ; }
|
||||
template<> uint32_t FileListIO::serial_size(const std::string & val) { return getRawStringSize(val) ; }
|
||||
template<> uint32_t FileListIO::serial_size(const Sha1CheckSum & ) { return Sha1CheckSum::serial_size(); }
|
||||
|
||||
bool FileListIO::writeField( unsigned char*&buff,uint32_t& buff_size,uint32_t& offset,uint8_t section_tag,const unsigned char * val,uint32_t size)
|
||||
{
|
||||
if(!checkSectionSize(buff,buff_size,offset,size))
|
||||
return false;
|
||||
|
||||
if(!writeSectionHeader(buff,buff_size,offset,section_tag,size))
|
||||
return false;
|
||||
|
||||
memcpy(&buff[offset],val,size) ;
|
||||
offset += size ;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileListIO::readField (const unsigned char *buff,uint32_t buff_size,uint32_t& offset,uint8_t check_section_tag, unsigned char *& val,uint32_t& size)
|
||||
{
|
||||
if(!readSectionHeader(buff,buff_size,offset,check_section_tag,size))
|
||||
return false;
|
||||
|
||||
val = (unsigned char *)rs_malloc(size) ;
|
||||
|
||||
if(!val)
|
||||
return false;
|
||||
|
||||
memcpy(val,&buff[offset],size);
|
||||
offset += size ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
bool FileListIO::write125Size(unsigned char *data,uint32_t data_size,uint32_t& offset,uint32_t S)
|
||||
{
|
||||
if(S < 192)
|
||||
{
|
||||
if(offset+1 > data_size)
|
||||
return false;
|
||||
|
||||
data[offset++] = (uint8_t)S ;
|
||||
return true;
|
||||
}
|
||||
else if(S < 8384)
|
||||
{
|
||||
if(offset+2 > data_size)
|
||||
return false;
|
||||
|
||||
data[offset+1] = (S - 192) & 0xff ;
|
||||
data[offset ] = ((S - 192 - data[offset+1]) >> 8) + 192;
|
||||
|
||||
offset += 2 ;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(offset+5 > data_size)
|
||||
return false;
|
||||
|
||||
data[offset++] = 0xff ;
|
||||
data[offset++] = (uint8_t)((S >> 24) & 255) ;
|
||||
data[offset++] = (uint8_t)((S >> 16) & 255) ;
|
||||
data[offset++] = (uint8_t)((S >> 8) & 255) ;
|
||||
data[offset++] = (uint8_t)((S ) & 255) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
|
||||
bool FileListIO::read125Size(const unsigned char *data,uint32_t data_size,uint32_t& offset,uint32_t& S)
|
||||
{
|
||||
if(offset + 1 >= data_size) return false;
|
||||
|
||||
uint8_t b1 = data[offset++] ;
|
||||
|
||||
if(b1 < 192)
|
||||
{
|
||||
S = b1;
|
||||
return true ;
|
||||
}
|
||||
if(offset + 1 >= data_size) return false;
|
||||
|
||||
uint8_t b2 = data[offset++] ;
|
||||
|
||||
if(b1 < 224)
|
||||
{
|
||||
S = ((b1-192) << 8) + b2 + 192 ;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(b1 != 0xff)
|
||||
return false;
|
||||
|
||||
if(offset + 3 >= data_size) return false;
|
||||
|
||||
uint8_t b3 = data[offset++];
|
||||
uint8_t b4 = data[offset++];
|
||||
uint8_t b5 = data[offset++];
|
||||
|
||||
S = (b2 << 24) | (b3 << 16) | (b4 << 8) | b5 ;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileListIO::saveEncryptedDataToFile(const std::string& fname,const unsigned char *data,uint32_t total_size)
|
||||
{
|
||||
void *encryptedData = NULL ;
|
||||
int encDataLen = 0 ;
|
||||
|
||||
if(!AuthSSL::getAuthSSL()->encrypt( encryptedData, encDataLen, data,total_size, AuthSSL::getAuthSSL()->OwnId()))
|
||||
{
|
||||
std::cerr << "Cannot encrypt hash cache. Something's wrong." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
FILE *F = fopen( (fname+".tmp").c_str(),"wb" ) ;
|
||||
|
||||
if(!F)
|
||||
{
|
||||
std::cerr << "Cannot open encrypted file cache for writing: " << fname+".tmp" << std::endl;
|
||||
|
||||
free(encryptedData);
|
||||
return false;
|
||||
}
|
||||
if(fwrite(encryptedData,1,encDataLen,F) != (uint32_t)encDataLen)
|
||||
{
|
||||
std::cerr << "Could not write entire encrypted hash cache file. Out of disc space??" << std::endl;
|
||||
fclose(F) ;
|
||||
|
||||
free(encryptedData);
|
||||
return false;
|
||||
}
|
||||
|
||||
fclose(F) ;
|
||||
|
||||
RsDirUtil::renameFile(fname+".tmp",fname) ;
|
||||
#ifdef FIM_DEBUG
|
||||
std::cerr << "done." << std::endl ;
|
||||
#endif
|
||||
|
||||
free(encryptedData);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileListIO::loadEncryptedDataFromFile(const std::string& fname,unsigned char *& data,uint32_t& total_size)
|
||||
{
|
||||
uint64_t file_size ;
|
||||
|
||||
if(!RsDirUtil::checkFile( fname,file_size,false ) )
|
||||
{
|
||||
std::cerr << "Encrypted hash cache file not present." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// read the binary stream into memory.
|
||||
//
|
||||
RsTemporaryMemory buffer(file_size) ;
|
||||
|
||||
if(buffer == NULL)
|
||||
return false;
|
||||
|
||||
FILE *F = fopen( fname.c_str(),"rb") ;
|
||||
if (!F)
|
||||
{
|
||||
std::cerr << "Cannot open file for reading encrypted file cache, filename " << fname << std::endl;
|
||||
return false;
|
||||
}
|
||||
if(fread(buffer,1,file_size,F) != file_size)
|
||||
{
|
||||
std::cerr << "Cannot read from file " + fname << ": something's wrong." << std::endl;
|
||||
fclose(F) ;
|
||||
return false;
|
||||
}
|
||||
fclose(F) ;
|
||||
|
||||
// now decrypt
|
||||
void *decrypted_data =NULL;
|
||||
int decrypted_data_size =0;
|
||||
|
||||
if(!AuthSSL::getAuthSSL()->decrypt(decrypted_data, decrypted_data_size, buffer, file_size))
|
||||
{
|
||||
std::cerr << "Cannot decrypt encrypted file cache. Something's wrong." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
data = (unsigned char*)decrypted_data ;
|
||||
total_size = decrypted_data_size ;
|
||||
|
||||
return true;
|
||||
}
|
145
libretroshare/src/file_sharing/filelist_io.h
Normal file
145
libretroshare/src/file_sharing/filelist_io.h
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* RetroShare C++ File lists IO methods.
|
||||
*
|
||||
* file_sharing/filelist_io.h
|
||||
*
|
||||
* Copyright 2016 by Mr.Alice
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare.project@gmail.com".
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "util/rsmemory.h"
|
||||
|
||||
// This file implements load/save of various fields used for file lists and directory content.
|
||||
// WARNING: the encoding is system-dependent, so this should *not* be used to exchange data between computers.
|
||||
|
||||
static const uint32_t FILE_LIST_IO_LOCAL_DIRECTORY_STORAGE_VERSION_0001 = 0x00000001 ;
|
||||
|
||||
static const uint8_t FILE_LIST_IO_TAG_UNKNOWN = 0x00 ;
|
||||
static const uint8_t FILE_LIST_IO_TAG_LOCAL_DIRECTORY_VERSION = 0x01 ;
|
||||
|
||||
static const uint8_t FILE_LIST_IO_TAG_HASH_STORAGE_ENTRY = 0x10 ;
|
||||
static const uint8_t FILE_LIST_IO_TAG_LOCAL_FILE_ENTRY = 0x11 ;
|
||||
static const uint8_t FILE_LIST_IO_TAG_LOCAL_DIR_ENTRY = 0x12 ;
|
||||
static const uint8_t FILE_LIST_IO_TAG_REMOTE_FILE_ENTRY = 0x13 ;
|
||||
|
||||
static const uint8_t FILE_LIST_IO_TAG_FILE_SHA1_HASH = 0x20 ;
|
||||
static const uint8_t FILE_LIST_IO_TAG_FILE_NAME = 0x21 ;
|
||||
static const uint8_t FILE_LIST_IO_TAG_FILE_SIZE = 0x22 ;
|
||||
|
||||
static const uint8_t FILE_LIST_IO_TAG_MODIF_TS = 0x30 ;
|
||||
static const uint8_t FILE_LIST_IO_TAG_RECURS_MODIF_TS = 0x31 ;
|
||||
static const uint8_t FILE_LIST_IO_TAG_UPDATE_TS = 0x32 ;
|
||||
|
||||
static const uint8_t FILE_LIST_IO_TAG_ENTRY_INDEX = 0x40 ;
|
||||
static const uint8_t FILE_LIST_IO_TAG_PARENT_INDEX = 0x41 ;
|
||||
|
||||
static const uint8_t FILE_LIST_IO_TAG_DIR_HASH = 0x50 ;
|
||||
static const uint8_t FILE_LIST_IO_TAG_DIR_NAME = 0x51 ;
|
||||
|
||||
static const uint8_t FILE_LIST_IO_TAG_ROW = 0x60 ;
|
||||
static const uint8_t FILE_LIST_IO_TAG_BINARY_DATA = 0x61 ;
|
||||
static const uint8_t FILE_LIST_IO_TAG_RAW_NUMBER = 0x62 ;
|
||||
|
||||
static const uint32_t SECTION_HEADER_MAX_SIZE = 6 ; // section tag (1 byte) + size (max = 5 bytes)
|
||||
|
||||
class FileListIO
|
||||
{
|
||||
public:
|
||||
template<typename T>
|
||||
static bool writeField(unsigned char *& buff,uint32_t& buff_size,uint32_t& offset,uint8_t section_tag,const T& val)
|
||||
{
|
||||
uint32_t s = serial_size(val) ;
|
||||
|
||||
if(!checkSectionSize(buff,buff_size,offset,s))
|
||||
return false;
|
||||
|
||||
if(!writeSectionHeader(buff,buff_size,offset,section_tag,s))
|
||||
return false;
|
||||
|
||||
return serialise(buff,buff_size,offset,val) ;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static bool readField(const unsigned char *buff,uint32_t buff_size,uint32_t& offset,uint8_t check_section_tag,T& val)
|
||||
{
|
||||
uint32_t section_size ;
|
||||
|
||||
if(!readSectionHeader(buff,buff_size,offset,check_section_tag,section_size))
|
||||
return false;
|
||||
|
||||
return deserialise(buff,buff_size,offset,val);
|
||||
}
|
||||
|
||||
static bool writeField( unsigned char*&buff,uint32_t& buff_size,uint32_t& offset,uint8_t section_tag,const unsigned char * val,uint32_t size) ;
|
||||
static bool readField (const unsigned char *buff,uint32_t buff_size,uint32_t& offset,uint8_t check_section_tag, unsigned char *& val,uint32_t& size) ;
|
||||
|
||||
template<class T> static bool serialise(unsigned char *buff,uint32_t size,uint32_t& offset,const T& val) ;
|
||||
template<class T> static bool deserialise(const unsigned char *buff,uint32_t size,uint32_t& offset,T& val) ;
|
||||
template<class T> static uint32_t serial_size(const T& val) ;
|
||||
|
||||
static bool saveEncryptedDataToFile(const std::string& fname,const unsigned char *data,uint32_t total_size);
|
||||
static bool loadEncryptedDataFromFile(const std::string& fname,unsigned char *& data,uint32_t& total_size);
|
||||
|
||||
private:
|
||||
static bool write125Size(unsigned char *data,uint32_t total_size,uint32_t& offset,uint32_t size) ;
|
||||
static bool read125Size (const unsigned char *data,uint32_t total_size,uint32_t& offset,uint32_t& size) ;
|
||||
|
||||
static bool checkSectionSize(unsigned char *& buff,uint32_t& buff_size,uint32_t offset,uint32_t S)
|
||||
{
|
||||
if(offset + S + SECTION_HEADER_MAX_SIZE > buff_size)
|
||||
{
|
||||
buff = (unsigned char *)realloc(buff,offset + S + SECTION_HEADER_MAX_SIZE) ;
|
||||
buff_size = offset + S + SECTION_HEADER_MAX_SIZE;
|
||||
|
||||
if(!buff)
|
||||
return false ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
static bool writeSectionHeader(unsigned char *& buff,uint32_t& buff_size,uint32_t& offset,uint8_t section_tag,uint32_t S)
|
||||
{
|
||||
buff[offset++] = section_tag ;
|
||||
if(!write125Size(buff,buff_size,offset,S)) return false ;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool readSectionHeader(const unsigned char *& buff,uint32_t buff_size,uint32_t& offset,uint8_t check_section_tag,uint32_t& S)
|
||||
{
|
||||
if(offset + 1 > buff_size)
|
||||
return false ;
|
||||
|
||||
uint8_t section_tag = buff[offset] ; // we do the offset++ after, only if the header can be read. Doing so, we can make multiple read attempts.
|
||||
|
||||
if(section_tag != check_section_tag)
|
||||
return false;
|
||||
|
||||
offset++ ;
|
||||
|
||||
return read125Size(buff,buff_size,offset,S) ;
|
||||
}
|
||||
};
|
393
libretroshare/src/file_sharing/hash_cache.cc
Normal file
393
libretroshare/src/file_sharing/hash_cache.cc
Normal file
@ -0,0 +1,393 @@
|
||||
/*
|
||||
* RetroShare Hash cache
|
||||
*
|
||||
* file_sharing/hash_cache.cc
|
||||
*
|
||||
* Copyright 2016 Mr.Alice
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare.project@gmail.com".
|
||||
*
|
||||
*/
|
||||
#include "util/rsdir.h"
|
||||
#include "util/rsprint.h"
|
||||
#include "rsserver/p3face.h"
|
||||
#include "pqi/authssl.h"
|
||||
#include "hash_cache.h"
|
||||
#include "filelist_io.h"
|
||||
#include "file_sharing_defaults.h"
|
||||
|
||||
//#define HASHSTORAGE_DEBUG 1
|
||||
|
||||
static const uint32_t DEFAULT_INACTIVITY_SLEEP_TIME = 50*1000;
|
||||
static const uint32_t MAX_INACTIVITY_SLEEP_TIME = 2*1000*1000;
|
||||
|
||||
HashStorage::HashStorage(const std::string& save_file_name)
|
||||
: mFilePath(save_file_name), mHashMtx("Hash Storage mutex")
|
||||
{
|
||||
mInactivitySleepTime = DEFAULT_INACTIVITY_SLEEP_TIME;
|
||||
mRunning = false ;
|
||||
mLastSaveTime = 0 ;
|
||||
mTotalSizeToHash = 0;
|
||||
mTotalFilesToHash = 0;
|
||||
mMaxStorageDurationDays = DEFAULT_HASH_STORAGE_DURATION_DAYS ;
|
||||
|
||||
{
|
||||
RS_STACK_MUTEX(mHashMtx) ;
|
||||
locked_load() ;
|
||||
}
|
||||
}
|
||||
static std::string friendlyUnit(uint64_t val)
|
||||
{
|
||||
const std::string units[5] = {"B","KB","MB","GB","TB"};
|
||||
char buf[50] ;
|
||||
|
||||
double fact = 1.0 ;
|
||||
|
||||
for(unsigned int i=0; i<5; ++i)
|
||||
if(double(val)/fact < 1024.0)
|
||||
{
|
||||
sprintf(buf,"%2.2f",double(val)/fact) ;
|
||||
return std::string(buf) + " " + units[i];
|
||||
}
|
||||
else
|
||||
fact *= 1024.0f ;
|
||||
|
||||
sprintf(buf,"%2.2f",double(val)/fact*1024.0f) ;
|
||||
return std::string(buf) + " TB";
|
||||
}
|
||||
|
||||
void HashStorage::data_tick()
|
||||
{
|
||||
FileHashJob job;
|
||||
RsFileHash hash;
|
||||
uint64_t size ;
|
||||
|
||||
{
|
||||
bool empty ;
|
||||
uint32_t st ;
|
||||
|
||||
{
|
||||
RS_STACK_MUTEX(mHashMtx) ;
|
||||
if(mChanged && mLastSaveTime + MIN_INTERVAL_BETWEEN_HASH_CACHE_SAVE < time(NULL))
|
||||
{
|
||||
locked_save();
|
||||
mLastSaveTime = time(NULL) ;
|
||||
mChanged = false ;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
RS_STACK_MUTEX(mHashMtx) ;
|
||||
|
||||
empty = mFilesToHash.empty();
|
||||
st = mInactivitySleepTime ;
|
||||
}
|
||||
|
||||
// sleep off mutex!
|
||||
if(empty)
|
||||
{
|
||||
#ifdef HASHSTORAGE_DEBUG
|
||||
std::cerr << "nothing to hash. Sleeping for " << st << " us" << std::endl;
|
||||
#endif
|
||||
|
||||
usleep(st); // when no files to hash, just wait for 2 secs. This avoids a dramatic loop.
|
||||
|
||||
if(st > MAX_INACTIVITY_SLEEP_TIME)
|
||||
{
|
||||
RS_STACK_MUTEX(mHashMtx) ;
|
||||
|
||||
mInactivitySleepTime = MAX_INACTIVITY_SLEEP_TIME;
|
||||
|
||||
if(!mChanged) // otherwise it might prevent from saving the hash cache
|
||||
{
|
||||
std::cerr << "Stopping hashing thread." << std::endl;
|
||||
shutdown();
|
||||
mRunning = false ;
|
||||
mTotalSizeToHash = 0;
|
||||
mTotalFilesToHash = 0;
|
||||
std::cerr << "done." << std::endl;
|
||||
}
|
||||
|
||||
RsServer::notify()->notifyHashingInfo(NOTIFY_HASHTYPE_FINISH, "") ;
|
||||
}
|
||||
else
|
||||
{
|
||||
RS_STACK_MUTEX(mHashMtx) ;
|
||||
mInactivitySleepTime = 2*st ;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
mInactivitySleepTime = DEFAULT_INACTIVITY_SLEEP_TIME;
|
||||
|
||||
{
|
||||
RS_STACK_MUTEX(mHashMtx) ;
|
||||
|
||||
job = mFilesToHash.begin()->second ;
|
||||
mFilesToHash.erase(mFilesToHash.begin()) ;
|
||||
}
|
||||
|
||||
if(job.client->hash_confirm(job.client_param))
|
||||
{
|
||||
std::cerr << "Hashing file " << job.full_path << "..." ; std::cerr.flush();
|
||||
|
||||
std::string tmpout;
|
||||
rs_sprintf(tmpout, "%lu/%lu (%s - %d%%) : %s", (unsigned long int)mHashCounter+1, (unsigned long int)mTotalFilesToHash, friendlyUnit(mTotalHashedSize).c_str(), int(mTotalHashedSize/double(mTotalSizeToHash)*100.0), job.full_path.c_str()) ;
|
||||
|
||||
RsServer::notify()->notifyHashingInfo(NOTIFY_HASHTYPE_HASH_FILE, tmpout) ;
|
||||
|
||||
if(!RsDirUtil::getFileHash(job.full_path, hash,size, this))
|
||||
std::cerr << "ERROR: cannot hash file " << job.full_path << std::endl;
|
||||
else
|
||||
std::cerr << "done."<< std::endl;
|
||||
|
||||
// store the result
|
||||
|
||||
{
|
||||
RS_STACK_MUTEX(mHashMtx) ;
|
||||
HashStorageInfo& info(mFiles[job.full_path]);
|
||||
|
||||
info.filename = job.full_path ;
|
||||
info.size = size ;
|
||||
info.modf_stamp = job.ts ;
|
||||
info.time_stamp = time(NULL);
|
||||
info.hash = hash;
|
||||
|
||||
mChanged = true ;
|
||||
++mHashCounter ;
|
||||
mTotalHashedSize += size ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// call the client
|
||||
|
||||
if(!hash.isNull())
|
||||
job.client->hash_callback(job.client_param, job.full_path, hash, size);
|
||||
}
|
||||
|
||||
bool HashStorage::requestHash(const std::string& full_path,uint64_t size,time_t mod_time,RsFileHash& known_hash,HashStorageClient *c,uint32_t client_param)
|
||||
{
|
||||
// check if the hash is up to date w.r.t. cache.
|
||||
|
||||
#ifdef HASHSTORAGE_DEBUG
|
||||
std::cerr << "HASH Requested for file " << full_path << ": ";
|
||||
#endif
|
||||
RS_STACK_MUTEX(mHashMtx) ;
|
||||
|
||||
time_t now = time(NULL) ;
|
||||
std::map<std::string,HashStorageInfo>::iterator it = mFiles.find(full_path) ;
|
||||
|
||||
// On windows we compare the time up to +/- 3600 seconds. This avoids re-hashing files in case of daylight saving change.
|
||||
//
|
||||
// See:
|
||||
// https://support.microsoft.com/en-us/kb/190315
|
||||
//
|
||||
if(it != mFiles.end()
|
||||
#ifdef WINDOWS_SYS
|
||||
&& ( (uint64_t)mod_time == it->second.modf_stamp || (uint64_t)mod_time+3600 == it->second.modf_stamp ||(uint64_t)mod_time == it->second.modf_stamp+3600)
|
||||
#else
|
||||
&& (uint64_t)mod_time == it->second.modf_stamp
|
||||
#endif
|
||||
&& size == it->second.size)
|
||||
{
|
||||
it->second.time_stamp = now ;
|
||||
|
||||
#ifdef WINDOWS_SYS
|
||||
if(it->second.time_stamp != (uint64_t)mod_time)
|
||||
{
|
||||
std::cerr << "(WW) detected a 1 hour shift in file modification time. This normally happens to many files at once, when daylight saving time shifts (file=\"" << full_path << "\")." << std::endl;
|
||||
it->second.time_stamp = (uint64_t)mod_time;
|
||||
}
|
||||
#endif
|
||||
|
||||
known_hash = it->second.hash;
|
||||
#ifdef HASHSTORAGE_DEBUG
|
||||
std::cerr << "Found in cache." << std::endl ;
|
||||
#endif
|
||||
return true ;
|
||||
}
|
||||
#ifdef HASHSTORAGE_DEBUG
|
||||
std::cerr << "Not in cache. Scheduling for re-hash." << std::endl ;
|
||||
#endif
|
||||
|
||||
// we need to schedule a re-hashing
|
||||
|
||||
if(mFilesToHash.find(full_path) != mFilesToHash.end())
|
||||
return false ;
|
||||
|
||||
FileHashJob job ;
|
||||
|
||||
job.client = c ;
|
||||
job.size = size ;
|
||||
job.client_param = client_param ;
|
||||
job.full_path = full_path ;
|
||||
job.ts = mod_time ;
|
||||
|
||||
mFilesToHash[full_path] = job;
|
||||
|
||||
mTotalSizeToHash += size ;
|
||||
++mTotalFilesToHash;
|
||||
|
||||
if(!mRunning)
|
||||
{
|
||||
mRunning = true ;
|
||||
std::cerr << "Starting hashing thread." << std::endl;
|
||||
mHashCounter = 0;
|
||||
mTotalHashedSize = 0;
|
||||
|
||||
start() ;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void HashStorage::clean()
|
||||
{
|
||||
RS_STACK_MUTEX(mHashMtx) ;
|
||||
|
||||
time_t now = time(NULL) ;
|
||||
time_t duration = mMaxStorageDurationDays * 24 * 3600 ; // seconds
|
||||
|
||||
#ifdef HASHSTORAGE_DEBUG
|
||||
std::cerr << "Cleaning hash cache." << std::endl ;
|
||||
#endif
|
||||
|
||||
for(std::map<std::string,HashStorageInfo>::iterator it(mFiles.begin());it!=mFiles.end();)
|
||||
if(it->second.time_stamp + duration < (uint64_t)now)
|
||||
{
|
||||
#ifdef HASHSTORAGE_DEBUG
|
||||
std::cerr << " Entry too old: " << it->first << ", ts=" << it->second.time_stamp << std::endl ;
|
||||
#endif
|
||||
std::map<std::string,HashStorageInfo>::iterator tmp(it) ;
|
||||
++tmp ;
|
||||
mFiles.erase(it) ;
|
||||
it=tmp ;
|
||||
mChanged = true ;
|
||||
}
|
||||
else
|
||||
++it ;
|
||||
|
||||
#ifdef HASHSTORAGE_DEBUG
|
||||
std::cerr << "Done." << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
void HashStorage::locked_load()
|
||||
{
|
||||
unsigned char *data = NULL ;
|
||||
uint32_t data_size=0;
|
||||
|
||||
if(!FileListIO::loadEncryptedDataFromFile(mFilePath,data,data_size))
|
||||
{
|
||||
std::cerr << "(EE) Cannot read hash cache." << std::endl;
|
||||
return ;
|
||||
}
|
||||
uint32_t offset = 0 ;
|
||||
HashStorageInfo info ;
|
||||
uint32_t n=0;
|
||||
|
||||
while(offset < data_size)
|
||||
if(readHashStorageInfo(data,data_size,offset,info))
|
||||
{
|
||||
#ifdef HASHSTORAGE_DEBUG
|
||||
std::cerr << info << std::endl;
|
||||
++n ;
|
||||
#endif
|
||||
mFiles[info.filename] = info ;
|
||||
}
|
||||
|
||||
free(data) ;
|
||||
#ifdef HASHSTORAGE_DEBUG
|
||||
std::cerr << n << " entries loaded." << std::endl ;
|
||||
#endif
|
||||
}
|
||||
|
||||
void HashStorage::locked_save()
|
||||
{
|
||||
#ifdef HASHSTORAGE_DEBUG
|
||||
std::cerr << "Saving Hash Cache to file " << mFilePath << "..." << std::endl ;
|
||||
#endif
|
||||
|
||||
unsigned char *data = NULL ;
|
||||
uint32_t offset = 0 ;
|
||||
uint32_t total_size = 0;
|
||||
|
||||
for(std::map<std::string,HashStorageInfo>::const_iterator it(mFiles.begin());it!=mFiles.end();++it)
|
||||
writeHashStorageInfo(data,total_size,offset,it->second) ;
|
||||
|
||||
if(!FileListIO::saveEncryptedDataToFile(mFilePath,data,offset))
|
||||
{
|
||||
std::cerr << "(EE) Cannot save hash cache data." << std::endl;
|
||||
free(data) ;
|
||||
return ;
|
||||
}
|
||||
|
||||
std::cerr << mFiles.size() << " entries saved in hash cache." << std::endl;
|
||||
|
||||
free(data) ;
|
||||
}
|
||||
|
||||
bool HashStorage::readHashStorageInfo(const unsigned char *data,uint32_t total_size,uint32_t& offset,HashStorageInfo& info) const
|
||||
{
|
||||
unsigned char *section_data = NULL ;
|
||||
uint32_t section_size = 0;
|
||||
uint32_t section_offset = 0;
|
||||
|
||||
// This way, the entire section is either read or skipped. That avoids the risk of being stuck somewhere in the middle
|
||||
// of a section because of some unknown field, etc.
|
||||
|
||||
if(!FileListIO::readField(data,total_size,offset,FILE_LIST_IO_TAG_HASH_STORAGE_ENTRY,section_data,section_size))
|
||||
return false;
|
||||
|
||||
if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_FILE_NAME ,info.filename )) return false ;
|
||||
if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_FILE_SIZE ,info.size )) return false ;
|
||||
if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_UPDATE_TS ,info.time_stamp)) return false ;
|
||||
if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_MODIF_TS ,info.modf_stamp)) return false ;
|
||||
if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_FILE_SHA1_HASH,info.hash )) return false ;
|
||||
|
||||
free(section_data);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HashStorage::writeHashStorageInfo(unsigned char *& data,uint32_t& total_size,uint32_t& offset,const HashStorageInfo& info) const
|
||||
{
|
||||
unsigned char *section_data = NULL ;
|
||||
uint32_t section_offset = 0 ;
|
||||
uint32_t section_size = 0;
|
||||
|
||||
if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_FILE_NAME ,info.filename )) return false ;
|
||||
if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_FILE_SIZE ,info.size )) return false ;
|
||||
if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_UPDATE_TS ,info.time_stamp)) return false ;
|
||||
if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_MODIF_TS ,info.modf_stamp)) return false ;
|
||||
if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_FILE_SHA1_HASH,info.hash )) return false ;
|
||||
|
||||
// now write the whole string into a single section in the file
|
||||
|
||||
if(!FileListIO::writeField(data,total_size,offset,FILE_LIST_IO_TAG_HASH_STORAGE_ENTRY,section_data,section_offset)) return false ;
|
||||
#ifdef HASHSTORAGE_DEBUG
|
||||
std::cerr << "Writing hash storage section " << RsUtil::BinToHex(section_data,section_offset) << std::endl;
|
||||
std::cerr << "Info.filename = " << info.filename << std::endl;
|
||||
#endif
|
||||
free(section_data) ;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& o,const HashStorage::HashStorageInfo& info)
|
||||
{
|
||||
return o << info.hash << " " << info.size << " " << info.filename ;
|
||||
}
|
139
libretroshare/src/file_sharing/hash_cache.h
Normal file
139
libretroshare/src/file_sharing/hash_cache.h
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* RetroShare C++ Hash cache.
|
||||
*
|
||||
* file_sharing/hash_cache.h
|
||||
*
|
||||
* Copyright 2016 by Mr.Alice
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare.project@gmail.com".
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include "util/rsthreads.h"
|
||||
#include "retroshare/rsfiles.h"
|
||||
|
||||
/*!
|
||||
* \brief The HashStorageClient class
|
||||
* Used by clients of the hash cache for receiving hash results when done. This is asynchrone of course since hashing
|
||||
* might be quite costly.
|
||||
*/
|
||||
class HashStorageClient
|
||||
{
|
||||
public:
|
||||
HashStorageClient() {}
|
||||
virtual ~HashStorageClient() {}
|
||||
|
||||
// the result of the hashing info is sent to this method
|
||||
|
||||
virtual void hash_callback(uint32_t client_param, const std::string& name, const RsFileHash& hash, uint64_t size)=0;
|
||||
|
||||
// this method is used to check that the client param is still valid just before hashing. This avoids hashing files
|
||||
// that are still in queue while removed from shared lists.
|
||||
|
||||
virtual bool hash_confirm(uint32_t client_param)=0 ;
|
||||
};
|
||||
|
||||
class HashStorage: public RsTickingThread
|
||||
{
|
||||
public:
|
||||
HashStorage(const std::string& save_file_name) ;
|
||||
|
||||
/*!
|
||||
* \brief requestHash Requests the hash for the given file, assuming size and mod_time are the same.
|
||||
*
|
||||
* \param full_path Full path to reach the file
|
||||
* \param size Actual file size
|
||||
* \param mod_time Actual file modification time
|
||||
* \param known_hash Returned hash for the file.
|
||||
* \param c Hash cache client to which the hash should be sent once calculated
|
||||
* \param client_param Param to be passed to the client callback. Useful if the client needs a file ID.
|
||||
*
|
||||
* \return true if the supplied hash info is up to date.
|
||||
*/
|
||||
bool requestHash(const std::string& full_path, uint64_t size, time_t mod_time, RsFileHash& known_hash, HashStorageClient *c, uint32_t client_param) ;
|
||||
|
||||
struct HashStorageInfo
|
||||
{
|
||||
std::string filename ; // full path of the file
|
||||
uint64_t size ;
|
||||
uint32_t time_stamp ; // last time the hash was tested/requested
|
||||
uint32_t modf_stamp ;
|
||||
RsFileHash hash ;
|
||||
} ;
|
||||
|
||||
// interaction with GUI, called from p3FileLists
|
||||
void setRememberHashFilesDuration(uint32_t days) { mMaxStorageDurationDays = days ; } // duration for which the hash is kept even if the file is not shared anymore
|
||||
uint32_t rememberHashFilesDuration() const { return mMaxStorageDurationDays ; }
|
||||
void clear() { mFiles.clear(); mChanged=true; } // drop all known hashes. Not something to do, except if you want to rehash the entire database
|
||||
bool empty() const { return mFiles.empty() ; }
|
||||
|
||||
// Functions called by the thread
|
||||
|
||||
virtual void data_tick() ;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& o,const HashStorageInfo& info) ;
|
||||
private:
|
||||
/*!
|
||||
* \brief clean
|
||||
* This function is responsible for removing old hashes, etc
|
||||
*/
|
||||
void clean() ;
|
||||
|
||||
// loading/saving the entire hash database to a file
|
||||
|
||||
void locked_save() ;
|
||||
void locked_load() ;
|
||||
|
||||
bool readHashStorageInfo(const unsigned char *data,uint32_t total_size,uint32_t& offset,HashStorageInfo& info) const;
|
||||
bool writeHashStorageInfo(unsigned char *& data,uint32_t& total_size,uint32_t& offset,const HashStorageInfo& info) const;
|
||||
|
||||
// Local configuration and storage
|
||||
|
||||
uint32_t mMaxStorageDurationDays ; // maximum duration of un-requested cache entries
|
||||
std::map<std::string, HashStorageInfo> mFiles ; // stored as (full_path, hash_info)
|
||||
std::string mFilePath ; // file where the hash database is stored
|
||||
bool mChanged ;
|
||||
|
||||
struct FileHashJob
|
||||
{
|
||||
std::string full_path;
|
||||
uint64_t size ;
|
||||
HashStorageClient *client;
|
||||
uint32_t client_param ;
|
||||
time_t ts;
|
||||
};
|
||||
|
||||
// current work
|
||||
|
||||
std::map<std::string,FileHashJob> mFilesToHash ;
|
||||
|
||||
// thread/mutex stuff
|
||||
|
||||
RsMutex mHashMtx ;
|
||||
bool mRunning;
|
||||
uint64_t mHashCounter;
|
||||
uint32_t mInactivitySleepTime ;
|
||||
uint64_t mTotalSizeToHash ;
|
||||
uint64_t mTotalHashedSize ;
|
||||
uint64_t mTotalFilesToHash ;
|
||||
time_t mLastSaveTime ;
|
||||
};
|
||||
|
1445
libretroshare/src/file_sharing/p3filelists.cc
Normal file
1445
libretroshare/src/file_sharing/p3filelists.cc
Normal file
File diff suppressed because it is too large
Load Diff
233
libretroshare/src/file_sharing/p3filelists.h
Normal file
233
libretroshare/src/file_sharing/p3filelists.h
Normal file
@ -0,0 +1,233 @@
|
||||
/*
|
||||
* RetroShare C++ File lists service.
|
||||
*
|
||||
* file_sharing/p3filelists.h
|
||||
*
|
||||
* Copyright 2016 by Mr.Alice
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare.project@gmail.com".
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
//
|
||||
// This class is responsible for
|
||||
// - maintaining a list of shared file hierarchies for each known friends
|
||||
// - talking to the GUI
|
||||
// - providing handles for the directory tree listing GUI
|
||||
// - providing search handles for FT
|
||||
// - keeping these lists up to date
|
||||
// - sending our own file list to friends depending on the defined access rights
|
||||
// - serving file search requests from other services such as file transfer
|
||||
//
|
||||
// p3FileList does the following micro-tasks:
|
||||
// - tick the watchers
|
||||
// - get incoming info from the service layer, which can be:
|
||||
// - directory content request => the directory content is shared to the friend
|
||||
// - directory content => the directory watcher is notified
|
||||
// - keep two queues of update requests:
|
||||
// - fast queue that is handled in highest priority. This one is used for e.g. updating while browsing.
|
||||
// - slow queue that is handled slowly. Used in background update of shared directories.
|
||||
//
|
||||
// The file lists are not directry updated. A FileListWatcher class is responsible for this
|
||||
// in every case.
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "ft/ftsearch.h"
|
||||
#include "retroshare/rsfiles.h"
|
||||
#include "services/p3service.h"
|
||||
|
||||
#include "file_sharing/hash_cache.h"
|
||||
#include "file_sharing/directory_storage.h"
|
||||
|
||||
#include "pqi/p3cfgmgr.h"
|
||||
#include "pqi/p3linkmgr.h"
|
||||
|
||||
class RemoteDirectoryUpdater ;
|
||||
class LocalDirectoryUpdater ;
|
||||
|
||||
class RemoteDirectoryStorage ;
|
||||
class LocalDirectoryStorage ;
|
||||
|
||||
class RsFileListsSyncRequestItem ;
|
||||
class RsFileListsSyncResponseItem ;
|
||||
|
||||
class HashStorage ;
|
||||
|
||||
class p3FileDatabase: public p3Service, public p3Config, public ftSearch //, public RsSharedFileService
|
||||
{
|
||||
public:
|
||||
typedef DirectoryStorage::EntryIndex EntryIndex; // this should probably be defined elsewhere
|
||||
|
||||
virtual RsServiceInfo getServiceInfo();
|
||||
|
||||
struct RsFileListSyncRequest
|
||||
{
|
||||
RsPeerId peerId ;
|
||||
EntryIndex index ;
|
||||
// [...] more to add here
|
||||
};
|
||||
|
||||
p3FileDatabase(p3ServiceControl *mpeers) ;
|
||||
~p3FileDatabase();
|
||||
|
||||
/*!
|
||||
* \brief forceSyncWithPeers
|
||||
*
|
||||
* Forces the synchronisation of the database with connected peers. This is triggered when e.g. a new group of friend is created, or when
|
||||
* a friend was added/removed from a group.
|
||||
*/
|
||||
void forceSyncWithPeers() { NOT_IMPLEMENTED() ; }
|
||||
|
||||
// derived from p3Service
|
||||
//
|
||||
virtual int tick() ;
|
||||
|
||||
// ftSearch
|
||||
virtual bool search(const RsFileHash &hash, FileSearchFlags hintflags, FileInfo &info) const;
|
||||
virtual int SearchKeywords(const std::list<std::string>& keywords, std::list<DirDetails>& results,FileSearchFlags flags,const RsPeerId& peer_id) ;
|
||||
virtual int SearchBoolExp(RsRegularExpression::Expression *exp, std::list<DirDetails>& results,FileSearchFlags flags,const RsPeerId& peer_id) const ;
|
||||
|
||||
// Interface for browsing dir hierarchy
|
||||
//
|
||||
|
||||
void stopThreads() ;
|
||||
void startThreads() ;
|
||||
|
||||
bool findChildPointer(void *ref, int row, void *& result, FileSearchFlags flags) const;
|
||||
|
||||
// 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 ;
|
||||
|
||||
// proxy method used by the web UI. Dont't delete!
|
||||
int RequestDirDetails(const RsPeerId& uid, const std::string& path, DirDetails &details)const;
|
||||
|
||||
// set/update shared directories
|
||||
|
||||
void setSharedDirectories(const std::list<SharedDirInfo>& dirs);
|
||||
void getSharedDirectories(std::list<SharedDirInfo>& dirs);
|
||||
void updateShareFlags(const SharedDirInfo& info) ;
|
||||
bool convertSharedFilePath(const std::string& path,std::string& fullpath);
|
||||
|
||||
// interface for hash caching
|
||||
|
||||
void setWatchPeriod(uint32_t seconds);
|
||||
uint32_t watchPeriod() ;
|
||||
void setWatchEnabled(bool b) ;
|
||||
bool watchEnabled() ;
|
||||
|
||||
// interfact for directory parsing
|
||||
|
||||
void forceDirectoryCheck(); // Force re-sweep the directories and see what's changed
|
||||
bool inDirectoryCheck();
|
||||
|
||||
protected:
|
||||
|
||||
int filterResults(const std::list<EntryIndex>& firesults,std::list<DirDetails>& results,FileSearchFlags flags,const RsPeerId& peer_id) const;
|
||||
std::string makeRemoteFileName(const RsPeerId& pid) const;
|
||||
|
||||
// Derived from p3Config
|
||||
//
|
||||
virtual bool loadList(std::list<RsItem *>& items);
|
||||
virtual bool saveList(bool &cleanup, std::list<RsItem *>&);
|
||||
virtual RsSerialiser *setupSerialiser() ;
|
||||
|
||||
void cleanup();
|
||||
void tickRecv();
|
||||
void tickSend();
|
||||
|
||||
private:
|
||||
p3ServiceControl *mServCtrl ;
|
||||
RsPeerId mOwnId ;
|
||||
|
||||
typedef uint64_t DirSyncRequestId ;
|
||||
|
||||
static DirSyncRequestId makeDirSyncReqId(const RsPeerId& peer_id, const RsFileHash &hash) ;
|
||||
|
||||
// utility functions to send items with some maximum size.
|
||||
|
||||
void splitAndSendItem(RsFileListsSyncResponseItem *ritem);
|
||||
RsFileListsSyncResponseItem *recvAndRebuildItem(RsFileListsSyncResponseItem *ritem);
|
||||
|
||||
/*!
|
||||
* \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 locked_generateAndSendSyncRequest(RemoteDirectoryStorage *rds,const DirectoryStorage::EntryIndex& e);
|
||||
|
||||
// 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.
|
||||
//
|
||||
std::map<DirSyncRequestId,RsFileListSyncRequest> mFastRequestQueue ;
|
||||
std::map<DirSyncRequestId,RsFileListSyncRequest> mSlowRequestQueue ;
|
||||
|
||||
// Directory storage hierarchies
|
||||
//
|
||||
// The remote one is the reference for the PeerId index below:
|
||||
// RemoteDirectories[ getFriendIndex(pid) - 1] = RemoteDirectoryStorage(pid)
|
||||
|
||||
std::vector<RemoteDirectoryStorage *> mRemoteDirectories ;
|
||||
LocalDirectoryStorage *mLocalSharedDirs ;
|
||||
|
||||
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(const EntryIndex &e, uint32_t friend_index, void *& p);
|
||||
static bool convertPointerToEntryIndex(const void *p, EntryIndex& e, uint32_t& friend_index) ;
|
||||
uint32_t locked_getFriendIndex(const RsPeerId& pid);
|
||||
const RsPeerId& locked_getFriendFromIndex(uint32_t indx) const;
|
||||
|
||||
void handleDirSyncRequest (RsFileListsSyncRequestItem *) ;
|
||||
void handleDirSyncResponse (RsFileListsSyncResponseItem *) ;
|
||||
|
||||
std::map<RsPeerId,uint32_t> mFriendIndexMap ;
|
||||
std::vector<RsPeerId> mFriendIndexTab;
|
||||
|
||||
// Directory synchronization
|
||||
//
|
||||
struct DirSyncRequestData
|
||||
{
|
||||
RsPeerId peer_id ;
|
||||
time_t request_TS ;
|
||||
uint32_t flags ;
|
||||
};
|
||||
|
||||
time_t mLastRemoteDirSweepTS ; // TS for friend list update
|
||||
std::map<DirSyncRequestId,DirSyncRequestData> mPendingSyncRequests ; // pending requests, waiting for an answer
|
||||
std::map<DirSyncRequestId,RsFileListsSyncResponseItem *> mPartialResponseItems;
|
||||
|
||||
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.
|
||||
//
|
||||
HashStorage *mHashCache ;
|
||||
|
||||
// Local flags and mutexes
|
||||
|
||||
mutable RsMutex mFLSMtx ;
|
||||
uint32_t mUpdateFlags ;
|
||||
std::string mFileSharingDir ;
|
||||
time_t mLastCleanupTime;
|
||||
};
|
||||
|
363
libretroshare/src/file_sharing/rsfilelistitems.cc
Normal file
363
libretroshare/src/file_sharing/rsfilelistitems.cc
Normal file
@ -0,0 +1,363 @@
|
||||
/*
|
||||
* RetroShare File lists service items
|
||||
*
|
||||
* file_sharing/rsfilelistsitems.cc
|
||||
*
|
||||
* Copyright 2016 Mr.Alice
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare.project@gmail.com".
|
||||
*
|
||||
*/
|
||||
#include "serialiser/rsbaseserial.h"
|
||||
|
||||
#include "file_sharing/rsfilelistitems.h"
|
||||
|
||||
RsItem* RsFileListsSerialiser::deserialise(void *data, uint32_t *size)
|
||||
{
|
||||
#ifdef RSSERIAL_DEBUG
|
||||
std::cerr << "RsFileListsSerialiser::deserialise()" << std::endl;
|
||||
#endif
|
||||
/* get the type and size */
|
||||
uint32_t rstype = getRsItemId(data);
|
||||
|
||||
if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || (getRsItemService(rstype) != RS_SERVICE_TYPE_FILE_DATABASE))
|
||||
return NULL; /* wrong type */
|
||||
|
||||
switch(getRsItemSubType(rstype))
|
||||
{
|
||||
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:
|
||||
{
|
||||
std::cerr << "(WW) RsFileListsSerialiser::deserialise() : unhandled item type " << getRsItemSubType(rstype) << std::endl;
|
||||
return NULL;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t RsFileListsSerialiser::size(RsItem *item)
|
||||
{
|
||||
RsFileListsItem *flst_item = dynamic_cast<RsFileListsItem*>(item) ;
|
||||
|
||||
if(flst_item != NULL)
|
||||
return flst_item->serial_size() ;
|
||||
else
|
||||
{
|
||||
std::cerr << "RsFileListsSerialiser::serialise(): Not an RsFileListsItem!" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool RsFileListsSerialiser::serialise(RsItem *item, void *data, uint32_t *size)
|
||||
{
|
||||
RsFileListsItem *flst_item = dynamic_cast<RsFileListsItem*>(item) ;
|
||||
|
||||
if(flst_item != NULL)
|
||||
return flst_item->serialise(data,*size) ;
|
||||
else
|
||||
{
|
||||
std::cerr << "RsFileListsSerialiser::serialise(): Not an RsFileListsItem!" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool RsFileListsItem::serialise_header(void *data,uint32_t& pktsize,uint32_t& tlvsize, uint32_t& offset) const
|
||||
{
|
||||
tlvsize = serial_size() ;
|
||||
offset = 0;
|
||||
|
||||
if (pktsize < tlvsize)
|
||||
return false; /* not enough space */
|
||||
|
||||
pktsize = tlvsize;
|
||||
|
||||
if(!setRsItemHeader(data, tlvsize, PacketId(), tlvsize))
|
||||
{
|
||||
std::cerr << "RsFileTransferItem::serialise_header(): ERROR. Not enough size!" << std::endl;
|
||||
return false ;
|
||||
}
|
||||
#ifdef RSSERIAL_DEBUG
|
||||
std::cerr << "RsFileItemSerialiser::serialiseData() Header: " << ok << std::endl;
|
||||
#endif
|
||||
offset += 8;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
bool RsFileListsSyncRequestItem::serialise(void *data, uint32_t& size) const
|
||||
{
|
||||
uint32_t tlvsize,offset=0;
|
||||
bool ok = true;
|
||||
|
||||
if(!serialise_header(data,size,tlvsize,offset))
|
||||
return false ;
|
||||
|
||||
#ifdef RSSERIAL_DEBUG
|
||||
std::cerr << "RsFileListsSerialiser::serialiseFileListsSyncReqItem()" << std::endl;
|
||||
#endif
|
||||
|
||||
/* RsFileListsSyncMsgItem */
|
||||
|
||||
ok &= entry_hash.serialise(data, size, offset);
|
||||
ok &= setRawUInt32(data, size, &offset, flags );
|
||||
ok &= setRawUInt32(data, size, &offset, last_known_recurs_modf_TS);
|
||||
ok &= setRawUInt64(data, size, &offset, request_id);
|
||||
|
||||
if(offset != tlvsize){
|
||||
#ifdef RSSERIAL_DEBUG
|
||||
std::cerr << "RsFileListsSerialiser::serialiseNxsSynMsgItem() FAIL Size Error! " << std::endl;
|
||||
#endif
|
||||
ok = false;
|
||||
}
|
||||
|
||||
#ifdef RSSERIAL_DEBUG
|
||||
if (!ok)
|
||||
{
|
||||
std::cerr << "RsFileListsSerialiser::serialiseNxsSynMsgItem() NOK" << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool RsFileListsSyncResponseItem::serialise(void *data, uint32_t& size) const
|
||||
{
|
||||
uint32_t tlvsize,offset=0;
|
||||
bool ok = true;
|
||||
|
||||
if(!serialise_header(data,size,tlvsize,offset))
|
||||
return false ;
|
||||
|
||||
#ifdef RSSERIAL_DEBUG
|
||||
std::cerr << "RsFileListsSerialiser::serialiseFileListsSyncReqItem()" << std::endl;
|
||||
#endif
|
||||
|
||||
/* RsFileListsSyncMsgItem */
|
||||
|
||||
ok &= entry_hash.serialise(data, size, offset);
|
||||
ok &= checksum.serialise(data, size, offset);
|
||||
ok &= setRawUInt32(data, size, &offset, flags );
|
||||
ok &= setRawUInt32(data, size, &offset, last_known_recurs_modf_TS);
|
||||
ok &= setRawUInt64(data, size, &offset, request_id);
|
||||
ok &= directory_content_data.SetTlv(data,size,&offset) ;
|
||||
|
||||
if(offset != tlvsize){
|
||||
#ifdef RSSERIAL_DEBUG
|
||||
std::cerr << "RsFileListsSerialiser::serialiseNxsSynMsgItem() FAIL Size Error! " << std::endl;
|
||||
#endif
|
||||
ok = false;
|
||||
}
|
||||
|
||||
#ifdef RSSERIAL_DEBUG
|
||||
if (!ok)
|
||||
{
|
||||
std::cerr << "RsFileListsSerialiser::serialiseNxsSynMsgItem() NOK" << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
//============================================================================================================================//
|
||||
// Deserialisation //
|
||||
//============================================================================================================================//
|
||||
|
||||
//RsFileListsConfigItem* RsFileListsSerialiser::deserialFileListsConfigItem(void *data, uint32_t *size)
|
||||
//{
|
||||
// NOT_IMPLEMENTED();
|
||||
//
|
||||
// return NULL ;
|
||||
//}
|
||||
|
||||
RsFileListsSyncRequestItem* RsFileListsSerialiser::deserialFileListsSyncRequestItem(void *data, uint32_t *size)
|
||||
{
|
||||
bool ok = checkItemHeader(data,size,RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM);
|
||||
uint32_t offset = 8;
|
||||
|
||||
RsFileListsSyncRequestItem* item = new RsFileListsSyncRequestItem();
|
||||
|
||||
ok &= item->entry_hash.deserialise(data, *size, offset);
|
||||
ok &= getRawUInt32(data, *size, &offset, &item->flags);
|
||||
ok &= getRawUInt32(data, *size, &offset, &item->last_known_recurs_modf_TS);
|
||||
ok &= getRawUInt64(data, *size, &offset, &item->request_id);
|
||||
|
||||
if (offset != *size)
|
||||
{
|
||||
#ifdef RSSERIAL_DEBUG
|
||||
std::cerr << "RsFileListsSerialiser::deserialNxsGrp() FAIL size mismatch" << std::endl;
|
||||
#endif
|
||||
/* error */
|
||||
delete item;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
#ifdef RSSERIAL_DEBUG
|
||||
std::cerr << "RsFileListsSerialiser::deserialNxsGrp() NOK" << std::endl;
|
||||
#endif
|
||||
delete item;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
RsFileListsSyncResponseItem* RsFileListsSerialiser::deserialFileListsSyncResponseItem(void *data, uint32_t *size)
|
||||
{
|
||||
bool ok = checkItemHeader(data,size,RS_PKT_SUBTYPE_FILELISTS_SYNC_RSP_ITEM);
|
||||
uint32_t offset = 8;
|
||||
|
||||
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.
|
||||
uint32_t last_known_recurs_modf_TS; // time of last modification, computed over all files+directories below.
|
||||
uint64_t request_id; // use to determine if changes that have occured since last hash
|
||||
|
||||
ok &= item->entry_hash.deserialise(data, *size, offset);
|
||||
ok &= item->checksum.deserialise(data, *size, offset);
|
||||
ok &= getRawUInt32(data, *size, &offset, &item->flags);
|
||||
ok &= getRawUInt32(data, *size, &offset, &item->last_known_recurs_modf_TS);
|
||||
ok &= getRawUInt64(data, *size, &offset, &item->request_id);
|
||||
|
||||
ok &= item->directory_content_data.GetTlv(data,*size,&offset) ;
|
||||
|
||||
if (offset != *size)
|
||||
{
|
||||
#ifdef RSSERIAL_DEBUG
|
||||
std::cerr << "RsFileListsSerialiser::deserialNxsGrp() FAIL size mismatch" << std::endl;
|
||||
#endif
|
||||
/* error */
|
||||
delete item;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
#ifdef RSSERIAL_DEBUG
|
||||
std::cerr << "RsFileListsSerialiser::deserialNxsGrp() NOK" << std::endl;
|
||||
#endif
|
||||
delete item;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
bool RsFileListsSerialiser::checkItemHeader(void *data,uint32_t *size,uint8_t subservice_type)
|
||||
{
|
||||
#ifdef RSSERIAL_DEBUG
|
||||
std::cerr << "RsFileListsSerialiser::checkItemHeader()" << std::endl;
|
||||
#endif
|
||||
/* get the type and size */
|
||||
uint32_t rstype = getRsItemId(data);
|
||||
uint32_t rssize = getRsItemSize(data);
|
||||
|
||||
if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || (RS_SERVICE_TYPE_FILE_DATABASE != getRsItemService(rstype)) || (subservice_type != getRsItemSubType(rstype)))
|
||||
{
|
||||
#ifdef RSSERIAL_DEBUG
|
||||
std::cerr << "RsFileListsSerialiser::checkItemHeader() FAIL wrong type" << std::endl;
|
||||
#endif
|
||||
return false; /* wrong type */
|
||||
}
|
||||
|
||||
if (*size < rssize) /* check size */
|
||||
{
|
||||
#ifdef RSSERIAL_DEBUG
|
||||
std::cerr << "RsFileListsSerialiser::checkItemHeader() FAIL wrong size" << std::endl;
|
||||
#endif
|
||||
return false; /* not enough data */
|
||||
}
|
||||
|
||||
/* set the packet length */
|
||||
*size = rssize;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//============================================================================================================================//
|
||||
// Sizes //
|
||||
//============================================================================================================================//
|
||||
|
||||
uint32_t RsFileListsSyncRequestItem::serial_size()const
|
||||
{
|
||||
|
||||
uint32_t s = 8; //header size
|
||||
|
||||
s += RsFileHash::serial_size(); // entry hash
|
||||
s += 4; // flags
|
||||
s += 4; // last_known_recurs_modf_TS
|
||||
s += 8; // request_id
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
uint32_t RsFileListsSyncResponseItem::serial_size()const
|
||||
{
|
||||
|
||||
uint32_t s = 8; //header size
|
||||
|
||||
s += RsFileHash::serial_size(); // entry hash
|
||||
s += RsFileHash::serial_size(); // checksum
|
||||
s += 4; // flags
|
||||
s += 4; // last_known_recurs_modf_TS
|
||||
s += 8; // request_id
|
||||
s += directory_content_data.TlvSize();
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void RsFileListsSyncRequestItem::clear()
|
||||
{
|
||||
}
|
||||
void RsFileListsSyncResponseItem::clear()
|
||||
{
|
||||
directory_content_data.TlvClear();
|
||||
}
|
||||
std::ostream& RsFileListsSyncRequestItem::print(std::ostream &out, uint16_t indent)
|
||||
{
|
||||
printRsItemBase(out, "RsFileListsSyncReqItem", indent);
|
||||
uint16_t int_Indent = indent + 2;
|
||||
|
||||
printIndent(out , int_Indent); out << "Entry hash: " << entry_hash << std::endl;
|
||||
printIndent(out , int_Indent); out << "Flags: " << (uint32_t) flags << std::endl;
|
||||
printIndent(out , int_Indent); out << "Last modf TS: " << last_known_recurs_modf_TS << std::endl;
|
||||
printIndent(out , int_Indent); out << "request id: " << std::hex << request_id << std::dec << std::endl;
|
||||
|
||||
printRsItemEnd(out ,"RsFileListsSyncReqItem", indent);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& RsFileListsSyncResponseItem::print(std::ostream &out, uint16_t indent)
|
||||
{
|
||||
printRsItemBase(out, "RsFileListsSyncDirItem", indent);
|
||||
uint16_t int_Indent = indent + 2;
|
||||
|
||||
printIndent(out , int_Indent); out << "Entry hash: " << entry_hash << std::endl;
|
||||
printIndent(out , int_Indent); out << "Checksum : " << checksum << std::endl;
|
||||
printIndent(out , int_Indent); out << "Flags: " << (uint32_t) flags << std::endl;
|
||||
printIndent(out , int_Indent); out << "Last modf TS: " << last_known_recurs_modf_TS << std::endl;
|
||||
printIndent(out , int_Indent); out << "request id: " << std::hex << request_id << std::dec << std::endl;
|
||||
printIndent(out , int_Indent); out << "Data size: " << directory_content_data.bin_len << std::endl;
|
||||
|
||||
printRsItemEnd(out ,"RsFileListsSyncDirItem", indent);
|
||||
|
||||
return out;
|
||||
}
|
135
libretroshare/src/file_sharing/rsfilelistitems.h
Normal file
135
libretroshare/src/file_sharing/rsfilelistitems.h
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* RetroShare File lists service items.
|
||||
*
|
||||
* file_sharing/rsfilelistitems.h
|
||||
*
|
||||
* Copyright 2016 Mr.Alice
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare.project@gmail.com".
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#include "serialiser/rsserviceids.h"
|
||||
#include "serialiser/rsserial.h"
|
||||
#include "serialiser/rstlvbase.h"
|
||||
#include "serialiser/rstlvitem.h"
|
||||
#include "serialiser/rstlvkeys.h"
|
||||
#include "gxs/rsgxsdata.h"
|
||||
|
||||
// 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_RSP_ITEM = 0x02;
|
||||
const uint8_t RS_PKT_SUBTYPE_FILELISTS_CONFIG_ITEM = 0x03;
|
||||
|
||||
/*!
|
||||
* Base class for filelist sync items
|
||||
*/
|
||||
class RsFileListsItem : public RsItem
|
||||
{
|
||||
public:
|
||||
RsFileListsItem(uint8_t subtype)
|
||||
: RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_FILE_DATABASE, subtype)
|
||||
{
|
||||
setPriorityLevel(QOS_PRIORITY_RS_SLOW_SYNC_REQUEST); // this is the default. Someitems may be faster, on demand.
|
||||
return;
|
||||
}
|
||||
virtual ~RsFileListsItem(){}
|
||||
|
||||
virtual bool serialise(void *data,uint32_t& size) const = 0 ;
|
||||
virtual uint32_t serial_size() const = 0 ;
|
||||
virtual void clear() = 0;
|
||||
virtual std::ostream &print(std::ostream &out, uint16_t indent = 0) = 0;
|
||||
|
||||
bool serialise_header(void *data,uint32_t& pktsize,uint32_t& tlvsize, uint32_t& offset) const;
|
||||
|
||||
static const uint32_t FLAGS_SYNC_REQUEST = 0x0001 ;
|
||||
static const uint32_t FLAGS_SYNC_RESPONSE = 0x0002 ;
|
||||
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 ;
|
||||
static const uint32_t FLAGS_SYNC_PARTIAL = 0x0020 ;
|
||||
static const uint32_t FLAGS_SYNC_PARTIAL_END = 0x0040 ;
|
||||
};
|
||||
|
||||
/*!
|
||||
* Use to request synchronization on a specific directory. Also used to respond that the directory is up to date.
|
||||
*/
|
||||
class RsFileListsSyncRequestItem : public RsFileListsItem
|
||||
{
|
||||
public:
|
||||
|
||||
RsFileListsSyncRequestItem() : RsFileListsItem(RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM) {}
|
||||
|
||||
virtual void clear();
|
||||
virtual std::ostream &print(std::ostream &out, uint16_t indent);
|
||||
|
||||
virtual bool serialise(void *data,uint32_t& size) const;
|
||||
virtual uint32_t serial_size() const ;
|
||||
|
||||
RsFileHash entry_hash ; // hash 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.
|
||||
uint32_t last_known_recurs_modf_TS; // time of last modification, computed over all files+directories below.
|
||||
uint64_t request_id; // use to determine if changes that have occured since last hash
|
||||
};
|
||||
|
||||
class RsFileListsSyncResponseItem : public RsFileListsItem
|
||||
{
|
||||
public:
|
||||
|
||||
RsFileListsSyncResponseItem() : RsFileListsItem(RS_PKT_SUBTYPE_FILELISTS_SYNC_RSP_ITEM) {}
|
||||
|
||||
virtual void clear();
|
||||
virtual std::ostream &print(std::ostream &out, uint16_t indent);
|
||||
|
||||
virtual bool serialise(void *data,uint32_t& size) const;
|
||||
virtual uint32_t serial_size() const ;
|
||||
|
||||
RsFileHash entry_hash ; // hash of the directory to sync
|
||||
RsFileHash checksum ; // checksum of the bindary data, for checking
|
||||
uint32_t flags; // is it a partial/final item (used for large items only)
|
||||
uint32_t last_known_recurs_modf_TS; // time of last modification, computed over all files+directories below.
|
||||
uint64_t request_id; // use to determine if changes that have occured since last hash
|
||||
|
||||
RsTlvBinaryData directory_content_data ; // encoded binary data. This allows to vary the encoding format, in a way that is transparent to the serialiser.
|
||||
};
|
||||
|
||||
class RsFileListsSerialiser : public RsSerialType
|
||||
{
|
||||
public:
|
||||
|
||||
RsFileListsSerialiser() : RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_FILE_DATABASE) {}
|
||||
|
||||
virtual ~RsFileListsSerialiser() {}
|
||||
|
||||
virtual uint32_t size(RsItem *item);
|
||||
virtual bool serialise(RsItem *item, void *data, uint32_t *size);
|
||||
virtual RsItem* deserialise(void *data, uint32_t *size);
|
||||
|
||||
private:
|
||||
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);
|
||||
};
|
||||
|
||||
|
@ -73,10 +73,8 @@
|
||||
static const int32_t SAVE_TRANSFERS_DELAY = 301 ; // save transfer progress every 301 seconds.
|
||||
static const int32_t INACTIVE_CHUNKS_CHECK_DELAY = 240 ; // time after which an inactive chunk is released
|
||||
static const int32_t MAX_TIME_INACTIVE_REQUEUED = 120 ; // time after which an inactive ftFileControl is bt-queued
|
||||
static const int32_t TIMOUT_CACHE_FILE_TRANSFER = 800 ; // time after which cache transfer gets cancelled if inactive.
|
||||
|
||||
static const int32_t FT_FILECONTROL_QUEUE_ADD_END = 0 ;
|
||||
static const int32_t FT_FILECONTROL_QUEUE_ADD_AFTER_CACHE = 1 ;
|
||||
|
||||
const uint32_t FT_CNTRL_STANDARD_RATE = 10 * 1024 * 1024;
|
||||
const uint32_t FT_CNTRL_SLOW_RATE = 100 * 1024;
|
||||
@ -99,8 +97,8 @@ ftFileControl::ftFileControl(std::string fname,
|
||||
return;
|
||||
}
|
||||
|
||||
ftController::ftController(CacheStrapper *cs, ftDataMultiplex *dm, p3ServiceControl *sc, uint32_t ftServiceId)
|
||||
:CacheTransfer(cs), p3Config(),
|
||||
ftController::ftController(ftDataMultiplex *dm, p3ServiceControl *sc, uint32_t ftServiceId)
|
||||
: p3Config(),
|
||||
last_save_time(0),
|
||||
last_clean_time(0),
|
||||
mDataplex(dm),
|
||||
@ -231,7 +229,6 @@ void ftController::data_tick()
|
||||
time_t now = time(NULL) ;
|
||||
if(now > last_save_time + SAVE_TRANSFERS_DELAY)
|
||||
{
|
||||
cleanCacheDownloads() ;
|
||||
searchForDirectSources() ;
|
||||
|
||||
IndicateConfigChanged() ;
|
||||
@ -282,7 +279,6 @@ void ftController::searchForDirectSources()
|
||||
|
||||
for(std::map<RsFileHash,ftFileControl*>::iterator it(mDownloads.begin()); it != mDownloads.end(); ++it)
|
||||
if(it->second->mState != ftFileControl::QUEUED && it->second->mState != ftFileControl::PAUSED)
|
||||
if(! (it->second->mFlags & RS_FILE_REQ_CACHE))
|
||||
{
|
||||
FileInfo info ; // info needs to be re-allocated each time, to start with a clear list of peers (it's not cleared down there)
|
||||
|
||||
@ -335,37 +331,6 @@ void ftController::setPriority(const RsFileHash& hash,DwlSpeed p)
|
||||
it->second->mTransfer->setDownloadPriority(p) ;
|
||||
}
|
||||
|
||||
void ftController::cleanCacheDownloads()
|
||||
{
|
||||
std::vector<RsFileHash> toCancel ;
|
||||
time_t now = time(NULL) ;
|
||||
|
||||
{
|
||||
RsStackMutex stack(ctrlMutex); /******* LOCKED ********/
|
||||
|
||||
for(std::map<RsFileHash,ftFileControl*>::iterator it(mDownloads.begin());it!=mDownloads.end();++it)
|
||||
if (((it->second)->mFlags & RS_FILE_REQ_CACHE) && it->second->mState != ftFileControl::DOWNLOADING)
|
||||
// check if a cache file is downloaded, if the case, timeout the transfer after TIMOUT_CACHE_FILE_TRANSFER
|
||||
{
|
||||
#ifdef CONTROL_DEBUG
|
||||
std::cerr << "ftController::run() cache transfer found. age of this tranfer is :" << (int)(time(NULL) - (it->second)->mCreateTime);
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
if (now > (it->second)->mCreator->creationTimeStamp() + TIMOUT_CACHE_FILE_TRANSFER)
|
||||
{
|
||||
#ifdef CONTROL_DEBUG
|
||||
std::cerr << "ftController::run() cache transfer to old. Cancelling transfer. Hash :" << (it->second)->mHash << ", time=" << (it->second)->mCreateTime << ", now = " << time(NULL) ;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
toCancel.push_back((it->second)->mHash);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(uint32_t i=0;i<toCancel.size();++i)
|
||||
FileCancel(toCancel[i]);
|
||||
}
|
||||
|
||||
/* Called every 10 seconds or so */
|
||||
void ftController::checkDownloadQueue()
|
||||
{
|
||||
@ -446,16 +411,12 @@ void ftController::checkDownloadQueue()
|
||||
for(uint32_t p=0;p<_queue.size();++p)
|
||||
{
|
||||
if(p < _min_prioritized_transfers)
|
||||
if(_queue[p]->mFlags & RS_FILE_REQ_CACHE) // cache file. add to potential move list
|
||||
to_move_before.push_back(p) ;
|
||||
else
|
||||
++user_transfers ; // count one more user file in the prioritized range.
|
||||
else
|
||||
{
|
||||
if(to_move_after.size() + user_transfers >= _min_prioritized_transfers) // we caught enough transfers to move back to the top of the queue.
|
||||
break ;
|
||||
|
||||
if(!(_queue[p]->mFlags & RS_FILE_REQ_CACHE)) // non cache file. add to potential move list
|
||||
to_move_after.push_back(p) ;
|
||||
}
|
||||
}
|
||||
@ -482,27 +443,6 @@ void ftController::locked_addToQueue(ftFileControl* ftfc,int add_strategy)
|
||||
case FT_FILECONTROL_QUEUE_ADD_END: _queue.push_back(ftfc) ;
|
||||
locked_checkQueueElement(_queue.size()-1) ;
|
||||
break ;
|
||||
case FT_FILECONTROL_QUEUE_ADD_AFTER_CACHE:
|
||||
{
|
||||
// We add the transfer just before the first non cache transfer.
|
||||
// This is costly, so only use this in case we really need it.
|
||||
//
|
||||
uint32_t pos =0;
|
||||
while(pos < _queue.size() && (pos < _min_prioritized_transfers || (_queue[pos]->mFlags & RS_FILE_REQ_CACHE)>0) )
|
||||
++pos ;
|
||||
|
||||
_queue.push_back(NULL) ;
|
||||
|
||||
for(int i=int(_queue.size())-1;i>(int)pos;--i)
|
||||
{
|
||||
_queue[i] = _queue[i-1] ;
|
||||
locked_checkQueueElement(i) ;
|
||||
}
|
||||
|
||||
_queue[pos] = ftfc ;
|
||||
locked_checkQueueElement(pos) ;
|
||||
}
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
@ -889,12 +829,8 @@ bool ftController::completeFile(const RsFileHash& hash)
|
||||
locked_queueRemove(it->second->mQueuePosition) ;
|
||||
|
||||
/* switch map */
|
||||
if (!(fc->mFlags & RS_FILE_REQ_CACHE)) /* clean up completed cache files automatically */
|
||||
{
|
||||
mCompleted[fc->mHash] = fc;
|
||||
completeCount = mCompleted.size();
|
||||
} else
|
||||
delete fc ;
|
||||
|
||||
mDownloads.erase(it);
|
||||
|
||||
@ -910,35 +846,7 @@ bool ftController::completeFile(const RsFileHash& hash)
|
||||
|
||||
/* If it has a callback - do it now */
|
||||
|
||||
if(flags & ( RS_FILE_REQ_CACHE | RS_FILE_REQ_EXTRA))// | RS_FILE_HINTS_MEDIA))
|
||||
{
|
||||
#ifdef CONTROL_DEBUG
|
||||
std::cerr << "ftController::completeFile() doing Callback, callbackflags:" << (flags & ( RS_FILE_REQ_CACHE | RS_FILE_REQ_EXTRA ));//| RS_FILE_HINTS_MEDIA)) ;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
if(flags & RS_FILE_REQ_CACHE)
|
||||
{
|
||||
/* callback */
|
||||
if (state == ftFileControl::COMPLETED)
|
||||
{
|
||||
#ifdef CONTROL_DEBUG
|
||||
std::cerr << "ftController::completeFile() doing Callback : Success";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
CompletedCache(hash);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef CONTROL_DEBUG
|
||||
std::cerr << "ftController::completeFile() Cache Callback : Failed";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
FailedCache(hash);
|
||||
}
|
||||
}
|
||||
|
||||
if(flags & RS_FILE_REQ_EXTRA)
|
||||
if(flags & RS_FILE_REQ_EXTRA)// | RS_FILE_HINTS_MEDIA))
|
||||
{
|
||||
#ifdef CONTROL_DEBUG
|
||||
std::cerr << "ftController::completeFile() adding to ExtraList";
|
||||
@ -947,15 +855,6 @@ bool ftController::completeFile(const RsFileHash& hash)
|
||||
|
||||
mExtraList->addExtraFile(path, hash, size, period, extraflags);
|
||||
}
|
||||
|
||||
// if(flags & RS_FILE_HINTS_MEDIA)
|
||||
// {
|
||||
//#ifdef CONTROL_DEBUG
|
||||
// std::cerr << "ftController::completeFile() NULL MEDIA callback";
|
||||
// std::cerr << std::endl;
|
||||
//#endif
|
||||
// }
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef CONTROL_DEBUG
|
||||
@ -965,14 +864,12 @@ bool ftController::completeFile(const RsFileHash& hash)
|
||||
}
|
||||
|
||||
/* Notify GUI */
|
||||
if ((flags & RS_FILE_REQ_CACHE) == 0) {
|
||||
RsServer::notify()->AddPopupMessage(RS_POPUP_DOWNLOAD, hash.toStdString(), name, "");
|
||||
|
||||
RsServer::notify()->notifyDownloadComplete(hash.toStdString());
|
||||
RsServer::notify()->notifyDownloadCompleteCount(completeCount);
|
||||
|
||||
rsFiles->ForceDirectoryCheck() ;
|
||||
}
|
||||
|
||||
IndicateConfigChanged(); /* completed transfer -> save */
|
||||
return true;
|
||||
@ -1134,7 +1031,6 @@ bool ftController::FileRequest(const std::string& fname, const RsFileHash& hash
|
||||
|
||||
// remove the sources from the list, if they don't have clearance for direct transfer. This happens only for non cache files.
|
||||
//
|
||||
if(!(flags & RS_FILE_REQ_CACHE))
|
||||
for(std::list<RsPeerId>::iterator it = srcIds.begin(); it != srcIds.end(); )
|
||||
if(!(rsPeers->servicePermissionFlags(*it) & RS_NODE_PERM_DIRECT_DL))
|
||||
{
|
||||
@ -1280,7 +1176,7 @@ bool ftController::FileRequest(const std::string& fname, const RsFileHash& hash
|
||||
if(flags & RS_FILE_REQ_ANONYMOUS_ROUTING)
|
||||
mTurtle->monitorTunnels(hash,mFtServer,true) ;
|
||||
|
||||
bool assume_availability = flags & RS_FILE_REQ_CACHE ; // assume availability for cache files
|
||||
bool assume_availability = false;
|
||||
|
||||
ftFileCreator *fc = new ftFileCreator(savepath, size, hash,assume_availability);
|
||||
ftTransferModule *tm = new ftTransferModule(fc, mDataplex,this);
|
||||
@ -1911,58 +1807,6 @@ void ftController::statusChange(const std::list<pqiServicePeer> &plist)
|
||||
}
|
||||
}
|
||||
|
||||
/* Cache Interface */
|
||||
bool ftController::RequestCacheFile(const RsPeerId& id, std::string path, const RsFileHash& hash, uint64_t size)
|
||||
{
|
||||
#ifdef CONTROL_DEBUG
|
||||
std::cerr << "ftController::RequestCacheFile(" << id << ",";
|
||||
std::cerr << path << "," << hash << "," << size << ")";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
/* Request File */
|
||||
std::list<RsPeerId> ids;
|
||||
ids.push_back(id);
|
||||
|
||||
FileInfo info ;
|
||||
if(mSearch->search(hash, RS_FILE_HINTS_CACHE, info))
|
||||
{
|
||||
#ifdef CONTROL_DEBUG
|
||||
std::cerr << "I already have this file:" << std::endl ;
|
||||
std::cerr << " path: " << info.path << std::endl ;
|
||||
std::cerr << " fname: " << info.fname << std::endl ;
|
||||
std::cerr << " hash: " << info.hash << std::endl ;
|
||||
|
||||
std::cerr << "Copying it !!" << std::endl ;
|
||||
#endif
|
||||
|
||||
if(info.size > 0 && copyFile(info.path,path+"/"+hash.toStdString()))
|
||||
{
|
||||
CompletedCache(hash);
|
||||
return true ;
|
||||
}
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
|
||||
FileRequest(hash.toStdString(), hash, size, path, RS_FILE_REQ_CACHE | RS_FILE_REQ_NO_SEARCH, ids);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ftController::CancelCacheFile(const RsPeerId& id, std::string path, const RsFileHash& hash, uint64_t size)
|
||||
{
|
||||
std::cerr << "ftController::CancelCacheFile(" << id << ",";
|
||||
std::cerr << path << "," << hash << "," << size << ")";
|
||||
std::cerr << std::endl;
|
||||
#ifdef CONTROL_DEBUG
|
||||
#endif
|
||||
|
||||
return FileCancel(hash);
|
||||
|
||||
}
|
||||
|
||||
const std::string active_downloads_size_ss("MAX_ACTIVE_DOWNLOADS");
|
||||
const std::string min_prioritized_downl_ss("MIN_PRORITIZED_DOWNLOADS");
|
||||
const std::string download_dir_ss("DOWN_DIR");
|
||||
@ -2056,14 +1900,6 @@ bool ftController::saveList(bool &cleanup, std::list<RsItem *>& saveData)
|
||||
|
||||
/* ignore cache files. As this is small files, better download them again from scratch at restart.*/
|
||||
|
||||
if (fit->second->mFlags & RS_FILE_REQ_CACHE)
|
||||
{
|
||||
#ifdef CONTROL_DEBUG
|
||||
std::cerr << "ftcontroller::saveList(): Not saving (callback) file entry " << fit->second->mName << ", " << fit->second->mHash << ", " << fit->second->mSize << std::endl ;
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
// Node: We still save finished transfers. This keeps transfers that are
|
||||
// in checking mode. Finished or checked transfers will restart and
|
||||
// immediately terminate/recheck at next startup.
|
||||
|
@ -48,7 +48,6 @@ class ftDataMultiplex;
|
||||
class p3turtle ;
|
||||
class p3ServiceControl;
|
||||
|
||||
#include "dbase/cachestrapper.h"
|
||||
#include "util/rsthreads.h"
|
||||
#include "pqi/pqiservicemonitor.h"
|
||||
#include "pqi/p3cfgmgr.h"
|
||||
@ -113,12 +112,12 @@ class ftPendingRequest
|
||||
};
|
||||
|
||||
|
||||
class ftController: public CacheTransfer, public RsTickingThread, public pqiServiceMonitor, public p3Config
|
||||
class ftController: public RsTickingThread, public pqiServiceMonitor, public p3Config
|
||||
{
|
||||
public:
|
||||
|
||||
/* Setup */
|
||||
ftController(CacheStrapper *cs, ftDataMultiplex *dm, p3ServiceControl *sc, uint32_t ftServiceId);
|
||||
ftController(ftDataMultiplex *dm, p3ServiceControl *sc, uint32_t ftServiceId);
|
||||
|
||||
void setFtSearchNExtra(ftSearch *, ftExtraList *);
|
||||
void setTurtleRouter(p3turtle *) ;
|
||||
@ -195,10 +194,6 @@ class ftController: public CacheTransfer, public RsTickingThread, public pqiServ
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool RequestCacheFile(const RsPeerId& id, std::string path, const RsFileHash& hash, uint64_t size);
|
||||
virtual bool CancelCacheFile(const RsPeerId& id, std::string path, const RsFileHash& hash, uint64_t size);
|
||||
|
||||
void cleanCacheDownloads() ;
|
||||
void searchForDirectSources() ;
|
||||
void tickTransfers() ;
|
||||
|
||||
|
@ -1104,8 +1104,6 @@ bool ftDataMultiplex::handleSearchRequest(const RsPeerId& peerId, const RsFileHa
|
||||
|
||||
if(rsTurtle->isTurtlePeer(peerId))
|
||||
hintflags |= RS_FILE_HINTS_NETWORK_WIDE ;
|
||||
else
|
||||
hintflags |= RS_FILE_HINTS_CACHE ;
|
||||
|
||||
if(mSearch->search(hash, hintflags, info))
|
||||
{
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "retroshare/rspeers.h"
|
||||
const int ftserverzone = 29539;
|
||||
|
||||
#include "file_sharing/p3filelists.h"
|
||||
#include "ft/ftturtlefiletransferitem.h"
|
||||
#include "ft/ftserver.h"
|
||||
#include "ft/ftextralist.h"
|
||||
@ -43,11 +44,6 @@ const int ftserverzone = 29539;
|
||||
#include "pqi/p3notify.h"
|
||||
#include "rsserver/p3face.h"
|
||||
|
||||
|
||||
// Includes CacheStrapper / FiMonitor / FiStore for us.
|
||||
|
||||
#include "ft/ftdbase.h"
|
||||
|
||||
#include "pqi/pqi.h"
|
||||
#include "pqi/p3linkmgr.h"
|
||||
|
||||
@ -64,15 +60,11 @@ static const time_t FILE_TRANSFER_LOW_PRIORITY_TASKS_PERIOD = 5 ; // low priorit
|
||||
/* Setup */
|
||||
ftServer::ftServer(p3PeerMgr *pm, p3ServiceControl *sc)
|
||||
: p3Service(),
|
||||
mPeerMgr(pm),
|
||||
mServiceCtrl(sc),
|
||||
mCacheStrapper(NULL),
|
||||
mFiStore(NULL), mFiMon(NULL),
|
||||
mPeerMgr(pm), mServiceCtrl(sc),
|
||||
mFileDatabase(NULL),
|
||||
mFtController(NULL), mFtExtra(NULL),
|
||||
mFtDataplex(NULL), mFtSearch(NULL), srvMutex("ftServer")
|
||||
{
|
||||
mCacheStrapper = new ftCacheStrapper(sc, getServiceInfo().mServiceType);
|
||||
|
||||
addSerialType(new RsFileTransferSerialiser()) ;
|
||||
}
|
||||
|
||||
@ -145,33 +137,25 @@ void ftServer::SetupFtServer()
|
||||
mFtDataplex = new ftDataMultiplex(ownId, this, mFtSearch);
|
||||
|
||||
/* make Controller */
|
||||
mFtController = new ftController(mCacheStrapper, mFtDataplex, mServiceCtrl, getServiceInfo().mServiceType);
|
||||
mFtController = new ftController(mFtDataplex, mServiceCtrl, getServiceInfo().mServiceType);
|
||||
mFtController -> setFtSearchNExtra(mFtSearch, mFtExtra);
|
||||
std::string tmppath = ".";
|
||||
mFtController->setPartialsDirectory(tmppath);
|
||||
mFtController->setDownloadDirectory(tmppath);
|
||||
|
||||
|
||||
/* Make Cache Source/Store */
|
||||
mFiStore = new ftFiStore(mCacheStrapper, mFtController, mPeerMgr, ownId, remotecachedir);
|
||||
mFiMon = new ftFiMonitor(mCacheStrapper,localcachedir, ownId,mConfigPath);
|
||||
|
||||
/* now add the set to the cachestrapper */
|
||||
CachePair cp(mFiMon, mFiStore, CacheId(RS_SERVICE_TYPE_FILE_INDEX, 0));
|
||||
mCacheStrapper -> addCachePair(cp);
|
||||
|
||||
/* complete search setup */
|
||||
mFtSearch->addSearchMode(mCacheStrapper, RS_FILE_HINTS_CACHE);
|
||||
mFtSearch->addSearchMode(mFtExtra, RS_FILE_HINTS_EXTRA);
|
||||
mFtSearch->addSearchMode(mFiMon, RS_FILE_HINTS_LOCAL);
|
||||
mFtSearch->addSearchMode(mFiStore, RS_FILE_HINTS_REMOTE);
|
||||
|
||||
mServiceCtrl->registerServiceMonitor(mFtController, getServiceInfo().mServiceType);
|
||||
mServiceCtrl->registerServiceMonitor(mCacheStrapper, getServiceInfo().mServiceType);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void ftServer::connectToFileDatabase(p3FileDatabase *fdb)
|
||||
{
|
||||
mFileDatabase = fdb ;
|
||||
mFtSearch->addSearchMode(fdb, RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_REMOTE);
|
||||
}
|
||||
void ftServer::connectToTurtleRouter(p3turtle *fts)
|
||||
{
|
||||
mTurtleRouter = fts ;
|
||||
@ -193,7 +177,7 @@ void ftServer::StartupThreads()
|
||||
/* startup Monitor Thread */
|
||||
/* startup the FileMonitor (after cache load) */
|
||||
/* start it up */
|
||||
mFiMon->start("ft monitor");
|
||||
mFileDatabase->startThreads();
|
||||
|
||||
/* Controller thread */
|
||||
mFtController->start("ft ctrl");
|
||||
@ -210,9 +194,6 @@ void ftServer::StopThreads()
|
||||
/* stop Controller thread */
|
||||
mFtController->join();
|
||||
|
||||
/* stop Monitor Thread */
|
||||
mFiMon->join();
|
||||
|
||||
/* self contained threads */
|
||||
/* stop ExtraList Thread */
|
||||
mFtExtra->join();
|
||||
@ -223,24 +204,15 @@ void ftServer::StopThreads()
|
||||
delete (mFtController);
|
||||
mFtController = NULL;
|
||||
|
||||
delete (mFiMon);
|
||||
mFiMon = NULL;
|
||||
|
||||
delete (mFtExtra);
|
||||
mFtExtra = NULL;
|
||||
}
|
||||
|
||||
CacheStrapper *ftServer::getCacheStrapper()
|
||||
{
|
||||
return mCacheStrapper;
|
||||
/* stop Monitor Thread */
|
||||
mFileDatabase->stopThreads();
|
||||
delete mFileDatabase;
|
||||
mFileDatabase = NULL ;
|
||||
}
|
||||
|
||||
CacheTransfer *ftServer::getCacheTransfer()
|
||||
{
|
||||
return mFtController;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************/
|
||||
/********************** RsFiles Interface **********************/
|
||||
/***************************************************************/
|
||||
@ -256,11 +228,6 @@ bool ftServer::ResumeTransfers()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ftServer::checkHash(const RsFileHash& /*hash*/, std::string& /*error_string*/)
|
||||
{
|
||||
return true ;
|
||||
}
|
||||
|
||||
bool ftServer::getFileData(const RsFileHash& hash, uint64_t offset, uint32_t& requested_size,uint8_t *data)
|
||||
{
|
||||
return mFtDataplex->getFileData(hash, offset, requested_size,data);
|
||||
@ -268,19 +235,11 @@ bool ftServer::getFileData(const RsFileHash& hash, uint64_t offset, uint32_t& re
|
||||
|
||||
bool ftServer::alreadyHaveFile(const RsFileHash& hash, FileInfo &info)
|
||||
{
|
||||
return mFtController->alreadyHaveFile(hash, info);
|
||||
return mFileDatabase->search(hash, RS_FILE_HINTS_LOCAL, info);
|
||||
}
|
||||
|
||||
bool ftServer::FileRequest(const std::string& fname, const RsFileHash& hash, uint64_t size, const std::string& dest, TransferRequestFlags flags, const std::list<RsPeerId>& srcIds)
|
||||
{
|
||||
std::string error_string ;
|
||||
|
||||
if(!checkHash(hash,error_string))
|
||||
{
|
||||
RsServer::notify()->notifyErrorMsg(0,0,"Error handling hash \""+hash.toStdString()+"\". This hash appears to be invalid(Error string=\""+error_string+"\"). This is probably due an bad handling of strings.") ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
std::cerr << "Requesting " << fname << std::endl ;
|
||||
|
||||
if(!mFtController->FileRequest(fname, hash, size, dest, flags, srcIds))
|
||||
@ -335,14 +294,6 @@ bool ftServer::FileClearCompleted()
|
||||
{
|
||||
return mFtController->FileClearCompleted();
|
||||
}
|
||||
void ftServer::setMinPrioritizedTransfers(uint32_t s)
|
||||
{
|
||||
mFtController->setMinPrioritizedTransfers(s) ;
|
||||
}
|
||||
uint32_t ftServer::getMinPrioritizedTransfers()
|
||||
{
|
||||
return mFtController->getMinPrioritizedTransfers() ;
|
||||
}
|
||||
void ftServer::setQueueSize(uint32_t s)
|
||||
{
|
||||
mFtController->setQueueSize(s) ;
|
||||
@ -381,6 +332,11 @@ bool ftServer::FileDownloadChunksDetails(const RsFileHash& hash,FileChunksInfo&
|
||||
return mFtController->getFileDownloadChunksDetails(hash,info);
|
||||
}
|
||||
|
||||
void ftServer::requestDirUpdate(void *ref)
|
||||
{
|
||||
mFileDatabase->requestDirUpdate(ref) ;
|
||||
}
|
||||
|
||||
/* Directory Handling */
|
||||
void ftServer::setDownloadDirectory(std::string path)
|
||||
{
|
||||
@ -402,16 +358,18 @@ std::string ftServer::getPartialsDirectory()
|
||||
return mFtController->getPartialsDirectory();
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************/
|
||||
/************************* Other Access ************************/
|
||||
/***************************************************************/
|
||||
|
||||
bool ftServer::copyFile(const std::string& source, const std::string& dest)
|
||||
{
|
||||
return mFtController->copyFile(source, dest);
|
||||
}
|
||||
|
||||
void ftServer::FileDownloads(std::list<RsFileHash> &hashs)
|
||||
{
|
||||
mFtController->FileDownloads(hashs);
|
||||
/* this only contains downloads.... not completed */
|
||||
//return mFtDataplex->FileDownloads(hashs);
|
||||
}
|
||||
|
||||
bool ftServer::FileUploadChunksDetails(const RsFileHash& hash,const RsPeerId& peer_id,CompressedChunkMap& cmap)
|
||||
@ -438,7 +396,7 @@ bool ftServer::FileDetails(const RsFileHash &hash, FileSearchFlags hintflags, Fi
|
||||
// file, we skip the call to fileDetails() for efficiency reasons.
|
||||
//
|
||||
FileInfo info2 ;
|
||||
if( (!(info.transfer_info_flags & RS_FILE_REQ_CACHE)) && mFtController->FileDetails(hash, info2))
|
||||
if(mFtController->FileDetails(hash, info2))
|
||||
info.fname = info2.fname ;
|
||||
|
||||
return true ;
|
||||
@ -543,8 +501,7 @@ bool ftServer::handleTunnelRequest(const RsFileHash& hash,const RsPeerId& peer_i
|
||||
/******************* ExtraFileList Access **********************/
|
||||
/***************************************************************/
|
||||
|
||||
bool ftServer::ExtraFileAdd(std::string fname, const RsFileHash& hash, uint64_t size,
|
||||
uint32_t period, TransferRequestFlags flags)
|
||||
bool ftServer::ExtraFileAdd(std::string fname, const RsFileHash& hash, uint64_t size, uint32_t period, TransferRequestFlags flags)
|
||||
{
|
||||
return mFtExtra->addExtraFile(fname, hash, size, period, flags);
|
||||
}
|
||||
@ -564,122 +521,53 @@ bool ftServer::ExtraFileStatus(std::string localpath, FileInfo &info)
|
||||
return mFtExtra->hashExtraFileDone(localpath, info);
|
||||
}
|
||||
|
||||
bool ftServer::ExtraFileMove(std::string fname, const RsFileHash& hash, uint64_t size,
|
||||
std::string destpath)
|
||||
bool ftServer::ExtraFileMove(std::string fname, const RsFileHash& hash, uint64_t size, std::string destpath)
|
||||
{
|
||||
return mFtExtra->moveExtraFile(fname, hash, size, destpath);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************/
|
||||
/******************** Directory Listing ************************/
|
||||
/***************************************************************/
|
||||
|
||||
int ftServer::RequestDirDetails(const RsPeerId& uid, const std::string& path, DirDetails &details)
|
||||
{
|
||||
#ifdef SERVER_DEBUG
|
||||
std::cerr << "ftServer::RequestDirDetails(uid:" << uid;
|
||||
std::cerr << ", path:" << path << ", ...) -> mFiStore";
|
||||
std::cerr << std::endl;
|
||||
return mFileDatabase->RequestDirDetails(uid, path, details);
|
||||
}
|
||||
|
||||
if (!mFiStore)
|
||||
bool ftServer::findChildPointer(void *ref, int row, void *& result, FileSearchFlags flags)
|
||||
{
|
||||
std::cerr << "mFiStore not SET yet = FAIL";
|
||||
std::cerr << std::endl;
|
||||
return mFileDatabase->findChildPointer(ref,row,result,flags) ;
|
||||
}
|
||||
#endif
|
||||
if(uid == mServiceCtrl->getOwnId())
|
||||
return mFiMon->RequestDirDetails(path, details);
|
||||
else
|
||||
return mFiStore->RequestDirDetails(uid, path, details);
|
||||
}
|
||||
|
||||
int ftServer::RequestDirDetails(void *ref, DirDetails &details, FileSearchFlags flags)
|
||||
{
|
||||
#ifdef SERVER_DEBUG
|
||||
std::cerr << "ftServer::RequestDirDetails(ref:" << ref;
|
||||
std::cerr << ", flags:" << flags << ", ...) -> mFiStore";
|
||||
std::cerr << std::endl;
|
||||
|
||||
if (!mFiStore)
|
||||
{
|
||||
std::cerr << "mFiStore not SET yet = FAIL";
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
#endif
|
||||
if(flags & RS_FILE_HINTS_LOCAL)
|
||||
return mFiMon->RequestDirDetails(ref, details, flags);
|
||||
else
|
||||
return mFiStore->RequestDirDetails(ref, details, flags);
|
||||
return mFileDatabase->RequestDirDetails(ref,details,flags) ;
|
||||
}
|
||||
uint32_t ftServer::getType(void *ref, FileSearchFlags flags)
|
||||
{
|
||||
#ifdef SERVER_DEBUG
|
||||
std::cerr << "ftServer::RequestDirDetails(ref:" << ref;
|
||||
std::cerr << ", flags:" << flags << ", ...) -> mFiStore";
|
||||
std::cerr << std::endl;
|
||||
|
||||
if (!mFiStore)
|
||||
{
|
||||
std::cerr << "mFiStore not SET yet = FAIL";
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
#endif
|
||||
if(flags & RS_FILE_HINTS_LOCAL)
|
||||
return mFiMon->getType(ref);
|
||||
else
|
||||
return mFiStore->getType(ref);
|
||||
return mFileDatabase->getType(ref) ;
|
||||
}
|
||||
/***************************************************************/
|
||||
/******************** Search Interface *************************/
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
int ftServer::SearchKeywords(std::list<std::string> keywords, std::list<DirDetails> &results,FileSearchFlags flags)
|
||||
{
|
||||
if(flags & RS_FILE_HINTS_LOCAL)
|
||||
return mFiMon->SearchKeywords(keywords, results,flags,RsPeerId());
|
||||
else
|
||||
return mFiStore->SearchKeywords(keywords, results,flags);
|
||||
return 0 ;
|
||||
return mFileDatabase->SearchKeywords(keywords, results,flags,RsPeerId());
|
||||
}
|
||||
int ftServer::SearchKeywords(std::list<std::string> keywords, std::list<DirDetails> &results,FileSearchFlags flags,const RsPeerId& peer_id)
|
||||
{
|
||||
#ifdef SERVER_DEBUG
|
||||
std::cerr << "ftServer::SearchKeywords()";
|
||||
std::cerr << std::endl;
|
||||
return mFileDatabase->SearchKeywords(keywords, results,flags,peer_id);
|
||||
}
|
||||
|
||||
if (!mFiStore)
|
||||
int ftServer::SearchBoolExp(RsRegularExpression::Expression * exp, std::list<DirDetails> &results,FileSearchFlags flags)
|
||||
{
|
||||
std::cerr << "mFiStore not SET yet = FAIL";
|
||||
std::cerr << std::endl;
|
||||
return mFileDatabase->SearchBoolExp(exp, results,flags,RsPeerId());
|
||||
}
|
||||
|
||||
#endif
|
||||
if(flags & RS_FILE_HINTS_LOCAL)
|
||||
return mFiMon->SearchKeywords(keywords, results,flags,peer_id);
|
||||
else
|
||||
return mFiStore->SearchKeywords(keywords, results,flags);
|
||||
}
|
||||
|
||||
int ftServer::SearchBoolExp(Expression * exp, std::list<DirDetails> &results,FileSearchFlags flags)
|
||||
int ftServer::SearchBoolExp(RsRegularExpression::Expression * exp, std::list<DirDetails> &results,FileSearchFlags flags,const RsPeerId& peer_id)
|
||||
{
|
||||
if(flags & RS_FILE_HINTS_LOCAL)
|
||||
return mFiMon->SearchBoolExp(exp,results,flags,RsPeerId()) ;
|
||||
else
|
||||
return mFiStore->searchBoolExp(exp, results);
|
||||
return 0 ;
|
||||
return mFileDatabase->SearchBoolExp(exp,results,flags,peer_id) ;
|
||||
}
|
||||
int ftServer::SearchBoolExp(Expression * exp, std::list<DirDetails> &results,FileSearchFlags flags,const RsPeerId& peer_id)
|
||||
{
|
||||
if(flags & RS_FILE_HINTS_LOCAL)
|
||||
return mFiMon->SearchBoolExp(exp,results,flags,peer_id) ;
|
||||
else
|
||||
return mFiStore->searchBoolExp(exp, results);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************/
|
||||
/*************** Local Shared Dir Interface ********************/
|
||||
@ -687,38 +575,33 @@ int ftServer::SearchBoolExp(Expression * exp, std::list<DirDetails> &results,Fil
|
||||
|
||||
bool ftServer::ConvertSharedFilePath(std::string path, std::string &fullpath)
|
||||
{
|
||||
return mFiMon->convertSharedFilePath(path, fullpath);
|
||||
return mFileDatabase->convertSharedFilePath(path, fullpath);
|
||||
}
|
||||
|
||||
void ftServer::updateSinceGroupPermissionsChanged()
|
||||
{
|
||||
mFiMon->forceDirListsRebuildAndSend();
|
||||
mFileDatabase->forceSyncWithPeers();
|
||||
}
|
||||
void ftServer::ForceDirectoryCheck()
|
||||
{
|
||||
mFiMon->forceDirectoryCheck();
|
||||
mFileDatabase->forceDirectoryCheck();
|
||||
return;
|
||||
}
|
||||
|
||||
bool ftServer::InDirectoryCheck()
|
||||
{
|
||||
return mFiMon->inDirectoryCheck();
|
||||
}
|
||||
|
||||
bool ftServer::copyFile(const std::string& source, const std::string& dest)
|
||||
{
|
||||
return mFtController->copyFile(source, dest);
|
||||
return mFileDatabase->inDirectoryCheck();
|
||||
}
|
||||
|
||||
bool ftServer::getSharedDirectories(std::list<SharedDirInfo> &dirs)
|
||||
{
|
||||
mFiMon->getSharedDirectories(dirs);
|
||||
mFileDatabase->getSharedDirectories(dirs);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ftServer::setSharedDirectories(std::list<SharedDirInfo> &dirs)
|
||||
{
|
||||
mFiMon->setSharedDirectories(dirs);
|
||||
mFileDatabase->setSharedDirectories(dirs);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -728,7 +611,7 @@ bool ftServer::addSharedDirectory(const SharedDirInfo& dir)
|
||||
_dir.filename = RsDirUtil::convertPathToUnix(_dir.filename);
|
||||
|
||||
std::list<SharedDirInfo> dirList;
|
||||
mFiMon->getSharedDirectories(dirList);
|
||||
mFileDatabase->getSharedDirectories(dirList);
|
||||
|
||||
// check that the directory is not already in the list.
|
||||
for(std::list<SharedDirInfo>::const_iterator it(dirList.begin());it!=dirList.end();++it)
|
||||
@ -738,13 +621,13 @@ bool ftServer::addSharedDirectory(const SharedDirInfo& dir)
|
||||
// ok then, add the shared directory.
|
||||
dirList.push_back(_dir);
|
||||
|
||||
mFiMon->setSharedDirectories(dirList);
|
||||
mFileDatabase->setSharedDirectories(dirList);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ftServer::updateShareFlags(const SharedDirInfo& info)
|
||||
{
|
||||
mFiMon->updateShareFlags(info);
|
||||
mFileDatabase->updateShareFlags(info);
|
||||
|
||||
return true ;
|
||||
}
|
||||
@ -761,7 +644,7 @@ bool ftServer::removeSharedDirectory(std::string dir)
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
mFiMon->getSharedDirectories(dirList);
|
||||
mFileDatabase->getSharedDirectories(dirList);
|
||||
|
||||
#ifdef SERVER_DEBUG
|
||||
for(it = dirList.begin(); it != dirList.end(); ++it)
|
||||
@ -776,12 +659,7 @@ bool ftServer::removeSharedDirectory(std::string dir)
|
||||
|
||||
if(it == dirList.end())
|
||||
{
|
||||
#ifdef SERVER_DEBUG
|
||||
std::cerr << "ftServer::removeSharedDirectory()";
|
||||
std::cerr << " Cannot Find Directory... Fail";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
std::cerr << "(EE) ftServer::removeSharedDirectory(): Cannot Find Directory... Fail" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -793,44 +671,20 @@ bool ftServer::removeSharedDirectory(std::string dir)
|
||||
#endif
|
||||
|
||||
dirList.erase(it);
|
||||
mFiMon->setSharedDirectories(dirList);
|
||||
mFileDatabase->setSharedDirectories(dirList);
|
||||
|
||||
return true;
|
||||
}
|
||||
void ftServer::setWatchPeriod(int minutes)
|
||||
{
|
||||
mFiMon->setWatchPeriod(minutes*60) ;
|
||||
}
|
||||
int ftServer::watchPeriod() const
|
||||
{
|
||||
return mFiMon->watchPeriod()/60 ;
|
||||
}
|
||||
bool ftServer::watchEnabled() { return mFileDatabase->watchEnabled() ; }
|
||||
int ftServer::watchPeriod() const { return mFileDatabase->watchPeriod()/60 ; }
|
||||
|
||||
void ftServer::setRememberHashFiles(bool b)
|
||||
{
|
||||
mFiMon->setRememberHashCache(b) ;
|
||||
}
|
||||
bool ftServer::rememberHashFiles() const
|
||||
{
|
||||
return mFiMon->rememberHashCache() ;
|
||||
}
|
||||
void ftServer::setRememberHashFilesDuration(uint32_t days)
|
||||
{
|
||||
mFiMon->setRememberHashCacheDuration(days) ;
|
||||
}
|
||||
uint32_t ftServer::rememberHashFilesDuration() const
|
||||
{
|
||||
return mFiMon->rememberHashCacheDuration() ;
|
||||
}
|
||||
void ftServer::clearHashCache()
|
||||
{
|
||||
mFiMon->clearHashCache() ;
|
||||
}
|
||||
void ftServer::setWatchEnabled(bool b) { mFileDatabase->setWatchEnabled(b) ; }
|
||||
void ftServer::setWatchPeriod(int minutes) { mFileDatabase->setWatchPeriod(minutes*60) ; }
|
||||
|
||||
bool ftServer::getShareDownloadDirectory()
|
||||
{
|
||||
std::list<SharedDirInfo> dirList;
|
||||
mFiMon->getSharedDirectories(dirList);
|
||||
mFileDatabase->getSharedDirectories(dirList);
|
||||
|
||||
std::string dir = mFtController->getDownloadDirectory();
|
||||
|
||||
@ -844,7 +698,8 @@ bool ftServer::getShareDownloadDirectory()
|
||||
|
||||
bool ftServer::shareDownloadDirectory(bool share)
|
||||
{
|
||||
if (share) {
|
||||
if (share)
|
||||
{
|
||||
/* Share */
|
||||
SharedDirInfo inf ;
|
||||
inf.filename = mFtController->getDownloadDirectory();
|
||||
@ -852,48 +707,22 @@ bool ftServer::shareDownloadDirectory(bool share)
|
||||
|
||||
return addSharedDirectory(inf);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
/* Unshare */
|
||||
std::string dir = mFtController->getDownloadDirectory();
|
||||
return removeSharedDirectory(dir);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/****************** End of RsFiles Interface *******************/
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
/***************************************************************/
|
||||
/**************** Config Interface *****************************/
|
||||
/***************************************************************/
|
||||
|
||||
/* Key Functions to be overloaded for Full Configuration */
|
||||
RsSerialiser *ftServer::setupSerialiser()
|
||||
{
|
||||
RsSerialiser *rss = new RsSerialiser ;
|
||||
rss->addSerialType(new RsFileTransferSerialiser) ;
|
||||
|
||||
//rss->addSerialType(new RsGeneralConfigSerialiser());
|
||||
|
||||
return rss ;
|
||||
}
|
||||
|
||||
bool ftServer::saveList(bool &/*cleanup*/, std::list<RsItem *>& /*list*/)
|
||||
{
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ftServer::loadList(std::list<RsItem *>& /*load*/)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ftServer::loadConfigMap(std::map<std::string, std::string> &/*configMap*/)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//bool ftServer::loadConfigMap(std::map<std::string, std::string> &/*configMap*/)
|
||||
//{
|
||||
// return true;
|
||||
//}
|
||||
|
||||
/***************************************************************/
|
||||
/********************** Data Flow **********************/
|
||||
@ -1257,9 +1086,6 @@ int ftServer::tick()
|
||||
if(handleIncoming())
|
||||
moreToTick = true;
|
||||
|
||||
if(handleCacheData())
|
||||
moreToTick = true;
|
||||
|
||||
static time_t last_law_priority_tasks_handling_time = 0 ;
|
||||
time_t now = time(NULL) ;
|
||||
|
||||
@ -1275,45 +1101,6 @@ int ftServer::tick()
|
||||
return moreToTick;
|
||||
}
|
||||
|
||||
bool ftServer::handleCacheData()
|
||||
{
|
||||
std::list<std::pair<RsPeerId, RsCacheData> > cacheUpdates;
|
||||
std::list<std::pair<RsPeerId, RsCacheData> >::iterator it;
|
||||
int i=0 ;
|
||||
|
||||
#ifdef SERVER_DEBUG_CACHE
|
||||
std::cerr << "handleCacheData() " << std::endl;
|
||||
#endif
|
||||
mCacheStrapper->getCacheUpdates(cacheUpdates);
|
||||
for(it = cacheUpdates.begin(); it != cacheUpdates.end(); ++it)
|
||||
{
|
||||
/* construct reply */
|
||||
RsFileTransferCacheItem *ci = new RsFileTransferCacheItem();
|
||||
|
||||
/* id from incoming */
|
||||
ci -> PeerId(it->first);
|
||||
|
||||
ci -> file.hash = (it->second).hash;
|
||||
ci -> file.name = (it->second).name;
|
||||
ci -> file.path = ""; // (it->second).path;
|
||||
ci -> file.filesize = (it->second).size;
|
||||
ci -> cacheType = (it->second).cid.type;
|
||||
ci -> cacheSubId = (it->second).cid.subid;
|
||||
|
||||
#ifdef SERVER_DEBUG_CACHE
|
||||
std::string out2 = "Outgoing CacheStrapper Update -> RsCacheItem:\n";
|
||||
ci -> print_string(out2);
|
||||
std::cerr << out2 << std::endl;
|
||||
#endif
|
||||
|
||||
sendItem(ci);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return i>0 ;
|
||||
}
|
||||
|
||||
int ftServer::handleIncoming()
|
||||
{
|
||||
// now File Input.
|
||||
@ -1411,42 +1198,6 @@ int ftServer::handleIncoming()
|
||||
}
|
||||
}
|
||||
break ;
|
||||
|
||||
case RS_PKT_SUBTYPE_FT_CACHE_ITEM:
|
||||
{
|
||||
RsFileTransferCacheItem *ci = dynamic_cast<RsFileTransferCacheItem*>(item) ;
|
||||
if (ci)
|
||||
{
|
||||
#ifdef SERVER_DEBUG_CACHE
|
||||
std::cerr << "ftServer::handleIncoming: received cache item hash=" << ci->file.hash << ". from peer " << ci->PeerId() << std::endl;
|
||||
#endif
|
||||
/* these go to the CacheStrapper! */
|
||||
RsCacheData data;
|
||||
data.pid = ci->PeerId();
|
||||
data.cid = CacheId(ci->cacheType, ci->cacheSubId);
|
||||
data.path = ci->file.path;
|
||||
data.name = ci->file.name;
|
||||
data.hash = ci->file.hash;
|
||||
data.size = ci->file.filesize;
|
||||
data.recvd = time(NULL) ;
|
||||
|
||||
mCacheStrapper->recvCacheResponse(data, time(NULL));
|
||||
}
|
||||
}
|
||||
break ;
|
||||
|
||||
// case RS_PKT_SUBTYPE_FT_CACHE_REQUEST:
|
||||
// {
|
||||
// // do nothing
|
||||
// RsFileTransferCacheRequestItem *cr = dynamic_cast<RsFileTransferCacheRequestItem*>(item) ;
|
||||
// if (cr)
|
||||
// {
|
||||
//#ifdef SERVER_DEBUG_CACHE
|
||||
// std::cerr << "ftServer::handleIncoming: received cache request from peer " << cr->PeerId() << std::endl;
|
||||
//#endif
|
||||
// }
|
||||
// }
|
||||
// break ;
|
||||
}
|
||||
|
||||
delete item ;
|
||||
@ -1465,7 +1216,7 @@ int ftServer::handleIncoming()
|
||||
bool ftServer::addConfiguration(p3ConfigMgr *cfgmgr)
|
||||
{
|
||||
/* add all the subbits to config mgr */
|
||||
cfgmgr->addConfiguration("ft_shared.cfg", mFiMon);
|
||||
cfgmgr->addConfiguration("ft_database.cfg", mFileDatabase);
|
||||
cfgmgr->addConfiguration("ft_extra.cfg", mFtExtra);
|
||||
cfgmgr->addConfiguration("ft_transfers.cfg", mFtController);
|
||||
|
||||
|
@ -47,17 +47,13 @@
|
||||
#include "turtle/turtleclientservice.h"
|
||||
#include "services/p3service.h"
|
||||
#include "retroshare/rsfiles.h"
|
||||
//#include "dbase/cachestrapper.h"
|
||||
|
||||
#include "pqi/pqi.h"
|
||||
#include "pqi/p3cfgmgr.h"
|
||||
|
||||
class p3ConnectMgr;
|
||||
class p3FileDatabase;
|
||||
|
||||
class CacheStrapper;
|
||||
class CacheTransfer;
|
||||
|
||||
class ftCacheStrapper;
|
||||
class ftFiStore;
|
||||
class ftFiMonitor;
|
||||
|
||||
@ -70,6 +66,7 @@ class p3turtle;
|
||||
|
||||
class p3PeerMgr;
|
||||
class p3ServiceControl;
|
||||
class p3FileDatabase;
|
||||
|
||||
class ftServer: public p3Service, public RsFiles, public ftDataSend, public RsTurtleClientService
|
||||
{
|
||||
@ -89,18 +86,12 @@ class ftServer: public p3Service, public RsFiles, public ftDataSend, public RsTu
|
||||
/* add Config Items (Extra, Controller) */
|
||||
void addConfigComponents(p3ConfigMgr *mgr);
|
||||
|
||||
virtual CacheStrapper *getCacheStrapper();
|
||||
virtual CacheTransfer *getCacheTransfer();
|
||||
|
||||
const RsPeerId& OwnId();
|
||||
|
||||
/* Final Setup (once everything is assigned) */
|
||||
void SetupFtServer() ;
|
||||
virtual void connectToTurtleRouter(p3turtle *p) ;
|
||||
|
||||
// Checks that the given hash is well formed. Used to chase
|
||||
// string bugs.
|
||||
static bool checkHash(const RsFileHash& hash,std::string& error_string) ;
|
||||
virtual void connectToFileDatabase(p3FileDatabase *b);
|
||||
|
||||
// Implements RsTurtleClientService
|
||||
//
|
||||
@ -149,8 +140,6 @@ class ftServer: public p3Service, public RsFiles, public ftDataSend, public RsTu
|
||||
/***
|
||||
* Control of Downloads Priority.
|
||||
***/
|
||||
virtual uint32_t getMinPrioritizedTransfers() ;
|
||||
virtual void setMinPrioritizedTransfers(uint32_t s) ;
|
||||
virtual uint32_t getQueueSize() ;
|
||||
virtual void setQueueSize(uint32_t s) ;
|
||||
virtual bool changeQueuePosition(const RsFileHash& hash, QueueMove queue_mv);
|
||||
@ -184,12 +173,13 @@ class ftServer: public p3Service, public RsFiles, public ftDataSend, public RsTu
|
||||
***/
|
||||
virtual int RequestDirDetails(const RsPeerId& uid, const std::string& path, DirDetails &details);
|
||||
virtual int RequestDirDetails(void *ref, DirDetails &details, FileSearchFlags flags);
|
||||
virtual bool findChildPointer(void *ref, int row, void *& result, FileSearchFlags flags) ;
|
||||
virtual uint32_t getType(void *ref,FileSearchFlags flags) ;
|
||||
|
||||
virtual int SearchKeywords(std::list<std::string> keywords, std::list<DirDetails> &results,FileSearchFlags flags);
|
||||
virtual int SearchKeywords(std::list<std::string> keywords, std::list<DirDetails> &results,FileSearchFlags flags,const RsPeerId& peer_id);
|
||||
virtual int SearchBoolExp(Expression * exp, std::list<DirDetails> &results,FileSearchFlags flags);
|
||||
virtual int SearchBoolExp(Expression * exp, std::list<DirDetails> &results,FileSearchFlags flags,const RsPeerId& peer_id);
|
||||
virtual int SearchBoolExp(RsRegularExpression::Expression * exp, std::list<DirDetails> &results,FileSearchFlags flags);
|
||||
virtual int SearchBoolExp(RsRegularExpression::Expression * exp, std::list<DirDetails> &results,FileSearchFlags flags,const RsPeerId& peer_id);
|
||||
|
||||
/***
|
||||
* Utility Functions
|
||||
@ -203,6 +193,7 @@ class ftServer: public p3Service, public RsFiles, public ftDataSend, public RsTu
|
||||
/***
|
||||
* 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();
|
||||
@ -217,17 +208,10 @@ class ftServer: public p3Service, public RsFiles, public ftDataSend, public RsTu
|
||||
virtual bool getShareDownloadDirectory();
|
||||
virtual bool shareDownloadDirectory(bool share);
|
||||
|
||||
virtual void setRememberHashFilesDuration(uint32_t days) ;
|
||||
virtual uint32_t rememberHashFilesDuration() const ;
|
||||
virtual bool rememberHashFiles() const ;
|
||||
virtual void setRememberHashFiles(bool) ;
|
||||
virtual void clearHashCache() ;
|
||||
virtual void setWatchPeriod(int minutes) ;
|
||||
virtual int watchPeriod() const ;
|
||||
|
||||
/***************************************************************/
|
||||
/*************** Control Interface *****************************/
|
||||
/***************************************************************/
|
||||
virtual void setWatchEnabled(bool b) ;
|
||||
virtual bool watchEnabled() ;
|
||||
|
||||
/***************************************************************/
|
||||
/*************** Data Transfer Interface ***********************/
|
||||
@ -247,17 +231,6 @@ class ftServer: public p3Service, public RsFiles, public ftDataSend, public RsTu
|
||||
bool addConfiguration(p3ConfigMgr *cfgmgr);
|
||||
bool ResumeTransfers();
|
||||
|
||||
/******************* p3 Config Overload ************************/
|
||||
protected:
|
||||
/* Key Functions to be overloaded for Full Configuration */
|
||||
virtual RsSerialiser *setupSerialiser();
|
||||
virtual bool saveList(bool &cleanup, std::list<RsItem *>&);
|
||||
virtual bool loadList(std::list<RsItem *>& load);
|
||||
|
||||
private:
|
||||
bool loadConfigMap(std::map<std::string, std::string> &configMap);
|
||||
/******************* p3 Config Overload ************************/
|
||||
|
||||
/*************************** p3 Config Overload ********************/
|
||||
|
||||
protected:
|
||||
@ -277,17 +250,11 @@ class ftServer: public p3Service, public RsFiles, public ftDataSend, public RsTu
|
||||
*/
|
||||
p3PeerMgr *mPeerMgr;
|
||||
p3ServiceControl *mServiceCtrl;
|
||||
|
||||
ftCacheStrapper *mCacheStrapper;
|
||||
ftFiStore *mFiStore;
|
||||
ftFiMonitor *mFiMon;
|
||||
|
||||
p3FileDatabase *mFileDatabase ;
|
||||
ftController *mFtController;
|
||||
ftExtraList *mFtExtra;
|
||||
|
||||
ftDataMultiplex *mFtDataplex;
|
||||
p3turtle *mTurtleRouter ;
|
||||
|
||||
ftFileSearch *mFtSearch;
|
||||
|
||||
RsMutex srvMutex;
|
||||
|
@ -37,6 +37,28 @@ debug {
|
||||
QMAKE_CXXFLAGS *= -g -fno-omit-frame-pointer
|
||||
}
|
||||
|
||||
CONFIG += file_lists
|
||||
|
||||
file_lists {
|
||||
HEADERS *= file_sharing/p3filelists.h \
|
||||
file_sharing/hash_cache.h \
|
||||
file_sharing/filelist_io.h \
|
||||
file_sharing/directory_storage.h \
|
||||
file_sharing/directory_updater.h \
|
||||
file_sharing/rsfilelistitems.h \
|
||||
file_sharing/dir_hierarchy.h \
|
||||
file_sharing/file_sharing_defaults.h
|
||||
|
||||
SOURCES *= file_sharing/p3filelists.cc \
|
||||
file_sharing/hash_cache.cc \
|
||||
file_sharing/filelist_io.cc \
|
||||
file_sharing/directory_storage.cc \
|
||||
file_sharing/directory_updater.cc \
|
||||
file_sharing/dir_hierarchy.cc \
|
||||
file_sharing/rsfilelistitems.cc
|
||||
}
|
||||
|
||||
|
||||
dsdv {
|
||||
DEFINES *= SERVICES_DSDV
|
||||
HEADERS += services/p3dsdv.h \
|
||||
@ -345,16 +367,10 @@ INCLUDEPATH *= $${OPENPGPSDK_DIR}
|
||||
PRE_TARGETDEPS *= $${OPENPGPSDK_DIR}/lib/libops.a
|
||||
LIBS *= $${OPENPGPSDK_DIR}/lib/libops.a -lbz2
|
||||
|
||||
HEADERS += dbase/cachestrapper.h \
|
||||
dbase/fimonitor.h \
|
||||
dbase/findex.h \
|
||||
dbase/fistore.h
|
||||
|
||||
HEADERS += ft/ftchunkmap.h \
|
||||
ft/ftcontroller.h \
|
||||
ft/ftdata.h \
|
||||
ft/ftdatamultiplex.h \
|
||||
ft/ftdbase.h \
|
||||
ft/ftextralist.h \
|
||||
ft/ftfilecreator.h \
|
||||
ft/ftfileprovider.h \
|
||||
@ -364,6 +380,10 @@ HEADERS += ft/ftchunkmap.h \
|
||||
ft/fttransfermodule.h \
|
||||
ft/ftturtlefiletransferitem.h
|
||||
|
||||
HEADERS += directory_updater.h \
|
||||
directory_list.h \
|
||||
p3filelists.h
|
||||
|
||||
HEADERS += chat/distantchat.h \
|
||||
chat/p3chatservice.h \
|
||||
chat/distributedchat.h \
|
||||
@ -507,17 +527,9 @@ HEADERS += util/folderiterator.h \
|
||||
util/rsscopetimer.h \
|
||||
util/stacktrace.h
|
||||
|
||||
SOURCES += dbase/cachestrapper.cc \
|
||||
dbase/fimonitor.cc \
|
||||
dbase/findex.cc \
|
||||
dbase/fistore.cc \
|
||||
dbase/rsexpr.cc
|
||||
|
||||
|
||||
SOURCES += ft/ftchunkmap.cc \
|
||||
ft/ftcontroller.cc \
|
||||
ft/ftdatamultiplex.cc \
|
||||
ft/ftdbase.cc \
|
||||
ft/ftextralist.cc \
|
||||
ft/ftfilecreator.cc \
|
||||
ft/ftfileprovider.cc \
|
||||
@ -638,6 +650,7 @@ SOURCES += turtle/p3turtle.cc \
|
||||
|
||||
SOURCES += util/folderiterator.cc \
|
||||
util/rsdebug.cc \
|
||||
util/rsexpr.cc \
|
||||
util/rscompress.cc \
|
||||
util/smallobject.cc \
|
||||
util/rsdir.cc \
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include <util/rsversioninfo.h>
|
||||
#include <util/folderiterator.h>
|
||||
#include <ft/ftserver.h>
|
||||
#include <dbase/cachestrapper.h>
|
||||
#include <retroshare/rsplugin.h>
|
||||
#include <retroshare/rsfiles.h>
|
||||
#include <pqi/pqiservice.h>
|
||||
@ -146,7 +145,7 @@ void RsPluginManager::loadPlugins(const std::vector<std::string>& plugin_directo
|
||||
continue ;
|
||||
}
|
||||
|
||||
while(dirIt.readdir())
|
||||
for(;dirIt.isValid();dirIt.next())
|
||||
{
|
||||
std::string fname;
|
||||
dirIt.d_name(fname);
|
||||
@ -410,14 +409,17 @@ void RsPluginManager::slowTickPlugins(time_t seconds)
|
||||
|
||||
void RsPluginManager::registerCacheServices()
|
||||
{
|
||||
// this is removed since the old cache syste is gone, but we need to make it register new GXS group services instead.
|
||||
#ifdef REMOVED
|
||||
std::cerr << " Registering cache services." << std::endl;
|
||||
|
||||
for(uint32_t i=0;i<_plugins.size();++i)
|
||||
if(_plugins[i].plugin != NULL && _plugins[i].plugin->rs_cache_service() != NULL)
|
||||
{
|
||||
rsFiles->getCacheStrapper()->addCachePair(CachePair(_plugins[i].plugin->rs_cache_service(),_plugins[i].plugin->rs_cache_service(),CacheId(_plugins[i].plugin->rs_service_id(), 0))) ;
|
||||
//rsFiles->getCacheStrapper()->addCachePair(CachePair(_plugins[i].plugin->rs_cache_service(),_plugins[i].plugin->rs_cache_service(),CacheId(_plugins[i].plugin->rs_service_id(), 0))) ;
|
||||
std::cerr << " adding new cache pair for plugin " << _plugins[i].plugin->getPluginName() << ", with RS_ID " << _plugins[i].plugin->rs_service_id() << std::endl ;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void RsPluginManager::registerClientServices(p3ServiceServer *pqih)
|
||||
@ -546,14 +548,6 @@ bool RsPluginManager::saveList(bool& cleanup, std::list<RsItem*>& list)
|
||||
return true;
|
||||
}
|
||||
|
||||
// RsCacheService::RsCacheService(uint16_t service_type,uint32_t tick_delay, RsPluginHandler* pgHandler)
|
||||
// : CacheSource(service_type, true, pgHandler->getFileServer()->getCacheStrapper(), pgHandler->getLocalCacheDir()),
|
||||
// CacheStore (service_type, true, pgHandler->getFileServer()->getCacheStrapper(), pgHandler->getFileServer()->getCacheTransfer(), pgHandler->getRemoteCacheDir()),
|
||||
// p3Config(),
|
||||
// _tick_delay_in_seconds(tick_delay)
|
||||
// {
|
||||
// }
|
||||
|
||||
RsPQIService::RsPQIService(uint16_t /*service_type*/, uint32_t /*tick_delay_in_seconds*/, RsPluginHandler* /*pgHandler*/)
|
||||
: p3Service(),p3Config()
|
||||
{
|
||||
|
@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <dbase/cachestrapper.h>
|
||||
#include "plugins/pluginmanager.h"
|
||||
|
||||
// This code needs to be re-written to work with GXS. For now it is obsolete.
|
||||
@ -9,7 +8,7 @@
|
||||
// The following class abstracts the construction of a cache service. The user only has to
|
||||
// supply RS with a type ID. If the ID is already in use, RS will complain.
|
||||
//
|
||||
class RsCacheService: public CacheSource, public CacheStore, public p3Config
|
||||
class RsCacheService: /* public CacheSource, public CacheStore, */ public p3Config
|
||||
{
|
||||
public:
|
||||
RsCacheService(uint16_t type,uint32_t tick_delay_in_seconds, RsPluginHandler* pgHandler) ;
|
||||
|
@ -1,6 +1,3 @@
|
||||
#ifndef RS_EXPRESSIONS_H
|
||||
#define RS_EXPRESSIONS_H
|
||||
|
||||
/*
|
||||
* rs-core/src/rsiface: rsexpr.h
|
||||
*
|
||||
@ -26,16 +23,19 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <stdint.h>
|
||||
#include "retroshare/rstypes.h"
|
||||
|
||||
/******************************************************************************************
|
||||
Enumerations defining the Operators usable in the Boolean search expressions
|
||||
******************************************************************************************/
|
||||
|
||||
|
||||
namespace RsRegularExpression
|
||||
{
|
||||
enum LogicalOperator{
|
||||
AndOp=0, /* exp AND exp */
|
||||
OrOp=1, /* exp OR exp */
|
||||
@ -50,7 +50,7 @@ enum StringOperator{
|
||||
EqualsString = 2 /* exactly equal*/
|
||||
};
|
||||
|
||||
/*Relational operators ( >, <, >=, <=, == and InRange )*/
|
||||
/* Comparison operators ( >, <, >=, <=, == and InRange ) */
|
||||
enum RelOperator{
|
||||
Equals = 0,
|
||||
GreaterEquals = 1,
|
||||
@ -105,25 +105,37 @@ classes:
|
||||
|
||||
******************************************************************************************/
|
||||
|
||||
class FileEntry;
|
||||
/*!
|
||||
* \brief The ExpFileEntry class
|
||||
* This is the base class the regular expressions can operate on. Derive it to fit your own needs!
|
||||
*/
|
||||
class ExpFileEntry
|
||||
{
|
||||
public:
|
||||
virtual const std::string& file_name() const =0;
|
||||
virtual uint64_t file_size() const =0;
|
||||
virtual time_t file_modtime() const =0;
|
||||
virtual uint32_t file_popularity() const =0;
|
||||
virtual std::string file_parent_path() const =0;
|
||||
virtual const RsFileHash& file_hash() const =0;
|
||||
};
|
||||
|
||||
class Expression
|
||||
{
|
||||
public:
|
||||
virtual bool eval (FileEntry *file) = 0;
|
||||
virtual bool eval (const ExpFileEntry& file) = 0;
|
||||
virtual ~Expression() {};
|
||||
|
||||
virtual void linearize(LinearizedExpression& e) const = 0 ;
|
||||
};
|
||||
|
||||
|
||||
class CompoundExpression : public Expression
|
||||
{
|
||||
public:
|
||||
CompoundExpression( enum LogicalOperator op, Expression * exp1, Expression *exp2)
|
||||
: Lexp(exp1), Rexp(exp2), Op(op){ }
|
||||
|
||||
bool eval (FileEntry *file) {
|
||||
bool eval (const ExpFileEntry& file) {
|
||||
if (Lexp == NULL or Rexp == NULL) {
|
||||
return false;
|
||||
}
|
||||
@ -231,7 +243,7 @@ class NameExpression: public StringExpression
|
||||
public:
|
||||
NameExpression(enum StringOperator op, std::list<std::string> &t, bool ic):
|
||||
StringExpression(op,t,ic) {}
|
||||
bool eval(FileEntry *file);
|
||||
bool eval(const ExpFileEntry& file);
|
||||
|
||||
virtual void linearize(LinearizedExpression& e) const
|
||||
{
|
||||
@ -244,7 +256,7 @@ class PathExpression: public StringExpression {
|
||||
public:
|
||||
PathExpression(enum StringOperator op, std::list<std::string> &t, bool ic):
|
||||
StringExpression(op,t,ic) {}
|
||||
bool eval(FileEntry *file);
|
||||
bool eval(const ExpFileEntry& file);
|
||||
|
||||
virtual void linearize(LinearizedExpression& e) const
|
||||
{
|
||||
@ -257,7 +269,7 @@ class ExtExpression: public StringExpression {
|
||||
public:
|
||||
ExtExpression(enum StringOperator op, std::list<std::string> &t, bool ic):
|
||||
StringExpression(op,t,ic) {}
|
||||
bool eval(FileEntry *file);
|
||||
bool eval(const ExpFileEntry& file);
|
||||
|
||||
virtual void linearize(LinearizedExpression& e) const
|
||||
{
|
||||
@ -270,7 +282,7 @@ class HashExpression: public StringExpression {
|
||||
public:
|
||||
HashExpression(enum StringOperator op, std::list<std::string> &t):
|
||||
StringExpression(op,t, true) {}
|
||||
bool eval(FileEntry *file);
|
||||
bool eval(const ExpFileEntry& file);
|
||||
|
||||
virtual void linearize(LinearizedExpression& e) const
|
||||
{
|
||||
@ -290,7 +302,7 @@ class DateExpression: public RelExpression<int>
|
||||
DateExpression(enum RelOperator op, int v): RelExpression<int>(op,v,v){}
|
||||
DateExpression(enum RelOperator op, int lv, int hv):
|
||||
RelExpression<int>(op,lv,hv) {}
|
||||
bool eval(FileEntry *file);
|
||||
bool eval(const ExpFileEntry& file);
|
||||
|
||||
virtual void linearize(LinearizedExpression& e) const
|
||||
{
|
||||
@ -305,7 +317,7 @@ class SizeExpression: public RelExpression<int>
|
||||
SizeExpression(enum RelOperator op, int v): RelExpression<int>(op,v,v){}
|
||||
SizeExpression(enum RelOperator op, int lv, int hv):
|
||||
RelExpression<int>(op,lv,hv) {}
|
||||
bool eval(FileEntry *file);
|
||||
bool eval(const ExpFileEntry& file);
|
||||
|
||||
virtual void linearize(LinearizedExpression& e) const
|
||||
{
|
||||
@ -320,7 +332,7 @@ class SizeExpressionMB: public RelExpression<int>
|
||||
SizeExpressionMB(enum RelOperator op, int v): RelExpression<int>(op,v,v){}
|
||||
SizeExpressionMB(enum RelOperator op, int lv, int hv):
|
||||
RelExpression<int>(op,lv,hv) {}
|
||||
bool eval(FileEntry *file);
|
||||
bool eval(const ExpFileEntry& file);
|
||||
|
||||
virtual void linearize(LinearizedExpression& e) const
|
||||
{
|
||||
@ -334,7 +346,7 @@ class PopExpression: public RelExpression<int>
|
||||
PopExpression(enum RelOperator op, int v): RelExpression<int>(op,v,v){}
|
||||
PopExpression(enum RelOperator op, int lv, int hv): RelExpression<int>(op,lv,hv) {}
|
||||
PopExpression(const LinearizedExpression& e) ;
|
||||
bool eval(FileEntry *file);
|
||||
bool eval(const ExpFileEntry& file);
|
||||
|
||||
virtual void linearize(LinearizedExpression& e) const
|
||||
{
|
||||
@ -342,6 +354,6 @@ class PopExpression: public RelExpression<int>
|
||||
RelExpression<int>::linearize(e) ;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* RS_EXPRESSIONS_H */
|
||||
|
||||
|
@ -36,9 +36,7 @@
|
||||
class RsFiles;
|
||||
extern RsFiles *rsFiles;
|
||||
|
||||
class Expression;
|
||||
class CacheStrapper ;
|
||||
class CacheTransfer;
|
||||
namespace RsRegularExpression { class Expression; }
|
||||
|
||||
/* These are used mainly by ftController at the moment */
|
||||
const uint32_t RS_FILE_CTRL_PAUSE = 0x00000100;
|
||||
@ -65,7 +63,7 @@ const uint32_t RS_FILE_PEER_OFFLINE = 0x00002000;
|
||||
|
||||
// Flags used when requesting info about transfers, mostly to filter out the result.
|
||||
//
|
||||
const FileSearchFlags RS_FILE_HINTS_CACHE ( 0x00000001 );
|
||||
const FileSearchFlags RS_FILE_HINTS_CACHE_deprecated ( 0x00000001 );
|
||||
const FileSearchFlags RS_FILE_HINTS_EXTRA ( 0x00000002 );
|
||||
const FileSearchFlags RS_FILE_HINTS_LOCAL ( 0x00000004 );
|
||||
const FileSearchFlags RS_FILE_HINTS_REMOTE ( 0x00000008 );
|
||||
@ -81,7 +79,7 @@ const FileSearchFlags RS_FILE_HINTS_PERMISSION_MASK ( 0x00000180 );// OR
|
||||
//
|
||||
const TransferRequestFlags RS_FILE_REQ_ANONYMOUS_ROUTING ( 0x00000040 ); // Use to ask turtle router to download the file.
|
||||
const TransferRequestFlags RS_FILE_REQ_ASSUME_AVAILABILITY ( 0x00000200 ); // Assume full source availability. Used for cache files.
|
||||
const TransferRequestFlags RS_FILE_REQ_CACHE ( 0x00000400 ); // Assume full source availability. Used for cache files.
|
||||
const TransferRequestFlags RS_FILE_REQ_CACHE_deprecated ( 0x00000400 ); // Assume full source availability. Used for cache files.
|
||||
const TransferRequestFlags RS_FILE_REQ_EXTRA ( 0x00000800 );
|
||||
const TransferRequestFlags RS_FILE_REQ_MEDIA ( 0x00001000 );
|
||||
const TransferRequestFlags RS_FILE_REQ_BACKGROUND ( 0x00002000 ); // To download slowly.
|
||||
@ -147,8 +145,6 @@ class RsFiles
|
||||
/***
|
||||
* Control of Downloads Priority.
|
||||
***/
|
||||
virtual uint32_t getMinPrioritizedTransfers() = 0 ;
|
||||
virtual void setMinPrioritizedTransfers(uint32_t s) = 0 ;
|
||||
virtual uint32_t getQueueSize() = 0 ;
|
||||
virtual void setQueueSize(uint32_t s) = 0 ;
|
||||
virtual bool changeQueuePosition(const RsFileHash& hash, QueueMove mv) = 0;
|
||||
@ -186,12 +182,13 @@ class RsFiles
|
||||
*/
|
||||
virtual int RequestDirDetails(const RsPeerId& uid, const std::string& path, DirDetails &details) = 0;
|
||||
virtual int RequestDirDetails(void *ref, DirDetails &details, FileSearchFlags flags) = 0;
|
||||
virtual bool findChildPointer(void *ref, int row, void *& result, FileSearchFlags flags) =0;
|
||||
virtual uint32_t getType(void *ref,FileSearchFlags flags) = 0;
|
||||
|
||||
virtual int SearchKeywords(std::list<std::string> keywords, std::list<DirDetails> &results,FileSearchFlags flags) = 0;
|
||||
virtual int SearchKeywords(std::list<std::string> keywords, std::list<DirDetails> &results,FileSearchFlags flags,const RsPeerId& peer_id) = 0;
|
||||
virtual int SearchBoolExp(Expression * exp, std::list<DirDetails> &results,FileSearchFlags flags) = 0;
|
||||
virtual int SearchBoolExp(Expression * exp, std::list<DirDetails> &results,FileSearchFlags flags,const RsPeerId& peer_id) = 0;
|
||||
virtual int SearchBoolExp(RsRegularExpression::Expression * exp, std::list<DirDetails> &results,FileSearchFlags flags) = 0;
|
||||
virtual int SearchBoolExp(RsRegularExpression::Expression * exp, std::list<DirDetails> &results,FileSearchFlags flags,const RsPeerId& peer_id) = 0;
|
||||
|
||||
/***
|
||||
* Utility Functions.
|
||||
@ -205,6 +202,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;
|
||||
@ -214,16 +213,11 @@ class RsFiles
|
||||
virtual bool addSharedDirectory(const SharedDirInfo& dir) = 0;
|
||||
virtual bool updateShareFlags(const SharedDirInfo& dir) = 0; // updates the flags. The directory should already exist !
|
||||
virtual bool removeSharedDirectory(std::string dir) = 0;
|
||||
virtual void setRememberHashFilesDuration(uint32_t days) = 0 ;
|
||||
virtual uint32_t rememberHashFilesDuration() const = 0 ;
|
||||
virtual void clearHashCache() = 0 ;
|
||||
virtual bool rememberHashFiles() const =0;
|
||||
virtual void setRememberHashFiles(bool) =0;
|
||||
virtual void setWatchPeriod(int minutes) =0;
|
||||
virtual int watchPeriod() const =0;
|
||||
|
||||
virtual CacheStrapper *getCacheStrapper() =0;
|
||||
virtual CacheTransfer *getCacheTransfer() =0;
|
||||
virtual void setWatchPeriod(int minutes) =0;
|
||||
virtual void setWatchEnabled(bool b) =0;
|
||||
virtual int watchPeriod() const =0;
|
||||
virtual bool watchEnabled() =0;
|
||||
|
||||
virtual bool getShareDownloadDirectory() = 0;
|
||||
virtual bool shareDownloadDirectory(bool share) = 0;
|
||||
|
@ -35,7 +35,7 @@
|
||||
|
||||
#include "retroshare/rstypes.h"
|
||||
|
||||
class LinearizedExpression ;
|
||||
namespace RsRegularExpression { class LinearizedExpression ; }
|
||||
class RsTurtleClientService ;
|
||||
|
||||
class RsTurtle;
|
||||
@ -102,7 +102,7 @@ class RsTurtle
|
||||
// as they come back.
|
||||
//
|
||||
virtual TurtleRequestId turtleSearch(const std::string& match_string) = 0 ;
|
||||
virtual TurtleRequestId turtleSearch(const LinearizedExpression& expr) = 0 ;
|
||||
virtual TurtleRequestId turtleSearch(const RsRegularExpression::LinearizedExpression& expr) = 0 ;
|
||||
|
||||
// Initiates tunnel handling for the given file hash. tunnels. Launches
|
||||
// an exception if an error occurs during the initialization process. The
|
||||
|
@ -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
|
||||
@ -216,7 +217,6 @@ class FileInfo
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const FileInfo& info);
|
||||
|
||||
|
||||
class DirStub
|
||||
{
|
||||
public:
|
||||
@ -236,16 +236,18 @@ class DirDetails
|
||||
RsPeerId id;
|
||||
std::string name;
|
||||
RsFileHash hash;
|
||||
std::string path;
|
||||
std::string path; // full path of the parent directory, when it is a file; full path of the dir otherwise.
|
||||
uint64_t count;
|
||||
uint32_t age;
|
||||
FileStorageFlags flags;
|
||||
uint32_t min_age ; // minimum age of files in this subtree
|
||||
|
||||
std::list<DirStub> children;
|
||||
std::vector<DirStub> children;
|
||||
std::list<RsNodeGroupId> parent_groups; // parent groups for the shared directory
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const DirDetails& details);
|
||||
|
||||
class FileDetail
|
||||
{
|
||||
public:
|
||||
|
@ -533,7 +533,7 @@ bool RsAccountsDetail::getAvailableAccounts(std::map<RsPeerId, AccountDetails> &
|
||||
|
||||
struct stat64 buf;
|
||||
|
||||
while (dirIt.readdir())
|
||||
for(;dirIt.isValid();dirIt.next())
|
||||
{
|
||||
/* check entry type */
|
||||
std::string fname;
|
||||
|
@ -56,7 +56,8 @@
|
||||
#include <openssl/rand.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <gxstunnel/p3gxstunnel.h>
|
||||
#include "gxstunnel/p3gxstunnel.h"
|
||||
#include "file_sharing/p3filelists.h"
|
||||
|
||||
#define ENABLE_GROUTER
|
||||
|
||||
@ -804,7 +805,6 @@ bool RsInit::SetHiddenLocation(const std::string& hiddenaddress, uint16_t port)
|
||||
#include <unistd.h>
|
||||
//#include <getopt.h>
|
||||
|
||||
#include "dbase/cachestrapper.h"
|
||||
#include "ft/ftserver.h"
|
||||
#include "ft/ftcontroller.h"
|
||||
|
||||
@ -1243,8 +1243,6 @@ int RsServer::StartupRetroShare()
|
||||
ftserver->setConfigDirectory(rsAccounts->PathAccountDirectory());
|
||||
|
||||
ftserver->SetupFtServer() ;
|
||||
CacheStrapper *mCacheStrapper = ftserver->getCacheStrapper();
|
||||
//CacheTransfer *mCacheTransfer = ftserver->getCacheTransfer();
|
||||
|
||||
/* setup any extra bits (Default Paths) */
|
||||
ftserver->setPartialsDirectory(emergencyPartialsDir);
|
||||
@ -1288,7 +1286,6 @@ int RsServer::StartupRetroShare()
|
||||
// These are needed to load plugins: plugin devs might want to know the place of
|
||||
// cache directories, get pointers to cache strapper, or access ownId()
|
||||
//
|
||||
mPluginsManager->setCacheDirectories(localcachedir,remotecachedir) ;
|
||||
mPluginsManager->setServiceControl(serviceCtrl) ;
|
||||
|
||||
// std::cerr << "rsinitconf (core 1) = " << (void*)rsInitConfig<<std::endl;
|
||||
@ -1499,9 +1496,11 @@ int RsServer::StartupRetroShare()
|
||||
pqih->addService(gr,true) ;
|
||||
#endif
|
||||
|
||||
p3FileDatabase *fdb = new p3FileDatabase(serviceCtrl) ;
|
||||
p3turtle *tr = new p3turtle(serviceCtrl,mLinkMgr) ;
|
||||
rsTurtle = tr ;
|
||||
pqih -> addService(tr,true);
|
||||
pqih -> addService(fdb,true);
|
||||
pqih -> addService(ftserver,true);
|
||||
|
||||
mGxsTunnels = new p3GxsTunnelService(mGxsIdService) ;
|
||||
@ -1514,6 +1513,7 @@ int RsServer::StartupRetroShare()
|
||||
// connect components to turtle router.
|
||||
|
||||
ftserver->connectToTurtleRouter(tr) ;
|
||||
ftserver->connectToFileDatabase(fdb) ;
|
||||
chatSrv->connectToGxsTunnelService(mGxsTunnels) ;
|
||||
gr->connectToTurtleRouter(tr) ;
|
||||
#ifdef ENABLE_GROUTER
|
||||
@ -1619,10 +1619,6 @@ int RsServer::StartupRetroShare()
|
||||
mLinkMgr->addMonitor(serviceCtrl);
|
||||
mLinkMgr->addMonitor(serviceInfo);
|
||||
|
||||
// NOTE these were added in ftServer (was added twice).
|
||||
//mLinkMgr->addMonitor(mCacheStrapper);
|
||||
//mLinkMgr->addMonitor(((ftController *) mCacheTransfer));
|
||||
|
||||
// Services that have been changed to pqiServiceMonitor
|
||||
serviceCtrl->registerServiceMonitor(msgSrv, msgSrv->getServiceInfo().mServiceType);
|
||||
serviceCtrl->registerServiceMonitor(mDisc, mDisc->getServiceInfo().mServiceType);
|
||||
@ -1678,12 +1674,6 @@ int RsServer::StartupRetroShare()
|
||||
/**************************************************************************/
|
||||
std::cerr << "(2) Load configuration files" << std::endl;
|
||||
|
||||
/* NOTE: CacheStrapper's load causes Cache Files to be
|
||||
* loaded into all the CacheStores/Sources. This happens
|
||||
* after all the other configurations have happened.
|
||||
*/
|
||||
|
||||
mConfigMgr->addConfiguration("cache.cfg", mCacheStrapper);
|
||||
mConfigMgr->loadConfiguration();
|
||||
|
||||
/**************************************************************************/
|
||||
|
@ -44,7 +44,26 @@
|
||||
*
|
||||
**********************************************************************/
|
||||
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const DirDetails& d)
|
||||
{
|
||||
std::cerr << "====DIR DETAILS====" << std::endl;
|
||||
std::cerr << " parent pointer: " << d.parent << std::endl;
|
||||
std::cerr << " current pointer: " << d.ref << std::endl;
|
||||
std::cerr << " parent row : " << d.prow << std::endl;
|
||||
std::cerr << " type : " << (int)d.type << std::endl;
|
||||
std::cerr << " PeerId : " << d.id << std::endl;
|
||||
std::cerr << " Name : " << d.name << std::endl;
|
||||
std::cerr << " Hash : " << d.hash << std::endl;
|
||||
std::cerr << " Path : " << d.path << std::endl;
|
||||
std::cerr << " Count : " << d.count << std::endl;
|
||||
std::cerr << " Age : " << d.age << std::endl;
|
||||
std::cerr << " Min age : " << d.min_age << std::endl;
|
||||
std::cerr << " Flags : " << d.flags << std::endl;
|
||||
std::cerr << " Parent groups : " ; for(std::list<RsNodeGroupId>::const_iterator it(d.parent_groups.begin());it!=d.parent_groups.end();++it) std::cerr << (*it) << " "; std::cerr << std::endl;
|
||||
std::cerr << " Children : " ; for(uint32_t i=0;i<d.children.size();++i) std::cerr << (void*)(intptr_t)d.children[i].ref << " "; std::cerr << std::endl;
|
||||
std::cerr << "===================" << std::endl;
|
||||
return out;
|
||||
}
|
||||
std::ostream &operator<<(std::ostream &out, const FileInfo &info)
|
||||
{
|
||||
out << "FileInfo: path: " << info.path;
|
||||
|
@ -76,6 +76,11 @@ const uint8_t QOS_PRIORITY_RS_DISC_PGP_LIST = 2 ; // same priority.
|
||||
const uint8_t QOS_PRIORITY_RS_DISC_SERVICES = 2 ;
|
||||
const uint8_t QOS_PRIORITY_RS_DISC_PGP_CERT = 1 ;
|
||||
|
||||
// File database
|
||||
//
|
||||
const uint8_t QOS_PRIORITY_RS_FAST_SYNC_REQUEST = 7 ;
|
||||
const uint8_t QOS_PRIORITY_RS_SLOW_SYNC_REQUEST = 3 ;
|
||||
|
||||
// Heartbeat.
|
||||
//
|
||||
const uint8_t QOS_PRIORITY_RS_HEARTBEAT_PULSE = 8 ;
|
||||
|
@ -231,6 +231,9 @@ uint32_t getRawStringSize(const std::string &outStr)
|
||||
|
||||
bool getRawString(void *data, uint32_t size, uint32_t *offset, std::string &outStr)
|
||||
{
|
||||
#warning I had to change this. It seems like a bug to not clear the string. Should make sure it's not introducing any side effect.
|
||||
outStr.clear();
|
||||
|
||||
uint32_t len = 0;
|
||||
if (!getRawUInt32(data, size, offset, &len))
|
||||
{
|
||||
|
@ -49,6 +49,7 @@ const uint16_t RS_SERVICE_TYPE_TUNNEL = 0x0015;
|
||||
const uint16_t RS_SERVICE_TYPE_HEARTBEAT = 0x0016;
|
||||
const uint16_t RS_SERVICE_TYPE_FILE_TRANSFER = 0x0017;
|
||||
const uint16_t RS_SERVICE_TYPE_GROUTER = 0x0018;
|
||||
const uint16_t RS_SERVICE_TYPE_FILE_DATABASE = 0x0019;
|
||||
|
||||
const uint16_t RS_SERVICE_TYPE_SERVICEINFO = 0x0020;
|
||||
/* Bandwidth Control */
|
||||
|
@ -1763,7 +1763,7 @@ void RsTurtleRegExpSearchRequestItem::performLocalSearch(std::list<TurtleFileInf
|
||||
std::list<DirDetails> initialResults;
|
||||
|
||||
// to do: split search string into words.
|
||||
Expression *exp = LinearizedExpression::toExpr(expr) ;
|
||||
RsRegularExpression::Expression *exp = RsRegularExpression::LinearizedExpression::toExpr(expr) ;
|
||||
|
||||
if(exp == NULL)
|
||||
return ;
|
||||
@ -1820,7 +1820,7 @@ TurtleRequestId p3turtle::turtleSearch(const std::string& string_to_match)
|
||||
|
||||
return id ;
|
||||
}
|
||||
TurtleRequestId p3turtle::turtleSearch(const LinearizedExpression& expr)
|
||||
TurtleRequestId p3turtle::turtleSearch(const RsRegularExpression::LinearizedExpression& expr)
|
||||
{
|
||||
// generate a new search id.
|
||||
|
||||
|
@ -239,7 +239,7 @@ class p3turtle: public p3Service, public RsTurtle, public p3Config
|
||||
// remove the specific file search packets from the turtle router.
|
||||
//
|
||||
virtual TurtleSearchRequestId turtleSearch(const std::string& string_to_match) ;
|
||||
virtual TurtleSearchRequestId turtleSearch(const LinearizedExpression& expr) ;
|
||||
virtual TurtleSearchRequestId turtleSearch(const RsRegularExpression::LinearizedExpression& expr) ;
|
||||
|
||||
// Initiates tunnel handling for the given file hash. tunnels. Launches
|
||||
// an exception if an error occurs during the initialization process. The
|
||||
|
@ -102,7 +102,7 @@ class RsTurtleRegExpSearchRequestItem: public RsTurtleSearchRequestItem
|
||||
RsTurtleRegExpSearchRequestItem() : RsTurtleSearchRequestItem(RS_TURTLE_SUBTYPE_REGEXP_SEARCH_REQUEST) {}
|
||||
RsTurtleRegExpSearchRequestItem(void *data,uint32_t size) ;
|
||||
|
||||
LinearizedExpression expr ; // Reg Exp in linearised mode
|
||||
RsRegularExpression::LinearizedExpression expr ; // Reg Exp in linearised mode
|
||||
|
||||
virtual RsTurtleSearchRequestItem *clone() const { return new RsTurtleRegExpSearchRequestItem(*this) ; }
|
||||
virtual void performLocalSearch(std::list<TurtleFileInfo>&) const ;
|
||||
|
@ -1,12 +1,39 @@
|
||||
#include <dirent.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef WINDOWS_SYS
|
||||
#include "util/rswin.h"
|
||||
#endif
|
||||
|
||||
#include "folderiterator.h"
|
||||
#include "rsstring.h"
|
||||
|
||||
|
||||
namespace librs { namespace util {
|
||||
|
||||
|
||||
FolderIterator::FolderIterator(const std::string& folderName)
|
||||
: mFolderName(folderName)
|
||||
{
|
||||
// Grab the last modification time for the directory
|
||||
|
||||
struct stat64 buf ;
|
||||
|
||||
#ifdef WINDOWS_SYS
|
||||
std::wstring wfullname;
|
||||
librs::util::ConvertUtf8ToUtf16(folderName, wfullname);
|
||||
if ( 0 == _wstati64(wfullname.c_str(), &buf))
|
||||
#else
|
||||
if ( 0 == stat64(folderName.c_str(), &buf))
|
||||
#endif
|
||||
{
|
||||
mFolderModTime = buf.st_mtime ;
|
||||
}
|
||||
|
||||
// Now open directory content and read the first entry
|
||||
|
||||
#ifdef WINDOWS_SYS
|
||||
std::wstring utf16Name;
|
||||
if(! ConvertUtf8ToUtf16(folderName, utf16Name)) {
|
||||
@ -17,11 +44,11 @@ FolderIterator::FolderIterator(const std::string& folderName)
|
||||
utf16Name += L"/*.*";
|
||||
|
||||
handle = FindFirstFileW(utf16Name.c_str(), &fileInfo);
|
||||
validity = handle != INVALID_HANDLE_VALUE;
|
||||
isFirstCall = true;
|
||||
is_open = validity = handle != INVALID_HANDLE_VALUE;
|
||||
#else
|
||||
handle = opendir(folderName.c_str());
|
||||
validity = handle != NULL;
|
||||
is_open = validity = handle != NULL;
|
||||
next();
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -30,19 +57,71 @@ FolderIterator::~FolderIterator()
|
||||
closedir();
|
||||
}
|
||||
|
||||
bool FolderIterator::readdir() {
|
||||
void FolderIterator::next()
|
||||
{
|
||||
do {
|
||||
if(!readdir())
|
||||
{
|
||||
validity = false ;
|
||||
break ;
|
||||
}
|
||||
|
||||
d_name(mFileName);
|
||||
} while(mFileName == "." || mFileName == "..") ;
|
||||
|
||||
mFullPath = mFolderName + "/" + mFileName ;
|
||||
|
||||
struct stat64 buf ;
|
||||
|
||||
#ifdef WINDOWS_SYS
|
||||
std::wstring wfullname;
|
||||
librs::util::ConvertUtf8ToUtf16(mFullPath, wfullname);
|
||||
if ( 0 == _wstati64(wfullname.c_str(), &buf))
|
||||
#else
|
||||
if ( 0 == stat64(mFullPath.c_str(), &buf))
|
||||
#endif
|
||||
{
|
||||
mFileModTime = buf.st_mtime ;
|
||||
mStatInfoOk = true;
|
||||
|
||||
if (S_ISDIR(buf.st_mode))
|
||||
{
|
||||
mType = TYPE_DIR ;
|
||||
mFileSize = 0 ;
|
||||
mFileModTime = buf.st_mtime;
|
||||
}
|
||||
else if (S_ISREG(buf.st_mode))
|
||||
{
|
||||
mType = TYPE_FILE ;
|
||||
mFileSize = buf.st_size;
|
||||
mFileModTime = buf.st_mtime;
|
||||
}
|
||||
else
|
||||
{
|
||||
mType = TYPE_UNKNOWN ;
|
||||
mFileSize = 0 ;
|
||||
mFileModTime = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mType = TYPE_UNKNOWN ;
|
||||
mFileSize = 0 ;
|
||||
mFileModTime = 0;
|
||||
validity = false ;
|
||||
}
|
||||
}
|
||||
|
||||
bool FolderIterator::readdir()
|
||||
{
|
||||
if(!validity)
|
||||
return false;
|
||||
|
||||
#ifdef WINDOWS_SYS
|
||||
if(isFirstCall) {
|
||||
isFirstCall = false;
|
||||
return true;
|
||||
}
|
||||
return FindNextFileW(handle, &fileInfo) != 0;
|
||||
#else
|
||||
ent = ::readdir(handle);
|
||||
return ent != 0;
|
||||
return ent != NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -65,13 +144,23 @@ bool FolderIterator::d_name(std::string& dest)
|
||||
return true;
|
||||
}
|
||||
|
||||
time_t FolderIterator::dir_modtime() const { return mFolderModTime ; }
|
||||
|
||||
const std::string& FolderIterator::file_fullpath() { return mFullPath ; }
|
||||
const std::string& FolderIterator::file_name() { return mFileName ; }
|
||||
uint64_t FolderIterator::file_size() { return mFileSize ; }
|
||||
time_t FolderIterator::file_modtime() { return mFileModTime ; }
|
||||
uint8_t FolderIterator::file_type() { return mType ; }
|
||||
|
||||
bool FolderIterator::closedir()
|
||||
{
|
||||
if(!validity)
|
||||
return false;
|
||||
|
||||
validity = false;
|
||||
|
||||
if(!is_open)
|
||||
return true ;
|
||||
|
||||
is_open = false ;
|
||||
|
||||
#ifdef WINDOWS_SYS
|
||||
return FindClose(handle) != 0;
|
||||
#else
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define FOLDERITERATOR_H
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <iostream>
|
||||
#include <cstdio>
|
||||
|
||||
@ -24,15 +25,32 @@ public:
|
||||
FolderIterator(const std::string& folderName);
|
||||
~FolderIterator();
|
||||
|
||||
enum { TYPE_UNKNOWN = 0x00,
|
||||
TYPE_FILE = 0x01,
|
||||
TYPE_DIR = 0x02
|
||||
};
|
||||
|
||||
// info about current parent directory
|
||||
time_t dir_modtime() const ;
|
||||
|
||||
// info about directory content
|
||||
|
||||
bool isValid() const { return validity; }
|
||||
|
||||
bool readdir();
|
||||
void next();
|
||||
|
||||
#warning this one should go, as it reports the same information than file_name()
|
||||
bool d_name(std::string& dest);
|
||||
|
||||
bool closedir();
|
||||
|
||||
const std::string& file_name() ;
|
||||
const std::string& file_fullpath() ;
|
||||
uint64_t file_size() ;
|
||||
uint8_t file_type() ;
|
||||
time_t file_modtime() ;
|
||||
|
||||
private:
|
||||
bool is_open;
|
||||
bool validity;
|
||||
|
||||
#ifdef WINDOWS_SYS
|
||||
@ -43,7 +61,16 @@ private:
|
||||
DIR* handle;
|
||||
struct dirent* ent;
|
||||
#endif
|
||||
void updateStatsInfo() ;
|
||||
|
||||
bool mStatInfoOk ;
|
||||
time_t mFileModTime ;
|
||||
time_t mFolderModTime ;
|
||||
uint64_t mFileSize ;
|
||||
uint8_t mType ;
|
||||
std::string mFileName ;
|
||||
std::string mFullPath ;
|
||||
std::string mFolderName ;
|
||||
};
|
||||
|
||||
|
||||
|
287
libretroshare/src/util/rsexpr.cc
Normal file
287
libretroshare/src/util/rsexpr.cc
Normal file
@ -0,0 +1,287 @@
|
||||
/*
|
||||
* rs-core/src/dbase: rsexpr.cc
|
||||
*
|
||||
* RetroShare C++ Interface.
|
||||
*
|
||||
* Copyright 2007-2008 by Kashif Kaleem.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare@lunamutt.com".
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "retroshare/rsexpr.h"
|
||||
#include "retroshare/rstypes.h"
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
/******************************************************************************************
|
||||
eval functions of relational expressions.
|
||||
|
||||
******************************************************************************************/
|
||||
|
||||
namespace RsRegularExpression
|
||||
{
|
||||
template<>
|
||||
void RelExpression<int>::linearize(LinearizedExpression& e) const
|
||||
{
|
||||
e._ints.push_back(Op) ;
|
||||
e._ints.push_back(LowerValue) ;
|
||||
e._ints.push_back(HigherValue) ;
|
||||
}
|
||||
|
||||
|
||||
bool DateExpression::eval(const ExpFileEntry& file)
|
||||
{
|
||||
return evalRel(file.file_modtime());
|
||||
}
|
||||
|
||||
bool SizeExpressionMB::eval(const ExpFileEntry& file)
|
||||
{
|
||||
return evalRel((int)(file.file_size()/(uint64_t)(1024*1024)));
|
||||
}
|
||||
|
||||
bool SizeExpression::eval(const ExpFileEntry& file)
|
||||
{
|
||||
return evalRel(file.file_size());
|
||||
}
|
||||
|
||||
bool PopExpression::eval(const ExpFileEntry& file)
|
||||
{
|
||||
return evalRel(file.file_popularity());
|
||||
}
|
||||
|
||||
/******************************************************************************************
|
||||
Code for evaluating string expressions
|
||||
|
||||
******************************************************************************************/
|
||||
|
||||
bool NameExpression::eval(const ExpFileEntry& file)
|
||||
{
|
||||
return evalStr(file.file_name());
|
||||
}
|
||||
|
||||
bool PathExpression::eval(const ExpFileEntry& file)
|
||||
{
|
||||
return evalStr(file.file_parent_path());
|
||||
}
|
||||
|
||||
bool ExtExpression::eval(const ExpFileEntry& file)
|
||||
{
|
||||
std::string ext;
|
||||
/*Get the part of the string after the last instance of . in the filename */
|
||||
size_t index = file.file_name().find_last_of('.');
|
||||
if (index != std::string::npos) {
|
||||
ext = file.file_name().substr(index+1);
|
||||
if (ext != "" ){
|
||||
return evalStr(ext);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HashExpression::eval(const ExpFileEntry& file){
|
||||
return evalStr(file.file_hash().toStdString());
|
||||
}
|
||||
|
||||
/*Check whether two strings are 'equal' to each other*/
|
||||
static bool StrEquals(const std::string & str1, const std::string & str2,
|
||||
bool IgnoreCase ){
|
||||
if ( str1.size() != str2.size() ){
|
||||
return false;
|
||||
} else if (IgnoreCase) {
|
||||
std::equal( str1.begin(), str1.end(),
|
||||
str2.begin(), CompareCharIC() );
|
||||
}
|
||||
return std::equal( str1.begin(), str1.end(),
|
||||
str2.begin());
|
||||
}
|
||||
|
||||
/*Check whether one string contains the other*/
|
||||
static bool StrContains( const std::string & str1, const std::string & str2,
|
||||
bool IgnoreCase){
|
||||
|
||||
std::string::const_iterator iter ;
|
||||
if (IgnoreCase) {
|
||||
iter = std::search( str1.begin(), str1.end(),
|
||||
str2.begin(), str2.end(), CompareCharIC() );
|
||||
} else {
|
||||
iter = std::search( str1.begin(), str1.end(),
|
||||
str2.begin(), str2.end());
|
||||
}
|
||||
|
||||
return ( iter != str1.end() );
|
||||
}
|
||||
|
||||
|
||||
bool StringExpression :: evalStr ( const std::string &str ){
|
||||
std::list<std::string>::iterator iter;
|
||||
switch (Op) {
|
||||
case ContainsAllStrings:
|
||||
for ( iter = terms.begin(); iter != terms.end(); ++iter ) {
|
||||
if ( StrContains (str, *iter, IgnoreCase) == false ){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
case ContainsAnyStrings:
|
||||
for ( iter = terms.begin(); iter != terms.end(); ++iter ) {
|
||||
if ( StrContains (str,*iter, IgnoreCase) == true ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EqualsString:
|
||||
for ( iter = terms.begin(); iter != terms.end(); ++iter ) {
|
||||
if ( StrEquals (str,*iter, IgnoreCase) == true ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* linearization code
|
||||
*************************************************************************/
|
||||
|
||||
void CompoundExpression::linearize(LinearizedExpression& e) const
|
||||
{
|
||||
e._tokens.push_back(LinearizedExpression::EXPR_COMP) ;
|
||||
e._ints.push_back(Op) ;
|
||||
|
||||
Lexp->linearize(e) ;
|
||||
Rexp->linearize(e) ;
|
||||
}
|
||||
|
||||
void StringExpression::linearize(LinearizedExpression& e) const
|
||||
{
|
||||
e._ints.push_back(Op) ;
|
||||
e._ints.push_back(IgnoreCase) ;
|
||||
e._ints.push_back(terms.size()) ;
|
||||
|
||||
for(std::list<std::string>::const_iterator it(terms.begin());it!=terms.end();++it)
|
||||
e._strings.push_back(*it) ;
|
||||
}
|
||||
|
||||
Expression *LinearizedExpression::toExpr(const LinearizedExpression& e)
|
||||
{
|
||||
int i=0,j=0,k=0 ;
|
||||
return toExpr(e,i,j,k) ;
|
||||
}
|
||||
|
||||
void LinearizedExpression::readStringExpr(const LinearizedExpression& e,int& n_ints,int& n_strings,std::list<std::string>& strings,bool& b,StringOperator& op)
|
||||
{
|
||||
op = static_cast<StringOperator>(e._ints[n_ints++]) ;
|
||||
b = e._ints[n_ints++] ;
|
||||
int n = e._ints[n_ints++] ;
|
||||
|
||||
strings.clear() ;
|
||||
for(int i=0;i<n;++i)
|
||||
strings.push_back(e._strings[n_strings++]) ;
|
||||
}
|
||||
|
||||
Expression *LinearizedExpression::toExpr(const LinearizedExpression& e,int& n_tok,int& n_ints,int& n_strings)
|
||||
{
|
||||
LinearizedExpression::token tok = static_cast<LinearizedExpression::token>(e._tokens[n_tok++]) ;
|
||||
|
||||
switch(tok)
|
||||
{
|
||||
case EXPR_DATE: {
|
||||
RelOperator op = static_cast<RelOperator>(e._ints[n_ints++]) ;
|
||||
int lv = e._ints[n_ints++] ;
|
||||
int hv = e._ints[n_ints++] ;
|
||||
|
||||
return new DateExpression(op,lv,hv) ;
|
||||
}
|
||||
|
||||
case EXPR_POP: {
|
||||
RelOperator op = static_cast<RelOperator>(e._ints[n_ints++]) ;
|
||||
int lv = e._ints[n_ints++] ;
|
||||
int hv = e._ints[n_ints++] ;
|
||||
|
||||
return new PopExpression(op,lv,hv) ;
|
||||
}
|
||||
case EXPR_SIZE: {
|
||||
RelOperator op = static_cast<RelOperator>(e._ints[n_ints++]) ;
|
||||
int lv = e._ints[n_ints++] ;
|
||||
int hv = e._ints[n_ints++] ;
|
||||
|
||||
return new SizeExpression(op,lv,hv) ;
|
||||
}
|
||||
case EXPR_HASH: {
|
||||
std::list<std::string> strings ;
|
||||
StringOperator op ;
|
||||
bool b ;
|
||||
|
||||
readStringExpr(e,n_ints,n_strings,strings,b,op) ;
|
||||
return new HashExpression(op,strings) ;
|
||||
}
|
||||
case EXPR_NAME: {
|
||||
std::list<std::string> strings ;
|
||||
StringOperator op ;
|
||||
bool b ;
|
||||
|
||||
readStringExpr(e,n_ints,n_strings,strings,b,op) ;
|
||||
|
||||
return new NameExpression(op,strings,b) ;
|
||||
}
|
||||
case EXPR_PATH: {
|
||||
std::list<std::string> strings ;
|
||||
StringOperator op ;
|
||||
bool b ;
|
||||
|
||||
readStringExpr(e,n_ints,n_strings,strings,b,op) ;
|
||||
|
||||
return new ExtExpression(op,strings,b) ;
|
||||
}
|
||||
case EXPR_EXT: {
|
||||
std::list<std::string> strings ;
|
||||
StringOperator op ;
|
||||
bool b ;
|
||||
|
||||
readStringExpr(e,n_ints,n_strings,strings,b,op) ;
|
||||
|
||||
return new ExtExpression(op,strings,b) ;
|
||||
}
|
||||
case EXPR_COMP: {
|
||||
LogicalOperator op = static_cast<LogicalOperator>(e._ints[n_ints++]) ;
|
||||
|
||||
Expression *e1 = toExpr(e,n_tok,n_ints,n_strings) ;
|
||||
Expression *e2 = toExpr(e,n_tok,n_ints,n_strings) ;
|
||||
|
||||
return new CompoundExpression(op,e1,e2) ;
|
||||
}
|
||||
case EXPR_SIZE_MB: {
|
||||
RelOperator op = static_cast<RelOperator>(e._ints[n_ints++]) ;
|
||||
int lv = e._ints[n_ints++] ;
|
||||
int hv = e._ints[n_ints++] ;
|
||||
|
||||
return new SizeExpressionMB(op,lv,hv) ;
|
||||
}
|
||||
default:
|
||||
std::cerr << "No expression match the current value " << tok << std::endl ;
|
||||
return NULL ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -774,7 +774,7 @@ void SearchDialog::initSearchResult(const QString& txt, qulonglong searchId, int
|
||||
ui.searchSummaryWidget->setCurrentItem(item2);
|
||||
}
|
||||
|
||||
void SearchDialog::advancedSearch(Expression* expression)
|
||||
void SearchDialog::advancedSearch(RsRegularExpression::Expression* expression)
|
||||
{
|
||||
advSearchDialog->hide();
|
||||
|
||||
@ -782,7 +782,7 @@ void SearchDialog::advancedSearch(Expression* expression)
|
||||
std::list<DirDetails> results;
|
||||
|
||||
// send a turtle search request
|
||||
LinearizedExpression e ;
|
||||
RsRegularExpression::LinearizedExpression e ;
|
||||
expression->linearize(e) ;
|
||||
|
||||
TurtleRequestId req_id = rsTurtle->turtleSearch(e) ;
|
||||
@ -843,8 +843,8 @@ void SearchDialog::searchKeywords(const QString& keywords)
|
||||
if (n < 1)
|
||||
return;
|
||||
|
||||
NameExpression exprs(ContainsAllStrings,words,true) ;
|
||||
LinearizedExpression lin_exp ;
|
||||
RsRegularExpression::NameExpression exprs(RsRegularExpression::ContainsAllStrings,words,true) ;
|
||||
RsRegularExpression::LinearizedExpression lin_exp ;
|
||||
exprs.linearize(lin_exp) ;
|
||||
|
||||
TurtleRequestId req_id ;
|
||||
@ -1042,9 +1042,10 @@ void SearchDialog::insertDirectory(const QString &txt, qulonglong searchId, cons
|
||||
}
|
||||
|
||||
/* go through all children directories/files for a recursive call */
|
||||
for (std::list<DirStub>::const_iterator it(dir.children.begin()); it != dir.children.end(); ++it) {
|
||||
for (uint32_t i=0;i<dir.children.size();++i)
|
||||
{
|
||||
DirDetails details;
|
||||
rsFiles->RequestDirDetails(it->ref, details, FileSearchFlags(0u));
|
||||
rsFiles->RequestDirDetails(dir.children[i].ref, details, FileSearchFlags(0u));
|
||||
insertDirectory(txt, searchId, details, child);
|
||||
}
|
||||
}
|
||||
|
@ -27,9 +27,10 @@
|
||||
#include "mainpage.h"
|
||||
|
||||
class AdvancedSearchDialog;
|
||||
class Expression;
|
||||
class RSTreeWidgetItemCompareRole;
|
||||
|
||||
namespace RsRegularExpression { class Expression; }
|
||||
|
||||
#define FRIEND_SEARCH 1
|
||||
#define ANONYMOUS_SEARCH 2
|
||||
class SearchDialog : public MainPage
|
||||
@ -99,7 +100,7 @@ private slots:
|
||||
void showAdvSearchDialog(bool=true);
|
||||
|
||||
/** perform the advanced search */
|
||||
void advancedSearch(Expression*);
|
||||
void advancedSearch(RsRegularExpression::Expression*);
|
||||
|
||||
void selectSearchResults(int index = -1);
|
||||
void hideOrShowSearchResult(QTreeWidgetItem* resultItem, QString currentSearchId = QString(), int fileTypeIndex = -1);
|
||||
|
@ -349,9 +349,6 @@ TransfersDialog::TransfersDialog(QWidget *parent)
|
||||
// ui.tunnelInfoWidget->setFocusPolicy(Qt::NoFocus);
|
||||
|
||||
/** Setup the actions for the context menu */
|
||||
toggleShowCacheTransfersAct = new QAction(tr( "Show file list transfers" ), this );
|
||||
toggleShowCacheTransfersAct->setCheckable(true) ;
|
||||
connect(toggleShowCacheTransfersAct,SIGNAL(triggered()),this,SLOT(toggleShowCacheTransfers())) ;
|
||||
|
||||
// Actions. Only need to be defined once.
|
||||
pauseAct = new QAction(QIcon(IMAGE_PAUSE), tr("Pause"), this);
|
||||
@ -519,12 +516,6 @@ UserNotify *TransfersDialog::getUserNotify(QObject *parent)
|
||||
return new TransferUserNotify(parent);
|
||||
}
|
||||
|
||||
void TransfersDialog::toggleShowCacheTransfers()
|
||||
{
|
||||
_show_cache_transfers = !_show_cache_transfers ;
|
||||
insertTransfers() ;
|
||||
}
|
||||
|
||||
void TransfersDialog::processSettings(bool bLoad)
|
||||
{
|
||||
m_bProcessSettings = true;
|
||||
@ -537,9 +528,6 @@ void TransfersDialog::processSettings(bool bLoad)
|
||||
if (bLoad) {
|
||||
// load settings
|
||||
|
||||
// state of checks
|
||||
_show_cache_transfers = Settings->value("showCacheTransfers", false).toBool();
|
||||
|
||||
// state of the lists
|
||||
DLHeader->restoreState(Settings->value("downloadList").toByteArray());
|
||||
ULHeader->restoreState(Settings->value("uploadList").toByteArray());
|
||||
@ -565,9 +553,6 @@ void TransfersDialog::processSettings(bool bLoad)
|
||||
} else {
|
||||
// save settings
|
||||
|
||||
// state of checks
|
||||
Settings->setValue("showCacheTransfers", _show_cache_transfers);
|
||||
|
||||
// state of the lists
|
||||
Settings->setValue("downloadList", DLHeader->saveState());
|
||||
Settings->setValue("uploadList", ULHeader->saveState());
|
||||
@ -801,9 +786,6 @@ void TransfersDialog::downloadListCustomPopupMenu( QPoint /*point*/ )
|
||||
|
||||
contextMnu.addSeparator() ;//-----------------------------------------------
|
||||
|
||||
contextMnu.addAction( toggleShowCacheTransfersAct ) ;
|
||||
toggleShowCacheTransfersAct->setChecked(_show_cache_transfers) ;
|
||||
|
||||
collCreateAct->setEnabled(true) ;
|
||||
collModifAct->setEnabled(single && add_CollActions) ;
|
||||
collViewAct->setEnabled(single && add_CollActions) ;
|
||||
@ -1269,13 +1251,6 @@ void TransfersDialog::insertTransfers()
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((fileInfo.transfer_info_flags & RS_FILE_REQ_CACHE) && !_show_cache_transfers) {
|
||||
// if file transfer is a cache file index file, don't show it
|
||||
DLListModel->removeRow(row);
|
||||
rowCount = DLListModel->rowCount();
|
||||
continue;
|
||||
}
|
||||
|
||||
hashs.erase(hashIt);
|
||||
|
||||
if (addItem(row, fileInfo) < 0) {
|
||||
@ -1295,11 +1270,6 @@ void TransfersDialog::insertTransfers()
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((fileInfo.transfer_info_flags & RS_FILE_REQ_CACHE) && !_show_cache_transfers) {
|
||||
//if file transfer is a cache file index file, don't show it
|
||||
continue;
|
||||
}
|
||||
|
||||
addItem(-1, fileInfo);
|
||||
}
|
||||
|
||||
@ -1322,9 +1292,6 @@ void TransfersDialog::insertTransfers()
|
||||
if (!rsFiles->FileDetails(*it, RS_FILE_HINTS_UPLOAD, info))
|
||||
continue;
|
||||
|
||||
if((info.transfer_info_flags & RS_FILE_REQ_CACHE) && _show_cache_transfers)
|
||||
continue ;
|
||||
|
||||
std::list<TransferInfo>::iterator pit;
|
||||
for(pit = info.peers.begin(); pit != info.peers.end(); ++pit)
|
||||
{
|
||||
|
@ -199,7 +199,6 @@ private:
|
||||
QAction *chunkProgressiveAct;
|
||||
QAction *chunkStreamingAct;
|
||||
QAction *detailsFileAct;
|
||||
QAction *toggleShowCacheTransfersAct;
|
||||
QAction *renameFileAct;
|
||||
QAction *specifyDestinationDirectoryAct;
|
||||
QAction *expandAllAct;
|
||||
@ -249,7 +248,6 @@ private:
|
||||
/** Qt Designer generated object */
|
||||
Ui::TransfersDialog ui;
|
||||
|
||||
bool _show_cache_transfers ;
|
||||
public slots:
|
||||
// these two functions add entries to the transfers dialog, and return the row id of the entry modified/added
|
||||
//
|
||||
@ -259,7 +257,6 @@ public slots:
|
||||
int addUploadItem(const QString& symbol, const QString& name, const QString& coreID, qlonglong size, const FileProgressInfo& pinfo, double dlspeed, const QString& sources,const QString& source_id, const QString& status, qlonglong completed, qlonglong remaining);
|
||||
|
||||
void showFileDetails() ;
|
||||
void toggleShowCacheTransfers() ;
|
||||
|
||||
double getProgress(int row, QStandardItemModel *model);
|
||||
double getSpeed(int row, QStandardItemModel *model);
|
||||
|
@ -756,7 +756,10 @@ void MainWindow::updateFriends()
|
||||
void MainWindow::postModDirectories(bool update_local)
|
||||
{
|
||||
RSettingsWin::postModDirectories(update_local);
|
||||
ShareManager::postModDirectories(update_local);
|
||||
|
||||
// Why would we need that?? The effect is to reset the flags while we're changing them, so it's really not
|
||||
// a good idea.
|
||||
//ShareManager::postModDirectories(update_local);
|
||||
|
||||
QCoreApplication::flush();
|
||||
}
|
||||
|
@ -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
|
||||
{
|
||||
|
||||
@ -99,9 +104,8 @@ bool TreeStyle_RDM::hasChildren(const QModelIndex &parent) const
|
||||
|
||||
void *ref = parent.internalPointer();
|
||||
|
||||
const DirDetails *details = requestDirDetails(ref, RemoteMode);
|
||||
|
||||
if (!details)
|
||||
DirDetails details ;
|
||||
if (!requestDirDetails(ref, RemoteMode,details))
|
||||
{
|
||||
/* error */
|
||||
#ifdef RDM_DEBUG
|
||||
@ -111,7 +115,7 @@ bool TreeStyle_RDM::hasChildren(const QModelIndex &parent) const
|
||||
return false;
|
||||
}
|
||||
|
||||
if (details->type == DIR_TYPE_FILE)
|
||||
if (details.type == DIR_TYPE_FILE)
|
||||
{
|
||||
#ifdef RDM_DEBUG
|
||||
std::cerr << "lookup FILE -> false";
|
||||
@ -124,7 +128,7 @@ bool TreeStyle_RDM::hasChildren(const QModelIndex &parent) const
|
||||
std::cerr << "lookup PER/DIR #" << details->count;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return (details->count > 0); /* do we have children? */
|
||||
return (details.count > 0); /* do we have children? */
|
||||
}
|
||||
bool FlatStyle_RDM::hasChildren(const QModelIndex &parent) const
|
||||
{
|
||||
@ -155,9 +159,9 @@ int TreeStyle_RDM::rowCount(const QModelIndex &parent) const
|
||||
|
||||
void *ref = (parent.isValid())? parent.internalPointer() : NULL ;
|
||||
|
||||
const DirDetails *details = requestDirDetails(ref, RemoteMode);
|
||||
DirDetails details ;
|
||||
|
||||
if (!details)
|
||||
if (! requestDirDetails(ref, RemoteMode,details))
|
||||
{
|
||||
#ifdef RDM_DEBUG
|
||||
std::cerr << "lookup failed -> 0";
|
||||
@ -165,7 +169,7 @@ int TreeStyle_RDM::rowCount(const QModelIndex &parent) const
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
if (details->type == DIR_TYPE_FILE)
|
||||
if (details.type == DIR_TYPE_FILE)
|
||||
{
|
||||
#ifdef RDM_DEBUG
|
||||
std::cerr << "lookup FILE: 0";
|
||||
@ -179,7 +183,7 @@ int TreeStyle_RDM::rowCount(const QModelIndex &parent) const
|
||||
std::cerr << "lookup PER/DIR #" << details->count;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return details->count;
|
||||
return details.count;
|
||||
}
|
||||
|
||||
int FlatStyle_RDM::rowCount(const QModelIndex &parent) const
|
||||
@ -190,6 +194,7 @@ int FlatStyle_RDM::rowCount(const QModelIndex &parent) const
|
||||
std::cerr << "RetroshareDirModel::rowCount(): " << parent.internalPointer();
|
||||
std::cerr << ": ";
|
||||
#endif
|
||||
RS_STACK_MUTEX(_ref_mutex) ;
|
||||
|
||||
return _ref_entries.size() ;
|
||||
}
|
||||
@ -294,6 +299,9 @@ QVariant RetroshareDirModel::decorationRole(const DirDetails& details,int coln)
|
||||
else if (details.type == DIR_TYPE_FILE) /* File */
|
||||
{
|
||||
// extensions predefined
|
||||
if(details.hash.isNull())
|
||||
return QIcon(":/images/reset.png") ; // file is being hashed
|
||||
else
|
||||
return FilesDefs::getIconFromFilename(QString::fromUtf8(details.name.c_str()));
|
||||
}
|
||||
else
|
||||
@ -381,16 +389,16 @@ QVariant TreeStyle_RDM::displayRole(const DirDetails& details,int coln) const
|
||||
QString FlatStyle_RDM::computeDirectoryPath(const DirDetails& details) const
|
||||
{
|
||||
QString dir ;
|
||||
const DirDetails *det = requestDirDetails(details.parent,RemoteMode);
|
||||
DirDetails det ;
|
||||
|
||||
if(!det)
|
||||
if(!requestDirDetails(details.parent,RemoteMode,det))
|
||||
return QString();
|
||||
|
||||
#ifdef SHOW_TOTAL_PATH
|
||||
do
|
||||
{
|
||||
#endif
|
||||
dir = QString::fromUtf8(det->name.c_str())+"/"+dir ;
|
||||
dir = QString::fromUtf8(det.name.c_str())+"/"+dir ;
|
||||
|
||||
#ifdef SHOW_TOTAL_PATH
|
||||
if(!requestDirDetails(det.parent,det,flags))
|
||||
@ -497,7 +505,12 @@ QVariant FlatStyle_RDM::sortRole(const QModelIndex& index,const DirDetails& deta
|
||||
case 1: return (qulonglong) details.count;
|
||||
case 2: return details.age;
|
||||
case 3: return QString::fromUtf8(rsPeers->getPeerName(details.id).c_str());
|
||||
case 4: return _ref_entries[index.row()].second ;
|
||||
|
||||
case 4: {
|
||||
RS_STACK_MUTEX(_ref_mutex) ;
|
||||
|
||||
return computeDirectoryPath(details);
|
||||
}
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
@ -521,28 +534,30 @@ QVariant RetroshareDirModel::data(const QModelIndex &index, int role) const
|
||||
void *ref = index.internalPointer();
|
||||
int coln = index.column();
|
||||
|
||||
const DirDetails *details = requestDirDetails(ref, RemoteMode);
|
||||
DirDetails details ;
|
||||
|
||||
if (!details)
|
||||
if (!requestDirDetails(ref, RemoteMode,details))
|
||||
return QVariant();
|
||||
|
||||
if (role == RetroshareDirModel::FileNameRole) /* end of FileNameRole */
|
||||
return QString::fromUtf8(details->name.c_str());
|
||||
return QString::fromUtf8(details.name.c_str());
|
||||
|
||||
if (role == Qt::TextColorRole)
|
||||
{
|
||||
if(details->min_age > ageIndicator)
|
||||
if(details.type == DIR_TYPE_FILE && details.hash.isNull())
|
||||
return QVariant(QColor(Qt::green)) ;
|
||||
else if(details.min_age > ageIndicator)
|
||||
return QVariant(QColor(Qt::gray)) ;
|
||||
else if(RemoteMode)
|
||||
{
|
||||
FileInfo info;
|
||||
QVariant local_file_color = QVariant(QColor(Qt::red));
|
||||
if(rsFiles->alreadyHaveFile(details->hash, info))
|
||||
if(rsFiles->alreadyHaveFile(details.hash, info))
|
||||
return local_file_color;
|
||||
|
||||
std::list<RsFileHash> downloads;
|
||||
rsFiles->FileDownloads(downloads);
|
||||
if(std::find(downloads.begin(), downloads.end(), details->hash) != downloads.end())
|
||||
if(std::find(downloads.begin(), downloads.end(), details.hash) != downloads.end())
|
||||
return local_file_color;
|
||||
else
|
||||
return QVariant();
|
||||
@ -553,7 +568,7 @@ QVariant RetroshareDirModel::data(const QModelIndex &index, int role) const
|
||||
|
||||
|
||||
if(role == Qt::DecorationRole)
|
||||
return decorationRole(*details,coln) ;
|
||||
return decorationRole(details,coln) ;
|
||||
|
||||
/*****************
|
||||
Qt::EditRole
|
||||
@ -578,10 +593,10 @@ QVariant RetroshareDirModel::data(const QModelIndex &index, int role) const
|
||||
} /* end of TextAlignmentRole */
|
||||
|
||||
if (role == Qt::DisplayRole)
|
||||
return displayRole(*details,coln) ;
|
||||
return displayRole(details,coln) ;
|
||||
|
||||
if (role == SortRole)
|
||||
return sortRole(index,*details,coln) ;
|
||||
return sortRole(index,details,coln) ;
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
@ -700,6 +715,9 @@ QModelIndex TreeStyle_RDM::index(int row, int column, const QModelIndex & parent
|
||||
std::cerr << ": row:" << row << " col:" << column << " ";
|
||||
#endif
|
||||
|
||||
// This function is used extensively. There's no way we can use requestDirDetails() in it, which would
|
||||
// cause far too much overhead. So we use a dedicated function that only grabs the required information.
|
||||
|
||||
if(row < 0)
|
||||
return QModelIndex() ;
|
||||
|
||||
@ -712,40 +730,15 @@ QModelIndex TreeStyle_RDM::index(int row, int column, const QModelIndex & parent
|
||||
}
|
||||
********/
|
||||
|
||||
const DirDetailsVector *details = requestDirDetails(ref, RemoteMode);
|
||||
|
||||
if (!details)
|
||||
{
|
||||
#ifdef RDM_DEBUG
|
||||
std::cerr << "lookup failed -> invalid";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
void *result ;
|
||||
|
||||
if(rsFiles->findChildPointer(ref, row, result, ((RemoteMode) ? RS_FILE_HINTS_REMOTE : RS_FILE_HINTS_LOCAL)))
|
||||
return createIndex(row, column, result) ;
|
||||
else
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
|
||||
/* now iterate through the details to
|
||||
* get the reference number
|
||||
*/
|
||||
|
||||
if (row >= (int) details->childrenVector.size())
|
||||
{
|
||||
#ifdef RDM_DEBUG
|
||||
std::cerr << "wrong number of children -> invalid";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
#ifdef RDM_DEBUG
|
||||
std::cerr << "success index(" << row << "," << column << "," << details->childrenVector[row].ref << ")";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
/* we can just grab the reference now */
|
||||
|
||||
return createIndex(row, column, details->childrenVector[row].ref);
|
||||
}
|
||||
QModelIndex FlatStyle_RDM::index(int row, int column, const QModelIndex & parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
@ -757,10 +750,15 @@ QModelIndex FlatStyle_RDM::index(int row, int column, const QModelIndex & parent
|
||||
if(row < 0)
|
||||
return QModelIndex() ;
|
||||
|
||||
RS_STACK_MUTEX(_ref_mutex) ;
|
||||
|
||||
if(row < (int) _ref_entries.size())
|
||||
{
|
||||
void *ref = _ref_entries[row].first ;
|
||||
void *ref = _ref_entries[row];
|
||||
|
||||
#ifdef RDM_DEBUG
|
||||
std::cerr << "Creating index 2 row=" << row << ", column=" << column << ", ref=" << (void*)ref << std::endl;
|
||||
#endif
|
||||
return createIndex(row, column, ref);
|
||||
}
|
||||
else
|
||||
@ -786,9 +784,9 @@ QModelIndex TreeStyle_RDM::parent( const QModelIndex & index ) const
|
||||
}
|
||||
void *ref = index.internalPointer();
|
||||
|
||||
const DirDetails *details = requestDirDetails(ref, RemoteMode);
|
||||
DirDetails details ;
|
||||
|
||||
if (!details)
|
||||
if (! requestDirDetails(ref, RemoteMode,details))
|
||||
{
|
||||
#ifdef RDM_DEBUG
|
||||
std::cerr << "Failed Lookup -> invalid";
|
||||
@ -797,7 +795,7 @@ QModelIndex TreeStyle_RDM::parent( const QModelIndex & index ) const
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
if (!(details->parent))
|
||||
if (!(details.parent))
|
||||
{
|
||||
#ifdef RDM_DEBUG
|
||||
std::cerr << "success. parent is Root/NULL --> invalid";
|
||||
@ -810,8 +808,9 @@ QModelIndex TreeStyle_RDM::parent( const QModelIndex & index ) const
|
||||
std::cerr << "success index(" << details->prow << ",0," << details->parent << ")";
|
||||
std::cerr << std::endl;
|
||||
|
||||
std::cerr << "Creating index 3 row=" << details.prow << ", column=" << 0 << ", ref=" << (void*)details.parent << std::endl;
|
||||
#endif
|
||||
return createIndex(details->prow, 0, details->parent);
|
||||
return createIndex(details.prow, 0, details.parent);
|
||||
}
|
||||
QModelIndex FlatStyle_RDM::parent( const QModelIndex & index ) const
|
||||
{
|
||||
@ -836,12 +835,12 @@ Qt::ItemFlags RetroshareDirModel::flags( const QModelIndex & index ) const
|
||||
|
||||
void *ref = index.internalPointer();
|
||||
|
||||
const DirDetails *details = requestDirDetails(ref, RemoteMode);
|
||||
DirDetails details ;
|
||||
|
||||
if (!details)
|
||||
if (! requestDirDetails(ref, RemoteMode,details))
|
||||
return Qt::ItemIsSelectable; // Error.
|
||||
|
||||
switch(details->type)
|
||||
switch(details.type)
|
||||
{
|
||||
case DIR_TYPE_PERSON: return Qt::ItemIsEnabled;
|
||||
case DIR_TYPE_DIR: return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
|
||||
@ -862,6 +861,7 @@ Qt::ItemFlags RetroshareDirModel::flags( const QModelIndex & index ) const
|
||||
/* Callback from */
|
||||
void RetroshareDirModel::preMods()
|
||||
{
|
||||
emit layoutAboutToBeChanged();
|
||||
#if QT_VERSION < 0x050000
|
||||
reset();
|
||||
#else
|
||||
@ -877,7 +877,7 @@ void RetroshareDirModel::preMods()
|
||||
/* Callback from */
|
||||
void RetroshareDirModel::postMods()
|
||||
{
|
||||
emit layoutAboutToBeChanged();
|
||||
// emit layoutAboutToBeChanged();
|
||||
#if QT_VERSION >= 0x040600
|
||||
beginResetModel();
|
||||
#endif
|
||||
@ -890,7 +890,7 @@ void RetroshareDirModel::postMods()
|
||||
// changePersistentIndexList(piList, empty);
|
||||
|
||||
/* Clear caches */
|
||||
mCache.clear();
|
||||
//mCache.clear();
|
||||
|
||||
#ifdef RDM_DEBUG
|
||||
std::cerr << "RetroshareDirModel::postMods()" << std::endl;
|
||||
@ -902,32 +902,36 @@ void RetroshareDirModel::postMods()
|
||||
emit layoutChanged();
|
||||
}
|
||||
|
||||
const DirDetailsVector *RetroshareDirModel::requestDirDetails(void *ref, bool remote) const
|
||||
bool RetroshareDirModel::requestDirDetails(void *ref, bool remote,DirDetails& d) const
|
||||
{
|
||||
const QMap<void*, DirDetailsVector>::const_iterator it = mCache.constFind(ref);
|
||||
if (it != mCache.constEnd()) {
|
||||
/* Details found in cache */
|
||||
return &it.value();
|
||||
}
|
||||
|
||||
/* Get details from the lib */
|
||||
DirDetailsVector details;
|
||||
FileSearchFlags flags = (remote) ? RS_FILE_HINTS_REMOTE : RS_FILE_HINTS_LOCAL;
|
||||
if (rsFiles->RequestDirDetails(ref, details, flags)) {
|
||||
/* Convert std::list to std::vector for fast access with index */
|
||||
std::list<DirStub>::const_iterator childIt;
|
||||
for (childIt = details.children.begin(); childIt != details.children.end(); ++childIt) {
|
||||
details.childrenVector.push_back(*childIt);
|
||||
}
|
||||
|
||||
/* Add to cache, must cast to none const */
|
||||
const QMap<void*, DirDetailsVector>::iterator it1 = ((QMap<void*, DirDetailsVector>*) &mCache)->insert(ref, details);
|
||||
return &it1.value();
|
||||
}
|
||||
|
||||
/* No details found */
|
||||
return NULL;
|
||||
return rsFiles->RequestDirDetails(ref, d, flags) ;
|
||||
}
|
||||
// const QMap<void*, DirDetailsVector>::const_iterator it = mCache.constFind(ref);
|
||||
// if (it != mCache.constEnd()) {
|
||||
// /* Details found in cache */
|
||||
// return &it.value();
|
||||
// }
|
||||
//
|
||||
//#warning this is terrible! A vector in a std::map will keep being copied and create a lot of CPU overload. Use a pointer instead.
|
||||
// /* Get details from the lib */
|
||||
//
|
||||
// if (rsFiles->RequestDirDetails(ref, details, flags)) {
|
||||
// /* Convert std::list to std::vector for fast access with index */
|
||||
// std::list<DirStub>::const_iterator childIt;
|
||||
// for (childIt = details.children.begin(); childIt != details.children.end(); ++childIt) {
|
||||
// details.childrenVector.push_back(*childIt);
|
||||
// }
|
||||
//
|
||||
// /* Add to cache, must cast to none const */
|
||||
// const QMap<void*, DirDetailsVector>::iterator it1 = ((QMap<void*, DirDetailsVector>*) &mCache)->insert(ref, details);
|
||||
// return &it1.value();
|
||||
// }
|
||||
//
|
||||
// /* No details found */
|
||||
// return NULL;
|
||||
//}
|
||||
|
||||
void RetroshareDirModel::createCollectionFile(QWidget *parent, const QModelIndexList &list)
|
||||
{
|
||||
@ -1010,15 +1014,16 @@ void RetroshareDirModel::downloadDirectory(const DirDetails & dirDetails, int pr
|
||||
|
||||
if (!dwlDir.mkpath(cleanPath)) return;
|
||||
|
||||
for (it = dirDetails.children.begin(); it != dirDetails.children.end(); ++it)
|
||||
for(uint32_t i=0;i<dirDetails.children.size();++i)
|
||||
{
|
||||
if (!it->ref) continue;
|
||||
if (!dirDetails.children[i].ref) continue;
|
||||
|
||||
const DirDetails *subDirDetails = requestDirDetails(it->ref, true);
|
||||
DirDetails subDirDetails ;
|
||||
|
||||
if (!subDirDetails) continue;
|
||||
if(!requestDirDetails(dirDetails.children[i].ref, true,subDirDetails))
|
||||
continue;
|
||||
|
||||
downloadDirectory(*subDirDetails, prefixLen);
|
||||
downloadDirectory(subDirDetails, prefixLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1035,12 +1040,12 @@ void RetroshareDirModel::getDirDetailsFromSelect (const QModelIndexList &list, s
|
||||
{
|
||||
void *ref = it -> internalPointer();
|
||||
|
||||
const DirDetails *details = requestDirDetails(ref, RemoteMode);
|
||||
DirDetails details ;
|
||||
|
||||
if (!details)
|
||||
if(!requestDirDetails(ref, RemoteMode,details))
|
||||
continue;
|
||||
|
||||
dirVec.push_back(*details);
|
||||
dirVec.push_back(details);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1072,12 +1077,12 @@ void RetroshareDirModel::getFileInfoFromIndexList(const QModelIndexList& list, s
|
||||
{
|
||||
void *ref = it -> internalPointer();
|
||||
|
||||
const DirDetails *details = requestDirDetails(ref, RemoteMode);
|
||||
DirDetails details;
|
||||
|
||||
if (!details)
|
||||
if (!requestDirDetails(ref, RemoteMode,details))
|
||||
continue;
|
||||
|
||||
if(details->type == DIR_TYPE_PERSON)
|
||||
if(details.type == DIR_TYPE_PERSON)
|
||||
continue ;
|
||||
|
||||
#ifdef RDM_DEBUG
|
||||
@ -1090,10 +1095,10 @@ void RetroshareDirModel::getFileInfoFromIndexList(const QModelIndexList& list, s
|
||||
// Note: for directories, the returned hash, is the peer id, so if we collect
|
||||
// dirs, we need to be a bit more conservative for the
|
||||
|
||||
if(already_in.find(details->hash.toStdString()+details->name) == already_in.end())
|
||||
if(already_in.find(details.hash.toStdString()+details.name) == already_in.end())
|
||||
{
|
||||
file_details.push_back(*details) ;
|
||||
already_in.insert(details->hash.toStdString()+details->name) ;
|
||||
file_details.push_back(details) ;
|
||||
already_in.insert(details.hash.toStdString()+details.name) ;
|
||||
}
|
||||
}
|
||||
#ifdef RDM_DEBUG
|
||||
@ -1149,11 +1154,29 @@ void RetroshareDirModel::openSelected(const QModelIndexList &qmil)
|
||||
#endif
|
||||
}
|
||||
|
||||
void RetroshareDirModel::getFilePath(const QModelIndex& index, std::string& fullpath)
|
||||
{
|
||||
void *ref = index.sibling(index.row(),1).internalPointer();
|
||||
|
||||
DirDetails details ;
|
||||
|
||||
if (!requestDirDetails(ref, false,details) )
|
||||
{
|
||||
#ifdef RDM_DEBUG
|
||||
std::cerr << "getFilePaths() Bad Request" << std::endl;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
fullpath = details.path + "/" + details.name;
|
||||
}
|
||||
|
||||
void RetroshareDirModel::getFilePaths(const QModelIndexList &list, std::list<std::string> &fullpaths)
|
||||
{
|
||||
#ifdef RDM_DEBUG
|
||||
std::cerr << "RetroshareDirModel::getFilePaths()" << std::endl;
|
||||
#endif
|
||||
#warning make sure we atually output something here
|
||||
if (RemoteMode)
|
||||
{
|
||||
#ifdef RDM_DEBUG
|
||||
@ -1162,47 +1185,17 @@ void RetroshareDirModel::getFilePaths(const QModelIndexList &list, std::list<std
|
||||
return;
|
||||
}
|
||||
/* translate */
|
||||
QModelIndexList::const_iterator it;
|
||||
for(it = list.begin(); it != list.end(); ++it)
|
||||
for(QModelIndexList::const_iterator it = list.begin(); it != list.end(); ++it)
|
||||
{
|
||||
void *ref = it -> internalPointer();
|
||||
std::string path ;
|
||||
|
||||
const DirDetails *details = requestDirDetails(ref, false);
|
||||
|
||||
if (!details)
|
||||
{
|
||||
getFilePath(*it,path) ;
|
||||
#ifdef RDM_DEBUG
|
||||
std::cerr << "getFilePaths() Bad Request" << std::endl;
|
||||
std::cerr << "Constructed FilePath: " << path << std::endl;
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
if (details->type != DIR_TYPE_FILE)
|
||||
{
|
||||
#ifdef RDM_DEBUG
|
||||
std::cerr << "getFilePaths() Not File" << std::endl;
|
||||
#endif
|
||||
continue; /* not file! */
|
||||
}
|
||||
|
||||
#ifdef RDM_DEBUG
|
||||
std::cerr << "::::::::::::File Details:::: " << std::endl;
|
||||
std::cerr << "Name: " << details->name << std::endl;
|
||||
std::cerr << "Hash: " << details->hash << std::endl;
|
||||
std::cerr << "Size: " << details->count << std::endl;
|
||||
std::cerr << "Path: " << details->path << std::endl;
|
||||
#endif
|
||||
|
||||
std::string filepath = details->path + "/";
|
||||
filepath += details->name;
|
||||
|
||||
#ifdef RDM_DEBUG
|
||||
std::cerr << "Constructed FilePath: " << filepath << std::endl;
|
||||
#endif
|
||||
if (fullpaths.end() == std::find(fullpaths.begin(), fullpaths.end(), filepath))
|
||||
{
|
||||
fullpaths.push_back(filepath);
|
||||
}
|
||||
#warning TERRIBLE COST here. Use a std::set!
|
||||
if (fullpaths.end() == std::find(fullpaths.begin(), fullpaths.end(), path))
|
||||
fullpaths.push_back(path);
|
||||
}
|
||||
#ifdef RDM_DEBUG
|
||||
std::cerr << "::::::::::::Done getFilePaths" << std::endl;
|
||||
@ -1222,12 +1215,9 @@ QMimeData * RetroshareDirModel::mimeData ( const QModelIndexList & indexes ) con
|
||||
{
|
||||
void *ref = it -> internalPointer();
|
||||
|
||||
const DirDetails *details = requestDirDetails(ref, RemoteMode);
|
||||
|
||||
if (!details)
|
||||
{
|
||||
DirDetails details ;
|
||||
if (!requestDirDetails(ref, RemoteMode,details))
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef RDM_DEBUG
|
||||
std::cerr << "::::::::::::FileDrag:::: " << std::endl;
|
||||
@ -1237,7 +1227,7 @@ QMimeData * RetroshareDirModel::mimeData ( const QModelIndexList & indexes ) con
|
||||
std::cerr << "Path: " << details->path << std::endl;
|
||||
#endif
|
||||
|
||||
if (details->type != DIR_TYPE_FILE)
|
||||
if (details.type != DIR_TYPE_FILE)
|
||||
{
|
||||
#ifdef RDM_DEBUG
|
||||
std::cerr << "RetroshareDirModel::mimeData() Not File" << std::endl;
|
||||
@ -1245,7 +1235,7 @@ QMimeData * RetroshareDirModel::mimeData ( const QModelIndexList & indexes ) con
|
||||
continue; /* not file! */
|
||||
}
|
||||
|
||||
if (drags.end() != (dit = drags.find(details->hash)))
|
||||
if (drags.end() != (dit = drags.find(details.hash)))
|
||||
{
|
||||
#ifdef RDM_DEBUG
|
||||
std::cerr << "RetroshareDirModel::mimeData() Duplicate" << std::endl;
|
||||
@ -1253,9 +1243,9 @@ QMimeData * RetroshareDirModel::mimeData ( const QModelIndexList & indexes ) con
|
||||
continue; /* duplicate */
|
||||
}
|
||||
|
||||
drags[details->hash] = details->count;
|
||||
drags[details.hash] = details.count;
|
||||
|
||||
QString line = QString("%1/%2/%3/").arg(QString::fromUtf8(details->name.c_str()), QString::fromStdString(details->hash.toStdString()), QString::number(details->count));
|
||||
QString line = QString("%1/%2/%3/").arg(QString::fromUtf8(details.name.c_str()), QString::fromStdString(details.hash.toStdString()), QString::number(details.count));
|
||||
|
||||
if (RemoteMode)
|
||||
{
|
||||
@ -1315,14 +1305,15 @@ void FlatStyle_RDM::postMods()
|
||||
{
|
||||
if(visible())
|
||||
{
|
||||
_ref_entries.clear() ;
|
||||
emit layoutAboutToBeChanged();
|
||||
|
||||
{
|
||||
RS_STACK_MUTEX(_ref_mutex) ;
|
||||
_ref_stack.clear() ;
|
||||
|
||||
_ref_stack.push_back(NULL) ; // init the stack with the topmost parent directory
|
||||
|
||||
std::cerr << "FlatStyle_RDM::postMods(): cleared ref entries" << std::endl;
|
||||
_needs_update = false ;
|
||||
updateRefs() ;
|
||||
}
|
||||
QTimer::singleShot(100,this,SLOT(updateRefs())) ;
|
||||
}
|
||||
else
|
||||
_needs_update = true ;
|
||||
@ -1338,9 +1329,17 @@ void FlatStyle_RDM::updateRefs()
|
||||
|
||||
RetroshareDirModel::preMods() ;
|
||||
|
||||
|
||||
static const uint32_t MAX_REFS_PER_SECOND = 2000 ;
|
||||
uint32_t nb_treated_refs = 0 ;
|
||||
|
||||
{
|
||||
RS_STACK_MUTEX(_ref_mutex) ;
|
||||
|
||||
_ref_entries.clear() ;
|
||||
|
||||
std::cerr << "FlatStyle_RDM::postMods(): cleared ref entries" << std::endl;
|
||||
|
||||
while(!_ref_stack.empty())
|
||||
{
|
||||
void *ref = _ref_stack.back() ;
|
||||
@ -1348,17 +1347,18 @@ void FlatStyle_RDM::updateRefs()
|
||||
std::cerr << "FlatStyle_RDM::postMods(): poped ref " << ref << std::endl;
|
||||
#endif
|
||||
_ref_stack.pop_back() ;
|
||||
const DirDetails *details = requestDirDetails(ref, RemoteMode) ;
|
||||
|
||||
if (details)
|
||||
DirDetails details ;
|
||||
|
||||
if (requestDirDetails(ref, RemoteMode,details))
|
||||
{
|
||||
if(details->type == DIR_TYPE_FILE) // only push files, not directories nor persons.
|
||||
_ref_entries.push_back(std::pair<void*,QString>(ref,computeDirectoryPath(*details)));
|
||||
if(details.type == DIR_TYPE_FILE) // only push files, not directories nor persons.
|
||||
_ref_entries.push_back(ref) ;
|
||||
#ifdef RDM_DEBUG
|
||||
std::cerr << "FlatStyle_RDM::postMods(): adding ref " << ref << std::endl;
|
||||
#endif
|
||||
for(std::list<DirStub>::const_iterator it = details->children.begin(); it != details->children.end(); ++it)
|
||||
_ref_stack.push_back(it->ref) ;
|
||||
for(uint32_t i=0;i<details.children.size();++i)
|
||||
_ref_stack.push_back(details.children[i].ref) ;
|
||||
}
|
||||
if(++nb_treated_refs > MAX_REFS_PER_SECOND) // we've done enough, let's give back hand to
|
||||
{ // the user and setup a timer to finish the job later.
|
||||
@ -1375,6 +1375,7 @@ void FlatStyle_RDM::updateRefs()
|
||||
|
||||
if(_ref_stack.empty())
|
||||
_needs_update = false ;
|
||||
}
|
||||
|
||||
RetroshareDirModel::postMods() ;
|
||||
}
|
||||
|
@ -72,11 +72,14 @@ class RetroshareDirModel : public QAbstractItemModel
|
||||
void getFileInfoFromIndexList(const QModelIndexList& list, std::list<DirDetails>& files_info) ;
|
||||
void openSelected(const QModelIndexList &list);
|
||||
void getFilePaths(const QModelIndexList &list, std::list<std::string> &fullpaths);
|
||||
void getFilePath(const QModelIndex& index, std::string& fullpath);
|
||||
void changeAgeIndicator(uint32_t indicator) { ageIndicator = indicator; }
|
||||
|
||||
const DirDetailsVector *requestDirDetails(void *ref, bool remote) const;
|
||||
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;
|
||||
@ -166,6 +169,8 @@ class TreeStyle_RDM: public RetroshareDirModel
|
||||
virtual ~TreeStyle_RDM() ;
|
||||
|
||||
protected:
|
||||
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;
|
||||
@ -189,7 +194,7 @@ class FlatStyle_RDM: public RetroshareDirModel
|
||||
|
||||
public:
|
||||
FlatStyle_RDM(bool mode)
|
||||
: RetroshareDirModel(mode)
|
||||
: RetroshareDirModel(mode), _ref_mutex("Flat file list")
|
||||
{
|
||||
_needs_update = true ;
|
||||
}
|
||||
@ -202,6 +207,7 @@ class FlatStyle_RDM: public RetroshareDirModel
|
||||
void updateRefs() ;
|
||||
|
||||
protected:
|
||||
virtual void updateRef(const QModelIndex&) const {}
|
||||
virtual void postMods();
|
||||
|
||||
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
@ -217,7 +223,8 @@ class FlatStyle_RDM: public RetroshareDirModel
|
||||
|
||||
QString computeDirectoryPath(const DirDetails& details) const ;
|
||||
|
||||
std::vector<std::pair<void *,QString> > _ref_entries ;// used to store the refs to display
|
||||
mutable RsMutex _ref_mutex ;
|
||||
std::vector<void *> _ref_entries ;// used to store the refs to display
|
||||
std::vector<void *> _ref_stack ; // used to store the refs to update
|
||||
bool _needs_update ;
|
||||
};
|
||||
|
@ -148,7 +148,7 @@ void ShareManager::load()
|
||||
|
||||
GroupFlagsWidget *widget = new GroupFlagsWidget(NULL,(*it).shareflags);
|
||||
|
||||
listWidget->setRowHeight(row, 32);
|
||||
listWidget->setRowHeight(row, 32 * QFontMetricsF(font()).height()/14.0);
|
||||
listWidget->setCellWidget(row, COLUMN_SHARE_FLAGS, widget);
|
||||
|
||||
listWidget->setItem(row, COLUMN_GROUPS, new QTableWidgetItem()) ;
|
||||
@ -157,7 +157,7 @@ void ShareManager::load()
|
||||
//connect(widget,SIGNAL(flagsChanged(FileStorageFlags)),this,SLOT(updateFlags())) ;
|
||||
}
|
||||
|
||||
listWidget->setColumnWidth(COLUMN_SHARE_FLAGS,132) ;
|
||||
listWidget->setColumnWidth(COLUMN_SHARE_FLAGS,132 * QFontMetricsF(font()).height()/14.0) ;
|
||||
|
||||
//ui.incomingDir->setText(QString::fromStdString(rsFiles->getDownloadDirectory()));
|
||||
|
||||
@ -282,6 +282,7 @@ void ShareManager::editShareDirectory()
|
||||
ShareDialog sharedlg (it->filename, this);
|
||||
sharedlg.setWindowTitle(tr("Edit Shared Folder"));
|
||||
sharedlg.exec();
|
||||
load();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -318,6 +319,7 @@ void ShareManager::showShareDialog()
|
||||
{
|
||||
ShareDialog sharedlg ("", this);
|
||||
sharedlg.exec();
|
||||
load();
|
||||
}
|
||||
|
||||
void ShareManager::shareddirListCurrentCellChanged(int currentRow, int currentColumn, int previousRow, int previousColumn)
|
||||
@ -387,4 +389,6 @@ void ShareManager::dropEvent(QDropEvent *event)
|
||||
|
||||
event->setDropAction(Qt::CopyAction);
|
||||
event->accept();
|
||||
|
||||
load();
|
||||
}
|
||||
|
@ -19,6 +19,8 @@
|
||||
* Boston, MA 02110-1301, USA.
|
||||
****************************************************************/
|
||||
|
||||
#include <set>
|
||||
|
||||
#include <QString>
|
||||
#include <QTreeView>
|
||||
#include <QClipboard>
|
||||
@ -83,6 +85,8 @@
|
||||
//
|
||||
#define DONT_USE_SEARCH_IN_TREE_VIEW 1
|
||||
|
||||
//#define DEBUG_SHARED_FILES_DIALOG 1
|
||||
|
||||
const QString Image_AddNewAssotiationForFile = ":/images/kcmsystem24.png";
|
||||
|
||||
class SFDSortFilterProxyModel : public QSortFilterProxyModel
|
||||
@ -134,19 +138,22 @@ SharedFilesDialog::SharedFilesDialog(RetroshareDirModel *_tree_model,RetroshareD
|
||||
flat_model = _flat_model ;
|
||||
|
||||
tree_proxyModel = new SFDSortFilterProxyModel(tree_model, this);
|
||||
tree_proxyModel->setDynamicSortFilter(true);
|
||||
tree_proxyModel->setSourceModel(tree_model);
|
||||
tree_proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||
tree_proxyModel->setSortRole(RetroshareDirModel::SortRole);
|
||||
tree_proxyModel->sort(COLUMN_NAME);
|
||||
|
||||
flat_proxyModel = new SFDSortFilterProxyModel(flat_model, this);
|
||||
flat_proxyModel->setDynamicSortFilter(true);
|
||||
flat_proxyModel->setSourceModel(flat_model);
|
||||
flat_proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||
flat_proxyModel->setSortRole(RetroshareDirModel::SortRole);
|
||||
flat_proxyModel->sort(COLUMN_NAME);
|
||||
|
||||
// Mr.Alice: I removed this because it causes a crash for some obscur reason. Apparently when the model is changed, the proxy model cannot
|
||||
// deal with the change by itself. Should I call something specific? I've no idea. Removing this does not seem to cause any harm either.
|
||||
//tree_proxyModel->setDynamicSortFilter(true);
|
||||
//flat_proxyModel->setDynamicSortFilter(true);
|
||||
|
||||
connect(ui.filterClearButton, SIGNAL(clicked()), this, SLOT(clearFilter()));
|
||||
connect(ui.filterStartButton, SIGNAL(clicked()), this, SLOT(startFilter()));
|
||||
connect(ui.filterPatternLineEdit, SIGNAL(returnPressed()), this, SLOT(startFilter()));
|
||||
@ -224,6 +231,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);
|
||||
@ -248,8 +256,13 @@ void SharedFilesDialog::showEvent(QShowEvent *)
|
||||
{
|
||||
if(model!=NULL)
|
||||
{
|
||||
std::set<std::string> expanded_indexes ;
|
||||
saveExpandedPaths(expanded_indexes);
|
||||
|
||||
model->setVisible(true) ;
|
||||
model->update() ;
|
||||
|
||||
restoreExpandedPaths(expanded_indexes);
|
||||
}
|
||||
}
|
||||
RemoteSharedFilesDialog::~RemoteSharedFilesDialog()
|
||||
@ -346,23 +359,29 @@ void SharedFilesDialog::changeCurrentViewModel(int viewTypeIndex)
|
||||
|
||||
showProperColumns() ;
|
||||
|
||||
std::set<std::string> expanded_indexes ;
|
||||
saveExpandedPaths(expanded_indexes);
|
||||
|
||||
if(isVisible())
|
||||
{
|
||||
model->setVisible(true) ;
|
||||
|
||||
model->update() ;
|
||||
}
|
||||
|
||||
//connect( ui.dirTreeView, SIGNAL( collapsed(const QModelIndex & ) ), model, SLOT( collapsed(const QModelIndex & ) ) );
|
||||
//connect( ui.dirTreeView, SIGNAL( expanded(const QModelIndex & ) ), model, SLOT( expanded(const QModelIndex & ) ) );
|
||||
// connect( ui.dirTreeView, SIGNAL( collapsed(const QModelIndex & ) ), this, SLOT( collapsed(const QModelIndex & ) ) );
|
||||
|
||||
ui.dirTreeView->setModel(proxyModel);
|
||||
ui.dirTreeView->update();
|
||||
|
||||
restoreExpandedPaths(expanded_indexes);
|
||||
|
||||
QHeaderView * header = ui.dirTreeView->header () ;
|
||||
QHeaderView_setSectionResizeModeColumn(header, COLUMN_NAME, QHeaderView::Interactive);
|
||||
|
||||
ui.dirTreeView->header()->headerDataChanged(Qt::Horizontal, COLUMN_NAME, COLUMN_DIR) ;
|
||||
|
||||
// recursRestoreExpandedItems(ui.dirTreeView->rootIndex(),expanded_indexes);
|
||||
FilterItems();
|
||||
}
|
||||
|
||||
@ -501,6 +520,15 @@ QModelIndexList SharedFilesDialog::getSelected()
|
||||
return proxyList ;
|
||||
}
|
||||
|
||||
void RemoteSharedFilesDialog::expanded(const QModelIndex& indx)
|
||||
{
|
||||
#ifdef DEBUG_SHARED_FILES_DIALOG
|
||||
std::cerr << "Expanding at " << indx.row() << " and " << indx.column() << " ref=" << indx.internalPointer() << ", pointer at 1: " << proxyModel->mapToSource(indx).internalPointer() << std::endl;
|
||||
#endif
|
||||
|
||||
model->updateRef(proxyModel->mapToSource(indx)) ;
|
||||
}
|
||||
|
||||
void RemoteSharedFilesDialog::downloadRemoteSelected()
|
||||
{
|
||||
/* call back to the model (which does all the interfacing? */
|
||||
@ -544,9 +572,9 @@ void SharedFilesDialog::copyLink (const QModelIndexList& lst, bool remote)
|
||||
|
||||
if (details.type == DIR_TYPE_DIR)
|
||||
{
|
||||
for (std::list<DirStub>::const_iterator cit = details.children.begin();cit != details.children.end(); ++cit)
|
||||
for(uint32_t j=0;j<details.children.size();++j)
|
||||
{
|
||||
const DirStub& dirStub = *cit;
|
||||
const DirStub& dirStub = details.children[j];
|
||||
|
||||
DirDetails details;
|
||||
FileSearchFlags flags = remote?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL ;
|
||||
@ -823,20 +851,109 @@ void SharedFilesDialog::preModDirectories(bool local)
|
||||
flat_model->preMods();
|
||||
}
|
||||
|
||||
void SharedFilesDialog::saveExpandedPaths(std::set<std::string>& expanded_indexes)
|
||||
{
|
||||
if(ui.dirTreeView->model() == NULL)
|
||||
return ;
|
||||
|
||||
#ifdef DEBUG_SHARED_FILES_DIALOG
|
||||
std::cerr << "Saving expanded items. " << std::endl;
|
||||
#endif
|
||||
for(int row = 0; row < ui.dirTreeView->model()->rowCount(); ++row)
|
||||
{
|
||||
std::string path = ui.dirTreeView->model()->index(row,0).data(Qt::DisplayRole).toString().toStdString();
|
||||
recursSaveExpandedItems(ui.dirTreeView->model()->index(row,0),path,expanded_indexes);
|
||||
}
|
||||
}
|
||||
|
||||
void SharedFilesDialog::restoreExpandedPaths(const std::set<std::string>& expanded_indexes)
|
||||
{
|
||||
if(ui.dirTreeView->model() == NULL)
|
||||
return ;
|
||||
|
||||
// we need to disable this, because the signal will trigger unnecessary update at the friend.
|
||||
|
||||
ui.dirTreeView->blockSignals(true) ;
|
||||
|
||||
#ifdef DEBUG_SHARED_FILES_DIALOG
|
||||
std::cerr << "Restoring expanded items. " << std::endl;
|
||||
#endif
|
||||
for(int row = 0; row < ui.dirTreeView->model()->rowCount(); ++row)
|
||||
{
|
||||
std::string path = ui.dirTreeView->model()->index(row,0).data(Qt::DisplayRole).toString().toStdString();
|
||||
recursRestoreExpandedItems(ui.dirTreeView->model()->index(row,0),path,expanded_indexes);
|
||||
}
|
||||
ui.dirTreeView->blockSignals(false) ;
|
||||
}
|
||||
|
||||
void SharedFilesDialog::recursSaveExpandedItems(const QModelIndex& index,const std::string& path,std::set<std::string>& exp)
|
||||
{
|
||||
std::string local_path = path+"/"+index.data(Qt::DisplayRole).toString().toStdString();
|
||||
#ifdef DEBUG_SHARED_FILES_DIALOG
|
||||
std::cerr << "at index " << index.row() << ". data[1]=" << local_path << std::endl;
|
||||
#endif
|
||||
|
||||
if(ui.dirTreeView->isExpanded(index))
|
||||
{
|
||||
#ifdef DEBUG_SHARED_FILES_DIALOG
|
||||
std::cerr << "Index " << local_path << " is expanded." << std::endl;
|
||||
#endif
|
||||
if(index.isValid())
|
||||
exp.insert(local_path) ;
|
||||
|
||||
for(int row=0;row<ui.dirTreeView->model()->rowCount(index);++row)
|
||||
recursSaveExpandedItems(index.child(row,0),local_path,exp) ;
|
||||
}
|
||||
#ifdef DEBUG_SHARED_FILES_DIALOG
|
||||
else
|
||||
std::cerr << "Index is not expanded." << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
void SharedFilesDialog::recursRestoreExpandedItems(const QModelIndex& index, const std::string &path, const std::set<std::string>& exp)
|
||||
{
|
||||
std::string local_path = path+"/"+index.data(Qt::DisplayRole).toString().toStdString();
|
||||
#ifdef DEBUG_SHARED_FILES_DIALOG
|
||||
std::cerr << "at index " << index.row() << ". data[1]=" << local_path << std::endl;
|
||||
#endif
|
||||
|
||||
if(exp.find(local_path) != exp.end())
|
||||
{
|
||||
#ifdef DEBUG_SHARED_FILES_DIALOG
|
||||
std::cerr << "re expanding index " << local_path << std::endl;
|
||||
#endif
|
||||
ui.dirTreeView->setExpanded(index,true) ;
|
||||
|
||||
for(int row=0;row<ui.dirTreeView->model()->rowCount(index);++row)
|
||||
recursRestoreExpandedItems(index.child(row,0),local_path,exp) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SharedFilesDialog::postModDirectories(bool local)
|
||||
{
|
||||
if (isRemote() == local) {
|
||||
return;
|
||||
}
|
||||
std::set<std::string> expanded_indexes;
|
||||
saveExpandedPaths(expanded_indexes) ;
|
||||
#ifdef DEBUG_SHARED_FILES_DIALOG
|
||||
std::cerr << "Saving expanded items. " << expanded_indexes.size() << " items found" << std::endl;
|
||||
#endif
|
||||
|
||||
/* Notify both models, only one is visible */
|
||||
tree_model->postMods();
|
||||
flat_model->postMods();
|
||||
ui.dirTreeView->update() ;
|
||||
|
||||
restoreExpandedPaths(expanded_indexes) ;
|
||||
|
||||
if (ui.filterPatternLineEdit->text().isEmpty() == false)
|
||||
FilterItems();
|
||||
|
||||
#ifdef DEBUG_SHARED_FILES_DIALOG
|
||||
std::cerr << "****** updated directories! ******" << std::endl;
|
||||
#endif
|
||||
QCoreApplication::flush();
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#ifndef _SHAREDFILESDIALOG_H
|
||||
#define _SHAREDFILESDIALOG_H
|
||||
|
||||
#include <set>
|
||||
#include "RsAutoUpdatePage.h"
|
||||
#include "ui_SharedFilesDialog.h"
|
||||
|
||||
@ -51,7 +52,6 @@ protected slots:
|
||||
virtual void spawnCustomPopupMenu(QPoint point) = 0;
|
||||
|
||||
private slots:
|
||||
|
||||
/* For handling the model updates */
|
||||
void preModDirectories(bool local) ;
|
||||
void postModDirectories(bool local) ;
|
||||
@ -94,6 +94,11 @@ protected:
|
||||
Ui::SharedFilesDialog ui;
|
||||
virtual void processSettings(bool bLoad) = 0;
|
||||
|
||||
void recursRestoreExpandedItems(const QModelIndex& index,const std::string& path,const std::set<std::string>& exp);
|
||||
void recursSaveExpandedItems(const QModelIndex& index, const std::string &path, std::set<std::string> &exp);
|
||||
void saveExpandedPaths(std::set<std::string>& paths) ;
|
||||
void restoreExpandedPaths(const std::set<std::string>& paths) ;
|
||||
|
||||
protected:
|
||||
//now context menu are created again every time theu are called ( in some
|
||||
//slots.. Maybe it's not good...
|
||||
@ -191,6 +196,7 @@ class RemoteSharedFilesDialog : public SharedFilesDialog
|
||||
|
||||
private slots:
|
||||
void downloadRemoteSelected();
|
||||
void expanded(const QModelIndex& indx);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -119,9 +119,9 @@ void AdvancedSearchDialog::prepareSearch()
|
||||
}
|
||||
|
||||
|
||||
Expression * AdvancedSearchDialog::getRsExpr()
|
||||
RsRegularExpression::Expression * AdvancedSearchDialog::getRsExpr()
|
||||
{
|
||||
Expression * wholeExpression;
|
||||
RsRegularExpression::Expression * wholeExpression;
|
||||
|
||||
// process the special case: first expression
|
||||
wholeExpression = expressions->at(0)->getRsExpression();
|
||||
@ -131,7 +131,7 @@ Expression * AdvancedSearchDialog::getRsExpr()
|
||||
for (int i = 1; i < expressions->size(); ++i) {
|
||||
// extract the expression information and compound it with the
|
||||
// first expression
|
||||
wholeExpression = new CompoundExpression(expressions->at(i)->getOperator(),
|
||||
wholeExpression = new RsRegularExpression::CompoundExpression(expressions->at(i)->getOperator(),
|
||||
wholeExpression,
|
||||
expressions->at(i)->getRsExpression());
|
||||
}
|
||||
|
@ -36,10 +36,10 @@ class AdvancedSearchDialog : public QDialog, public Ui::AdvancedSearchDialog
|
||||
|
||||
public:
|
||||
AdvancedSearchDialog(QWidget * parent = 0 );
|
||||
Expression * getRsExpr();
|
||||
RsRegularExpression::Expression * getRsExpr();
|
||||
QString getSearchAsString();
|
||||
signals:
|
||||
void search(Expression*);
|
||||
void search(RsRegularExpression::Expression*);
|
||||
|
||||
private slots:
|
||||
void deleteExpression(ExpressionWidget*);
|
||||
|
@ -130,7 +130,7 @@ void ExpressionWidget::deleteExpression()
|
||||
emit signalDelete(this);
|
||||
}
|
||||
|
||||
LogicalOperator ExpressionWidget::getOperator()
|
||||
RsRegularExpression::LogicalOperator ExpressionWidget::getOperator()
|
||||
{
|
||||
return exprOpElem->getLogicalOperator();
|
||||
}
|
||||
@ -145,9 +145,9 @@ static int checkedConversion(uint64_t s)
|
||||
return (int)s ;
|
||||
}
|
||||
|
||||
Expression* ExpressionWidget::getRsExpression()
|
||||
RsRegularExpression::Expression* ExpressionWidget::getRsExpression()
|
||||
{
|
||||
Expression * expr = NULL;
|
||||
RsRegularExpression::Expression * expr = NULL;
|
||||
|
||||
std::list<std::string> wordList;
|
||||
uint64_t lowVal = 0;
|
||||
@ -174,54 +174,54 @@ Expression* ExpressionWidget::getRsExpression()
|
||||
switch (searchType)
|
||||
{
|
||||
case NameSearch:
|
||||
expr = new NameExpression(exprCondElem->getStringOperator(),
|
||||
expr = new RsRegularExpression::NameExpression(exprCondElem->getStringOperator(),
|
||||
wordList,
|
||||
exprParamElem->ignoreCase());
|
||||
break;
|
||||
case PathSearch:
|
||||
expr = new PathExpression(exprCondElem->getStringOperator(),
|
||||
expr = new RsRegularExpression::PathExpression(exprCondElem->getStringOperator(),
|
||||
wordList,
|
||||
exprParamElem->ignoreCase());
|
||||
break;
|
||||
case ExtSearch:
|
||||
expr = new ExtExpression(exprCondElem->getStringOperator(),
|
||||
expr = new RsRegularExpression::ExtExpression(exprCondElem->getStringOperator(),
|
||||
wordList,
|
||||
exprParamElem->ignoreCase());
|
||||
break;
|
||||
case HashSearch:
|
||||
expr = new HashExpression(exprCondElem->getStringOperator(),
|
||||
expr = new RsRegularExpression::HashExpression(exprCondElem->getStringOperator(),
|
||||
wordList);
|
||||
break;
|
||||
case DateSearch:
|
||||
if (inRangedConfig) {
|
||||
expr = new DateExpression(exprCondElem->getRelOperator(), checkedConversion(lowVal), checkedConversion(highVal));
|
||||
expr = new RsRegularExpression::DateExpression(exprCondElem->getRelOperator(), checkedConversion(lowVal), checkedConversion(highVal));
|
||||
} else {
|
||||
expr = new DateExpression(exprCondElem->getRelOperator(), checkedConversion(exprParamElem->getIntValue()));
|
||||
expr = new RsRegularExpression::DateExpression(exprCondElem->getRelOperator(), checkedConversion(exprParamElem->getIntValue()));
|
||||
}
|
||||
break;
|
||||
case PopSearch:
|
||||
if (inRangedConfig) {
|
||||
expr = new DateExpression(exprCondElem->getRelOperator(), checkedConversion(lowVal), checkedConversion(highVal));
|
||||
expr = new RsRegularExpression::DateExpression(exprCondElem->getRelOperator(), checkedConversion(lowVal), checkedConversion(highVal));
|
||||
} else {
|
||||
expr = new DateExpression(exprCondElem->getRelOperator(), checkedConversion(exprParamElem->getIntValue()));
|
||||
expr = new RsRegularExpression::DateExpression(exprCondElem->getRelOperator(), checkedConversion(exprParamElem->getIntValue()));
|
||||
}
|
||||
break;
|
||||
case SizeSearch:
|
||||
if (inRangedConfig)
|
||||
{
|
||||
if(lowVal >= (uint64_t)(1024*1024*1024) || highVal >= (uint64_t)(1024*1024*1024))
|
||||
expr = new SizeExpressionMB(exprCondElem->getRelOperator(), (int)(lowVal / (1024*1024)), (int)(highVal / (1024*1024)));
|
||||
expr = new RsRegularExpression::SizeExpressionMB(exprCondElem->getRelOperator(), (int)(lowVal / (1024*1024)), (int)(highVal / (1024*1024)));
|
||||
else
|
||||
expr = new SizeExpression(exprCondElem->getRelOperator(), lowVal, highVal);
|
||||
expr = new RsRegularExpression::SizeExpression(exprCondElem->getRelOperator(), lowVal, highVal);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64_t s = exprParamElem->getIntValue() ;
|
||||
|
||||
if(s >= (uint64_t)(1024*1024*1024))
|
||||
expr = new SizeExpressionMB(exprCondElem->getRelOperator(), (int)(s/(1024*1024))) ;
|
||||
expr = new RsRegularExpression::SizeExpressionMB(exprCondElem->getRelOperator(), (int)(s/(1024*1024))) ;
|
||||
else
|
||||
expr = new SizeExpression(exprCondElem->getRelOperator(), (int)s) ;
|
||||
expr = new RsRegularExpression::SizeExpression(exprCondElem->getRelOperator(), (int)s) ;
|
||||
}
|
||||
break;
|
||||
};
|
||||
|
@ -45,11 +45,11 @@ public:
|
||||
/** delivers the expression represented by this widget
|
||||
the operator to join this expression with any previous
|
||||
expressions is provided by the getOperator method */
|
||||
Expression* getRsExpression();
|
||||
RsRegularExpression::Expression* getRsExpression();
|
||||
|
||||
/** supplies the operator to be used when joining this expression
|
||||
to the whole query */
|
||||
LogicalOperator getOperator();
|
||||
RsRegularExpression::LogicalOperator getOperator();
|
||||
|
||||
QString toString();
|
||||
|
||||
|
@ -62,9 +62,9 @@ QStringList GuiExprElement::relOptionsList;
|
||||
|
||||
QMap<int, ExprSearchType> GuiExprElement::TermsIndexMap;
|
||||
|
||||
QMap<int, LogicalOperator> GuiExprElement::logicalOpIndexMap;
|
||||
QMap<int, StringOperator> GuiExprElement::strConditionIndexMap;
|
||||
QMap<int, RelOperator> GuiExprElement::relConditionIndexMap;
|
||||
QMap<int, RsRegularExpression::LogicalOperator> GuiExprElement::logicalOpIndexMap;
|
||||
QMap<int, RsRegularExpression::StringOperator> GuiExprElement::strConditionIndexMap;
|
||||
QMap<int, RsRegularExpression::RelOperator> GuiExprElement::relConditionIndexMap;
|
||||
|
||||
QMap<int, QString> GuiExprElement::logicalOpStrMap;
|
||||
QMap<int, QString> GuiExprElement::termsStrMap;
|
||||
@ -141,9 +141,9 @@ void GuiExprElement::initialiseOptionsLists()
|
||||
GuiExprElement::relOptionsList.append(RANGE);
|
||||
|
||||
// now the maps
|
||||
GuiExprElement::logicalOpIndexMap[GuiExprElement::AND_INDEX] = AndOp;
|
||||
GuiExprElement::logicalOpIndexMap[GuiExprElement::OR_INDEX] = OrOp;
|
||||
GuiExprElement::logicalOpIndexMap[GuiExprElement::XOR_INDEX] = XorOp;
|
||||
GuiExprElement::logicalOpIndexMap[GuiExprElement::AND_INDEX] = RsRegularExpression::AndOp;
|
||||
GuiExprElement::logicalOpIndexMap[GuiExprElement::OR_INDEX] = RsRegularExpression::OrOp;
|
||||
GuiExprElement::logicalOpIndexMap[GuiExprElement::XOR_INDEX] = RsRegularExpression::XorOp;
|
||||
|
||||
GuiExprElement::TermsIndexMap[GuiExprElement::NAME_INDEX] = NameSearch;
|
||||
GuiExprElement::TermsIndexMap[GuiExprElement::PATH_INDEX] = PathSearch;
|
||||
@ -153,9 +153,9 @@ void GuiExprElement::initialiseOptionsLists()
|
||||
GuiExprElement::TermsIndexMap[GuiExprElement::SIZE_INDEX] = SizeSearch;
|
||||
GuiExprElement::TermsIndexMap[GuiExprElement::POP_INDEX] = PopSearch;
|
||||
|
||||
GuiExprElement::strConditionIndexMap[GuiExprElement::CONTAINS_INDEX] = ContainsAnyStrings;
|
||||
GuiExprElement::strConditionIndexMap[GuiExprElement::CONTALL_INDEX] = ContainsAllStrings;
|
||||
GuiExprElement::strConditionIndexMap[GuiExprElement::IS_INDEX] = EqualsString;
|
||||
GuiExprElement::strConditionIndexMap[GuiExprElement::CONTAINS_INDEX] = RsRegularExpression::ContainsAnyStrings;
|
||||
GuiExprElement::strConditionIndexMap[GuiExprElement::CONTALL_INDEX] = RsRegularExpression::ContainsAllStrings;
|
||||
GuiExprElement::strConditionIndexMap[GuiExprElement::IS_INDEX] = RsRegularExpression::EqualsString;
|
||||
|
||||
/* W A R N I N G !!!!
|
||||
the cb elements correspond to their inverse rel op counterparts in rsexpr.h due to the nature of
|
||||
@ -166,12 +166,12 @@ void GuiExprElement::initialiseOptionsLists()
|
||||
files where the condition is greater than the file size i.e. files whose size is less than or equal to the condition
|
||||
Therefore we invert the mapping of rel conditions here to match the behaviour of the impl.
|
||||
*/
|
||||
GuiExprElement::relConditionIndexMap[GuiExprElement::LT_INDEX] = GreaterEquals;
|
||||
GuiExprElement::relConditionIndexMap[GuiExprElement::LTE_INDEX] = Greater;
|
||||
GuiExprElement::relConditionIndexMap[GuiExprElement::EQUAL_INDEX] = Equals;
|
||||
GuiExprElement::relConditionIndexMap[GuiExprElement::GTE_INDEX] = Smaller;
|
||||
GuiExprElement::relConditionIndexMap[GuiExprElement::GT_INDEX] = SmallerEquals;
|
||||
GuiExprElement::relConditionIndexMap[GuiExprElement::RANGE_INDEX] = InRange;
|
||||
GuiExprElement::relConditionIndexMap[GuiExprElement::LT_INDEX] = RsRegularExpression::GreaterEquals;
|
||||
GuiExprElement::relConditionIndexMap[GuiExprElement::LTE_INDEX] = RsRegularExpression::Greater;
|
||||
GuiExprElement::relConditionIndexMap[GuiExprElement::EQUAL_INDEX] = RsRegularExpression::Equals;
|
||||
GuiExprElement::relConditionIndexMap[GuiExprElement::GTE_INDEX] = RsRegularExpression::Smaller;
|
||||
GuiExprElement::relConditionIndexMap[GuiExprElement::GT_INDEX] = RsRegularExpression::SmallerEquals;
|
||||
GuiExprElement::relConditionIndexMap[GuiExprElement::RANGE_INDEX] = RsRegularExpression::InRange;
|
||||
|
||||
// the string to index map
|
||||
GuiExprElement::termsStrMap[GuiExprElement::NAME_INDEX] = NAME;
|
||||
@ -260,7 +260,7 @@ QString ExprOpElement::toString()
|
||||
}
|
||||
|
||||
|
||||
LogicalOperator ExprOpElement::getLogicalOperator()
|
||||
RsRegularExpression::LogicalOperator ExprOpElement::getLogicalOperator()
|
||||
{
|
||||
return GuiExprElement::logicalOpIndexMap[cb->currentIndex()];
|
||||
}
|
||||
@ -313,12 +313,12 @@ QString ExprConditionElement::toString()
|
||||
return GuiExprElement::relConditionStrMap[cb->currentIndex()];
|
||||
}
|
||||
|
||||
RelOperator ExprConditionElement::getRelOperator()
|
||||
RsRegularExpression::RelOperator ExprConditionElement::getRelOperator()
|
||||
{
|
||||
return GuiExprElement::relConditionIndexMap[cb->currentIndex()];
|
||||
}
|
||||
|
||||
StringOperator ExprConditionElement::getStringOperator()
|
||||
RsRegularExpression::StringOperator ExprConditionElement::getStringOperator()
|
||||
{
|
||||
return GuiExprElement::strConditionIndexMap[cb->currentIndex()];
|
||||
}
|
||||
|
@ -114,9 +114,9 @@ protected:
|
||||
static QStringList relOptionsList;
|
||||
|
||||
// provides a mapping of condition operators to RSExpr reloperators
|
||||
static QMap<int, LogicalOperator> logicalOpIndexMap;
|
||||
static QMap<int, StringOperator> strConditionIndexMap;
|
||||
static QMap<int, RelOperator> relConditionIndexMap;
|
||||
static QMap<int, RsRegularExpression::LogicalOperator> logicalOpIndexMap;
|
||||
static QMap<int, RsRegularExpression::StringOperator> strConditionIndexMap;
|
||||
static QMap<int, RsRegularExpression::RelOperator> relConditionIndexMap;
|
||||
|
||||
// provides a mapping of indexes to translatable strings
|
||||
static QMap<int, QString> logicalOpStrMap;
|
||||
@ -134,7 +134,7 @@ class ExprOpElement : public GuiExprElement
|
||||
|
||||
public:
|
||||
ExprOpElement(QWidget * parent = 0);
|
||||
LogicalOperator getLogicalOperator();
|
||||
RsRegularExpression::LogicalOperator getLogicalOperator();
|
||||
QString toString();
|
||||
private:
|
||||
QComboBox * cb;
|
||||
@ -148,8 +148,8 @@ class ExprTermsElement : public GuiExprElement
|
||||
public:
|
||||
ExprTermsElement(QWidget * parent = 0);
|
||||
int getTermsIndex();
|
||||
RelOperator getRelOperator();
|
||||
StringOperator getStringOperator();
|
||||
RsRegularExpression::RelOperator getRelOperator();
|
||||
RsRegularExpression::StringOperator getStringOperator();
|
||||
void set(int i) {cb->setCurrentIndex(i);}
|
||||
QString toString();
|
||||
|
||||
@ -167,8 +167,8 @@ class ExprConditionElement : public GuiExprElement
|
||||
|
||||
public:
|
||||
ExprConditionElement(ExprSearchType, QWidget * parent = 0);
|
||||
RelOperator getRelOperator();
|
||||
StringOperator getStringOperator();
|
||||
RsRegularExpression::RelOperator getRelOperator();
|
||||
RsRegularExpression::StringOperator getStringOperator();
|
||||
void adjustForSearchType(ExprSearchType);
|
||||
void set(int i) {cb->setCurrentIndex(i);}
|
||||
QString toString();
|
||||
|
@ -35,8 +35,8 @@ GroupFlagsWidget::GroupFlagsWidget(QWidget *parent,FileStorageFlags flags)
|
||||
{
|
||||
_layout = new QHBoxLayout(this) ;
|
||||
|
||||
setMinimumSize(128,32) ;
|
||||
setMaximumSize(128,32) ;
|
||||
setMinimumSize(128 * QFontMetricsF(font()).height()/14.0,32 * QFontMetricsF(font()).height()/14.0) ;
|
||||
setMaximumSize(128 * QFontMetricsF(font()).height()/14.0,32 * QFontMetricsF(font()).height()/14.0) ;
|
||||
setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed);
|
||||
|
||||
_icons[INDEX_GROUP_BROWSABLE] = new QIcon(FLAGS_GROUP_BROWSABLE_ICON) ;
|
||||
@ -58,7 +58,7 @@ GroupFlagsWidget::GroupFlagsWidget(QWidget *parent,FileStorageFlags flags)
|
||||
_buttons[i] = new QPushButton(this) ;
|
||||
_buttons[i]->setCheckable(true) ;
|
||||
_buttons[i]->setChecked(flags & _flags[i]) ;
|
||||
_buttons[i]->setIconSize(QSize(32,32));
|
||||
_buttons[i]->setIconSize(QSize(32 * QFontMetricsF(font()).height()/14.0,32 * QFontMetricsF(font()).height()/14.0));
|
||||
update_button_state(_buttons[i]->isChecked(),i) ;
|
||||
_layout->addWidget(_buttons[i]) ;
|
||||
}
|
||||
|
@ -157,15 +157,15 @@ void RsCollectionFile::recursAddElements(QDomDocument& doc,const DirDetails& det
|
||||
|
||||
d.setAttribute(QString("name"),QString::fromUtf8(details.name.c_str())) ;
|
||||
|
||||
for (std::list<DirStub>::const_iterator it = details.children.begin(); it != details.children.end(); ++it)
|
||||
for(uint32_t i=0;i<details.children.size();++i)
|
||||
{
|
||||
if (!it->ref)
|
||||
if (!details.children[i].ref)
|
||||
continue;
|
||||
|
||||
DirDetails subDirDetails;
|
||||
FileSearchFlags flags = RS_FILE_HINTS_LOCAL;
|
||||
|
||||
if (!rsFiles->RequestDirDetails(it->ref, subDirDetails, flags))
|
||||
if (!rsFiles->RequestDirDetails(details.children[i].ref, subDirDetails, flags))
|
||||
continue;
|
||||
|
||||
recursAddElements(doc,subDirDetails,d) ;
|
||||
|
@ -36,18 +36,9 @@ DirectoriesPage::DirectoriesPage(QWidget * parent, Qt::WindowFlags flags)
|
||||
connect(ui.incomingButton, SIGNAL(clicked( bool ) ), this , SLOT( setIncomingDirectory() ) );
|
||||
connect(ui.partialButton, SIGNAL(clicked( bool ) ), this , SLOT( setPartialsDirectory() ) );
|
||||
connect(ui.editShareButton, SIGNAL(clicked()), this, SLOT(editDirectories()));
|
||||
connect(ui.cleanHashCachePB, SIGNAL(clicked()), this, SLOT(clearHashCache()));
|
||||
connect(ui.rememberHashesCB, SIGNAL(clicked(bool)), this, SLOT(clickedRememberHashes(bool)));
|
||||
connect(ui.rememberHashesCB, SIGNAL(clicked(bool)), this, SLOT(toggleRememberHashes()));
|
||||
connect(ui.autoCheckDirectories_CB, SIGNAL(clicked(bool)), this, SLOT(toggleAutoCheckDirectories(bool)));
|
||||
}
|
||||
|
||||
void DirectoriesPage::clearHashCache()
|
||||
{
|
||||
if(QMessageBox::question(this, tr("Cache cleaning confirmation"), tr("This will forget any former hash of non shared files. Do you confirm ?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes)
|
||||
rsFiles->clearHashCache() ;
|
||||
}
|
||||
|
||||
void DirectoriesPage::toggleAutoCheckDirectories(bool b)
|
||||
{
|
||||
ui.autoCheckDirectoriesDelay_SB->setEnabled(b);
|
||||
@ -58,28 +49,9 @@ void DirectoriesPage::editDirectories()
|
||||
ShareManager::showYourself() ;
|
||||
}
|
||||
|
||||
void DirectoriesPage::clickedRememberHashes(bool b)
|
||||
{
|
||||
if (!b) {
|
||||
if (QMessageBox::question(this,tr("Cache cleaning confirmation"), tr("This will forget any former hash of non shared files. Do you confirm ?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No) {
|
||||
ui.rememberHashesCB->setChecked(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DirectoriesPage::toggleRememberHashes()
|
||||
{
|
||||
bool b = ui.rememberHashesCB->isChecked();
|
||||
ui.rememberHashesSB->setEnabled(b);
|
||||
ui.cleanHashCachePB->setEnabled(b);
|
||||
}
|
||||
|
||||
/** Saves the changes on this page */
|
||||
bool DirectoriesPage::save(QString &/*errmsg*/)
|
||||
{
|
||||
rsFiles->setRememberHashFilesDuration(ui.rememberHashesSB->value());
|
||||
rsFiles->setWatchPeriod(ui.autoCheckDirectoriesDelay_SB->value());
|
||||
|
||||
std::string dir = ui.incomingDir->text().toUtf8().constData();
|
||||
if (!dir.empty())
|
||||
{
|
||||
@ -92,18 +64,8 @@ bool DirectoriesPage::save(QString &/*errmsg*/)
|
||||
rsFiles->setPartialsDirectory(dir);
|
||||
}
|
||||
|
||||
if (ui.rememberHashesCB->isChecked()) {
|
||||
rsFiles->setRememberHashFiles(true);
|
||||
} else {
|
||||
rsFiles->setRememberHashFiles(false);
|
||||
rsFiles->clearHashCache() ;
|
||||
}
|
||||
|
||||
if (ui.autoCheckDirectories_CB->isChecked()) {
|
||||
rsFiles->setWatchEnabled(ui.autoCheckDirectories_CB->isChecked()) ;
|
||||
rsFiles->setWatchPeriod(ui.autoCheckDirectoriesDelay_SB->value());
|
||||
} else {
|
||||
rsFiles->setWatchPeriod(-ui.autoCheckDirectoriesDelay_SB->value());
|
||||
}
|
||||
|
||||
rsFiles->shareDownloadDirectory(ui.shareDownloadDirectoryCB->isChecked());
|
||||
|
||||
@ -115,14 +77,9 @@ void DirectoriesPage::load()
|
||||
{
|
||||
ui.shareDownloadDirectoryCB->setChecked(rsFiles->getShareDownloadDirectory());
|
||||
|
||||
ui.rememberHashesSB->setValue(rsFiles->rememberHashFilesDuration());
|
||||
ui.rememberHashesCB->setChecked(rsFiles->rememberHashFiles());
|
||||
toggleRememberHashes();
|
||||
|
||||
int u = rsFiles->watchPeriod() ;
|
||||
ui.autoCheckDirectoriesDelay_SB->setValue(abs(u)) ;
|
||||
ui.autoCheckDirectories_CB->setChecked(u>0) ;
|
||||
ui.autoCheckDirectoriesDelay_SB->setEnabled(u>0) ;
|
||||
ui.autoCheckDirectoriesDelay_SB->setValue(u) ;
|
||||
ui.autoCheckDirectories_CB->setChecked(rsFiles->watchEnabled()) ; ;
|
||||
|
||||
ui.incomingDir->setText(QString::fromUtf8(rsFiles->getDownloadDirectory().c_str()));
|
||||
ui.partialsDir->setText(QString::fromUtf8(rsFiles->getPartialsDirectory().c_str()));
|
||||
|
@ -45,9 +45,6 @@ private slots:
|
||||
void editDirectories() ;
|
||||
void setIncomingDirectory();
|
||||
void setPartialsDirectory();
|
||||
void clearHashCache();
|
||||
void clickedRememberHashes(bool);
|
||||
void toggleRememberHashes();
|
||||
void toggleAutoCheckDirectories(bool);
|
||||
|
||||
private:
|
||||
|
@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>485</width>
|
||||
<width>895</width>
|
||||
<height>549</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -144,50 +144,7 @@
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="rememberHashesCB">
|
||||
<property name="toolTip">
|
||||
<string>Remember file hashes even if not shared.
|
||||
This might be useful if you're sharing an
|
||||
external HD, to avoid re-hashing files when
|
||||
you plug it in.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remember hashed files for </string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="rememberHashesSB">
|
||||
<property name="suffix">
|
||||
<string> days</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>365</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cleanHashCachePB">
|
||||
<property name="toolTip">
|
||||
<string>Forget any hashed file that is not anymore shared.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Clean Hash Cache</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
@ -240,9 +197,6 @@ you plug it in.</string>
|
||||
<tabstops>
|
||||
<tabstop>shareDownloadDirectoryCB</tabstop>
|
||||
<tabstop>editShareButton</tabstop>
|
||||
<tabstop>rememberHashesCB</tabstop>
|
||||
<tabstop>rememberHashesSB</tabstop>
|
||||
<tabstop>cleanHashCachePB</tabstop>
|
||||
<tabstop>autoCheckDirectories_CB</tabstop>
|
||||
<tabstop>autoCheckDirectoriesDelay_SB</tabstop>
|
||||
<tabstop>incomingDir</tabstop>
|
||||
|
@ -36,7 +36,6 @@ TransferPage::TransferPage(QWidget * parent, Qt::WindowFlags flags)
|
||||
ui.setupUi(this);
|
||||
|
||||
ui._queueSize_SB->setValue(rsFiles->getQueueSize()) ;
|
||||
ui._minPrioritized_SB->setValue(rsFiles->getMinPrioritizedTransfers()) ;
|
||||
|
||||
switch(rsFiles->defaultChunkStrategy())
|
||||
{
|
||||
@ -48,7 +47,6 @@ TransferPage::TransferPage(QWidget * parent, Qt::WindowFlags flags)
|
||||
ui._diskSpaceLimit_SB->setValue(rsFiles->freeDiskSpaceLimit()) ;
|
||||
|
||||
QObject::connect(ui._queueSize_SB,SIGNAL(valueChanged(int)),this,SLOT(updateQueueSize(int))) ;
|
||||
QObject::connect(ui._minPrioritized_SB,SIGNAL(valueChanged(int)),this,SLOT(updateMinPrioritized(int))) ;
|
||||
QObject::connect(ui._defaultStrategy_CB,SIGNAL(activated(int)),this,SLOT(updateDefaultStrategy(int))) ;
|
||||
QObject::connect(ui._diskSpaceLimit_SB,SIGNAL(valueChanged(int)),this,SLOT(updateDiskSizeLimit(int))) ;
|
||||
QObject::connect(ui._max_tr_up_per_sec_SB, SIGNAL( valueChanged( int ) ), this, SLOT( updateMaxTRUpRate(int) ) );
|
||||
@ -80,15 +78,7 @@ void TransferPage::updateDiskSizeLimit(int s)
|
||||
rsFiles->setFreeDiskSpaceLimit(s) ;
|
||||
}
|
||||
|
||||
void TransferPage::updateMinPrioritized(int s)
|
||||
{
|
||||
rsFiles->setMinPrioritizedTransfers(s) ;
|
||||
}
|
||||
void TransferPage::updateQueueSize(int s)
|
||||
{
|
||||
if(ui._minPrioritized_SB->value() > s)
|
||||
{
|
||||
ui._minPrioritized_SB->setValue(s) ;
|
||||
}
|
||||
rsFiles->setQueueSize(s) ;
|
||||
}
|
||||
|
@ -46,7 +46,6 @@ class TransferPage: public ConfigPage
|
||||
|
||||
public slots:
|
||||
void updateQueueSize(int) ;
|
||||
void updateMinPrioritized(int) ;
|
||||
void updateDefaultStrategy(int) ;
|
||||
void updateDiskSizeLimit(int) ;
|
||||
void updateMaxTRUpRate(int);
|
||||
|
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>604</width>
|
||||
<height>340</height>
|
||||
<width>700</width>
|
||||
<height>356</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
@ -28,13 +28,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Slots reserved for non-cache transfers:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
@ -76,19 +69,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="_minPrioritized_SB">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>You can use this to force RetroShare to download your files rather <br/>than cache files for as many slots as requested. Setting that number <br/>to be equal to the queue size above will always prioritize your files<br/>over cache. <br/><br/>It is however recommended to leave at least a few slots for cache files. For now, cache files are only used to transfer friend file lists.</p></body></html></string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>3</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="_defaultStrategy_CB">
|
||||
<property name="enabled">
|
||||
@ -168,12 +148,12 @@
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p>
|
||||
<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li>
|
||||
<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html></string>
|
||||
</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-size:8pt;"> is capable of transferring data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p>
|
||||
<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li>
|
||||
<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -382,7 +382,7 @@ feenableexcept(FE_INVALID | FE_DIVBYZERO);
|
||||
QObject::connect(notify,SIGNAL(deferredSignatureHandlingRequested()),notify,SLOT(handleSignatureEvent()),Qt::QueuedConnection) ;
|
||||
QObject::connect(notify,SIGNAL(chatLobbyTimeShift(int)),notify,SLOT(handleChatLobbyTimeShift(int)),Qt::QueuedConnection) ;
|
||||
QObject::connect(notify,SIGNAL(diskFull(int,int)) ,w ,SLOT(displayDiskSpaceWarning(int,int))) ;
|
||||
QObject::connect(notify,SIGNAL(filesPostModChanged(bool)) ,w ,SLOT(postModDirectories(bool) )) ;
|
||||
QObject::connect(notify,SIGNAL(filesPostModChanged(bool)) ,w ,SLOT(postModDirectories(bool)) ,Qt::QueuedConnection ) ;
|
||||
QObject::connect(notify,SIGNAL(transfersChanged()) ,w->transfersDialog ,SLOT(insertTransfers() )) ;
|
||||
QObject::connect(notify,SIGNAL(publicChatChanged(int)) ,w->friendsDialog ,SLOT(publicChatChanged(int) ));
|
||||
QObject::connect(notify,SIGNAL(neighboursChanged()) ,w->friendsDialog->networkDialog ,SLOT(securedUpdateDisplay())) ;
|
||||
|
@ -290,7 +290,7 @@ int RsIntroServer::checkForNewCerts()
|
||||
mCertCheckTime = now;
|
||||
struct stat64 buf;
|
||||
|
||||
while(dirIt.readdir())
|
||||
for(;dirIt.isValid();dirIt.next())
|
||||
{
|
||||
/* check entry type */
|
||||
std::string fname;
|
||||
|
@ -353,9 +353,9 @@ SOURCES += libretroshare/gxs/data_service/rsdataservice_test.cc \
|
||||
################################ dbase #####################################
|
||||
|
||||
|
||||
SOURCES += libretroshare/dbase/fisavetest.cc \
|
||||
libretroshare/dbase/fitest2.cc \
|
||||
libretroshare/dbase/searchtest.cc \
|
||||
#SOURCES += libretroshare/dbase/fisavetest.cc \
|
||||
# libretroshare/dbase/fitest2.cc \
|
||||
# libretroshare/dbase/searchtest.cc \
|
||||
|
||||
# libretroshare/dbase/ficachetest.cc \
|
||||
# libretroshare/dbase/fimontest.cc \
|
||||
|
Loading…
Reference in New Issue
Block a user