PaCO++  0.05
BasicBC.cc
Go to the documentation of this file.
00001 #include "BasicBC.h"
00002 #include <iostream>
00003 
00004 #define SRC_TOPOLOGY 1
00005 #define DST_TOPOLOGY 2
00006 #define ELEMENT_SIZE 4
00007 #define TOTAL_SIZE   8
00008 #define DISTRIBUTION_TYPE 16
00009 
00010 #undef DEBUG_INTERNAL
00011 #undef DEBUG_INTERNAL2
00012 
00014 
00015 // Compute the owner of a bloc accoring a cyclic distribution
00016 static inline unsigned OwnerBloc(const unsigned bid, const unsigned nbprocs) {
00017   return bid % nbprocs;
00018 }
00019 
00021 
00022 // Compute the id of a proc owning an element 
00023 inline static unsigned getProcRangeInf(unsigned low, unsigned bsz) {
00024   return low / bsz;      // first remote node
00025 }
00026 
00027 // Compue the id of the proc owning the previous element
00028 inline static unsigned getProcRangeSup(unsigned high, unsigned bsz) {
00029   return (high-1) / bsz; //  last remote node
00030 }
00031 
00033 
00034 // Compute the number of bloc a given processor owns accoring to a cyclic distribution
00035 static inline unsigned NumberOfBlocProc(const unsigned glen, const unsigned nbprocs,
00036                 const unsigned bsz, const unsigned rank) {
00037   unsigned nbbloc = (glen + bsz - 1 ) / bsz;
00038   return (nbbloc / nbprocs) + (rank < (nbbloc % nbprocs ) ) ;
00039 }
00040 
00042 
00043 // Compute the number of element of a given bloc (local bloc pos)
00044 // on a proc of given rank according to a cyclic distribution
00045 static inline unsigned BlocNumberOfElementProc(const unsigned glen, const unsigned rank,
00046                   const unsigned nbprocs, const unsigned bsz,
00047                   const unsigned pos) {
00048   
00049   unsigned long low = ( pos * nbprocs + rank ) * bsz;
00050   unsigned long end = low + bsz;
00051   unsigned long high = (glen < end ? glen : end);
00052   
00053   return ( high - low );
00054   
00055 }
00056 
00058 
00059 // compute the global low bounds of local bloc number pos
00060 static inline unsigned computeBlocBoundInf(const unsigned bsz, const unsigned rank,
00061                    const unsigned nbprocs, const unsigned pos) {
00062   return  ( pos * nbprocs + rank) * bsz;
00063 }
00064 
00066 
00067 // Compute the global bounds (low & high) of a given bloc (local bloc pos)
00068 // on a proc of given rank according to a cyclic distribution
00069 static inline void computeBlocBounds(unsigned long *low, unsigned long *high,
00070                   const unsigned glen, const unsigned rank,
00071                   const unsigned nbprocs, const unsigned bsz,
00072                   const unsigned pos) {
00073   unsigned long start = (pos * nbprocs + rank) * bsz;
00074   unsigned long end = start + bsz;
00075   *low =  start;
00076   *high = ((glen <= end)?glen:end); // min
00077 }
00078 
00080 
00081 // Compute the number of element own by the processor of rank rank
00082 static inline unsigned TotalNumberOfElementProc(const unsigned glen, const unsigned rank,
00083                   const unsigned nbprocs, const unsigned bsz) {
00084 
00085   unsigned nbblocfull = NumberOfBlocProc(glen, nbprocs, bsz, rank) - 1;
00086   // Is the last full ?
00087   unsigned long low = ( nbblocfull * nbprocs + rank ) * bsz;
00088   unsigned long end = low + bsz;
00089   unsigned long high = (glen < end ? glen : end);
00090   
00091   return nbblocfull * bsz + ( high - low );
00092 }
00093 
00095 
00096 // Compute the size in octet of a bloc according to the given parameter
00097 // 
00098 static inline unsigned blocSize(const unsigned glen, const unsigned nbprocs,
00099              const BasicBC_param_t& param) {
00100   switch(param.type)
00101     {
00102     case BASICBC_BLOC:
00103       {
00104    unsigned nbbloc = (glen + param.unitsize - 1) / param.unitsize;
00105    return ((nbbloc + nbprocs - 1 ) / nbprocs) * param.unitsize;
00106       }
00107     case BASICBC_CYCLIC: return param.unitsize; break;
00108     case BASICBC_BLOCCYCLIC: return param.blocsize*param.unitsize; break;
00109     }
00110   return 0;
00111 }
00112 
00116 
00117 BasicBC::BasicBC()
00118 {
00119   // Common
00120   _config = 0;
00121 
00122   // By default 1->1 :)
00123   _sTopo.total=1;
00124   _dTopo.total=1;
00125   _param.type = BASICBC_BLOC;
00126   _nodeRank=0;
00127   
00128   // Client side
00129   _clientBuffer=NULL;
00130   _descr_to_be_cleaned=true;
00131 
00132   this->internalSetComId(-1); // set anonymous & init iterator, infolists & _cur_id
00133   
00134   // Server side
00135   _serverDescr=NULL;
00136   _serverBuffer=NULL;
00137 }
00138 
00139 BasicBC::~BasicBC() 
00140 {
00141   for(info_list_map_t::iterator it=_info_list_map.begin(); it!=_info_list_map.end(); ++it)
00142     this->internalFreeComId(it);
00143   _info_list_map.clear();
00144 }
00145 
00146 void
00147 BasicBC::setSourceTopology(PaCO::PacoTopology_t topo)
00148 {
00149 #ifdef DEBUG_INTERNAL
00150   std::cerr << "-- setSourceTopology: " << topo.total << std::endl;
00151 #endif
00152   _config |= SRC_TOPOLOGY;
00153   _sTopo = topo;
00154 }
00155 
00156 PaCO::PacoTopology_t
00157 BasicBC::getSourceTopology()
00158 {
00159   std::cerr << "****** Why is the method " << __FUNCTION__ << "called?\n";
00160   abort();
00161   return _sTopo;
00162 }
00163 
00164 void
00165 BasicBC::setDestTopology(PaCO::PacoTopology_t topo)
00166 {
00167 #ifdef DEBUG_INTERNAL
00168   std::cerr << "-- setDestTopology: " << topo.total << std::endl;
00169 #endif
00170   _config |= DST_TOPOLOGY;
00171 
00172   if ( _dTopo.total == topo.total ) return ; // Nothing change !!!!
00173 
00174   // Delete old entries wrt to old state
00175   info_list_map_t::iterator it = _info_list_map.find(_cur_id);
00176   this->internalFreeComId(it);
00177   _info_list_map.erase(it);
00178 
00179   // Change the state of the object
00180   _dTopo = topo;
00181 
00182   // Set new entries
00183   this->internalSetComId(_cur_id);
00184 
00185   // BUG: MUST ALSO DELETE ALL ENTRIES IN _info_list_map 
00186 
00187 }
00188 
00189 PaCO::PacoTopology_t
00190 BasicBC::getDestTopology()
00191 {
00192   std::cerr << "****** Why is the method " << __FUNCTION__ << "called?\n";
00193   abort();
00194   return _dTopo;
00195 }
00196 
00197 void
00198 BasicBC::setNodeRank(long Rank)
00199 {
00200 #ifdef DEBUG_INTERNAL
00201   std::cerr << "-- setNodeRank: " << Rank << std::endl;
00202 #endif
00203   _nodeRank = Rank;
00204 }
00205 
00206 long
00207 BasicBC::getNodeRank()
00208 {
00209   return _nodeRank;
00210 }
00211 
00212 void
00213 BasicBC::setBlocSize(unsigned long size)
00214 {
00215 #ifdef DEBUG_INTERNAL
00216   std::cerr << "-- setBlocSize: " << size << std::endl;
00217 #endif
00218   _config |= DISTRIBUTION_TYPE;
00219   switch(size) {
00220   case 0:
00221 #ifdef DEBUG_INTERNAL
00222     cout << "Selecting a BLOC distribution\n";
00223 #endif
00224     _param.type = BASICBC_BLOC;
00225     _clientDescr.bsz  = 0;
00226     break;
00227   case 1:
00228 #ifdef DEBUG_INTERNAL
00229     cout << "Selecting a CYCLIC distribution\n";
00230 #endif
00231     _param.type = BASICBC_CYCLIC;
00232     _clientDescr.bsz  = 1;
00233     break;
00234   default:
00235 #ifdef DEBUG_INTERNAL
00236     cout << "Selecting a BLOCCYCLIC with bsz= " << size << " \n";
00237 #endif
00238     _param.type = BASICBC_BLOCCYCLIC;
00239     _clientDescr.bsz  =  _param.blocsize = size;
00240   }
00241 }
00242 
00243 void
00244 BasicBC::setEltSize(unsigned long size)
00245 {
00246 #ifdef DEBUG_INTERNAL
00247   std::cerr << "-- setEltSize: " << size << std::endl;
00248 #endif
00249   _config |= ELEMENT_SIZE;
00250   _param.unitsize = size;
00251 }
00252 
00253 void
00254 BasicBC::setTotalNbElt(unsigned long elt_nb)
00255 {
00256 #ifdef DEBUG_INTERNAL
00257   std::cerr << "-- setTotalNbElt: " << elt_nb << std::endl;
00258 #endif
00259   _config |= TOTAL_SIZE;
00260   _clientDescr.glen = _glen = elt_nb;
00261 }
00262   
00263 
00264 PieceToSend* 
00265 BasicBC::computePiecesToSend(unsigned& size_out)
00266 {
00267   /*
00268    * store src/dst/sz/start
00269    *
00270    * where start is a local offset to apply to the vector
00271    *
00272    */
00273 
00274   PieceToSend * sched;
00275   unsigned long golen = _glen*_param.unitsize;
00276 
00277   // We need to compute _lstart and _llen
00278   _sbsz = blocSize( golen, _sTopo.total, _param);
00279   _lstart = _nodeRank*_sbsz;
00280   _lstart = (_lstart < golen ? _lstart:golen);
00281   _llen   = TotalNumberOfElementProc(golen, _nodeRank, _sTopo.total, _sbsz);
00282 
00283 #ifdef DEBUG_INTERNAL
00284   //  std::cerr << "In computePiecesToSend-------------------- all in octet !\n";
00285 
00286   fprintf(stderr, "-- stopo: %ld\tdtopo: %ld\n", _sTopo.total, _dTopo.total);
00287   fprintf(stderr, "-- golen: %ld\ttype: %d\tsd.start %d\tllen: %d\n", golen,
00288      _param.type, _lstart, _llen);
00289 #endif
00290 
00291   if (_sTopo.total == _dTopo.total) {
00292 #ifdef DEBUG_INTERNAL
00293     fprintf(stderr, "-- easy: n<->n case !\n");
00294 #endif
00295     size_out = 1;
00296     sched = new PieceToSend[1];
00297     sched[0].sourceNode = _nodeRank; // my self :)
00298     sched[0].destNode   = _nodeRank; // the corresponding node
00299     sched[0].size       = _llen;     // msg size
00300     
00301     info_t* inf = new info_t();
00302     
00303     inf->gstart         = _lstart/_param.unitsize; // used start as id -> same at server side
00304     inf->lstart         = 0;       // do not apply any offset to local ptr
00305     inf->msg_size       = _llen; 
00306     inf->sent_size      = 0;
00307 
00308     // add inf to the list
00309     _infolists[_nodeRank]->push_back(inf);
00310     // sched points to the list
00311     sched[0].id         = (void*) _infolists[_nodeRank];
00312 
00313 #ifdef DEBUG_INTERNAL
00314     fprintf(stderr, "--  %2d -> %2d : gstart:%2u lstart:%2u len:%2d\n",
00315        sched[0].sourceNode, sched[0].destNode, inf->gstart, inf->lstart, inf->msg_size);
00316 #endif
00317 
00318   } else {        
00319     if (_param.type == BASICBC_BLOC ) {
00320       // that's a standard bloc redistribution
00321 #ifdef DEBUG_INTERNAL
00322     fprintf(stderr, "-- medium: n<->m bloc redistribution case !\n");
00323 #endif
00324 
00325       unsigned long slow;
00326       unsigned long shigh;
00327       computeBlocBounds(&slow, &shigh, golen, _nodeRank, _sTopo.total, _sbsz, 0);
00328     
00329 #ifdef DEBUG_INTERNAL
00330       std::cerr << "--  sbsz: "<<_sbsz<<" sbounds: "<<slow<<" - "<<shigh<<endl;
00331 #endif
00332 
00333       unsigned dbsz = blocSize(golen, _dTopo.total, _param);
00334 
00335 #ifdef DEBUG_INTERNAL
00336       std::cerr << "--  dbsz: "<<dbsz<<endl;
00337 #endif
00338 
00339       unsigned fpid, lpid;
00340       fpid = getProcRangeInf(slow,  dbsz);
00341       lpid = getProcRangeSup(shigh, dbsz);
00342     
00343 #ifdef DEBUG_INTERNAL
00344       fprintf(stderr, "--  loop from %d to %d width dtotal: %ld\n", fpid, lpid, _dTopo.total);
00345 #endif
00346     
00347       // for each dest bloc
00348       size_out = lpid-fpid+1;
00349       sched = new PieceToSend[size_out];
00350       for(unsigned i=fpid; i <= lpid; i++) {
00351    PieceToSend& s   =  sched[i-fpid];  
00352    s.sourceNode     = _nodeRank;
00353    s.destNode       = i;
00354 
00355    info_t* inf      = new info_t();
00356 
00357    unsigned tmp     = i*dbsz;
00358    unsigned tmp2;
00359    tmp2 = ( slow >= tmp)?slow:tmp; // max : global offset in octet as ID
00360    inf->gstart      = tmp2 / _param.unitsize;
00361    inf->lstart      = tmp2 - _lstart;
00362 
00363    tmp += dbsz;
00364    unsigned end     = ( shigh <= tmp)?shigh:tmp; // min
00365 
00366    inf->msg_size  =  s.size  = end - tmp2;
00367    inf->sent_size = 0;
00368 
00369    // add inf to the list
00370    _infolists[i-fpid]->push_back(inf);
00371    // sched points to the list
00372    s.id             = (void*) _infolists[i-fpid];
00373 
00374 #ifdef DEBUG_INTERNAL
00375    fprintf(stderr, "--  %2d -> %2d : gstart:%2u lstart:%2u len:%2d\n",
00376       s.sourceNode, s.destNode, inf->gstart, inf->lstart, inf->msg_size);
00377 #endif
00378       }
00379     } else {
00380       // it is a bloccyclic distribution
00381    
00382 #ifdef DEBUG_INTERNAL
00383     fprintf(stderr, "-- hard: n<->m bloccyclic redistribution case !\n");
00384 #endif
00385 
00386       unsigned stbsz  = _sbsz * _sTopo.total;
00387       unsigned nbbloc = NumberOfBlocProc(golen, _sTopo.total, _sbsz, _nodeRank);
00388 
00389 #ifdef DEBUG_INTERNAL
00390       std::cerr << "--  sbsz: "<<_sbsz<<" nbbloc: "<<nbbloc<<endl;
00391 #endif
00392 
00393       // for each src bloc, find a dst node
00394       // But only one struct for each dst -> pre-count
00395 
00396       // should be equal to the number of real dest !
00397       size_out = 0;
00398       unsigned *tmp_dnb    = (unsigned*) calloc(_dTopo.total, sizeof(unsigned)); // zeroed array
00399       PieceToSend **tmp_dor = (PieceToSend**) calloc(_dTopo.total, sizeof(PieceToSend*)); // zeroed array
00400       for(unsigned b=0; b<nbbloc; b++) {
00401    unsigned gb            = b * _sTopo.total + _nodeRank; // global bloc id
00402    unsigned drank         = OwnerBloc(gb, _dTopo.total);
00403    if (tmp_dnb[drank]++ == 0) // detect if it is the 1st time
00404      size_out++;
00405       }
00406       // Allocating output
00407       sched = new PieceToSend[size_out];
00408       unsigned cur=0;
00409       for(unsigned i=0; i<_dTopo.total; i++) {
00410    sched[cur].sourceNode = _nodeRank;
00411    sched[cur].destNode   = i;
00412    sched[cur].size       = 0;
00413    sched[cur].id         = (void*) _infolists[i]; 
00414    tmp_dor[i]            = &sched[cur];   // an index if valid only if tmp_dnb[index]>0 !!!!
00415    cur+= (tmp_dnb[i]>0?1:0); // increment order only if this dest is not zero
00416       }
00417    
00418 #ifdef DEBUG_INTERNAL
00419       cerr << "-- size_out: "<<size_out<<endl;
00420 #endif
00421 
00422       for(unsigned b=0; b<nbbloc; b++) {
00423    unsigned gb    = b * _sTopo.total + _nodeRank; // global bloc id
00424    unsigned drank = OwnerBloc(gb, _dTopo.total);
00425    
00426    PieceToSend* s = tmp_dor[drank];
00427 
00428    // Allocate new element
00429    info_t* inf    = new info_t();
00430 
00431    inf->gstart    = ((stbsz*b) + (_nodeRank*_sbsz))/ _param.unitsize;
00432    inf->lstart    = b * _sbsz;
00433    inf->msg_size  = BlocNumberOfElementProc(golen, _nodeRank, _sTopo.total, _sbsz, b);
00434    inf->sent_size = 0;
00435 
00436    // Accumulate msg length in PieceToSend
00437    s->size           += inf->msg_size;
00438    
00439    // insert it in the list
00440    info_list_t* ilsp  = (info_list_t*) s->id; // pointer to a list
00441    ilsp->push_back(inf);
00442 
00443    
00444 #ifdef DEBUG_INTERNAL
00445    fprintf(stderr, "--  %2d -> %2d : gstart:%2u lstart:%2u len:%2d\n",
00446       s->sourceNode, s->destNode, inf->gstart, inf->lstart, inf->msg_size);
00447 #endif
00448       }
00449     }
00450   }
00451 
00452 #ifdef DEBUG_INTERNAL
00453   //  std::cerr << "computePiecesToSend-------------------- done\n";
00454 #endif
00455 
00456   return sched;
00457 }
00458 
00459 void
00460 BasicBC::setDataPtr(void* dataPtr)
00461 {
00462   _clientBuffer = (char *) dataPtr;
00463 #ifdef DEBUG_INTERNAL
00464   cerr << "-- _clientBuffer set to "<<dataPtr<<endl;
00465 #endif
00466 }
00467 
00468 void *
00469 BasicBC::getClientData(void *pid, int dnode, long & remaining_size_octet, long & returned_length_element, bool & end)  
00470 {
00471   info_list_t* ilsp  = (info_list_t*) pid;
00472 
00473 #ifdef DEBUG_INTERNAL2
00474   std::cerr << "-- getClientData : _clientBuffer=" << (void*) _clientBuffer << std::endl;
00475   std::cerr << "-- getClientData : " << dnode << " " << remaining_size_octet << std::endl;
00476 #endif
00477 
00478   if (_descr_to_be_cleaned) {
00479     _descr_to_be_cleaned = false;
00480     _clientDescr.ids.length(0);
00481   }
00482 
00483   // look for 1st one not "empty"
00484   long rst_data=0;
00485   info_list_t::const_iterator ci;
00486   for(ci=ilsp->begin(); ci!=ilsp->end(); ++ci) {
00487     rst_data = (*ci)->msg_size - (*ci)->sent_size;
00488     if (rst_data>0)
00489       break;
00490   }
00491 
00492   // No more element: return immediatly
00493   if (ci == ilsp->end())
00494     {
00495 #ifdef DEBUG_INTERNAL2
00496       std::cerr << "-- getClientData0 : no more block for this argument\n";
00497 #endif
00498       returned_length_element = 0;
00499       end = true;
00500       return NULL;
00501     }
00502   // No more data of this element but there are more
00503   if (rst_data == 0)
00504     {
00505 #ifdef DEBUG_INTERNAL2
00506       std::cerr << "-- getClientData0 : no more data for this bloc\n";
00507 #endif
00508       returned_length_element = 0;
00509       end = false;
00510       return NULL;
00511     }
00512   // *ci assumed ok here (else return above !!)
00513   info_t* info = *ci;
00514 
00515   // More asked data as I can provide -> give all the data of this bloc
00516   if (remaining_size_octet >= rst_data)
00517     {
00518       unsigned descr_len       = _clientDescr.ids.length();
00519       _clientDescr.ids.length(descr_len+1);
00520       _clientDescr.ids[descr_len] = info->gstart+(info->sent_size/_param.unitsize);
00521 
00522       unsigned start           = info->lstart+info->sent_size;
00523       info->sent_size         += rst_data;
00524       returned_length_element  = rst_data / _param.unitsize; // should divide;
00525       remaining_size_octet    -= rst_data;
00526       end                      = (remaining_size_octet == 0);
00527 
00528 #ifdef DEBUG_INTERNAL2
00529       std::cerr << "-- getClientData1 : gstart:"<<_clientDescr.ids[descr_len]<<" #element:"<<returned_length_element<<endl;
00530 #endif
00531 
00532       return (void *)&_clientBuffer[start];
00533     }
00534   else
00535     {
00536       // I have more data than requested
00537       unsigned descr_len       = _clientDescr.ids.length();
00538       _clientDescr.ids.length(descr_len+1);
00539       _clientDescr.ids[descr_len]    = info->gstart+(info->sent_size/_param.unitsize);
00540 
00541       unsigned start           = info->lstart+info->sent_size;
00542       returned_length_element  = (remaining_size_octet+_param.unitsize-1)/_param.unitsize; // max
00543       unsigned mlen            = returned_length_element*_param.unitsize;
00544       info->sent_size         += mlen;
00545       remaining_size_octet    -= mlen;
00546       end                      = true;
00547 
00548 
00549 #ifdef DEBUG_INTERNAL2
00550       std::cerr << "-- getClientData1 : gstart:"<<_clientDescr.ids[descr_len]<<" #element:"<<returned_length_element<<endl;
00551 #endif
00552 
00553       return (void *)&_clientBuffer[start];
00554     }
00555 }
00556 
00557 void
00558 BasicBC::clientFree() // always called at the end of an invocation (reset some variables)
00559 {
00560 
00561 #ifdef DEBUG_INTERNAL
00562   std::cerr << "-- clientFree\n";
00563 #endif
00564   if (_cur_id == -1) {
00565     this->clear_info_list();
00566   } else {
00567     this->reset_info_list();
00568   }
00569 }
00570 
00571 void *
00572 BasicBC::getDescr()
00573 {
00574 #ifdef DEBUG_INTERNAL
00575   std::cerr << "-- descr: glen: "<<_clientDescr.glen<<" #element: "<<_clientDescr.ids.length()<<" bsz: "<<_clientDescr.bsz;
00576   for(unsigned i=0;i<_clientDescr.ids.length();i++) {
00577     std::cerr<<" "<<_clientDescr.ids[i];
00578   }
00579   std::cerr<<std::endl;
00580 #endif
00581   _descr_to_be_cleaned = true;
00582   return &_clientDescr;
00583 }
00584 
00585 bool
00586 BasicBC::insertData(void* rcptBuf, unsigned long element_nb)
00587 {
00588   // We are receiving one bloc
00589   unsigned gstart = _serverDescr->ids[_descr_ids_counter++]; // in octet !!!
00590   unsigned lstart;
00591   unsigned llen   = element_nb*_param.unitsize;
00592 
00593   // Need to compute lstart :(
00594   if (_param.type == BASICBC_BLOC ) {
00595     lstart = (gstart*_param.unitsize)/ _dbsz; // bloc number
00596     lstart = (gstart*_param.unitsize) - (lstart*_dbsz);
00597   } else {
00598     lstart = (gstart*_param.unitsize)/ _dbsz; // bloc number
00599     lstart /= _dTopo.total;                   // local number
00600   }
00601 
00602   char*    rptr   = &_serverBuffer[lstart];
00603 #ifdef DEBUG_INTERNAL
00604   std::cerr << "  gstart: "<< gstart<<" lstart: "<<lstart<<" #element " << element_nb<<" llen: "<<llen<<std::endl;
00605 #endif
00606   memcpy(rptr, rcptBuf, llen);
00607 
00608   _serverToReceived -= llen;
00609 #ifdef DEBUG_INTERNAL
00610   std::cerr << " #missing data"<<_serverToReceived<<std::endl;
00611 #endif
00612   return (_serverToReceived == 0);
00613 }
00614 
00615 void *
00616 BasicBC::getServerData(long & length) // in element !
00617 {
00618   length= _llen / _param.unitsize;
00619 #ifdef DEBUG_INTERNAL
00620   std::cerr << "-- getServerData: ptr : "<<(void*)_serverBuffer<<" #element:"<<length<<std::endl;
00621 #endif  
00622   return (void*) _serverBuffer;
00623 }
00624 
00625 void
00626 BasicBC::setDescr(void * descr)
00627 {
00628   _serverDescr = (BasicBCLib::BasicBCDescr*) descr;
00629   _descr_ids_counter=0;
00630 
00631   // Descr already received
00632 
00633   if ( _serverBuffer == NULL)
00634     {
00635       // 1st time -> allocate memory & init
00636       //this->setEltSize(_descr->usz); BUG: usz can be different in client and server (32bit vs 64bit)
00637       unsigned long golen = _serverDescr->glen*_param.unitsize;
00638       this->setTotalNbElt(_serverDescr->glen);
00639       this->setBlocSize(_serverDescr->bsz);
00640       _dbsz = blocSize( golen, _dTopo.total, _param);
00641       _llen  = TotalNumberOfElementProc(golen, _nodeRank, _dTopo.total, _dbsz);
00642       
00643 #ifdef DEBUG_INTERNAL
00644       fprintf(stderr, "-- setDescr: stopo: %ld\tdtopo: %ld\n",_sTopo.total, _dTopo.total);
00645       fprintf(stderr, "   setDescr: golen: %ld\tllen %d\tbsz:%ld\n", _serverDescr->glen, _llen, _serverDescr->bsz);
00646 #endif  
00647       _serverBuffer = (char*) malloc(_llen);
00648 #ifdef DEBUG_INTERNAL
00649       std::cerr << "-- serverMalloc: "<<(void*)_serverBuffer<<" - "<<_llen<<endl;
00650 #endif
00651       _serverToReceived = _llen;
00652     }
00653 }
00654 
00655 void
00656 BasicBC::serverFree() 
00657 { 
00658 #ifdef DEBUG_INTERNAL
00659   std::cerr << "-- serverFree: "<<(void*)_serverBuffer<<endl;
00660 #endif
00661   free(_serverBuffer);
00662   _serverBuffer=NULL; // the orb (or the user) need to free the memory!
00663 }
00664 
00665 void
00666 BasicBC::internalSetComId(long id) // called by constructor
00667 { 
00668   info_list_map_t::iterator it = _info_list_map.find(id);
00669 
00670   if (it == _info_list_map.end() ) {
00671 #ifdef DEBUG_INTERNAL
00672     cerr << "setComiI: set 1st time communication id "<<id<<endl;
00673 #endif
00674     // we must allocate a new one
00675     this->allocate_new_info_list();
00676 #ifdef DEBUG_INTERNAL
00677     cerr << "setComId: allocating a new _infolists: "<<_infolists<<endl;      
00678 #endif
00679     _info_list_map[id] = _infolists;
00680   } else {
00681 #ifdef DEBUG_INTERNAL
00682     cerr << "setComId: set (not 1st time) communication id "<<id<<endl;
00683 #endif
00684     _infolists   = it->second;
00685   }
00686 
00687   _cur_id = id;
00688 }
00689 
00690 bool
00691 BasicBC::setComId(long id)
00692 { 
00693   if (_cur_id == id) return true; // already initialized
00694 
00695   this->internalSetComId(id);
00696 
00697   return true;
00698 }
00699 
00700 
00701 void
00702 BasicBC::internalFreeComId(info_list_map_t::iterator& it)
00703 {
00704   if (it == _info_list_map.end() ) {
00705 #ifdef DEBUG_INTERNAL
00706     cerr << "freeComid: communication id  not found (ignoring)\n";
00707 #endif
00708   } else {
00709 #ifdef DEBUG_INTERNAL
00710     cerr << "freeComid: freeing communication "<<endl;
00711 #endif
00712     info_list_t** info = it->second;
00713     // for each destNode
00714     for(unsigned i=0; i< _dTopo.total; i++) {
00715       // for each element of the list
00716       info_list_t *ilp = info[i];
00717       for(info_list_t::const_iterator ci=ilp->begin(); ci!=ilp->end(); ++ci)
00718    delete (*ci);
00719       info[i] -> clear();
00720       delete info[i];
00721     }
00722   }
00723 }
00724 
00725 bool
00726 BasicBC::freeComId(long id)
00727 { 
00728   if (id == -1) {
00729 #ifdef DEBUG_INTERNAL
00730     cerr << "freeComId: not allowed to free com id -1 (ignoring)\n";
00731 #endif
00732     return true;
00733   }
00734 
00735   if (_cur_id == id) {
00736 #ifdef DEBUG_INTERNAL
00737     cerr << "freeComId: not allowed to free current com (ignoring)\n";
00738 #endif
00739     return true;
00740   }
00741 
00742 #ifdef DEBUG_INTERNAL
00743   cerr << "freeComid: communication id: "<<id<<endl;
00744 #endif
00745 
00746   info_list_map_t::iterator it = _info_list_map.find(id);
00747   this->internalFreeComId(it);
00748   _info_list_map.erase(it);
00749 
00750   return true;
00751 }
00752 
00753 void
00754 BasicBC::allocate_new_info_list()
00755 {
00756   _infolists = new info_list_t*[_dTopo.total];
00757   for(unsigned i=0;i<_dTopo.total;i++)
00758     _infolists[i]=new info_list_t();
00759 }
00760 
00761 void
00762 BasicBC::reset_info_list()
00763 {
00764 #ifdef DEBUG_INTERNAL
00765   std::cerr << "-- reset info list\n";
00766 #endif
00767   // for each destNode
00768   for(unsigned i=0; i< _dTopo.total; i++) {
00769     // for each element of the list
00770     info_list_t *ilp = _infolists[i];
00771     for(info_list_t::const_iterator ci=ilp->begin(); ci!=ilp->end(); ++ci)
00772       (*ci)->sent_size = 0;
00773   }
00774 }
00775 
00776 void
00777 BasicBC::clear_info_list()
00778 {
00779 #ifdef DEBUG_INTERNAL
00780   std::cerr << "-- clear info list\n";
00781 #endif
00782   // for each destNode
00783   for(unsigned i=0; i< _dTopo.total; i++) {
00784     // for each element of the list
00785     info_list_t *ilp = _infolists[i];
00786     for(info_list_t::const_iterator ci=ilp->begin(); ci!=ilp->end(); ++ci)
00787       delete (*ci);
00788     _infolists[i] -> clear();
00789   }
00790 }