Almost done... very few std::map<>s remaining in any spot that matters.

This commit is contained in:
Adam Ierymenko 2015-09-04 15:21:22 -07:00
parent db0369e9b8
commit 3dba016a93
3 changed files with 39 additions and 23 deletions

View File

@ -39,8 +39,9 @@ namespace ZeroTier {
* A minimal hash table implementation for the ZeroTier core
*
* This is not a drop-in replacement for STL containers, and has several
* limitations. It's designed to be small and fast for use in the
* ZeroTier core.
* limitations. Keys can be uint64_t or an object, and if the latter they
* must implement a method called hashCode() that returns an unsigned long
* value that is evenly distributed.
*/
template<typename K,typename V>
class Hashtable

View File

@ -309,31 +309,18 @@ bool Switch::unite(const Address &p1,const Address &p2,bool force)
const uint64_t now = RR->node->now();
std::pair<InetAddress,InetAddress> cg(Peer::findCommonGround(*p1p,*p2p,now));
if (!(cg.first))
return false;
if (cg.first.ipScope() != cg.second.ipScope())
return false;
// Addresses are sorted in key for last unite attempt map for order
// invariant lookup: (p1,p2) == (p2,p1)
Array<Address,2> uniteKey;
if (p1 >= p2) {
uniteKey[0] = p2;
uniteKey[1] = p1;
} else {
uniteKey[0] = p1;
uniteKey[1] = p2;
}
{
Mutex::Lock _l(_lastUniteAttempt_m);
std::map< Array< Address,2 >,uint64_t >::const_iterator e(_lastUniteAttempt.find(uniteKey));
if ((!force)&&(e != _lastUniteAttempt.end())&&((now - e->second) < ZT_MIN_UNITE_INTERVAL))
uint64_t &luts = _lastUniteAttempt[_LastUniteKey(p1,p2)];
if (((now - luts) < ZT_MIN_UNITE_INTERVAL)&&(!force))
return false;
else _lastUniteAttempt[uniteKey] = now;
luts = now;
}
std::pair<InetAddress,InetAddress> cg(Peer::findCommonGround(*p1p,*p2p,now));
if ((!(cg.first))||(cg.first.ipScope() != cg.second.ipScope()))
return false;
TRACE("unite: %s(%s) <> %s(%s)",p1.toString().c_str(),cg.second.toString().c_str(),p2.toString().c_str(),cg.first.toString().c_str());
/* Tell P1 where to find P2 and vice versa, sending the packets to P1 and
@ -543,6 +530,17 @@ unsigned long Switch::doTimerTasks(uint64_t now)
}
}
{ // Remove really old last unite attempt entries to keep table size controlled
Mutex::Lock _l(_lastUniteAttempt_m);
Hashtable< _LastUniteKey,uint64_t >::Iterator i(_lastUniteAttempt);
_LastUniteKey *k = (_LastUniteKey *)0;
uint64_t *v = (uint64_t *)0;
while (i.next(k,v)) {
if ((now - *v) >= (ZT_MIN_UNITE_INTERVAL * 16))
_lastUniteAttempt.erase(*k);
}
}
return nextDelay;
}

View File

@ -235,7 +235,24 @@ private:
Mutex _txQueue_m;
// Tracks sending of VERB_RENDEZVOUS to relaying peers
std::map< Array< Address,2 >,uint64_t > _lastUniteAttempt; // key is always sorted in ascending order, for set-like behavior
struct _LastUniteKey
{
_LastUniteKey() : x(0),y(0) {}
_LastUniteKey(const Address &a1,const Address &a2)
{
if (a1 > a2) {
x = a2.toInt();
y = a1.toInt();
} else {
x = a1.toInt();
y = a2.toInt();
}
}
inline unsigned long hashCode() const throw() { return ((unsigned long)x ^ (unsigned long)y); }
inline bool operator==(const _LastUniteKey &k) const throw() { return ((x == k.x)&&(y == k.y)); }
uint64_t x,y;
};
Hashtable< _LastUniteKey,uint64_t > _lastUniteAttempt; // key is always sorted in ascending order, for set-like behavior
Mutex _lastUniteAttempt_m;
// Active attempts to contact remote peers, including state of multi-phase NAT traversal