mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
74961774cc
* Implemented start/stop interface in udpbitdht and bemanager * added Restart of DHT if it fails to get going. * added start / stop functionality to bdnode and bdstore * added cleanup code to rest of bitdht classes. * reworked NetworkSize calc functions. * added thread debugging (prints at start / stop / join). * TESTS: added utest.h header file for automated unit testing (from libretroshare) * TESTS: bdmetric_test started conversion to automated tests * TESTS: udpbitdht_nettest. Added dht start / stop and network reset (thread join) functionality. * TESTS: fresh bdboot.txt git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@3678 b45a01b8-16f6-495d-af2f-9b41ad6348cc
288 lines
6.6 KiB
C++
288 lines
6.6 KiB
C++
/*
|
|
* bitdht/bdhash.cc
|
|
*
|
|
* BitDHT: An Flexible DHT library.
|
|
*
|
|
* Copyright 2010 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 3 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 "bitdht@lunamutt.com".
|
|
*
|
|
*/
|
|
|
|
|
|
#include "bitdht/bdhash.h"
|
|
#include "bitdht/bdstddht.h"
|
|
#include <iostream>
|
|
|
|
bdHashEntry::bdHashEntry(std::string value, std::string secret, time_t lifetime, time_t store)
|
|
:mValue(value), mStoreTS(store), mSecret(secret), mLifetime(lifetime)
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
/**************************** class bdHashSet ********************************/
|
|
|
|
bdHashSet::bdHashSet(bdNodeId *id)
|
|
:mId(*id)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int bdHashSet::search(std::string key, uint32_t maxAge, std::list<bdHashEntry> &entries)
|
|
{
|
|
std::multimap<std::string, bdHashEntry>::iterator sit, eit, it;
|
|
sit = mEntries.lower_bound(key);
|
|
eit = mEntries.upper_bound(key);
|
|
|
|
time_t now = time(NULL);
|
|
|
|
for(it = sit; it != eit; it++)
|
|
{
|
|
time_t age = now - it->second.mStoreTS;
|
|
if (age < (int32_t) maxAge)
|
|
{
|
|
entries.push_back(it->second);
|
|
}
|
|
}
|
|
return (0 < entries.size());
|
|
}
|
|
|
|
/***
|
|
* With modification.
|
|
* If there is no secret -> it cannot be deleted (must timeout), but can be extended.
|
|
* If there is a secret -> must include it to modify.
|
|
*
|
|
* Therefore if identical entry without secret comes along - what do I do?
|
|
* -> create duplicate?
|
|
*/
|
|
|
|
int bdHashSet::modify(std::string key, bdHashEntry *entry, uint32_t modFlags)
|
|
{
|
|
std::multimap<std::string, bdHashEntry>::iterator sit, eit, it;
|
|
sit = mEntries.lower_bound(key);
|
|
eit = mEntries.upper_bound(key);
|
|
|
|
time_t now = time(NULL);
|
|
|
|
bool updated = false;
|
|
for(it = sit; it != eit; it++)
|
|
{
|
|
/* check it all */
|
|
if (it->second.mValue == entry->mValue)
|
|
{
|
|
bool noSecret = (it->second.mSecret == "");
|
|
bool sameSecret = (it->second.mSecret == entry->mSecret);
|
|
bool update = false;
|
|
|
|
if (noSecret && sameSecret)
|
|
{
|
|
/* only allowed to increase lifetime */
|
|
if (modFlags == BITDHT_HASH_ENTRY_ADD)
|
|
{
|
|
time_t existKillTime = it->second.mLifetime + it->second.mStoreTS;
|
|
time_t newKillTime = entry->mLifetime + now;
|
|
if (newKillTime > existKillTime)
|
|
{
|
|
update = true;
|
|
}
|
|
}
|
|
}
|
|
else if (sameSecret)
|
|
{
|
|
if (modFlags == BITDHT_HASH_ENTRY_ADD)
|
|
{
|
|
update = true;
|
|
}
|
|
else if (modFlags == BITDHT_HASH_ENTRY_DELETE)
|
|
{
|
|
/* do it here */
|
|
mEntries.erase(it);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
if (update)
|
|
{
|
|
it->second.mStoreTS = now;
|
|
it->second.mLifetime = entry->mLifetime;
|
|
updated = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((!updated) && (modFlags == BITDHT_HASH_ENTRY_ADD))
|
|
{
|
|
/* create a new entry */
|
|
bdHashEntry newEntry(entry->mValue, entry->mSecret, entry->mLifetime, now);
|
|
mEntries.insert(std::pair<std::string, bdHashEntry>(key, newEntry));
|
|
updated = true;
|
|
}
|
|
return updated;
|
|
}
|
|
|
|
int bdHashSet::printHashSet(std::ostream &out)
|
|
{
|
|
time_t now = time(NULL);
|
|
std::multimap<std::string, bdHashEntry>::iterator it;
|
|
out << "Hash: ";
|
|
bdStdPrintNodeId(out, &mId); // Allowing "Std" as we dont need dht functions everywhere.
|
|
out << std::endl;
|
|
|
|
for(it = mEntries.begin(); it != mEntries.end();it++)
|
|
{
|
|
time_t age = now - it->second.mStoreTS;
|
|
out << "\tK:" << bdStdConvertToPrintable(it->first);
|
|
out << " V:" << bdStdConvertToPrintable(it->second.mValue);
|
|
out << " A:" << age << " L:" << it->second.mLifetime;
|
|
out << " S:" << bdStdConvertToPrintable(it->second.mSecret);
|
|
out << std::endl;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
|
|
int bdHashSet::cleanupHashSet(uint32_t maxAge)
|
|
{
|
|
time_t now = time(NULL);
|
|
|
|
/* this is nasty... but don't know how to effectively remove from multimaps
|
|
* * Must do full repeat for each removal.
|
|
*/
|
|
|
|
std::multimap<std::string, bdHashEntry>::iterator it;
|
|
for(it = mEntries.begin(); it != mEntries.end();)
|
|
{
|
|
time_t age = now - it->second.mStoreTS;
|
|
if ((age > (int32_t) maxAge) || (age > it->second.mLifetime))
|
|
{
|
|
mEntries.erase(it);
|
|
it = mEntries.begin();
|
|
}
|
|
else
|
|
{
|
|
it++;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/******************************* class bdHashSpace ***************************/
|
|
|
|
bdHashSpace::bdHashSpace()
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* accessors */
|
|
int bdHashSpace::search(bdNodeId *id, std::string key, uint32_t maxAge, std::list<bdHashEntry> &entries)
|
|
{
|
|
std::map<bdNodeId, bdHashSet>::iterator it;
|
|
it = mHashTable.find(*id);
|
|
if (it == mHashTable.end())
|
|
{
|
|
/* no entry */
|
|
return 1;
|
|
}
|
|
|
|
return it->second.search(key, maxAge, entries);
|
|
}
|
|
|
|
int bdHashSpace::modify(bdNodeId *id, std::string key, bdHashEntry *entry, uint32_t modFlags)
|
|
{
|
|
std::map<bdNodeId, bdHashSet>::iterator it;
|
|
it = mHashTable.find(*id);
|
|
if (it == mHashTable.end())
|
|
{
|
|
if (modFlags == BITDHT_HASH_ENTRY_DELETE)
|
|
{
|
|
/* done already */
|
|
return 1;
|
|
}
|
|
|
|
//mHashTable[*id] = bdHashSet(id);
|
|
mHashTable.insert(std::pair<bdNodeId, bdHashSet>(*id, bdHashSet(id)));
|
|
it = mHashTable.find(*id);
|
|
}
|
|
|
|
return it->second.modify(key, entry, modFlags);
|
|
}
|
|
|
|
int bdHashSpace::printHashSpace(std::ostream &out)
|
|
{
|
|
std::map<bdNodeId, bdHashSet>::iterator it;
|
|
out << "bdHashSpace::printHashSpace()" << std::endl;
|
|
out << "--------------------------------------------" << std::endl;
|
|
|
|
for(it = mHashTable.begin(); it != mHashTable.end(); it++)
|
|
{
|
|
it->second.printHashSet(out);
|
|
}
|
|
out << "--------------------------------------------" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
int bdHashSpace::cleanHashSpace(bdNodeId *min, bdNodeId *max, time_t maxAge)
|
|
{
|
|
std::map<bdNodeId, bdHashSet>::iterator it;
|
|
std::list<bdNodeId> eraseList;
|
|
std::list<bdNodeId>::iterator eit;
|
|
|
|
for(it = mHashTable.begin(); it != mHashTable.end(); it++)
|
|
{
|
|
if ((it->first < *min) ||
|
|
(*max < it->first))
|
|
{
|
|
/* schedule for erasure */
|
|
eraseList.push_back(it->first);
|
|
}
|
|
else
|
|
{
|
|
/* clean up Hash Set */
|
|
it->second.cleanupHashSet(maxAge);
|
|
}
|
|
}
|
|
|
|
/* cleanup */
|
|
while(eraseList.size() > 0)
|
|
{
|
|
bdNodeId &eId = eraseList.front();
|
|
it = mHashTable.find(eId);
|
|
if (it != mHashTable.end())
|
|
{
|
|
mHashTable.erase(it);
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
int bdHashSpace::clear()
|
|
{
|
|
mHashTable.clear();
|
|
return 1;
|
|
}
|
|
|
|
|