00001 #include "BaseConnectionManager.h"
00002
00003 #include "NicEntryDebug.h"
00004 #include "NicEntryDirect.h"
00005
00006 #include "BaseWorldUtility.h"
00007
00008 #include "FindModule.h"
00009
00010 #include <cassert>
00011
00012 #ifndef ccEV
00013 #define ccEV (ev.isDisabled()||!coreDebug) ? ev : ev << getName() << ": "
00014 #endif
00015
00016 void BaseConnectionManager::initialize(int stage)
00017 {
00018
00019
00020 if (stage == 0)
00021 {
00022 if(hasPar("coreDebug"))
00023 coreDebug = par("coreDebug").boolValue();
00024 else
00025 coreDebug = false;
00026
00027 drawMIR = hasPar("drawMaxIntfDist")
00028 ? par("drawMaxIntfDist").boolValue() : false;
00029
00030 ccEV <<"initializing BaseConnectionManager\n";
00031
00032 BaseWorldUtility* world = FindModule<BaseWorldUtility*>
00033 ::findGlobalModule();
00034
00035 assert(world != 0);
00036
00037 playgroundSize = world->getPgs();
00038 useTorus = world->useTorus();
00039
00040 if(hasPar("sendDirect"))
00041 sendDirect = par("sendDirect").boolValue();
00042 else
00043 sendDirect = false;
00044
00045 maxInterferenceDistance = calcInterfDist();
00046 maxDistSquared = maxInterferenceDistance * maxInterferenceDistance;
00047
00048
00049
00050
00051
00052 Coord dim((*playgroundSize) / maxInterferenceDistance);
00053 gridDim = GridCoord(dim);
00054
00055
00056
00057
00058
00059 if((gridDim.x <= 3) && (gridDim.y <= 3) && (gridDim.z <= 3))
00060 {
00061 gridDim.x = 1;
00062 gridDim.y = 1;
00063 gridDim.z = 1;
00064 } else {
00065 gridDim.x = std::max(1, gridDim.x);
00066 gridDim.y = std::max(1, gridDim.y);
00067 gridDim.z = std::max(1, gridDim.z);
00068 }
00069
00070
00071 NicEntries entries;
00072 RowVector row;
00073 NicMatrix matrix;
00074
00075 for (int i = 0; i < gridDim.z; ++i) {
00076 row.push_back(entries);
00077 }
00078 for (int i = 0; i < gridDim.y; ++i) {
00079 matrix.push_back(row);
00080 }
00081 for (int i = 0; i < gridDim.x; ++i) {
00082 nicGrid.push_back(matrix);
00083 }
00084 ccEV << " using " << gridDim.x << "x" <<
00085 gridDim.y << "x" <<
00086 gridDim.z << " grid" << endl;
00087
00088
00089
00090
00091 findDistance = Coord(std::max(playgroundSize->getX(),
00092 maxInterferenceDistance),
00093 std::max(playgroundSize->getY(),
00094 maxInterferenceDistance),
00095 std::max(playgroundSize->getZ(),
00096 maxInterferenceDistance));
00097
00098
00099 if (gridDim.x != 1)
00100 findDistance.setX(playgroundSize->getX() / gridDim.x);
00101 if (gridDim.y != 1)
00102 findDistance.setY(playgroundSize->getY() / gridDim.y);
00103 if (gridDim.z != 1)
00104 findDistance.setZ(playgroundSize->getZ() / gridDim.z);
00105
00106
00107
00108
00109
00110
00111 findDistance += Coord(EPSILON, EPSILON, EPSILON);
00112
00113
00114
00115 assert(findDistance.getX() >= maxInterferenceDistance);
00116 assert(findDistance.getY() >= maxInterferenceDistance);
00117 assert(world->use2D()
00118 || findDistance.getZ() >= maxInterferenceDistance);
00119
00120
00121 assert(GridCoord(*playgroundSize, findDistance).x == gridDim.x - 1);
00122 assert(GridCoord(*playgroundSize, findDistance).y == gridDim.y - 1);
00123 assert(GridCoord(*playgroundSize, findDistance).z == gridDim.z - 1);
00124 ccEV << "findDistance is " << findDistance.info() << endl;
00125 }
00126 else if (stage == 1)
00127 {
00128
00129 }
00130 }
00131
00132 BaseConnectionManager::GridCoord BaseConnectionManager
00133 ::getCellForCoordinate(const Coord& c)
00134 {
00135 return GridCoord(c, findDistance);
00136 }
00137
00138 void BaseConnectionManager::updateConnections(int nicID,
00139 const Coord* oldPos,
00140 const Coord* newPos)
00141 {
00142 GridCoord oldCell = getCellForCoordinate(*oldPos);
00143 GridCoord newCell = getCellForCoordinate(*newPos);
00144
00145 checkGrid(oldCell, newCell, nicID );
00146 }
00147
00148 BaseConnectionManager::NicEntries& BaseConnectionManager
00149 ::getCellEntries(BaseConnectionManager::GridCoord& cell)
00150 {
00151 return nicGrid[cell.x][cell.y][cell.z];
00152 }
00153
00154 void BaseConnectionManager::registerNicExt(int nicID)
00155 {
00156 NicEntry* nicEntry = nics[nicID];
00157
00158 GridCoord cell = getCellForCoordinate(nicEntry->pos);
00159
00160 ccEV <<" registering (ext) nic at loc " << cell.info() << std::endl;
00161
00162
00163 NicEntries& cellEntries = getCellEntries(cell);
00164 cellEntries[nicID] = nicEntry;
00165 }
00166
00167 void BaseConnectionManager::checkGrid(BaseConnectionManager::GridCoord& oldCell,
00168 BaseConnectionManager::GridCoord& newCell,
00169 int id)
00170
00171 {
00172
00173
00174 CoordSet gridUnion(74);
00175
00176
00177 NicEntries& oldCellEntries = getCellEntries(oldCell);
00178 NicEntries::iterator it = oldCellEntries.find(id);
00179 NicEntry *nic = it->second;
00180
00181
00182
00183 if(oldCell != newCell) {
00184 oldCellEntries.erase(it);
00185 getCellEntries(newCell)[id] = nic;
00186 }
00187
00188 if((gridDim.x == 1) && (gridDim.y == 1) && (gridDim.z == 1)) {
00189 gridUnion.add(oldCell);
00190 } else {
00191
00192 fillUnionWithNeighbors(gridUnion, oldCell);
00193
00194
00195 if(oldCell != newCell) {
00196
00197 fillUnionWithNeighbors(gridUnion, newCell);
00198 }
00199 }
00200
00201 GridCoord* c = gridUnion.next();
00202 while(c != 0) {
00203 ccEV << "Update cons in [" << c->info() << "]" << endl;
00204 updateNicConnections(getCellEntries(*c), nic);
00205 c = gridUnion.next();
00206 }
00207 }
00208
00209 int BaseConnectionManager::wrapIfTorus(int value, int max) {
00210 if(value < 0) {
00211 if(useTorus) {
00212 return max + value;
00213 } else {
00214 return -1;
00215 }
00216 } else if(value >= max) {
00217 if(useTorus) {
00218 return value - max;
00219 } else {
00220 return -1;
00221 }
00222 } else {
00223 return value;
00224 }
00225 }
00226
00227 void BaseConnectionManager::fillUnionWithNeighbors(CoordSet& gridUnion,
00228 GridCoord cell)
00229 {
00230 for(int iz = (int)cell.z - 1; iz <= (int)cell.z + 1; iz++) {
00231 if(iz != cell.z && cell.use2D) {
00232 continue;
00233 }
00234 int cz = wrapIfTorus(iz, gridDim.z);
00235 if(cz == -1) {
00236 continue;
00237 }
00238 for(int ix = (int)cell.x - 1; ix <= (int)cell.x + 1; ix++) {
00239 int cx = wrapIfTorus(ix, gridDim.x);
00240 if(cx == -1) {
00241 continue;
00242 }
00243 for(int iy = (int)cell.y - 1; iy <= (int)cell.y + 1; iy++) {
00244 int cy = wrapIfTorus(iy, gridDim.y);
00245 if(cy != -1) {
00246 if(cell.use2D) {
00247 gridUnion.add(GridCoord(cx, cy));
00248 } else {
00249 gridUnion.add(GridCoord(cx, cy, cz));
00250 }
00251 }
00252 }
00253 }
00254 }
00255 }
00256
00257 void BaseConnectionManager::updateNicConnections(NicEntries& nmap,
00258 NicEntry* nic)
00259 {
00260 int id = nic->nicId;
00261
00262 for(NicEntries::iterator i = nmap.begin(); i != nmap.end(); ++i)
00263 {
00264 NicEntry* nic_i = i->second;
00265
00266
00267 if ( nic_i->nicId == id ) continue;
00268
00269 double distance;
00270
00271 if(useTorus)
00272 {
00273 distance = nic->pos.sqrTorusDist(nic_i->pos, playgroundSize);
00274 } else {
00275 distance = nic->pos.sqrdist(nic_i->pos);
00276 }
00277
00278 bool inRange = (distance <= maxDistSquared);
00279 bool connected = nic->isConnected(nic_i);
00280
00281
00282 if ( inRange && !connected ){
00283
00284
00285 ccEV << "nic #" << id << " and #" << nic_i->nicId
00286 << " are in range" << endl;
00287 nic->connectTo( nic_i );
00288 nic_i->connectTo( nic );
00289 }
00290 else if ( !inRange && connected ){
00291
00292
00293 ccEV << "nic #" << id << " and #" << nic_i->nicId
00294 << " are NOT in range" << endl;
00295 nic->disconnectFrom( nic_i );
00296 nic_i->disconnectFrom( nic );
00297 }
00298 }
00299 }
00300
00301 bool BaseConnectionManager::registerNic(cModule* nic,
00302 ChannelAccess* chAccess,
00303 const Coord* nicPos)
00304 {
00305 assert(nic != 0);
00306
00307 int nicID = nic->getId();
00308 ccEV << " registering nic #" << nicID << endl;
00309
00310
00311 NicEntry *nicEntry;
00312
00313 if(sendDirect)
00314 nicEntry = new NicEntryDirect(coreDebug);
00315 else
00316 nicEntry = new NicEntryDebug(coreDebug);
00317
00318
00319 nicEntry->nicPtr = nic;
00320 nicEntry->nicId = nicID;
00321 nicEntry->hostId = nic->getParentModule()->getId();
00322 nicEntry->pos = nicPos;
00323 nicEntry->chAccess = chAccess;
00324
00325
00326 nics[nicID] = nicEntry;
00327
00328 registerNicExt(nicID);
00329
00330 updateConnections(nicID, nicPos, nicPos);
00331
00332 if(drawMIR) {
00333 nic->getParentModule()->getDisplayString().setTagArg("r", 0, maxInterferenceDistance);
00334 }
00335
00336 return sendDirect;
00337 }
00338
00339 bool BaseConnectionManager::unregisterNic(cModule* nicModule)
00340 {
00341 assert(nicModule != 0);
00342
00343
00344 int nicID = nicModule->getId();
00345 ccEV << " unregistering nic #" << nicID << endl;
00346
00347
00348
00349 assert(nics.find(nicID) != nics.end());
00350 NicEntry* nicEntry = nics[nicID];
00351
00352
00353 CoordSet gridUnion(74);
00354 GridCoord cell = getCellForCoordinate(nicEntry->pos);
00355 if((gridDim.x == 1) && (gridDim.y == 1) && (gridDim.z == 1)) {
00356 gridUnion.add(cell);
00357 } else {
00358 fillUnionWithNeighbors(gridUnion, cell);
00359 }
00360
00361
00362 GridCoord* c = gridUnion.next();
00363 while(c != 0) {
00364 ccEV << "Update cons in [" << c->info() << "]" << endl;
00365 NicEntries& nmap = getCellEntries(*c);
00366 for(NicEntries::iterator i = nmap.begin(); i != nmap.end(); ++i) {
00367 NicEntry* other = i->second;
00368 if (other == nicEntry) continue;
00369 if (!other->isConnected(nicEntry)) continue;
00370 other->disconnectFrom(nicEntry);
00371 nicEntry->disconnectFrom(other);
00372 }
00373 c = gridUnion.next();
00374 }
00375
00376
00377 NicEntries& cellEntries = getCellEntries(cell);
00378 cellEntries.erase(nicID);
00379
00380
00381 nics.erase(nicID);
00382
00383 return true;
00384 }
00385
00386 void BaseConnectionManager::updateNicPos(int nicID, const Coord* newPos)
00387 {
00388 NicEntry* nicEntry = nics[nicID];
00389 if(nicEntry == 0)
00390 error("No nic with this ID is registered with this ConnectionManager.");
00391
00392 Coord oldPos = nicEntry->pos;
00393 nicEntry->pos = newPos;
00394
00395 updateConnections(nicID, &oldPos, newPos);
00396 }
00397
00398 const NicEntry::GateList& BaseConnectionManager::getGateList(int nicID)
00399 {
00400 NicEntry* nicEntry = nics[nicID];
00401 if(nicEntry == 0)
00402 error("No nic with this ID is registered with this ConnectionManager.");
00403 return nicEntry->getGateList();
00404 }
00405
00406 const cGate* BaseConnectionManager::getOutGateTo(const NicEntry* nic,
00407 const NicEntry* targetNic)
00408 {
00409 NicEntry* nicEntry = nics[nic->nicId];
00410 if(nicEntry == 0)
00411 error("No nic with this ID is registered with this ConnectionManager.");
00412 return nicEntry->getOutGateTo(targetNic);
00413 }
00414
00415 BaseConnectionManager::~BaseConnectionManager()
00416 {
00417 for (NicEntries::iterator ne = nics.begin(); ne != nics.end(); ne++)
00418 {
00419 delete ne->second;
00420 }
00421 }