SlotAllocator.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "Qt.h"
00024 #include "SlotAllocator.h"
00025 #include "HandshakeSession.h"
00026 #include "Imports.cpp"
00027
00028 using namespace Gnutella::Handshaking;
00029
00030 namespace Gnutella {
00031 namespace Handshaking {
00032
00033 enum Constants
00034 {
00035 TotalHandshakingSlots = 5,
00036 TotalUltrapeerSlots = 2,
00037 TotalPeerSlots = 32,
00038 TotalLeafSlots = 0,
00039 BootstrappingThreshold = 4,
00040 WellConnectedThreshold = 24
00041 };
00042
00043 class SlotAllocatorPrivate
00044 {
00045 REFERENCE_OBJECT (SlotAllocatorPrivate)
00046
00047 public:
00048 LocalPeer *localPeer;
00049 uint freeHandshakingSlots;
00050 uint freeUltrapeerSlots;
00051 uint freePeerSlots;
00052 uint freeLeafSlots;
00053 QSignalMapper destroyedMapper;
00054
00055 SlotAllocatorPrivate (LocalPeer *localPeer_)
00056 : localPeer (localPeer_),
00057 freeHandshakingSlots (TotalHandshakingSlots),
00058 freeUltrapeerSlots (TotalUltrapeerSlots),
00059 freePeerSlots (TotalPeerSlots),
00060 freeLeafSlots (TotalLeafSlots),
00061 destroyedMapper()
00062 {}
00063 };
00064
00065 enum SlotType
00066 {
00067 HandshakingSlot,
00068 UltrapeerSlot,
00069 PeerSlot,
00070 LeafSlot
00071 };
00072
00073 struct Slot
00074 {
00075 SlotType type;
00076 };
00077
00078 }
00079 }
00080
00081 uint SlotAllocator::freeHandshakingSlots() const
00082 {
00083 return (p->freeHandshakingSlots > 0) ? p->freeHandshakingSlots : 0;
00084 }
00085
00086 uint SlotAllocator::freeUltrapeerSlots() const
00087 {
00088 return p->freeUltrapeerSlots;
00089 }
00090
00091 uint SlotAllocator::freePeerSlots() const
00092 {
00093 return p->freePeerSlots;
00094 }
00095
00096 uint SlotAllocator::freeLeafSlots() const
00097 {
00098 return p->freeLeafSlots;
00099 }
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 bool SlotAllocator::isBootstrapping() const
00124 {
00125 return (TotalPeerSlots - p->freePeerSlots) < BootstrappingThreshold;
00126 }
00127
00128 bool SlotAllocator::isWellConnected() const
00129 {
00130 return (TotalPeerSlots - p->freePeerSlots) >= WellConnectedThreshold;
00131 }
00132
00133 SlotAllocator::SlotAllocator (LocalPeer *localPeer)
00134 : p (new SlotAllocatorPrivate (localPeer))
00135 {
00136 connect (&p->destroyedMapper, SIGNAL (mapped (QObject *)),
00137 this, SLOT (freeSlot (QObject *)));
00138 }
00139
00140 SlotAllocator::~SlotAllocator()
00141 {
00142 delete p;
00143 }
00144
00145 bool SlotAllocator::hasSlotFor (const NodeInfo &otherNodeInfo) const
00146 {
00147 if (!p->localPeer->isUltrapeer()) {
00148 return hasFreeUltrapeerSlots();
00149 } else {
00150 if (otherNodeInfo.type == TypeLeaf)
00151 return hasFreeLeafSlots();
00152 else
00153 return hasFreePeerSlots();
00154 }
00155 }
00156
00157 bool SlotAllocator::allocateSlot (HandshakeSession *session)
00158 {
00159 qDebug() << "SlotAllocator::allocateSlot (handshakeSession)";
00160
00161 Q_ASSERT (session != 0);
00164 p->freeHandshakingSlots--;
00165 Slot *slot = new Slot;
00166 slot->type = HandshakingSlot;
00167 connect (session, SIGNAL (destroyed()), &p->destroyedMapper, SLOT (map()));
00168 p->destroyedMapper.setMapping (session, reinterpret_cast <QObject *> (slot));
00169
00170 qDebug() << "SlotAllocator::allocateSlot (handshakeSession) exit";
00171 return true;
00172 }
00173
00174 bool SlotAllocator::allocateSlot (PacketSession *session)
00175 {
00176 qDebug() << "SlotAllocator::allocateSlot (packetSession)";
00177
00178 NodeInfo otherNodeInfo = session->nodeInfo();
00179 if (!hasSlotFor (otherNodeInfo))
00180 return false;
00181
00182 Slot *slot = new Slot;
00183 if (!p->localPeer->isUltrapeer()) {
00184 slot->type = UltrapeerSlot;
00185 Q_ASSERT (p->freeUltrapeerSlots > 0);
00186 p->freeUltrapeerSlots--;
00187 } else {
00188 if (otherNodeInfo.type == TypeLeaf) {
00189 slot->type = LeafSlot;
00190 Q_ASSERT (p->freeLeafSlots > 0);
00191 p->freeLeafSlots--;
00192 } else {
00193 slot->type = PeerSlot;
00194 Q_ASSERT (p->freePeerSlots > 0);
00195 p->freePeerSlots--;
00196 }
00197 }
00198
00199 connect (session, SIGNAL (destroyed()), &p->destroyedMapper, SLOT (map()));
00200 p->destroyedMapper.setMapping (session, reinterpret_cast <QObject *> (slot));
00201
00202 return true;
00203 }
00204
00205 void SlotAllocator::freeSlot (QObject *pointer)
00206 {
00207 qDebug() << "SlotAllocator::freeSlot";
00208
00209 Slot *slot = reinterpret_cast <Slot *> (pointer);
00210 Q_ASSERT (slot != 0);
00211
00212 switch (slot->type) {
00213 case HandshakingSlot:
00214 p->freeHandshakingSlots++;
00215 emit handshakingSlotFreed();
00216 break;
00217 case LeafSlot:
00218 p->freeLeafSlots++;
00219 emit leafSlotFreed();
00220 break;
00221 case PeerSlot:
00222 p->freePeerSlots++;
00223 emit peerSlotFreed();
00224 break;
00225 case UltrapeerSlot:
00226 p->freeUltrapeerSlots++;
00227 emit ultrapeerSlotFreed();
00228 break;
00229 default:
00230 Q_ASSERT (false);
00231 break;
00232 }
00233 delete slot;
00234
00235
00236
00237 }