Your IP : 216.73.216.48
/***************************************************************************
* Copyright (C) 2005 by Joris Guisson *
* joris.guisson@gmail.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef DHTKBUCKET_H
#define DHTKBUCKET_H
#include <set>
#include <QList>
#include <util/constants.h>
#include <net/address.h>
#include "key.h"
#include "rpccall.h"
#include "kbucketentry.h"
namespace bt
{
class File;
class BEncoder;
}
namespace dht
{
class RPCServerInterface;
class KClosestNodesSearch;
class Task;
const bt::Uint32 K = 20;
const bt::Uint32 BUCKET_MAGIC_NUMBER = 0xB0C4B0C4;
const bt::Uint32 BUCKET_REFRESH_INTERVAL = 15 * 60 * 1000;
/**
* @author Joris Guisson
*
* A KBucket is just a list of KBucketEntry objects.
* The list is sorted by time last seen :
* The first element is the least recently seen, the last
* the most recently seen.
*/
class KBucket : public RPCCallListener
{
Q_OBJECT
public:
KBucket(RPCServerInterface* srv, const Key & our_id);
KBucket(const dht::Key & min_key, const dht::Key & max_key, RPCServerInterface* srv, const Key & our_id);
virtual ~KBucket();
typedef QSharedPointer<KBucket> Ptr;
/// Get the min key
const dht::Key & minKey() const {return min_key;}
/// Get the max key
const dht::Key & maxKey() const {return max_key;}
/// Does the key k lies in in the range of this bucket
bool keyInRange(const dht::Key & k) const;
/// Are we allowed to split
bool splitAllowed() const;
class UnableToSplit
{};
/**
* Split the bucket in two new buckets, each containing half the range of the original one.
* @return A pair of KBucket's
* @throw UnableToSplit if something goes wrong
*/
std::pair<KBucket::Ptr, KBucket::Ptr> split() throw (UnableToSplit);
/**
* Inserts an entry into the bucket.
* @param entry The entry to insert
* @return true If the bucket needs to be splitted, false otherwise
*/
bool insert(const KBucketEntry & entry);
/// Get the least recently seen node
const KBucketEntry & leastRecentlySeen() const {return entries[0];}
/// Get the number of entries
bt::Uint32 getNumEntries() const {return entries.count();}
/// See if this bucket contains an entry
bool contains(const KBucketEntry & entry) const;
/**
* Find the K closest entries to a key and store them in the KClosestNodesSearch
* object.
* @param kns The object to storre the search results
*/
void findKClosestNodes(KClosestNodesSearch & kns);
/**
* A peer failed to respond
* @param addr Address of the peer
*/
bool onTimeout(const net::Address & addr);
/// Check if the bucket needs to be refreshed
bool needsToBeRefreshed() const;
/// save the bucket to a file
void save(bt::BEncoder & enc);
/// Load the bucket from a file
void load(bt::BDictNode* dict);
/// Update the refresh timer of the bucket
void updateRefreshTimer();
/// Set the refresh task
void setRefreshTask(Task* t);
private:
virtual void onResponse(RPCCall* c, RPCMsg::Ptr rsp);
virtual void onTimeout(RPCCall* c);
void pingQuestionable(const KBucketEntry & replacement_entry);
bool replaceBadEntry(const KBucketEntry & entry);
private slots:
void onFinished(Task* t);
private:
dht::Key min_key, max_key;
QList<KBucketEntry> entries, pending_entries;
RPCServerInterface* srv;
Key our_id;
QMap<RPCCall*, KBucketEntry> pending_entries_busy_pinging;
mutable bt::TimeStamp last_modified;
Task* refresh_task;
};
}
template <class T>
inline uint qHash(const T & e)
{
return e.hash();
}
#endif