BaseConnectionManager.cc

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   //BaseModule::initialize(stage);
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     //----initialize node grid-----
00049     //step 1 - calculate dimension of grid
00050     //one cell should have at least the size of maxInterferenceDistance
00051     //but also should divide the playground in equal parts
00052     Coord dim((*playgroundSize) / maxInterferenceDistance);
00053     gridDim = GridCoord(dim);
00054 
00055     //A grid smaller or equal to 3x3 would mean that every cell has every
00056     //other cell as direct neighbor (if our playground is a torus, even if
00057     //not the most of the cells are direct neighbors of each other. So we
00058     //reduce the grid size to 1x1.
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     //step 2 - initialize the matrix which represents our grid
00071     NicEntries entries;
00072     RowVector row;
00073     NicMatrix matrix;
00074 
00075     for (int i = 0; i < gridDim.z; ++i) {
00076       row.push_back(entries);     //copy empty NicEntries to RowVector
00077     }
00078     for (int i = 0; i < gridDim.y; ++i) {//fill the ColVector with copies of
00079       matrix.push_back(row);       //the RowVector.
00080     }
00081     for (int i = 0; i < gridDim.x; ++i) { //fill the grid with copies of
00082       nicGrid.push_back(matrix);      //the matrix.
00083     }
00084     ccEV << " using " << gridDim.x << "x" <<
00085                gridDim.y << "x" <<
00086                gridDim.z << " grid" << endl;
00087 
00088     //step 3 -  calculate the factor which maps the coordinate of a node
00089     //      to the grid cell
00090     //if we use a 1x1 grid every coordinate is mapped to (0,0, 0)
00091     findDistance = Coord(std::max(playgroundSize->getX(),
00092                     maxInterferenceDistance),
00093                std::max(playgroundSize->getY(),
00094                     maxInterferenceDistance),
00095                std::max(playgroundSize->getZ(),
00096                     maxInterferenceDistance));
00097     //otherwise we divide the playground into cells of size of the maximum
00098     //interference distance
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     //since the upper playground borders (at pg-size) are part of the
00107     //playground we have to assure that they are mapped to a valid
00108     //(the last) grid cell we do this by increasing the find distance
00109     //by a small value.
00110     //This also assures that findDistance is never zero.
00111     findDistance += Coord(EPSILON, EPSILON, EPSILON);
00112 
00113     //findDistance (equals cell size) has to be greater or equal
00114     //maxInt-distance
00115     assert(findDistance.getX() >= maxInterferenceDistance);
00116     assert(findDistance.getY() >= maxInterferenceDistance);
00117     assert(world->use2D()
00118          || findDistance.getZ() >= maxInterferenceDistance);
00119 
00120     //playGroundSize has to be part of the playGround
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   // add to matrix
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     // structure to find union of grid squares
00174     CoordSet gridUnion(74);
00175 
00176     // find nic at old position
00177     NicEntries& oldCellEntries = getCellEntries(oldCell);
00178     NicEntries::iterator it = oldCellEntries.find(id);
00179     NicEntry *nic = it->second;
00180 
00181 
00182     // move nic to a new position in matrix
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     //add grid around oldPos
00192     fillUnionWithNeighbors(gridUnion, oldCell);
00193 
00194 
00195         if(oldCell != newCell) {
00196             //add grid around newPos
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         // no recursive connections
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             // nodes within communication range: connect
00284             // nodes within communication range && not yet connected
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             // out of range: disconnect
00292             // out of range, and still connected
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   // create new NicEntry
00311   NicEntry *nicEntry;
00312 
00313   if(sendDirect)
00314     nicEntry = new NicEntryDirect(coreDebug);
00315   else
00316     nicEntry = new NicEntryDebug(coreDebug);
00317 
00318   // fill nicEntry
00319   nicEntry->nicPtr = nic;
00320   nicEntry->nicId = nicID;
00321   nicEntry->hostId = nic->getParentModule()->getId();
00322   nicEntry->pos = nicPos;
00323   nicEntry->chAccess = chAccess;
00324 
00325   // add to map
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   // find nicEntry
00344   int nicID = nicModule->getId();
00345   ccEV << " unregistering nic #" << nicID << endl;
00346 
00347   //we assume that the module was previously registered with this CM
00348   //TODO: maybe change this to an omnet-error instead of an assertion
00349   assert(nics.find(nicID) != nics.end());
00350   NicEntry* nicEntry = nics[nicID];
00351 
00352   // get all affected grid squares
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   // disconnect from all NICs in these grid squares
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   // erase from grid
00377   NicEntries& cellEntries = getCellEntries(cell);
00378   cellEntries.erase(nicID);
00379 
00380   // erase from list of known nics
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 }