00001 
00011 #include "hilbert.h"
00012 #include "partitioning_strategies.h"
00013 #include "charm++.h"
00014 #include "register.h"
00015 #include "ck.h"
00016 #include "trace.h"
00017 #include "TopoManager.h"
00018 #include <vector>
00019 #include <algorithm>
00020 #include <sstream>
00021 #include <limits>
00022 #include "pup_stl.h"
00023 
00024 #if CMK_LBDB_ON
00025 #include "LBDatabase.h"
00026 #include "MetaBalancer.h"
00027 #if CMK_GLOBAL_LOCATION_UPDATE
00028 #include "BaseLB.h"
00029 #include "init.h"
00030 #endif
00031 CkpvExtern(int, _lb_obj_index);                
00032 #endif // CMK_LBDB_ON
00033 
00034 #ifndef CMK_CHARE_USE_PTR
00035 CkpvExtern(int, currentChareIdx);
00036 #endif
00037 
00038 #if CMK_GRID_QUEUE_AVAILABLE
00039 CpvExtern(void *, CkGridObject);
00040 #endif
00041 
00042 #define ARRAY_DEBUG_OUTPUT 0
00043 
00044 #if ARRAY_DEBUG_OUTPUT 
00045 #   define DEB(x) CkPrintf x  //General debug messages
00046 #   define DEBI(x) CkPrintf x  //Index debug messages
00047 #   define DEBC(x) CkPrintf x  //Construction debug messages
00048 #   define DEBS(x) CkPrintf x  //Send/recv/broadcast debug messages
00049 #   define DEBM(x) CkPrintf x  //Migration debug messages
00050 #   define DEBL(x) CkPrintf x  //Load balancing debug messages
00051 #   define DEBN(x) CkPrintf x  //Location debug messages
00052 #   define DEBB(x) CkPrintf x  //Broadcast debug messages
00053 #   define AA "LocMgr on %d: "
00054 #   define AB ,CkMyPe()
00055 #   define DEBUG(x) CkPrintf x
00056 #   define DEBAD(x) CkPrintf x
00057 #else
00058 #   define DEB(X) 
00059 #   define DEBI(X) 
00060 #   define DEBC(X) 
00061 #   define DEBS(x) 
00062 #   define DEBM(X) 
00063 #   define DEBL(X) 
00064 #   define DEBN(x) 
00065 #   define DEBB(x) 
00066 #   define str(x) 
00067 #   define DEBUG(x)   
00068 #   define DEBAD(x) 
00069 #endif
00070 
00071 
00072 bool useNodeBlkMapping;
00073 
00076 int _messageBufferingThreshold;
00077 
00078 #if CMK_LBDB_ON
00079 
00080 #if CMK_GLOBAL_LOCATION_UPDATE
00081 void UpdateLocation(MigrateInfo& migData) {
00082 
00083   CkGroupID locMgrGid = ck::ObjID(migData.obj.id).getCollectionID();
00084   if (locMgrGid.idx == 0) {
00085     return;
00086   }
00087 
00088   CkLocMgr *localLocMgr = (CkLocMgr *) CkLocalBranch(locMgrGid);
00089   localLocMgr->updateLocation(migData.obj.id, migData.to_pe);
00090 }
00091 #endif
00092 
00093 #endif
00094 
00095 
00096 CmiUInt8 CkArrayMessage::array_element_id(void)
00097 {
00098   return ck::ObjID(UsrToEnv((void *)this)->getRecipientID()).getElementID();
00099 }
00100 unsigned short &CkArrayMessage::array_ep(void)
00101 {
00102     return UsrToEnv((void *)this)->getsetArrayEp();
00103 }
00104 unsigned short &CkArrayMessage::array_ep_bcast(void)
00105 {
00106     return UsrToEnv((void *)this)->getsetArrayBcastEp();
00107 }
00108 unsigned char &CkArrayMessage::array_hops(void)
00109 {
00110     return UsrToEnv((void *)this)->getsetArrayHops();
00111 }
00112 unsigned int CkArrayMessage::array_getSrcPe(void)
00113 {
00114     return UsrToEnv((void *)this)->getsetArraySrcPe();
00115 }
00116 unsigned int CkArrayMessage::array_ifNotThere(void)
00117 {
00118     return UsrToEnv((void *)this)->getArrayIfNotThere();
00119 }
00120 void CkArrayMessage::array_setIfNotThere(unsigned int i)
00121 {
00122     UsrToEnv((void *)this)->setArrayIfNotThere(i);
00123 }
00124 
00125 
00126 
00127 
00128 
00129 
00130 
00131 
00132 CkArrayMap::CkArrayMap(void) { }
00133 CkArrayMap::~CkArrayMap() { }
00134 int CkArrayMap::registerArray(const CkArrayIndex& numElements, CkArrayID aid)
00135 {return 0;}
00136 void CkArrayMap::unregisterArray(int idx)
00137 { }
00138 
00139 #define CKARRAYMAP_POPULATE_INITIAL(POPULATE_CONDITION) \
00140 int i; \
00141 int index[6]; \
00142 int start_data[6], end_data[6], step_data[6]; \
00143 for (int d = 0; d < 6; d++) { \
00144   start_data[d] = 0; \
00145   end_data[d] = step_data[d] = 1; \
00146   if (end.dimension >= 4 && d < end.dimension) { \
00147     start_data[d] = ((short int*)start.data())[d]; \
00148     end_data[d] = ((short int*)end.data())[d]; \
00149     step_data[d] = ((short int*)step.data())[d]; \
00150   } else if (d < end.dimension) { \
00151     start_data[d] = start.data()[d]; \
00152     end_data[d] = end.data()[d]; \
00153     step_data[d] = step.data()[d]; \
00154   } \
00155 } \
00156  \
00157 for (index[0] = start_data[0]; index[0] < end_data[0]; index[0] += step_data[0]) { \
00158   for (index[1] = start_data[1]; index[1] < end_data[1]; index[1] += step_data[1]) { \
00159     for (index[2] = start_data[2]; index[2] < end_data[2]; index[2] += step_data[2]) { \
00160       for (index[3] = start_data[3]; index[3] < end_data[3]; index[3] += step_data[3]) { \
00161         for (index[4] = start_data[4]; index[4] < end_data[4]; index[4] += step_data[4]) { \
00162           for (index[5] = start_data[5]; index[5] < end_data[5]; index[5] += step_data[5]) { \
00163             if (end.dimension == 1) { \
00164               i = index[0]; \
00165               CkArrayIndex1D idx(index[0]); \
00166               if (POPULATE_CONDITION) { \
00167                 mgr->insertInitial(idx,CkCopyMsg(&ctorMsg)); \
00168               } \
00169             } else if (end.dimension == 2) { \
00170               i = index[0] * end_data[1] + index[1]; \
00171               CkArrayIndex2D idx(index[0], index[1]); \
00172               if (POPULATE_CONDITION) { \
00173                 mgr->insertInitial(idx,CkCopyMsg(&ctorMsg)); \
00174               } \
00175             } else if (end.dimension == 3) { \
00176               i = (index[0]*end_data[1] + index[1]) * end_data[2] + index[2]; \
00177               CkArrayIndex3D idx(index[0], index[1], index[2]); \
00178               if (POPULATE_CONDITION) { \
00179                 mgr->insertInitial(idx,CkCopyMsg(&ctorMsg)); \
00180               } \
00181             } else if (end.dimension == 4) { \
00182               i = ((index[0]*end_data[1] + index[1]) * end_data[2] + index[2]) * end_data[3] + index[3]; \
00183               CkArrayIndex4D idx(index[0], index[1], index[2], index[3]); \
00184               if (POPULATE_CONDITION) { \
00185                 mgr->insertInitial(idx,CkCopyMsg(&ctorMsg)); \
00186               } \
00187             } else if (end.dimension == 5) { \
00188               i = (((index[0]*end_data[1] + index[1]) * end_data[2] + index[2]) * end_data[3] + index[3]) * end_data[4] + index[4]; \
00189               CkArrayIndex5D idx(index[0], index[1], index[2], index[3], index[4]); \
00190               if (POPULATE_CONDITION) { \
00191                 mgr->insertInitial(idx,CkCopyMsg(&ctorMsg)); \
00192               } \
00193             } else if (end.dimension == 6) { \
00194               i = ((((index[0]*end_data[1] + index[1]) * end_data[2] + index[2]) * end_data[3] + index[3]) * end_data[4] + index[4]) * end_data[5] + index[5]; \
00195               CkArrayIndex6D idx(index[0], index[1], index[2], index[3], index[4], index[5]); \
00196               if (POPULATE_CONDITION) { \
00197                 mgr->insertInitial(idx,CkCopyMsg(&ctorMsg)); \
00198               } \
00199             } \
00200           } \
00201         } \
00202       } \
00203     } \
00204   } \
00205 }
00206   
00207 void CkArrayMap::populateInitial(int arrayHdl,CkArrayOptions& options,void *ctorMsg,CkArray *mgr)
00208 {
00209   CkArrayIndex start = options.getStart();
00210   CkArrayIndex end = options.getEnd();
00211   CkArrayIndex step = options.getStep();
00212     if (end.nInts==0) {
00213           CkFreeMsg(ctorMsg);
00214           return;
00215         }
00216     int thisPe=CkMyPe();
00217         
00218 
00219 
00220         CKARRAYMAP_POPULATE_INITIAL(CMK_RANK_0(procNum(arrayHdl,idx))==thisPe);
00221 
00222 #if CMK_BIGSIM_CHARM
00223         BgEntrySplit("split-array-new-end");
00224 #endif
00225 
00226     mgr->doneInserting();
00227     CkFreeMsg(ctorMsg);
00228 }
00229 
00230 void CkArrayMap::storeCkArrayOpts(CkArrayOptions options) {
00231 
00232   storeOpts = options;
00233 }
00234 
00235 void CkArrayMap::pup(PUP::er &p) {
00236   p|storeOpts;
00237   p|dynamicIns;
00238 }
00239 
00240 CkGroupID _defaultArrayMapID;
00241 CkGroupID _fastArrayMapID;
00242 
00243 class RRMap : public CkArrayMap
00244 {
00245 private:
00246   CkArrayIndex maxIndex;
00247   uint64_t products[2*CK_ARRAYINDEX_MAXLEN];
00248   bool productsInit;
00249 
00250 public:
00251   RRMap(void)
00252   {
00253     DEBC((AA "Creating RRMap\n" AB));
00254     productsInit = false;
00255   }
00256   RRMap(CkMigrateMessage *m):CkArrayMap(m){}
00257 
00258   void indexInit() {
00259     productsInit = true;
00260     maxIndex = storeOpts.getEnd();
00261     products[maxIndex.dimension - 1] = 1;
00262     if(maxIndex.dimension <= CK_ARRAYINDEX_MAXLEN) {
00263       for(int dim = maxIndex.dimension - 2; dim >= 0; dim--) {
00264         products[dim] = products[dim + 1] * maxIndex.index[dim + 1];
00265       }
00266     } else {
00267       for(int dim = maxIndex.dimension - 2; dim >= 0; dim--) {
00268         products[dim] = products[dim + 1] * maxIndex.indexShorts[dim + 1];
00269       }
00270     }
00271   } 
00272 
00273   int procNum(int arrayHdl, const CkArrayIndex &i)
00274   {
00275     if (i.dimension == 1) {
00276       
00277       int ans = (i.data()[0])%CkNumPes();
00278 #if CMK_FAULT_EVAC
00279       while(!CmiNodeAlive(ans) || (ans == CkMyPe() && CkpvAccess(startedEvac))){
00280         ans = (ans+1)%CkNumPes();
00281       }
00282 #endif
00283       return ans;
00284     }
00285     else {
00286       if(dynamicIns.find(arrayHdl) != dynamicIns.end()) {
00287         
00288         
00289         unsigned int hash=(i.hash()+739)%1280107;
00290         int ans = (hash % CkNumPes());
00291 #if CMK_FAULT_EVAC
00292         while(!CmiNodeAlive(ans)){
00293           ans = (ans+1)%CkNumPes();
00294         }
00295 #endif
00296         return ans;
00297       } else {
00298         if(!productsInit) { indexInit(); }
00299 
00300         int indexOffset = 0;
00301         if(i.dimension <= CK_ARRAYINDEX_MAXLEN) {
00302           for(int dim = i.dimension - 1; dim >= 0; dim--) {
00303             indexOffset += (i.index[dim] * products[dim]);
00304           }
00305         } else {
00306           for(int dim = maxIndex.dimension - 1; dim >= 0; dim--) {
00307             indexOffset += (i.indexShorts[dim] * products[dim]);
00308           }
00309         }
00310         return indexOffset % CkNumPes();
00311       }
00312     }
00313   }
00314 
00315   void pup(PUP::er& p) {
00316     CkArrayMap::pup(p);
00317     p|maxIndex;
00318     p|productsInit;
00319     PUParray(p, products, 2*CK_ARRAYINDEX_MAXLEN);
00320   }
00321 };
00322 
00327 class arrayMapInfo {
00328 public:
00329   CkArrayIndex _nelems;
00330   int _binSizeFloor;        
00331   int _binSizeCeil;     
00332   int _numChares;       
00333   int _remChares;       
00334 
00335   int _numFirstSet;     
00336 
00337 
00338   int _nBinSizeFloor;           
00339   int _nRemChares;              
00340 
00341   int _nNumFirstSet;            
00342 
00343 
00347   arrayMapInfo(void) { }
00348 
00349   arrayMapInfo(const CkArrayIndex& n) : _nelems(n), _numChares(0) {
00350     compute_binsize();
00351   }
00352 
00353   ~arrayMapInfo() {}
00354   
00355   void compute_binsize()
00356   {
00357     int numPes = CkNumPes();
00358     
00359     int numNodes = CkNumNodes();
00360 
00361     if (_nelems.dimension == 1) {
00362       _numChares = _nelems.data()[0];
00363     } else if (_nelems.dimension == 2) {
00364       _numChares = _nelems.data()[0] * _nelems.data()[1];
00365     } else if (_nelems.dimension == 3) {
00366       _numChares = _nelems.data()[0] * _nelems.data()[1] * _nelems.data()[2];
00367     } else if (_nelems.dimension == 4) {
00368       _numChares = (int)(((short int*)_nelems.data())[0] * ((short int*)_nelems.data())[1] * ((short int*)_nelems.data())[2] *
00369                    ((short int*)_nelems.data())[3]);
00370     } else if (_nelems.dimension == 5) {
00371       _numChares = (int)(((short int*)_nelems.data())[0] * ((short int*)_nelems.data())[1] * ((short int*)_nelems.data())[2] *
00372                    ((short int*)_nelems.data())[3] * ((short int*)_nelems.data())[4]);
00373     } else if (_nelems.dimension == 6) {
00374       _numChares = (int)(((short int*)_nelems.data())[0] * ((short int*)_nelems.data())[1] * ((short int*)_nelems.data())[2] *
00375                    ((short int*)_nelems.data())[3] * ((short int*)_nelems.data())[4] * ((short int*)_nelems.data())[5]);
00376     }
00377 
00378     _remChares = _numChares % numPes;
00379     _binSizeFloor = (int)floor((double)_numChares/(double)numPes);
00380     _binSizeCeil = (int)ceil((double)_numChares/(double)numPes);
00381     _numFirstSet = _remChares * (_binSizeFloor + 1);
00382 
00383     _nRemChares = _numChares % numNodes;
00384     _nBinSizeFloor = _numChares/numNodes;
00385     _nNumFirstSet = _nRemChares * (_nBinSizeFloor +1);
00386   }
00387 
00388   void pup(PUP::er& p){
00389     p|_nelems;
00390     p|_binSizeFloor;
00391     p|_binSizeCeil;
00392     p|_numChares;
00393     p|_remChares;
00394     p|_numFirstSet;
00395     p|_nBinSizeFloor;
00396     p|_nRemChares;
00397     p|_nNumFirstSet;
00398   }
00399 };
00400 
00401 
00406 class DefaultArrayMap : public RRMap
00407 {
00408 public:
00411   CkPupPtrVec<arrayMapInfo> amaps;
00412 
00413 public:
00414   DefaultArrayMap(void) {
00415     DEBC((AA "Creating DefaultArrayMap\n" AB));
00416   }
00417 
00418   DefaultArrayMap(CkMigrateMessage *m) : RRMap(m){}
00419 
00420   int registerArray(const CkArrayIndex& numElements, CkArrayID aid)
00421   {
00422     int idx = amaps.size();
00423     amaps.resize(idx+1);
00424     amaps[idx] = new arrayMapInfo(numElements);
00425     return idx;
00426   }
00427 
00428   void unregisterArray(int idx)
00429   {
00430     delete amaps[idx];
00431     amaps[idx] = NULL;
00432   }
00433  
00434   int procNum(int arrayHdl, const CkArrayIndex &i) {
00435     int flati;
00436     if (amaps[arrayHdl]->_nelems.dimension == 0) {
00437       dynamicIns[arrayHdl] = true;
00438       return RRMap::procNum(arrayHdl, i);
00439     }
00440 
00441     if (i.dimension == 1) {
00442       flati = i.data()[0];
00443     } else if (i.dimension == 2) {
00444       flati = i.data()[0] * amaps[arrayHdl]->_nelems.data()[1] + i.data()[1];
00445     } else if (i.dimension == 3) {
00446       flati = (i.data()[0] * amaps[arrayHdl]->_nelems.data()[1] + i.data()[1]) *
00447               amaps[arrayHdl]->_nelems.data()[2] + i.data()[2];
00448     } else if (i.dimension == 4) {
00449       flati = (int)(((((short int*)i.data())[0] * ((short int*)amaps[arrayHdl]->_nelems.data())[1] + ((short int*)i.data())[1]) *
00450               ((short int*)amaps[arrayHdl]->_nelems.data())[2] + ((short int*)i.data())[2]) *
00451               ((short int*)amaps[arrayHdl]->_nelems.data())[3] + ((short int*)i.data())[3]);
00452     } else if (i.dimension == 5) {
00453       flati = (int)((((((short int*)i.data())[0] * ((short int*)amaps[arrayHdl]->_nelems.data())[1] + ((short int*)i.data())[1]) *
00454               ((short int*)amaps[arrayHdl]->_nelems.data())[2] + ((short int*)i.data())[2]) *
00455               ((short int*)amaps[arrayHdl]->_nelems.data())[3] + ((short int*)i.data())[3]) *
00456               ((short int*)amaps[arrayHdl]->_nelems.data())[4] + ((short int*)i.data())[4]);
00457     } else if (i.dimension == 6) {
00458       flati = (int)(((((((short int*)i.data())[0] * ((short int*)amaps[arrayHdl]->_nelems.data())[1] + ((short int*)i.data())[1]) *
00459               ((short int*)amaps[arrayHdl]->_nelems.data())[2] + ((short int*)i.data())[2]) *
00460               ((short int*)amaps[arrayHdl]->_nelems.data())[3] + ((short int*)i.data())[3]) *
00461               ((short int*)amaps[arrayHdl]->_nelems.data())[4] + ((short int*)i.data())[4]) *
00462               ((short int*)amaps[arrayHdl]->_nelems.data())[5] + ((short int*)i.data())[5]);
00463     }
00464 #if CMK_ERROR_CHECKING
00465     else {
00466       CkAbort("CkArrayIndex has more than 6 dimensions!");
00467     }
00468 #endif
00469 
00470     if(useNodeBlkMapping){
00471       if(flati < amaps[arrayHdl]->_numChares){
00472         int numCharesOnNode = amaps[arrayHdl]->_nBinSizeFloor;
00473         int startNodeID, offsetInNode;
00474         if(flati < amaps[arrayHdl]->_nNumFirstSet){
00475           numCharesOnNode++;
00476           startNodeID = flati/numCharesOnNode;
00477           offsetInNode = flati%numCharesOnNode;
00478         }else{
00479           startNodeID = amaps[arrayHdl]->_nRemChares+(flati-amaps[arrayHdl]->_nNumFirstSet)/numCharesOnNode;
00480           offsetInNode = (flati-amaps[arrayHdl]->_nNumFirstSet)%numCharesOnNode;
00481         }
00482         int nodeSize = CkMyNodeSize(); 
00483         int elemsPerPE = numCharesOnNode/nodeSize;
00484         int remElems = numCharesOnNode%nodeSize;
00485         int firstSetPEs = remElems*(elemsPerPE+1);
00486         if(offsetInNode<firstSetPEs){
00487           return CkNodeFirst(startNodeID)+offsetInNode/(elemsPerPE+1);
00488         }else{
00489           return CkNodeFirst(startNodeID)+remElems+(offsetInNode-firstSetPEs)/elemsPerPE;
00490         }
00491       } else
00492           return (flati % CkNumPes());
00493     }
00494     
00495     if(flati < amaps[arrayHdl]->_numFirstSet)
00496       return (flati / (amaps[arrayHdl]->_binSizeFloor + 1));
00497     else if (flati < amaps[arrayHdl]->_numChares)
00498       return (amaps[arrayHdl]->_remChares + (flati - amaps[arrayHdl]->_numFirstSet) / (amaps[arrayHdl]->_binSizeFloor));
00499     else
00500       return (flati % CkNumPes());
00501   }
00502 
00503   void pup(PUP::er& p){
00504     RRMap::pup(p);
00505     int npes = CkNumPes();
00506     p|npes;
00507     p|amaps;
00508     if (p.isUnpacking() && npes != CkNumPes())  {   
00509       for (int i=0; i<amaps.size(); i++)
00510         if (amaps[i])
00511           amaps[i]->compute_binsize();
00512     }
00513   }
00514 };
00515 
00520 class FastArrayMap : public DefaultArrayMap
00521 {
00522 public:
00523   FastArrayMap(void) {
00524     DEBC((AA "Creating FastArrayMap\n" AB));
00525   }
00526 
00527   FastArrayMap(CkMigrateMessage *m) : DefaultArrayMap(m){}
00528 
00529   int registerArray(const CkArrayIndex& numElements, CkArrayID aid)
00530   {
00531     int idx;
00532     idx = DefaultArrayMap::registerArray(numElements, aid);
00533 
00534     return idx;
00535   }
00536 
00537   int procNum(int arrayHdl, const CkArrayIndex &i) {
00538     int flati = 0;
00539     if (amaps[arrayHdl]->_nelems.dimension == 0) {
00540       return RRMap::procNum(arrayHdl, i);
00541     }
00542 
00543     if (i.dimension == 1) {
00544       flati = i.data()[0];
00545     } else if (i.dimension == 2) {
00546       flati = i.data()[0] * amaps[arrayHdl]->_nelems.data()[1] + i.data()[1];
00547     } else if (i.dimension == 3) {
00548       flati = (i.data()[0] * amaps[arrayHdl]->_nelems.data()[1] + i.data()[1]) *
00549               amaps[arrayHdl]->_nelems.data()[2] + i.data()[2];
00550     } else if (i.dimension == 4) {
00551       flati = (int)(((((short int*)i.data())[0] * ((short int*)amaps[arrayHdl]->_nelems.data())[1] + ((short int*)i.data())[1]) *
00552               ((short int*)amaps[arrayHdl]->_nelems.data())[2] + ((short int*)i.data())[2]) *
00553               ((short int*)amaps[arrayHdl]->_nelems.data())[3] + ((short int*)i.data())[3]);
00554     } else if (i.dimension == 5) {
00555       flati = (int)((((((short int*)i.data())[0] * ((short int*)amaps[arrayHdl]->_nelems.data())[1] + ((short int*)i.data())[1]) *
00556               ((short int*)amaps[arrayHdl]->_nelems.data())[2] + ((short int*)i.data())[2]) *
00557               ((short int*)amaps[arrayHdl]->_nelems.data())[3] + ((short int*)i.data())[3]) *
00558               ((short int*)amaps[arrayHdl]->_nelems.data())[4] + ((short int*)i.data())[4]);
00559     } else if (i.dimension == 6) {
00560       flati = (int)(((((((short int*)i.data())[0] * ((short int*)amaps[arrayHdl]->_nelems.data())[1] + ((short int*)i.data())[1]) *
00561               ((short int*)amaps[arrayHdl]->_nelems.data())[2] + ((short int*)i.data())[2]) *
00562               ((short int*)amaps[arrayHdl]->_nelems.data())[3] + ((short int*)i.data())[3]) *
00563               ((short int*)amaps[arrayHdl]->_nelems.data())[4] + ((short int*)i.data())[4]) *
00564               ((short int*)amaps[arrayHdl]->_nelems.data())[5] + ((short int*)i.data())[5]);
00565     }
00566 #if CMK_ERROR_CHECKING
00567     else {
00568       CkAbort("CkArrayIndex has more than 6 dimensions!");
00569     }
00570 #endif
00571 
00574     return (flati / amaps[arrayHdl]->_binSizeCeil);
00575   }
00576 
00577   void pup(PUP::er& p){
00578     DefaultArrayMap::pup(p);
00579   }
00580 };
00581 
00582 
00583 
00584 
00585 
00586 
00587 typedef struct {
00588     int intIndex;
00589     std::vector<int> coords;
00590 }hilbert_pair;
00591 
00592 bool operator== ( hilbert_pair p1, hilbert_pair p2) 
00593 {
00594     return p1.intIndex == p2.intIndex;
00595 }
00596 
00597 bool myCompare(hilbert_pair p1, hilbert_pair p2)
00598 {
00599     return p1.intIndex < p2.intIndex;
00600 }
00601 
00602 class HilbertArrayMap: public DefaultArrayMap
00603 {
00604   std::vector<int> allpairs;
00605   std::vector<int> procList;
00606 public:
00607   HilbertArrayMap(void) {
00608     procList.resize(CkNumPes());
00609     getHilbertList(procList.data());
00610     DEBC((AA "Creating HilbertArrayMap\n" AB));
00611   }
00612 
00613   HilbertArrayMap(CkMigrateMessage *m) : DefaultArrayMap(m){}
00614 
00615   ~HilbertArrayMap() {}
00616 
00617   int registerArray(const CkArrayIndex& i, CkArrayID aid)
00618   {
00619     int idx;
00620     idx = DefaultArrayMap::registerArray(i, aid);
00621    
00622     if (i.dimension == 1) {
00623       
00624     } else if (i.dimension == 2) {
00625       
00626       const int dims = 2;
00627       int nDim0 = amaps[idx]->_nelems.data()[0];
00628       int nDim1 = amaps[idx]->_nelems.data()[1];
00629       int index;
00630       int counter = 0;
00631       std::vector<int> coords;
00632       allpairs.resize(nDim0*nDim1);
00633       coords.resize(dims);
00634       for(int i=0; i<nDim0; i++)
00635         for(int j=0; j<nDim1; j++)
00636         {
00637           coords[0] = i;
00638           coords[1] = j;
00639           index = Hilbert_to_int( coords, dims);
00640           
00641           allpairs[counter] = index;
00642           counter++;
00643         }
00644     } else if (i.dimension == 3) {
00645       
00646       
00647       const int dims = 3;
00648       int nDim0 = amaps[idx]->_nelems.data()[0];
00649       int nDim1 = amaps[idx]->_nelems.data()[1];
00650       int nDim2 = amaps[idx]->_nelems.data()[2];
00651       int index;
00652       int counter = 0;
00653       std::vector<int> coords;
00654       allpairs.resize(nDim0*nDim1*nDim2);
00655       coords.resize(dims);
00656       for(int i=0; i<nDim0; i++)
00657         for(int j=0; j<nDim1; j++)
00658           for(int k=0; k<nDim2; k++)
00659           {
00660             coords[0] = i;
00661             coords[1] = j;
00662             coords[2] = k;
00663             index = Hilbert_to_int( coords, dims);
00664             allpairs[counter] = index;
00665             counter++;
00666           }
00667     } else if (i.dimension == 4) {
00668       
00669       
00670       
00671       const int dims = 4;
00672       int nDim[dims];
00673       for(int k=0; k<dims; k++) {
00674         nDim[k] = (int)((short int*)amaps[idx]->_nelems.data())[k];
00675       }
00676       int index;
00677       int counter = 0;
00678       std::vector<int> coords;
00679       allpairs.resize(nDim[0]*nDim[1]*nDim[2]*nDim[3]);
00680       coords.resize(dims);
00681       for(int i=0; i<nDim[0]; i++)
00682         for(int j=0; j<nDim[1]; j++)
00683           for(int k=0; k<nDim[2]; k++)
00684             for(int x=0; x<nDim[3]; x++)
00685             {
00686               coords[0] = i;
00687               coords[1] = j;
00688               coords[2] = k;
00689               coords[3] = x;
00690               index = Hilbert_to_int(coords, dims);
00691               allpairs[counter] = index;
00692               counter++;
00693             }
00694     } else if (i.dimension == 5) {
00695       
00696       
00697       
00698       const int dims = 5;
00699       int nDim[dims];
00700       for(int k=0; k<dims; k++) {
00701         nDim[k] = (int)((short int*)amaps[idx]->_nelems.data())[k];
00702       }
00703       int index;
00704       int counter = 0;
00705       std::vector<int> coords;
00706       allpairs.resize(nDim[0]*nDim[1]*nDim[2]*nDim[3]*nDim[4]);
00707       coords.resize(dims);
00708       for(int i=0; i<nDim[0]; i++)
00709         for(int j=0; j<nDim[1]; j++)
00710           for(int k=0; k<nDim[2]; k++)
00711             for(int x=0; x<nDim[3]; x++)
00712               for(int y=0; y<nDim[4]; y++)
00713               {
00714                 coords[0] = i;
00715                 coords[1] = j;
00716                 coords[2] = k;
00717                 coords[3] = x;
00718                 coords[4] = y;
00719                 index = Hilbert_to_int(coords, dims);
00720                 allpairs[counter] = index;
00721                 counter++;
00722               }
00723     } else if (i.dimension == 6) {
00724       
00725       
00726       
00727       
00728       const int dims = 6;
00729       int nDim[dims];
00730       for(int k=0; k<dims; k++) {
00731         nDim[k] = (int)((short int*)amaps[idx]->_nelems.data())[k];
00732       }
00733       int index;
00734       int counter = 0;
00735       std::vector<int> coords;
00736       allpairs.resize(nDim[0]*nDim[1]*nDim[2]*nDim[3]*nDim[4]*nDim[5]);
00737       coords.resize(dims);
00738       for(int i=0; i<nDim[0]; i++)
00739         for(int j=0; j<nDim[1]; j++)
00740           for(int k=0; k<nDim[2]; k++)
00741             for(int x=0; x<nDim[3]; x++)
00742               for(int y=0; y<nDim[4]; y++)
00743                 for(int z=0; z<nDim[5]; z++)
00744                 {
00745                   coords[0] = i;
00746                   coords[1] = j;
00747                   coords[2] = k;
00748                   coords[3] = x;
00749                   coords[4] = y;
00750                   coords[5] = y;
00751                   index = Hilbert_to_int(coords, dims);
00752                   allpairs[counter] = index;
00753                   counter++;
00754                 }
00755     }
00756     return idx;
00757   }
00758 
00759   int procNum(int arrayHdl, const CkArrayIndex &i) {
00760     int flati = 0;
00761     int myInt;
00762     int dest;
00763     if (amaps[arrayHdl]->_nelems.dimension == 0) {
00764       return RRMap::procNum(arrayHdl, i);
00765     }
00766     if (i.dimension == 1) {
00767       flati = i.data()[0];
00768     } else if (i.dimension == 2) {
00769       int nDim1 = amaps[arrayHdl]->_nelems.data()[1];
00770       myInt = i.data()[0] * nDim1 + i.data()[1];
00771       flati = allpairs[myInt];
00772     } else if (i.dimension == 3) {
00773       hilbert_pair mypair;
00774       mypair.coords.resize(3);
00775       int nDim[2];
00776       for (int j = 0; j < 2; j++) {
00777         nDim[j] = amaps[arrayHdl]->_nelems.data()[j+1];
00778       }
00779       myInt = i.data()[0] * nDim[0] * nDim[1] + i.data()[1] * nDim[1] + i.data()[2];
00780       flati = allpairs[myInt];
00781     } else if (i.dimension == 4) {
00782       hilbert_pair mypair;
00783       mypair.coords.resize(4);
00784       short int nDim[3];
00785       for (int j = 0; j < 3; j++) {
00786         nDim[j] = ((short int*)amaps[arrayHdl]->_nelems.data())[j+1];
00787       }
00788       myInt = (int)(((short int*)i.data())[0] * nDim[0] * nDim[1] * nDim[2] +
00789               ((short int*)i.data())[1] * nDim[1] * nDim[2] +
00790               ((short int*)i.data())[2] * nDim[2] +
00791               ((short int*)i.data())[3]);
00792       flati = allpairs[myInt];
00793     } else if (i.dimension == 5) {
00794       hilbert_pair mypair;
00795       mypair.coords.resize(5);
00796       short int nDim[4];
00797       for (int j = 0; j < 4; j++) {
00798         nDim[j] = ((short int*)amaps[arrayHdl]->_nelems.data())[j+1];
00799       }
00800       myInt = (int)(((short int*)i.data())[0] * nDim[0] * nDim[1] * nDim[2] * nDim[3] +
00801               ((short int*)i.data())[1] * nDim[1] * nDim[2] * nDim[3] +
00802               ((short int*)i.data())[2] * nDim[2] * nDim[3] +
00803               ((short int*)i.data())[3] * nDim[3] +
00804               ((short int*)i.data())[4]);
00805       flati = allpairs[myInt];
00806     } else if (i.dimension == 6) {
00807       hilbert_pair mypair;
00808       mypair.coords.resize(6);
00809       short int nDim[5];
00810       for (int j = 0; j < 5; j++) {
00811         nDim[j] = ((short int*)amaps[arrayHdl]->_nelems.data())[j+1];
00812       }
00813       myInt = (int)(((short int*)i.data())[0] * nDim[0] * nDim[1] * nDim[2] * nDim[3] * nDim[4] +
00814               ((short int*)i.data())[1] * nDim[1] * nDim[2] * nDim[3] * nDim[4] +
00815               ((short int*)i.data())[2] * nDim[2] * nDim[3] * nDim[4] +
00816               ((short int*)i.data())[3] * nDim[3] * nDim[4] +
00817               ((short int*)i.data())[4] * nDim[4] +
00818               ((short int*)i.data())[5]);
00819       flati = allpairs[myInt];
00820     }
00821 #if CMK_ERROR_CHECKING
00822     else {
00823       CkAbort("CkArrayIndex has more than 6 dimensions!");
00824     }
00825 #endif
00826 
00829     int block = flati / amaps[arrayHdl]->_binSizeCeil;
00830     
00831     
00832     
00833     
00834     return procList[block];
00835   }
00836 
00837   void pup(PUP::er& p){
00838     DefaultArrayMap::pup(p);
00839   }
00840 };
00841 
00842 
00847 class ReadFileMap : public DefaultArrayMap
00848 {
00849 private:
00850   std::vector<int> mapping;
00851 
00852 public:
00853   ReadFileMap(void) {
00854     DEBC((AA "Creating ReadFileMap\n" AB));
00855   }
00856 
00857   ReadFileMap(CkMigrateMessage *m) : DefaultArrayMap(m){}
00858 
00859   int registerArray(const CkArrayIndex& numElements, CkArrayID aid)
00860   {
00861     int idx;
00862     idx = DefaultArrayMap::registerArray(numElements, aid);
00863 
00864     if(mapping.size() == 0) {
00865       int numChares;
00866 
00867       if (amaps[idx]->_nelems.dimension == 1) {
00868         numChares = amaps[idx]->_nelems.data()[0];
00869       } else if (amaps[idx]->_nelems.dimension == 2) {
00870         numChares = amaps[idx]->_nelems.data()[0] * amaps[idx]->_nelems.data()[1];
00871       } else if (amaps[idx]->_nelems.dimension == 3) {
00872         numChares = amaps[idx]->_nelems.data()[0] * amaps[idx]->_nelems.data()[1] *
00873                     amaps[idx]->_nelems.data()[2];
00874       } else if (amaps[idx]->_nelems.dimension == 4) {
00875         numChares = (int)(((short int*)amaps[idx]->_nelems.data())[0] * ((short int*)amaps[idx]->_nelems.data())[1] *
00876                     ((short int*)amaps[idx]->_nelems.data())[2] * ((short int*)amaps[idx]->_nelems.data())[3]);
00877       } else if (amaps[idx]->_nelems.dimension == 5) {
00878         numChares = (int)(((short int*)amaps[idx]->_nelems.data())[0] * ((short int*)amaps[idx]->_nelems.data())[1] *
00879                     ((short int*)amaps[idx]->_nelems.data())[2] * ((short int*)amaps[idx]->_nelems.data())[3] *
00880                     ((short int*)amaps[idx]->_nelems.data())[4]);
00881       } else if (amaps[idx]->_nelems.dimension == 6) {
00882         numChares = (int)(((short int*)amaps[idx]->_nelems.data())[0] * ((short int*)amaps[idx]->_nelems.data())[1] *
00883                     ((short int*)amaps[idx]->_nelems.data())[2] * ((short int*)amaps[idx]->_nelems.data())[3] *
00884                     ((short int*)amaps[idx]->_nelems.data())[4] * ((short int*)amaps[idx]->_nelems.data())[5]);
00885       } else {
00886         CkAbort("CkArrayIndex has more than 6 dimension!");
00887       }
00888 
00889       mapping.resize(numChares);
00890       FILE *mapf = fopen("mapfile", "r");
00891       TopoManager tmgr;
00892       int x, y, z, t;
00893 
00894       for(int i=0; i<numChares; i++) {
00895         if (fscanf(mapf, "%d %d %d %d", &x, &y, &z, &t) != 4) {
00896           CkAbort("ReadFileMap> reading from mapfile failed!");
00897         }
00898         mapping[i] = tmgr.coordinatesToRank(x, y, z, t);
00899       }
00900       fclose(mapf);
00901     }
00902 
00903     return idx;
00904   }
00905 
00906   int procNum(int arrayHdl, const CkArrayIndex &i) {
00907     int flati;
00908 
00909     if (i.dimension == 1) {
00910       flati = i.data()[0];
00911     } else if (i.dimension == 2) {
00912       flati = i.data()[0] * amaps[arrayHdl]->_nelems.data()[1] + i.data()[1];
00913     } else if (i.dimension == 3) {
00914       flati = (i.data()[0] * amaps[arrayHdl]->_nelems.data()[1] + i.data()[1]) *
00915               amaps[arrayHdl]->_nelems.data()[2] + i.data()[2];
00916     } else if (i.dimension == 4) {
00917       flati = (int)(((((short int*)i.data())[0] * ((short int*)amaps[arrayHdl]->_nelems.data())[1] + ((short int*)i.data())[1]) *
00918               ((short int*)amaps[arrayHdl]->_nelems.data())[2] + ((short int*)i.data())[2]) *
00919               ((short int*)amaps[arrayHdl]->_nelems.data())[3] + ((short int*)i.data())[3]);
00920     } else if (i.dimension == 5) {
00921       flati = (int)((((((short int*)i.data())[0] * ((short int*)amaps[arrayHdl]->_nelems.data())[1] + ((short int*)i.data())[1]) *
00922               ((short int*)amaps[arrayHdl]->_nelems.data())[2] + ((short int*)i.data())[2]) *
00923               ((short int*)amaps[arrayHdl]->_nelems.data())[3] + ((short int*)i.data())[3]) *
00924               ((short int*)amaps[arrayHdl]->_nelems.data())[4] + ((short int*)i.data())[4]);
00925     } else if (i.dimension == 6) {
00926       flati = (int)(((((((short int*)i.data())[0] * ((short int*)amaps[arrayHdl]->_nelems.data())[1] + ((short int*)i.data())[1]) *
00927               ((short int*)amaps[arrayHdl]->_nelems.data())[2] + ((short int*)i.data())[2]) *
00928               ((short int*)amaps[arrayHdl]->_nelems.data())[3] + ((short int*)i.data())[3]) *
00929               ((short int*)amaps[arrayHdl]->_nelems.data())[4] + ((short int*)i.data())[4]) *
00930               ((short int*)amaps[arrayHdl]->_nelems.data())[5] + ((short int*)i.data())[5]);
00931     } else {
00932       CkAbort("CkArrayIndex has more than 6 dimensions!");
00933     }
00934 
00935     return mapping[flati];
00936   }
00937 
00938   void pup(PUP::er& p){
00939     DefaultArrayMap::pup(p);
00940     p|mapping;
00941   }
00942 };
00943 
00944 class BlockMap : public RRMap
00945 {
00946 public:
00947   BlockMap(void){
00948     DEBC((AA "Creating BlockMap\n" AB));
00949   }
00950   BlockMap(CkMigrateMessage *m):RRMap(m){ }
00951   void populateInitial(int arrayHdl,CkArrayOptions& options,void *ctorMsg,CkArray *mgr){
00952     CkArrayIndex start = options.getStart();
00953     CkArrayIndex end = options.getEnd();
00954     CkArrayIndex step = options.getStep();
00955     if (end.dimension == 0) {
00956       CkFreeMsg(ctorMsg);
00957       return;
00958     }
00959     int thisPe=CkMyPe();
00960     int numPes=CkNumPes();
00961     int binSize;
00962     if (end.dimension == 1) {
00963       binSize = (int)ceil((double)(end.data()[0]) / (double)numPes);
00964     } else if (end.dimension == 2) {
00965       binSize = (int)ceil((double)(end.data()[0] * end.data()[1]) / (double)numPes);
00966     } else if (end.dimension == 3) {
00967       binSize = (int)ceil((double)(end.data()[0] * end.data()[1] * end.data()[2])) / (double)numPes;
00968     } else if (end.dimension == 4) {
00969       binSize = (int)ceil((double)(((short int*)end.data())[0] * ((short int*)end.data())[1] *
00970                 ((short int*)end.data())[2] * ((short int*)end.data())[3]) / (double)numPes);
00971     } else if (end.dimension == 5) {
00972       binSize = (int)ceil((double)(((short int*)end.data())[0] * ((short int*)end.data())[1] *
00973                 ((short int*)end.data())[2] * ((short int*)end.data())[3] * ((short int*)end.data())[4]) /
00974                 (double)numPes);
00975     } else if (end.dimension == 6) {
00976       binSize = (int)ceil((double)(((short int*)end.data())[0] * ((short int*)end.data())[1] *
00977                 ((short int*)end.data())[2] * ((short int*)end.data())[3] * ((short int*)end.data())[4] *
00978                 ((short int*)end.data())[5]) / (double)numPes);
00979     } else {
00980       CkAbort("CkArrayIndex has more than 6 dimensions!");
00981     }
00982     CKARRAYMAP_POPULATE_INITIAL(i/binSize==thisPe);
00983 
00984     
00985 
00986 
00987 
00988 
00989 
00990     mgr->doneInserting();
00991     CkFreeMsg(ctorMsg);
00992   }
00993 };
00994 
00998 class CldMap : public CkArrayMap
00999 {
01000 public:
01001   CldMap(void)
01002   {
01003       DEBC((AA "Creating CldMap\n" AB));
01004   }
01005   CldMap(CkMigrateMessage *m):CkArrayMap(m){}
01006   int homePe(int , const CkArrayIndex &i)
01007   {
01008     if (i.dimension == 1) {
01009       
01010       return (i.data()[0])%CkNumPes();
01011     }
01012     else 
01013       {
01014     
01015     unsigned int hash=(i.hash()+739)%1280107;
01016     return (hash % CkNumPes());
01017       }
01018   }
01019   int procNum(int arrayHdl, const CkArrayIndex &i)
01020   {
01021      return CLD_ANYWHERE;   
01022   }
01023   void populateInitial(int arrayHdl,CkArrayOptions& options,void *ctorMsg,CkArray *mgr)  {
01024         CkArrayIndex start = options.getStart();
01025         CkArrayIndex end = options.getEnd();
01026         CkArrayIndex step = options.getStep();
01027         if (end.dimension == 0) {
01028           CkFreeMsg(ctorMsg);
01029           return;
01030         }
01031         int thisPe=CkMyPe();
01032         int numPes=CkNumPes();
01033 
01034         CKARRAYMAP_POPULATE_INITIAL(i%numPes==thisPe);
01035         mgr->doneInserting();
01036         CkFreeMsg(ctorMsg);
01037   }
01038 };
01039 
01040 
01043 class ConfigurableRRMapLoader {
01044 public:
01045   
01046   std::vector<int> locations;
01047   int objs_per_block;
01048   int PE_per_block;
01049 
01051   enum ConfigurableRRMapLoadStatus : uint8_t {
01052     not_loaded,
01053     loaded_found,
01054     loaded_not_found
01055   };
01056   
01057   enum ConfigurableRRMapLoadStatus state;
01058   
01059   ConfigurableRRMapLoader(){
01060     state = not_loaded;
01061     objs_per_block = 0;
01062     PE_per_block = 0;
01063   }
01064   
01066   bool haveConfiguration() {
01067     if(state == not_loaded) {
01068       DEBUG(("[%d] loading ConfigurableRRMap configuration\n", CkMyPe()));
01069       char **argv=CkGetArgv();
01070       char *configuration = NULL;
01071       bool found = CmiGetArgString(argv, "+ConfigurableRRMap", &configuration);
01072       if(!found){
01073     DEBUG(("Couldn't find +ConfigurableRRMap command line argument\n"));
01074     state = loaded_not_found;
01075     return false;
01076       } else {
01077 
01078     DEBUG(("Found +ConfigurableRRMap command line argument in %p=\"%s\"\n", configuration, configuration));
01079 
01080     std::istringstream instream(configuration);
01081     CkAssert(instream.good());
01082      
01083     
01084     
01085     
01086     
01087     
01088     instream >> objs_per_block >> PE_per_block;
01089     CkAssert(instream.good());
01090     CkAssert(objs_per_block > 0);
01091     CkAssert(PE_per_block > 0);
01092     locations.resize(objs_per_block);
01093     for(int i=0;i<objs_per_block;i++){
01094       locations[i] = 0;
01095       CkAssert(instream.good());
01096       instream >> locations[i];
01097       CkAssert(locations[i] < PE_per_block);
01098     }
01099     state = loaded_found;
01100     return true;
01101       }
01102 
01103     } else {
01104       DEBUG(("[%d] ConfigurableRRMap has already been loaded\n", CkMyPe()));
01105       return state == loaded_found;
01106     }      
01107      
01108   }
01109   
01110 };
01111 
01112 CkpvDeclare(ConfigurableRRMapLoader, myConfigRRMapState);
01113 
01114 void _initConfigurableRRMap(){
01115   CkpvInitialize(ConfigurableRRMapLoader, myConfigRRMapState);
01116 }
01117 
01118 
01120 bool haveConfigurableRRMap(){
01121   DEBUG(("haveConfigurableRRMap()\n"));
01122   ConfigurableRRMapLoader &loader =  CkpvAccess(myConfigRRMapState);
01123   return loader.haveConfiguration();
01124 }
01125 
01126 class ConfigurableRRMap : public RRMap
01127 {
01128 public:
01129   ConfigurableRRMap(void){
01130     DEBC((AA "Creating ConfigurableRRMap\n" AB));
01131   }
01132   ConfigurableRRMap(CkMigrateMessage *m):RRMap(m){ }
01133 
01134 
01135   void populateInitial(int arrayHdl,CkArrayOptions& options,void *ctorMsg,CkArray *mgr){
01136     CkArrayIndex start = options.getStart();
01137     CkArrayIndex end = options.getEnd();
01138     CkArrayIndex step = options.getStep();
01139     
01140     CkAssert(haveConfigurableRRMap());
01141     ConfigurableRRMapLoader &loader =  CkpvAccess(myConfigRRMapState);
01142     if (end.dimension == 0) {
01143       CkFreeMsg(ctorMsg);
01144       return;
01145     }
01146     int thisPe=CkMyPe();
01147     int maxIndex = end.data()[0];
01148     DEBUG(("[%d] ConfigurableRRMap: index=%d,%d,%d\n", CkMyPe(),(int)end.data()[0], (int)end.data()[1], (int)end.data()[2]));
01149 
01150     if (end.dimension != 1) {
01151       CkAbort("ConfigurableRRMap only supports dimension 1!");
01152     }
01153     
01154     for (int index=0; index<maxIndex; index++) {    
01155       CkArrayIndex1D idx(index);        
01156       
01157       int cyclic_block = index / loader.objs_per_block;
01158       int cyclic_local = index % loader.objs_per_block;
01159       int l = loader.locations[ cyclic_local ];
01160       int PE = (cyclic_block*loader.PE_per_block + l) % CkNumPes();
01161 
01162       DEBUG(("[%d] ConfigurableRRMap: index=%d is located on PE %d l=%d\n", CkMyPe(), (int)index, (int)PE, l));
01163 
01164       if(PE == thisPe)
01165     mgr->insertInitial(idx,CkCopyMsg(&ctorMsg));
01166 
01167     }
01168     
01169     
01170     mgr->doneInserting();
01171     CkFreeMsg(ctorMsg);
01172   }
01173 };
01174 
01175 
01176 CkpvStaticDeclare(double*, rem);
01177 
01178 class arrInfo {
01179  private:
01180    CkArrayIndex _nelems;
01181    std::vector<int> _map;
01182  public:
01183    arrInfo() {}
01184    arrInfo(const CkArrayIndex& n, int *speeds) : _nelems(n), _map(_nelems.getCombinedCount())
01185    {
01186      distrib(speeds);
01187    }
01188    ~arrInfo() {}
01189    int getMap(const CkArrayIndex &i);
01190    void distrib(int *speeds);
01191    void pup(PUP::er& p){
01192      p|_nelems;
01193      p|_map;
01194    }
01195 };
01196 
01197 static int cmp(const void *first, const void *second)
01198 {
01199   int fi = *((const int *)first);
01200   int si = *((const int *)second);
01201   return ((CkpvAccess(rem)[fi]==CkpvAccess(rem)[si]) ?
01202           0 :
01203           ((CkpvAccess(rem)[fi]<CkpvAccess(rem)[si]) ?
01204           1 : (-1)));
01205 }
01206 
01207 void
01208 arrInfo::distrib(int *speeds)
01209 {
01210   int _nelemsCount = _nelems.getCombinedCount();
01211   double total = 0.0;
01212   int npes = CkNumPes();
01213   int i,j,k;
01214   for(i=0;i<npes;i++)
01215     total += (double) speeds[i];
01216   std::vector<double> nspeeds(npes);
01217   for(i=0;i<npes;i++)
01218     nspeeds[i] = (double) speeds[i] / total;
01219   std::vector<int> cp(npes);
01220   for(i=0;i<npes;i++)
01221     cp[i] = (int) (nspeeds[i]*_nelemsCount);
01222   int nr = 0;
01223   for(i=0;i<npes;i++)
01224     nr += cp[i];
01225   nr = _nelemsCount - nr;
01226   if(nr != 0)
01227   {
01228     CkpvAccess(rem) = new double[npes];
01229     for(i=0;i<npes;i++)
01230       CkpvAccess(rem)[i] = (double)_nelemsCount*nspeeds[i] - cp[i];
01231     std::vector<int> pes(npes);
01232     for(i=0;i<npes;i++)
01233       pes[i] = i;
01234     qsort(pes.data(), npes, sizeof(int), cmp);
01235     for(i=0;i<nr;i++)
01236       cp[pes[i]]++;
01237     delete[] CkpvAccess(rem);
01238   }
01239   k = 0;
01240   for(i=0;i<npes;i++)
01241   {
01242     for(j=0;j<cp[i];j++)
01243       _map[k++] = i;
01244   }
01245 }
01246 
01247 int
01248 arrInfo::getMap(const CkArrayIndex &i)
01249 {
01250   if(i.dimension == 1)
01251     return _map[i.data()[0]];
01252   else
01253     return _map[((i.hash()+739)%1280107)%_nelems.getCombinedCount()];
01254 }
01255 
01256 
01257 
01258 static int* speeds;
01259 
01260 #if CMK_USE_PROP_MAP
01261 typedef struct _speedmsg
01262 {
01263   char hdr[CmiMsgHeaderSizeBytes];
01264   int node;
01265   int speed;
01266 } speedMsg;
01267 
01268 static void _speedHdlr(void *m)
01269 {
01270   speedMsg *msg=(speedMsg *)m;
01271   if (CmiMyRank()==0)
01272     for (int pe=0;pe<CmiNodeSize(msg->node);pe++)
01273       speeds[CmiNodeFirst(msg->node)+pe] = msg->speed;  
01274   CmiFree(m);
01275 }
01276 
01277 
01278 void _propMapInit(void)
01279 {
01280   speeds = new int[CkNumPes()];
01281   int hdlr = CkRegisterHandler(_speedHdlr);
01282   CmiPrintf("[%d]Measuring processor speed for prop. mapping...\n", CkMyPe());
01283   int s = LDProcessorSpeed();
01284   speedMsg msg;
01285   CmiSetHandler(&msg, hdlr);
01286   msg.node = CkMyNode();
01287   msg.speed = s;
01288   CmiSyncBroadcastAllAndFree(sizeof(msg), &msg);
01289   for(int i=0;i<CkNumNodes();i++)
01290     CmiDeliverSpecificMsg(hdlr);
01291 }
01292 #else
01293 void _propMapInit(void)
01294 {
01295   speeds = new int[CkNumPes()];
01296   int i;
01297   for(i=0;i<CkNumPes();i++)
01298     speeds[i] = 1;
01299 }
01300 #endif
01301 
01307 class PropMap : public CkArrayMap
01308 {
01309 private:
01310   CkPupPtrVec<arrInfo> arrs;
01311 public:
01312   PropMap(void)
01313   {
01314     CkpvInitialize(double*, rem);
01315     DEBC((AA "Creating PropMap\n" AB));
01316   }
01317   PropMap(CkMigrateMessage *m) {}
01318   int registerArray(const CkArrayIndex& numElements, CkArrayID aid)
01319   {
01320     int idx = arrs.size();
01321     arrs.resize(idx+1);
01322     arrs[idx] = new arrInfo(numElements, speeds);
01323     return idx;
01324   }
01325   void unregisterArray(int idx)
01326   {
01327     arrs[idx].destroy();
01328   }
01329   int procNum(int arrayHdl, const CkArrayIndex &i)
01330   {
01331     return arrs[arrayHdl]->getMap(i);
01332   }
01333   void pup(PUP::er& p){
01334     int oldNumPes = -1;
01335     if(p.isPacking()){
01336       oldNumPes = CkNumPes();
01337     }
01338     p|oldNumPes;
01339     p|arrs;
01340     if(p.isUnpacking() && oldNumPes != CkNumPes()){
01341       for(int idx = 0; idx < arrs.length(); ++idx){
01342         arrs[idx]->distrib(speeds);
01343       }
01344     }
01345   }
01346 };
01347 
01348 class CkMapsInit : public Chare
01349 {
01350 public:
01351     CkMapsInit(CkArgMsg *msg) {
01352         
01353         _defaultArrayMapID = CProxy_DefaultArrayMap::ckNew();
01354         _fastArrayMapID = CProxy_FastArrayMap::ckNew();
01355         delete msg;
01356     }
01357 
01358     CkMapsInit(CkMigrateMessage *m) {}
01359 };
01360 
01361 
01362 CkMigratable * CkArrayMessageObjectPtr(envelope *env) {
01363   if (env->getMsgtype() != ForArrayEltMsg)
01364       return NULL;   
01365 
01367   CkArray *mgr = CProxy_CkArray(env->getArrayMgr()).ckLocalBranch();
01368   return mgr ? mgr->lookup(ck::ObjID(env->getRecipientID()).getElementID()) : NULL;
01369 }
01370 
01371 
01372 
01373 #if CMK_OUT_OF_CORE
01374 CooPrefetchManager CkArrayElementPrefetcher;
01375 CkpvDeclare(int,CkSaveRestorePrefetch);
01376 
01382 int CkArrayPrefetch_msg2ObjId(void *msg) {
01383   envelope *env=(envelope *)msg;
01384   CkMigratable *elt = CkArrayMessageObjectPtr(env);
01385   return elt?elt->prefetchObjID:-1;
01386 }
01387 
01392 void CkArrayPrefetch_writeToSwap(FILE *swapfile,void *objptr) {
01393   CkMigratable *elt=(CkMigratable *)objptr;
01394 
01395   
01396   PUP::toDisk p(swapfile);
01397   elt->virtual_pup(p);
01398 
01399   
01400   CkpvAccess(CkSaveRestorePrefetch)=1;
01401   elt->~CkMigratable(); 
01402   CkpvAccess(CkSaveRestorePrefetch)=0;
01403 }
01404     
01409 void CkArrayPrefetch_readFromSwap(FILE *swapfile,void *objptr) {
01410   CkMigratable *elt=(CkMigratable *)objptr;
01411   
01412   CkpvAccess(CkSaveRestorePrefetch)=1;
01413   int ctorIdx=_chareTable[elt->thisChareType]->migCtor;
01414   elt->myRec->invokeEntry(elt,(CkMigrateMessage *)0,ctorIdx,true);
01415   CkpvAccess(CkSaveRestorePrefetch)=0;
01416   
01417   
01418   PUP::fromDisk p(swapfile);
01419   elt->virtual_pup(p);
01420 }
01421 
01422 static void _CkMigratable_prefetchInit(void) 
01423 {
01424   CkpvExtern(int,CkSaveRestorePrefetch);
01425   CkpvAccess(CkSaveRestorePrefetch)=0;
01426   CkArrayElementPrefetcher.msg2ObjId=CkArrayPrefetch_msg2ObjId;
01427   CkArrayElementPrefetcher.writeToSwap=CkArrayPrefetch_writeToSwap;
01428   CkArrayElementPrefetcher.readFromSwap=CkArrayPrefetch_readFromSwap;
01429   CooRegisterManager(&CkArrayElementPrefetcher, _charmHandlerIdx);
01430 }
01431 #endif
01432 
01433 
01438 class CkMigratable_initInfo {
01439 public:
01440     CkLocRec *locRec;
01441     int chareType;
01442     bool forPrefetch; 
01443 };
01444 
01445 CkpvStaticDeclare(CkMigratable_initInfo,mig_initInfo);
01446 
01447 
01448 void _CkMigratable_initInfoInit(void) {
01449   CkpvInitialize(CkMigratable_initInfo,mig_initInfo);
01450 #if CMK_OUT_OF_CORE
01451   _CkMigratable_prefetchInit();
01452 #endif
01453 }
01454 
01455 void CkMigratable::commonInit(void) {
01456     CkMigratable_initInfo &i=CkpvAccess(mig_initInfo);
01457 #if CMK_OUT_OF_CORE
01458     isInCore=true;
01459     if (CkpvAccess(CkSaveRestorePrefetch))
01460         return; 
01461     prefetchObjID=-1; 
01462 #endif
01463     myRec=i.locRec;
01464     thisIndexMax=myRec->getIndex();
01465     thisChareType=i.chareType;
01466     usesAtSync=false;
01467     usesAutoMeasure=true;
01468     barrierRegistered=false;
01469 
01470   local_state = OFF;
01471   prev_load = 0.0;
01472   can_reset = false;
01473 
01474 #if CMK_LBDB_ON
01475   if (_lb_args.metaLbOn()) {
01476     atsync_iteration = myRec->getMetaBalancer()->get_iteration();
01477     myRec->getMetaBalancer()->AdjustCountForNewContributor(atsync_iteration);
01478   }
01479 #endif
01480 
01481 #if CMK_FAULT_EVAC
01482     AsyncEvacuate(true);
01483 #endif
01484 }
01485 
01486 CkMigratable::CkMigratable(void) {
01487     DEBC((AA "In CkMigratable constructor\n" AB));
01488     commonInit();
01489 }
01490 CkMigratable::CkMigratable(CkMigrateMessage *m): Chare(m) {
01491     commonInit();
01492 }
01493 
01494 int CkMigratable::ckGetChareType(void) const {return thisChareType;}
01495 
01496 void CkMigratable::pup(PUP::er &p) {
01497     DEBM((AA "In CkMigratable::pup %s\n" AB,idx2str(thisIndexMax)));
01498     Chare::pup(p);
01499     p|thisIndexMax;
01500     p(usesAtSync);
01501   p(can_reset);
01502     p(usesAutoMeasure);
01503 #if CMK_LBDB_ON 
01504     int readyMigrate = 0;
01505     if (p.isPacking()) readyMigrate = myRec->isReadyMigrate();
01506     p|readyMigrate;
01507     if (p.isUnpacking()) myRec->ReadyMigrate(readyMigrate);
01508 #endif
01509     if(p.isUnpacking()) barrierRegistered=false;
01510 
01511 #if CMK_FAULT_EVAC
01512     p | asyncEvacuate;
01513     if(p.isUnpacking()){myRec->AsyncEvacuate(asyncEvacuate);}
01514 #endif
01515     
01516     ckFinishConstruction();
01517 }
01518 
01519 void CkMigratable::ckDestroy(void) {}
01520 void CkMigratable::ckAboutToMigrate(void) { }
01521 void CkMigratable::ckJustMigrated(void) { }
01522 void CkMigratable::ckJustRestored(void) { }
01523 
01524 CkMigratable::~CkMigratable() {
01525     DEBC((AA "In CkMigratable::~CkMigratable %s\n" AB,idx2str(thisIndexMax)));
01526 #if CMK_OUT_OF_CORE
01527     isInCore=false;
01528     if (CkpvAccess(CkSaveRestorePrefetch)) 
01529         return; 
01530     
01531     if (prefetchObjID!=-1) {
01532         CooDeregisterObject(prefetchObjID);
01533         prefetchObjID=-1;
01534     }
01535 #endif
01536 #if CMK_LBDB_ON 
01537     if (barrierRegistered) {
01538       DEBL((AA "Removing barrier for element %s\n" AB,idx2str(thisIndexMax)));
01539       if (usesAtSync)
01540         myRec->getLBDB()->RemoveLocalBarrierClient(ldBarrierHandle);
01541       else
01542         myRec->getLBDB()->RemoveLocalBarrierReceiver(ldBarrierRecvHandle);
01543     }
01544 
01545   if (_lb_args.metaLbOn()) {
01546     myRec->getMetaBalancer()->AdjustCountForDeadContributor(atsync_iteration);
01547   }
01548 #endif
01549     myRec->destroy(); 
01550     
01551     thisIndexMax.nInts=0;
01552     thisIndexMax.dimension=0;
01553 }
01554 
01555 void CkMigratable::CkAbort(const char *why) const {
01556     CkError("CkMigratable '%s' aborting:\n",_chareTable[thisChareType]->name);
01557 	::CkAbort(why);
01558 }
01559 
01560 void CkMigratable::ResumeFromSync(void)
01561 {
01562 
01563 }
01564 
01565 void CkMigratable::UserSetLBLoad() {
01566     CkAbort("::UserSetLBLoad() not defined for this array element!\n");
01567 }
01568 
01569 #if CMK_LBDB_ON  //For load balancing:
01570 
01571 void CkMigratable::setObjTime(double cputime) {
01572     myRec->setObjTime(cputime);
01573 }
01574 double CkMigratable::getObjTime() {
01575     return myRec->getObjTime();
01576 }
01577 
01578 #if CMK_LB_USER_DATA
01579 
01595 void *CkMigratable::getObjUserData(int idx) {
01596     return myRec->getObjUserData(idx);
01597 }
01598 #endif
01599 
01600 void CkMigratable::clearMetaLBData() {
01601 
01602     local_state = OFF;
01603     atsync_iteration = -1;
01604     prev_load = 0.0;
01605     can_reset = false;
01606 
01607 }
01608 
01609 void CkMigratable::recvLBPeriod(void *data) {
01610   if (atsync_iteration < 0) {
01611     return;
01612   }
01613   int lb_period = *((int *) data);
01614  DEBAD(("\t[obj %s] Received the LB Period %d current iter %d state %d on PE %d\n",
01615      idx2str(thisIndexMax), lb_period, atsync_iteration, local_state, CkMyPe()));
01616 
01617   bool is_tentative;
01618   if (local_state == LOAD_BALANCE) {
01619     CkAssert(lb_period == myRec->getMetaBalancer()->getPredictedLBPeriod(is_tentative));
01620     return;
01621   }
01622 
01623   if (local_state == PAUSE) {
01624     if (atsync_iteration < lb_period) {
01625       local_state = DECIDED;
01626       ResumeFromSync();
01627       return;
01628     }
01629     local_state = LOAD_BALANCE;
01630 
01631     can_reset = true;
01632     
01633     return;
01634   }
01635   local_state = DECIDED;
01636 }
01637 
01638 void CkMigratable::metaLBCallLB() {
01639   if(usesAtSync)
01640     myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
01641 }
01642 
01643 void CkMigratable::ckFinishConstruction(void)
01644 {
01645 
01646     myRec->setMeasure(usesAutoMeasure);
01647     if (barrierRegistered) return;
01648     DEBL((AA "Registering barrier client for %s\n" AB,idx2str(thisIndexMax)));
01649         if (usesAtSync)
01650       ldBarrierHandle = myRec->getLBDB()->AddLocalBarrierClient(
01651         (LDBarrierFn)staticResumeFromSync,(void*)(this));
01652         else
01653       ldBarrierRecvHandle = myRec->getLBDB()->AddLocalBarrierReceiver(
01654         (LDBarrierFn)staticResumeFromSync,(void*)(this));
01655     barrierRegistered=true;
01656 }
01657 
01658 void CkMigratable::AtSync(int waitForMigration)
01659 {
01660     if (!usesAtSync)
01661         CkAbort("You must set usesAtSync=true in your array element constructor to use AtSync!\n");
01662 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
01663         mlogData->toResumeOrNot=1;
01664 #endif
01665     if(CkpvAccess(hasNullLB)) {
01666         ResumeFromSync();
01667         return;
01668     }
01669     myRec->AsyncMigrate(!waitForMigration);
01670     if (waitForMigration) ReadyMigrate(true);
01671     ckFinishConstruction();
01672   DEBL((AA "Element %s going to sync\n" AB,idx2str(thisIndexMax)));
01673   
01674   if (usesAutoMeasure == false) UserSetLBLoad();
01675 
01676   if(_lb_psizer_on || _lb_args.metaLbOn()){
01677     PUP::sizer ps;
01678     this->virtual_pup(ps);
01679     if(_lb_psizer_on)
01680       setPupSize(ps.size());
01681     if(_lb_args.metaLbOn())
01682       myRec->getMetaBalancer()->SetCharePupSize(ps.size());
01683   }
01684 
01685   if (!_lb_args.metaLbOn()) {
01686     myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
01687     return;
01688   }
01689 
01690   
01691 
01692   if (atsync_iteration == -1) {
01693     can_reset = false;
01694     local_state = OFF;
01695     prev_load = 0.0;
01696   }
01697 
01698   atsync_iteration++;
01699   
01700   
01701   
01702   double tmp = prev_load;
01703   prev_load = myRec->getObjTime();
01704   double current_load = prev_load - tmp;
01705 
01706   
01707   
01708   if (!usesAutoMeasure) {
01709     current_load = myRec->getObjTime();
01710   }
01711 
01712   if (atsync_iteration <= myRec->getMetaBalancer()->get_finished_iteration()) {
01713     CkPrintf("[%d:%s] Error!! Contributing to iter %d < current iter %d\n",
01714       CkMyPe(), idx2str(thisIndexMax), atsync_iteration,
01715       myRec->getMetaBalancer()->get_finished_iteration());
01716     CkAbort("Not contributing to the right iteration\n");
01717   }
01718 
01719   if (atsync_iteration != 0) {
01720     myRec->getMetaBalancer()->AddLoad(atsync_iteration, current_load);
01721   }
01722 
01723   bool is_tentative;
01724   if (atsync_iteration < myRec->getMetaBalancer()->getPredictedLBPeriod(is_tentative)) {
01725     ResumeFromSync();
01726   } else if (is_tentative) {
01727     local_state = PAUSE;
01728   } else if (local_state == DECIDED) {
01729     DEBAD(("[%d:%s] Went to load balance iter %d\n", CkMyPe(), idx2str(thisIndexMax), atsync_iteration));
01730     local_state = LOAD_BALANCE;
01731     can_reset = true;
01732     
01733   } else {
01734     DEBAD(("[%d:%s] Went to pause state iter %d\n", CkMyPe(), idx2str(thisIndexMax), atsync_iteration));
01735     local_state = PAUSE;
01736   }
01737 }
01738 
01739 void CkMigratable::ReadyMigrate(bool ready)
01740 {
01741     myRec->ReadyMigrate(ready);
01742 }
01743 
01744 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
01745     extern int globalResumeCount;
01746 #endif
01747 
01748 void CkMigratable::staticResumeFromSync(void* data)
01749 {
01750     CkMigratable *el=(CkMigratable *)data;
01751 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
01752     if(el->mlogData->toResumeOrNot ==0 || el->mlogData->resumeCount >= globalResumeCount){
01753         return;
01754     }
01755 #endif
01756     DEBL((AA "Element %s resuming from sync\n" AB,idx2str(el->thisIndexMax)));
01757 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
01758     CpvAccess(_currentObj) = el;
01759 #endif
01760 
01761   if (_lb_args.metaLbOn()) {
01762     el->clearMetaLBData();
01763     }
01764     el->ResumeFromSync();
01765 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
01766     el->mlogData->resumeCount++;
01767 #endif
01768 }
01769 
01770 void CkMigratable::setMigratable(int migratable) 
01771 {
01772     myRec->setMigratable(migratable);
01773 }
01774 
01775 void CkMigratable::setPupSize(size_t obj_pup_size)
01776 {
01777     myRec->setPupSize(obj_pup_size);
01778 }
01779 
01780 struct CkArrayThreadListener {
01781         struct CthThreadListener base;
01782         CkMigratable *mig;
01783 };
01784 
01785 static void CkArrayThreadListener_suspend(struct CthThreadListener *l)
01786 {
01787         CkArrayThreadListener *a=(CkArrayThreadListener *)l;
01788         a->mig->ckStopTiming();
01789 }
01790 
01791 static void CkArrayThreadListener_resume(struct CthThreadListener *l)
01792 {
01793         CkArrayThreadListener *a=(CkArrayThreadListener *)l;
01794         a->mig->ckStartTiming();
01795 }
01796 
01797 static void CkArrayThreadListener_free(struct CthThreadListener *l)
01798 {
01799         CkArrayThreadListener *a=(CkArrayThreadListener *)l;
01800         delete a;
01801 }
01802 
01803 void CkMigratable::CkAddThreadListeners(CthThread tid, void *msg)
01804 {
01805         Chare::CkAddThreadListeners(tid, msg);   
01806         CthSetThreadID(tid, thisIndexMax.data()[0], thisIndexMax.data()[1], 
01807                thisIndexMax.data()[2]);
01808     CkArrayThreadListener *a=new CkArrayThreadListener;
01809     a->base.suspend=CkArrayThreadListener_suspend;
01810     a->base.resume=CkArrayThreadListener_resume;
01811     a->base.free=CkArrayThreadListener_free;
01812     a->mig=this;
01813     CthAddListener(tid,(struct CthThreadListener *)a);
01814 }
01815 #else
01816 void CkMigratable::setObjTime(double cputime) {}
01817 double CkMigratable::getObjTime() {return 0.0;}
01818 
01819 #if CMK_LB_USER_DATA
01820 void *CkMigratable::getObjUserData(int idx) { return NULL; }
01821 #endif
01822 
01823 
01824 void CkMigratable::CkAddThreadListeners(CthThread tid, void *msg)
01825 {
01826 }
01827 #endif
01828 
01829 
01830 
01831 
01832 
01833 
01834 
01835 
01836 
01837 
01838 CkLocRec::CkLocRec(CkLocMgr *mgr,bool fromMigration,
01839                    bool ignoreArrival, const CkArrayIndex &idx_, CmiUInt8 id_)
01840   :myLocMgr(mgr),idx(idx_), id(id_),
01841      deletedMarker(NULL),running(false)
01842 {
01843 #if CMK_LBDB_ON
01844     DEBL((AA "Registering element %s with load balancer\n" AB,idx2str(idx)));
01845     
01846     
01847     nextPe = -1;
01848     asyncMigrate = false;
01849     readyMigrate = true;
01850         enable_measure = true;
01851 #if CMK_FAULT_EVAC
01852     bounced  = false;
01853 #endif
01854     the_lbdb=mgr->getLBDB();
01855     if(_lb_args.metaLbOn())
01856       the_metalb=mgr->getMetaBalancer();
01857 #if CMK_GLOBAL_LOCATION_UPDATE
01858     CmiUInt8 locMgrGid = mgr->getGroupID().idx;
01859     id_ = ck::ObjID(id_).getElementID();
01860     id_ |= locMgrGid << ck::ObjID().ELEMENT_BITS;
01861 #endif        
01862     ldHandle=the_lbdb->RegisterObj(mgr->getOMHandle(),
01863         id_, (void *)this,1);
01864     if (fromMigration) {
01865         DEBL((AA "Element %s migrated in\n" AB,idx2str(idx)));
01866         if (!ignoreArrival)  {
01867             the_lbdb->Migrated(ldHandle, true);
01868           
01869         
01870         }
01871     }
01872 #endif
01873 
01874 #if CMK_FAULT_EVAC
01875     asyncEvacuate = true;
01876 #endif
01877 }
01878 CkLocRec::~CkLocRec()
01879 {
01880     if (deletedMarker!=NULL) *deletedMarker=true;
01881 #if CMK_LBDB_ON
01882     stopTiming();
01883     DEBL((AA "Unregistering element %s from load balancer\n" AB,idx2str(idx)));
01884     the_lbdb->UnregisterObj(ldHandle);
01885 #endif
01886 }
01887 void CkLocRec::migrateMe(int toPe) 
01888 {
01889     
01890 
01891     myLocMgr->emigrate(this,toPe);
01892 }
01893 
01894 #if CMK_LBDB_ON
01895 void CkLocRec::startTiming(int ignore_running) {
01896     if (!ignore_running) running=true;
01897     DEBL((AA "Start timing for %s at %.3fs {\n" AB,idx2str(idx),CkWallTimer()));
01898     if (enable_measure) the_lbdb->ObjectStart(ldHandle);
01899 }
01900 void CkLocRec::stopTiming(int ignore_running) {
01901     DEBL((AA "} Stop timing for %s at %.3fs\n" AB,idx2str(idx),CkWallTimer()));
01902     if ((ignore_running || running) && enable_measure) the_lbdb->ObjectStop(ldHandle);
01903     if (!ignore_running) running=false;
01904 }
01905 void CkLocRec::setObjTime(double cputime) {
01906     the_lbdb->EstObjLoad(ldHandle, cputime);
01907 }
01908 double CkLocRec::getObjTime() {
01909         LBRealType walltime, cputime;
01910         the_lbdb->GetObjLoad(ldHandle, walltime, cputime);
01911         return walltime;
01912 }
01913 #if CMK_LB_USER_DATA
01914 void* CkLocRec::getObjUserData(int idx) {
01915         return the_lbdb->GetDBObjUserData(ldHandle, idx);
01916 }
01917 #endif
01918 #endif
01919 
01920 
01921 
01922 void CkLocRec::destroy(void) {
01923     myLocMgr->reclaim(this);
01924 }
01925 
01926 
01927 
01928 LDObjHandle CkMigratable::timingBeforeCall(int* objstopped){
01929     LDObjHandle objHandle;
01930 #if CMK_LBDB_ON
01931     if (getLBDB()->RunningObject(&objHandle)) {
01932         *objstopped = 1;
01933         getLBDB()->ObjectStop(objHandle);
01934     }
01935     myRec->startTiming(1);
01936 #endif
01937 
01938   return objHandle;
01939 }
01940 
01941 void CkMigratable::timingAfterCall(LDObjHandle objHandle,int *objstopped){
01942     myRec->stopTiming(1);
01943 #if CMK_LBDB_ON
01944     if (*objstopped) {
01945          getLBDB()->ObjectStart(objHandle);
01946     }
01947 #endif
01948 
01949  return;
01950 }
01951 
01952 
01953 
01954 bool CkLocRec::invokeEntry(CkMigratable *obj,void *msg,
01955     int epIdx,bool doFree) 
01956 {
01957 
01958     DEBS((AA "   Invoking entry %d on element %s\n" AB,epIdx,idx2str(idx)));
01959     bool isDeleted=false; 
01960     deletedMarker=&isDeleted;
01961     startTiming();
01962 
01963 
01964 #if CMK_TRACE_ENABLED
01965     if (msg) { 
01966         envelope *env=UsrToEnv(msg);
01967     
01968         if (_entryTable[epIdx]->traceEnabled)
01969         {
01970             _TRACE_BEGIN_EXECUTE_DETAILED(env->getEvent(), ForChareMsg,epIdx,env->getSrcPe(), env->getTotalsize(), idx.getProjectionID(), obj);
01971             if(_entryTable[epIdx]->appWork)
01972                 _TRACE_BEGIN_APPWORK();
01973         }
01974     }
01975 #endif
01976 
01977     if (doFree) 
01978        CkDeliverMessageFree(epIdx,msg,obj);
01979     else 
01980        CkDeliverMessageReadonly(epIdx,msg,obj);
01981 
01982 
01983 #if CMK_TRACE_ENABLED
01984     if (msg) { 
01985         if (_entryTable[epIdx]->traceEnabled)
01986         {
01987             if(_entryTable[epIdx]->appWork)
01988                 _TRACE_END_APPWORK();
01989             _TRACE_END_EXECUTE();
01990         }
01991     }
01992 #endif
01993 #if CMK_LBDB_ON
01994         if (!isDeleted) checkBufferedMigration();   
01995 #endif
01996     if (isDeleted) return false;
01997     deletedMarker=NULL;
01998     stopTiming();
01999     return true;
02000 }
02001 
02002 #if CMK_LBDB_ON
02003 
02004 void CkLocRec::staticMetaLBResumeWaitingChares(LDObjHandle h, int lb_ideal_period) {
02005     CkLocRec *el=(CkLocRec *)LDObjUserData(h);
02006     DEBL((AA "MetaBalancer wants to resume waiting chare %s\n" AB,idx2str(el->idx)));
02007     el->myLocMgr->informLBPeriod(el, lb_ideal_period);
02008 }
02009 
02010 void CkLocRec::staticMetaLBCallLBOnChares(LDObjHandle h) {
02011     CkLocRec *el=(CkLocRec *)LDObjUserData(h);
02012     DEBL((AA "MetaBalancer wants to call LoadBalance on chare %s\n" AB,idx2str(el->idx)));
02013     el->myLocMgr->metaLBCallLB(el);
02014 }
02015 
02016 void CkLocRec::staticMigrate(LDObjHandle h, int dest)
02017 {
02018     CkLocRec *el=(CkLocRec *)LDObjUserData(h);
02019     DEBL((AA "Load balancer wants to migrate %s to %d\n" AB,idx2str(el->idx),dest));
02020     el->recvMigrate(dest);
02021 }
02022 
02023 void CkLocRec::recvMigrate(int toPe)
02024 {
02025     
02026     
02027     if (readyMigrate) { migrateMe(toPe); }
02028     else nextPe = toPe;
02029 }
02030 
02031 void CkLocRec::AsyncMigrate(bool use)  
02032 {
02033         asyncMigrate = use; 
02034     the_lbdb->UseAsyncMigrate(ldHandle, use);
02035 }
02036 
02037 bool CkLocRec::checkBufferedMigration()
02038 {
02039     
02040     
02041     if (readyMigrate && nextPe != -1) {
02042         int toPe = nextPe;
02043         nextPe = -1;
02044         
02045         migrateMe(toPe);
02046         
02047         return true;
02048     }
02049     return false;
02050 }
02051 
02052 int CkLocRec::MigrateToPe()
02053 {
02054     int pe = nextPe;
02055     nextPe = -1;
02056     return pe;
02057 }
02058 
02059 void CkLocRec::setMigratable(int migratable)
02060 {
02061     if (migratable)
02062       the_lbdb->Migratable(ldHandle);
02063     else
02064       the_lbdb->NonMigratable(ldHandle);
02065 }
02066 
02067 void CkLocRec::setPupSize(size_t obj_pup_size) {
02068   the_lbdb->setPupSize(ldHandle, obj_pup_size);
02069 }
02070 
02071 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
02072 void CkLocRec::Migrated(){
02073     the_lbdb->Migrated(ldHandle, true);
02074 }
02075 #endif
02076 #endif
02077 
02078 
02079 
02080 
02081 void CkLocMgr::flushLocalRecs(void)
02082 {
02083   CmiImmediateLock(hashImmLock);
02084   while (hash.size()) {
02085     CkLocRec* rec = hash.begin()->second;
02086     callMethod(rec, &CkMigratable::ckDestroy);
02087   }
02088   CmiImmediateUnlock(hashImmLock);
02089 }
02090 
02091 
02092 void CkLocMgr::flushAllRecs(void)
02093 {
02094   flushLocalRecs();
02095 }
02096 
02097 
02098 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
02099 void CkLocMgr::callForAllRecords(CkLocFn fnPointer,CkArray *arr,void *data){
02100   CmiImmediateLock(hashImmLock);
02101   for (LocRecHash::iterator it = hash.begin(); it != hash.end(); it++) {
02102     fnPointer(arr,data,it->second,it->second->idx);
02103   }
02104   CmiImmediateUnlock(hashImmLock);
02105 }
02106 #endif
02107 
02108 
02109 CkLocMgr::CkLocMgr(CkArrayOptions opts)
02110     :idCounter(1), thisProxy(thisgroup),
02111   thislocalproxy(thisgroup,CkMyPe())
02112         , bounds(opts.getBounds())
02113 {
02114     DEBC((AA "Creating new location manager %d\n" AB,thisgroup));
02115 
02116 
02117 
02118     duringMigration = false;
02119 
02120 
02121     mapID = opts.getMap();
02122     map=(CkArrayMap *)CkLocalBranch(mapID);
02123     if (map==NULL) CkAbort("ERROR!  Local branch of array map is NULL!");
02124     mapHandle=map->registerArray(opts.getEnd(), thisgroup);
02125 
02126         
02127         compressor = ck::FixedArrayIndexCompressor::make(bounds);
02128 
02129 
02130 #if CMK_LBDB_ON
02131         lbdbID = _lbdb;
02132         metalbID = _metalb;
02133 #endif
02134         initLB(lbdbID, metalbID);
02135     hashImmLock = CmiCreateImmediateLock();
02136 }
02137 
02138 CkLocMgr::CkLocMgr(CkMigrateMessage* m)
02139     :IrrGroup(m),thisProxy(thisgroup),thislocalproxy(thisgroup,CkMyPe())
02140 {
02141     duringMigration = false;
02142     hashImmLock = CmiCreateImmediateLock();
02143 }
02144 
02145 CkLocMgr::~CkLocMgr() {
02146 #if CMK_LBDB_ON
02147   the_lbdb->RemoveLocalBarrierClient(dummyBarrierHandle);
02148   the_lbdb->DecreaseLocalBarrier(dummyBarrierHandle, 1);
02149   the_lbdb->RemoveLocalBarrierReceiver(lbBarrierReceiver);
02150   the_lbdb->UnregisterOM(myLBHandle);
02151 #endif
02152   map->unregisterArray(mapHandle);
02153   CmiDestroyLock(hashImmLock);
02154 }
02155 
02156 void CkLocMgr::pup(PUP::er &p){
02157     IrrGroup::pup(p);
02158     p|mapID;
02159     p|mapHandle;
02160     p|lbdbID;
02161         p|metalbID;
02162         p|bounds;
02163     if(p.isUnpacking()) {
02164         thisProxy=thisgroup;
02165         CProxyElement_CkLocMgr newlocalproxy(thisgroup,CkMyPe());
02166         thislocalproxy=newlocalproxy;
02167         
02168         map=(CkArrayMap *)CkLocalBranch(mapID);
02169         if (map==NULL) CkAbort("ERROR!  Local branch of array map is NULL!");
02170                 CkArrayIndex emptyIndex;
02171         
02172         initLB(lbdbID, metalbID);
02173                 compressor = ck::FixedArrayIndexCompressor::make(bounds);
02174 #if __FAULT__
02175         int count = 0;
02176         p | count;
02177         DEBUG(CmiPrintf("[%d] Unpacking Locmgr %d has %d home elements\n",CmiMyPe(),thisgroup.idx,count));
02178 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))    
02179         homeElementCount = count;
02180 #endif
02181         for(int i=0;i<count;i++){
02182             CkArrayIndex idx;
02183             int pe = 0;
02184             p | idx;
02185             p | pe;
02186   
02187             inform(idx, lookupID(idx), pe);
02188             CmiUInt8 id = lookupID(idx);
02189             CkLocRec *rec = elementNrec(id);
02190             CmiAssert(rec!=NULL);
02191             CmiAssert(lastKnown(idx) == pe);
02192         }
02193 #endif
02194         
02195         
02196         if (!CkInRestarting()) 
02197             doneInserting();
02198     }else{
02205 #if __FAULT__
02206         int count=0;
02207         std::vector<int> pe_list;
02208         std::vector<CmiUInt8> idx_list;
02209         for (auto itr = id2pe.begin(); itr != id2pe.end(); ++itr)
02210             if (homePe(itr->first) == CmiMyPe() && itr->second != CmiMyPe())
02211             {
02212                 idx_list.push_back(itr->first);
02213                 pe_list.push_back(itr->second);
02214                 count++;
02215             }
02216 
02217         p | count;
02218         
02219         for (int i=0; i<count; i++)
02220         {
02221           p | idx_list[i];
02222           p | pe_list[i];
02223         }
02224 #endif
02225 
02226     }
02227 }
02228 
02230 void CkLocMgr::addManager(CkArrayID id,CkArray *mgr)
02231 {
02232     CK_MAGICNUMBER_CHECK
02233     DEBC((AA "Adding new array manager\n" AB));
02234     managers[id] = mgr;
02235 }
02236 
02237 void CkLocMgr::deleteManager(CkArrayID id, CkArray *mgr) {
02238   CkAssert(managers[id] == mgr);
02239   managers.erase(id);
02240 
02241   if (managers.size() == 0)
02242     delete this;
02243 }
02244 
02245 
02246 void CkLocMgr::informHome(const CkArrayIndex &idx,int nowOnPe)
02247 {
02248     int home=homePe(idx);
02249     if (home!=CkMyPe() && home!=nowOnPe) {
02250         
02251         DEBC((AA "  Telling %s's home %d that it lives on %d.\n" AB,idx2str(idx),home,nowOnPe));
02252 
02253 
02254 
02255 
02256         thisProxy[home].updateLocation(idx, lookupID(idx), nowOnPe);
02257 
02258     }
02259 }
02260 
02261 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
02262 CkLocRec *CkLocMgr::createLocal(const CkArrayIndex &idx,
02263         bool forMigration, bool ignoreArrival,
02264         bool notifyHome,int dummy)
02265 {
02266     DEBC((AA "Adding new record for element %s\n" AB,idx2str(idx)));
02267     CkLocRec *rec=new CkLocRec(this,forMigration,ignoreArrival,idx);
02268     if(!dummy){
02269         insertRec(rec,idx); 
02270         id2pe[idx] = CkMyPe();
02271         deliverAnyBufferedMsgs(idx, bufferedMsgs);
02272     }   
02273     if (notifyHome) informHome(idx,CkMyPe());
02274     return rec; 
02275 }
02276 #else
02277 CkLocRec *CkLocMgr::createLocal(const CkArrayIndex &idx, 
02278         bool forMigration, bool ignoreArrival,
02279         bool notifyHome)
02280 {
02281     DEBC((AA "Adding new record for element %s\n" AB,idx2str(idx)));
02282     CmiUInt8 id = lookupID(idx);
02283 
02284     CkLocRec *rec=new CkLocRec(this, forMigration, ignoreArrival, idx, id);
02285     insertRec(rec, id);
02286         inform(idx, id, CkMyPe());
02287 
02288     if (notifyHome) { informHome(idx,CkMyPe()); }
02289     return rec;
02290 }
02291 #endif
02292 
02293 
02294 void CkLocMgr::deliverAnyBufferedMsgs(CmiUInt8 id, MsgBuffer &buffer)
02295 {
02296     auto itr = buffer.find(id);
02297     
02298     if (itr == buffer.end()) return;
02299 
02300     std::vector<CkArrayMessage*> messagesToFlush;
02301     messagesToFlush.swap(itr->second);
02302 
02303     
02304     for (int i = 0; i < messagesToFlush.size(); ++i)
02305     {
02306 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
02307         envelope *env = UsrToEnv(messagesToFlush[i]);
02308         Chare *oldObj = CpvAccess(_currentObj);
02309         CpvAccess(_currentObj) =(Chare *) env->sender.getObject();
02310         env->sender.type = TypeInvalid;
02311 #endif
02312         CkArrayMessage *m = messagesToFlush[i];
02313         deliverMsg(m, UsrToEnv(m)->getArrayMgr(), id, NULL, CkDeliver_queue);
02314 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
02315         CpvAccess(_currentObj) = oldObj;
02316 #endif
02317     }
02318 
02319     CkAssert(itr->second.empty()); 
02320                                    
02321 
02322     
02323     buffer.erase(itr);
02324 }
02325 
02326 CmiUInt8 CkLocMgr::getNewObjectID(const CkArrayIndex &idx)
02327 {
02328   CmiUInt8 id;
02329   if (!lookupID(idx, id)) {
02330     id = idCounter++ + ((CmiUInt8)CkMyPe() << 24);
02331     insertID(idx,id);
02332   }
02333   return id;
02334 }
02335 
02336 
02337 bool CkLocMgr::addElement(CkArrayID mgr,const CkArrayIndex &idx,
02338         CkMigratable *elt,int ctorIdx,void *ctorMsg)
02339 {
02340     CK_MAGICNUMBER_CHECK
02341 
02342         CmiUInt8 id = getNewObjectID(idx);
02343 
02344     CkLocRec *rec = elementNrec(id);
02345     if (rec == NULL)
02346     { 
02347         rec=createLocal(idx,false,false,true);
02348 #if CMK_GLOBAL_LOCATION_UPDATE
02349                 if (homePe(idx) != CkMyPe()) {
02350                   DEBC((AA "Global location broadcast for new element idx %s "
02351                         "assigned to %d \n" AB, idx2str(idx), CkMyPe()));
02352                   thisProxy.updateLocation(id, CkMyPe());
02353                 }
02354 #endif
02355                 
02356     }
02357     
02358         else
02359         deliverAnyBufferedMsgs(id, bufferedShadowElemMsgs);
02360     if (!addElementToRec(rec, managers[mgr], elt, ctorIdx, ctorMsg)) return false;
02361     elt->ckFinishConstruction();
02362     return true;
02363 }
02364 
02365 
02366 bool CkLocMgr::addElementToRec(CkLocRec *rec,CkArray *mgr,
02367         CkMigratable *elt,int ctorIdx,void *ctorMsg)
02368 {
02369   CmiUInt8 id = lookupID(rec->getIndex());
02370   if (mgr->getEltFromArrMgr(id))
02371     CkAbort("Cannot insert array element twice!");
02372   mgr->putEltInArrMgr(id, elt); 
02373 
02374 
02375     DEBC((AA "Constructing element %s of array\n" AB,idx2str(rec->getIndex())));
02376     CkMigratable_initInfo &i=CkpvAccess(mig_initInfo);
02377     i.locRec=rec;
02378     i.chareType=_entryTable[ctorIdx]->chareIdx;
02379 
02380 #ifndef CMK_CHARE_USE_PTR
02381   int callingChareIdx = CkpvAccess(currentChareIdx);
02382   CkpvAccess(currentChareIdx) = -1;
02383 #endif
02384 
02385     if (!rec->invokeEntry(elt,ctorMsg,ctorIdx,true)) return false;
02386 
02387 #ifndef CMK_CHARE_USE_PTR
02388   CkpvAccess(currentChareIdx) = callingChareIdx;
02389 #endif
02390 
02391 #if CMK_OUT_OF_CORE
02392     
02393     PUP::sizer p_getSize;
02394     elt->virtual_pup(p_getSize);
02395     elt->prefetchObjID=CooRegisterObject(&CkArrayElementPrefetcher,p_getSize.size(),elt);
02396 #endif
02397     
02398     return true;
02399 }
02400 
02401 
02402 
02403 void CkLocMgr::requestLocation(const CkArrayIndex &idx, const int peToTell,
02404                                bool suppressIfHere, int ifNonExistent, int chareType, CkArrayID mgr) {
02405   int onPe = -1;
02406   DEBN(("%d requestLocation for %s peToTell %d\n", CkMyPe(), idx2str(idx), peToTell));
02407 
02408   if (peToTell == CkMyPe())
02409     return;
02410 
02411   CmiUInt8 id;
02412   if (lookupID(idx,id)) {
02413     
02414     onPe = lastKnown(idx);
02415     thisProxy[peToTell].updateLocation(idx, id, onPe);
02416   } else {
02417     
02418     DEBN(("%d Buffering ID/location req for %s\n", CkMyPe(), idx2str(idx)));
02419     bufferedLocationRequests[idx].emplace_back(peToTell, suppressIfHere);
02420 
02421     switch (ifNonExistent) {
02422     case CkArray_IfNotThere_createhome:
02423       demandCreateElement(idx, chareType, CkMyPe(), mgr);
02424       break;
02425     case CkArray_IfNotThere_createhere:
02426       demandCreateElement(idx, chareType, peToTell, mgr);
02427       break;
02428     default:
02429       break;
02430     }
02431   }
02432 }
02433 
02434 void CkLocMgr::requestLocation(CmiUInt8 id, const int peToTell,
02435                                bool suppressIfHere) {
02436   int onPe = -1;
02437   DEBN(("%d requestLocation for %u peToTell %d\n", CkMyPe(), id, peToTell));
02438 
02439   if (peToTell == CkMyPe())
02440     return;
02441 
02442   onPe = lastKnown(id);
02443 
02444   if (suppressIfHere && peToTell == CkMyPe())
02445     return;
02446 
02447   thisProxy[peToTell].updateLocation(id, onPe);
02448 }
02449 
02450 void CkLocMgr::updateLocation(const CkArrayIndex &idx, CmiUInt8 id, int nowOnPe) {
02451   DEBN(("%d updateLocation for %s on %d\n", CkMyPe(), idx2str(idx), nowOnPe));
02452   inform(idx, id, nowOnPe);
02453   deliverAnyBufferedMsgs(id, bufferedRemoteMsgs);
02454 }
02455 
02456 void CkLocMgr::updateLocation(CmiUInt8 id, int nowOnPe) {
02457   DEBN(("%d updateLocation for %s on %d\n", CkMyPe(), idx2str(idx), nowOnPe));
02458   inform(id, nowOnPe);
02459   deliverAnyBufferedMsgs(id, bufferedRemoteMsgs);
02460 }
02461 
02462 void CkLocMgr::inform(const CkArrayIndex &idx, CmiUInt8 id, int nowOnPe) {
02463   
02464   
02465   
02466   if (CkInRestarting()) {
02467     CmiUInt8 maskedID = id & ((1u << 24) - 1);
02468     CmiUInt8 origPe = id >> 24;
02469     if (origPe == CkMyPe()) {
02470       if (maskedID >= idCounter)
02471         idCounter = maskedID + 1;
02472     } else {
02473       if (origPe < CkNumPes())
02474         thisProxy[origPe].updateLocation(idx, id, nowOnPe);
02475     }
02476   }
02477 
02478   insertID(idx,id);
02479   id2pe[id] = nowOnPe;
02480 
02481   auto itr = bufferedLocationRequests.find(idx);
02482   if (itr != bufferedLocationRequests.end()) {
02483     for (std::vector<std::pair<int, bool> >::iterator i = itr->second.begin();
02484          i != itr->second.end(); ++i) {
02485       int peToTell = i->first;
02486       DEBN(("%d Replying to buffered ID/location req to pe %d\n", CkMyPe(), peToTell));
02487       if (peToTell != CkMyPe())
02488         thisProxy[peToTell].updateLocation(idx, id, nowOnPe);
02489     }
02490     bufferedLocationRequests.erase(itr);
02491   }
02492 
02493   deliverAnyBufferedMsgs(id, bufferedMsgs);
02494 
02495   auto idx_itr = bufferedIndexMsgs.find(idx);
02496   if (idx_itr != bufferedIndexMsgs.end()) {
02497     vector<CkArrayMessage*> &msgs = idx_itr->second;
02498     for (int i = 0; i < msgs.size(); ++i) {
02499       envelope *env = UsrToEnv(msgs[i]);
02500       CkGroupID mgr = ck::ObjID(env->getRecipientID()).getCollectionID();
02501       env->setRecipientID(ck::ObjID(mgr, id));
02502       deliverMsg(msgs[i], mgr, id, &idx, CkDeliver_queue);
02503     }
02504     bufferedIndexMsgs.erase(idx_itr);
02505   }
02506 }
02507 
02508 void CkLocMgr::inform(CmiUInt8 id, int nowOnPe) {
02509   id2pe[id] = nowOnPe;
02510   deliverAnyBufferedMsgs(id, bufferedMsgs);
02511 }
02512 
02513 
02514 
02515 
02516 
02517 
02518 void CkLocMgr::reclaim(CkLocRec* rec) {
02519     CK_MAGICNUMBER_CHECK
02520     
02521     for (auto itr = managers.begin(); itr != managers.end(); ++itr) {
02522         if (itr->second->lookup(rec->getID())) return;
02523     }
02524     removeFromTable(rec->getID());
02525     
02526     DEBC((AA "Destroying record for element %s\n" AB,idx2str(rec->getIndex())));
02527     if (!duringMigration) 
02528     { 
02529 #if CMK_BIGSIM_CHARM
02530         
02531         
02532         
02533         
02534         
02535         
02536         
02537         if(_BgOutOfCoreFlag==1) return; 
02538 #endif
02539         int home=homePe(rec->getIndex());
02540         if (home!=CkMyPe())
02541 #if CMK_MEM_CHECKPOINT
02542             if (!CkInRestarting()) 
02543 #endif
02544             if (!duringDestruction)
02545                 thisProxy[home].reclaimRemote(rec->getIndex(),CkMyPe());
02546     }
02547     delete rec;
02548 }
02549 
02550 
02551 
02552 void CkLocMgr::reclaimRemote(const CkArrayIndex &idx,int deletedOnPe) {
02553     DEBC((AA "Our element %s died on PE %d\n" AB,idx2str(idx),deletedOnPe));
02554 
02555     CmiUInt8 id;
02556     if (!lookupID(idx, id)) CkAbort("Cannot find ID for the given index\n");
02557 
02558     
02559     id2pe.erase(id);
02560     idx2id.erase(idx);
02561 
02562     
02563     CkAssert(bufferedMsgs.count(id) == 0);
02564     CkAssert(bufferedRemoteMsgs.count(id) == 0);
02565     CkAssert(bufferedShadowElemMsgs.count(id) == 0);
02566     CkAssert(bufferedLocationRequests.count(idx) == 0);
02567     CkAssert(bufferedIndexMsgs.count(idx) == 0);
02568 }
02569 
02570 void CkLocMgr::removeFromTable(const CmiUInt8 id) {
02571 #if CMK_ERROR_CHECKING
02572     
02573     if (NULL==elementNrec(id))
02574         CkAbort("CkLocMgr::removeFromTable called on invalid index!");
02575 #endif
02576         CmiImmediateLock(hashImmLock);
02577         hash.erase(id);
02578         CmiImmediateUnlock(hashImmLock);
02579 #if CMK_ERROR_CHECKING
02580     
02581     if (NULL!=elementNrec(id))
02582         CkAbort("CkLocMgr::removeFromTable called, but element still there!");
02583 #endif
02584 }
02585 
02586 
02589 int CkLocMgr::deliverMsg(CkArrayMessage *msg, CkArrayID mgr, CmiUInt8 id, const CkArrayIndex* idx, CkDeliver_t type, int opts) {
02590   CkLocRec *rec = elementNrec(id);
02591 
02592 #if CMK_LBDB_ON
02593   if ((idx || compressor) && type==CkDeliver_queue && !(opts & CK_MSG_LB_NOTRACE) && the_lbdb->CollectingCommStats())
02594   {
02595 #if CMK_GLOBAL_LOCATION_UPDATE
02596     CmiUInt8 locMgrGid = thisgroup.idx;
02597     id = ck::ObjID(id).getElementID();
02598     id |= locMgrGid << ck::ObjID().ELEMENT_BITS;
02599 #endif
02600     the_lbdb->Send(myLBHandle
02601                    , id
02602                    , UsrToEnv(msg)->getTotalsize()
02603                    , lastKnown(id)
02604                    , 1);
02605   }
02606 #endif
02607 
02608   
02609   if (rec == NULL)
02610   {
02611     if (opts & CK_MSG_KEEP)
02612       msg = (CkArrayMessage *)CkCopyMsg((void **)&msg);
02613     
02614     int destPE = whichPE(id);
02615     if (destPE != -1)
02616     {
02617 #if CMK_FAULT_EVAC
02618       if((!CmiNodeAlive(destPE) && destPE != allowMessagesOnly)){
02619         CkAbort("Cannot send to a chare on a dead node");
02620       }
02621 #endif
02622       msg->array_hops()++;
02623       CkArrayManagerDeliver(destPE,msg,opts);
02624       return true;
02625     }
02626     
02627     deliverUnknown(msg,idx,type,opts);
02628     return true;
02629   }
02630 
02631   
02632   if (type==CkDeliver_queue)
02633   {
02634     if (opts & CK_MSG_KEEP)
02635       msg = (CkArrayMessage *)CkCopyMsg((void **)&msg);
02636     CkArrayManagerDeliver(CkMyPe(),msg,opts);
02637     return true;
02638   }
02639 
02640   CkAssert(mgr == UsrToEnv(msg)->getArrayMgr());
02641   CkArray *arr = managers[mgr];
02642   if (!arr) {
02643     bufferedShadowElemMsgs[id].push_back(msg);
02644     return true;
02645   }
02646   CkMigratable *obj = arr->lookup(id);
02647   if (obj==NULL) {
02648     if (opts & CK_MSG_KEEP)
02649       msg = (CkArrayMessage *)CkCopyMsg((void **)&msg);
02650     if (msg->array_ifNotThere()!=CkArray_IfNotThere_buffer)
02651       return demandCreateElement(msg, rec->getIndex(), CkMyPe(),type);
02652     else { 
02653       bufferedShadowElemMsgs[id].push_back(msg);
02654       return true;
02655     }
02656   }
02657         
02658   if (msg->array_hops()>1)
02659     multiHop(msg);
02660 #if CMK_LBDB_ON
02661   
02662   LDObjHandle objHandle;
02663   bool wasAnObjRunning = false;
02664   if ((wasAnObjRunning = the_lbdb->RunningObject(&objHandle)))
02665     the_lbdb->ObjectStop(objHandle);
02666 #endif
02667   
02668   bool result = ((CkLocRec*)rec)->invokeEntry(obj,(void *)msg,msg->array_ep(),!(opts & CK_MSG_KEEP));
02669 #if CMK_LBDB_ON
02670   if (wasAnObjRunning) the_lbdb->ObjectStart(objHandle);
02671 #endif
02672   return result;
02673 }
02674 
02675 void CkLocMgr::sendMsg(CkArrayMessage *msg, CkArrayID mgr, const CkArrayIndex &idx, CkDeliver_t type, int opts) {
02676   CK_MAGICNUMBER_CHECK
02677   DEBS((AA "send %s\n" AB,idx2str(idx)));
02678   envelope *env = UsrToEnv(msg);
02679   env->setMsgtype(ForArrayEltMsg);
02680 
02681   checkInBounds(idx);
02682 
02683   if (type==CkDeliver_queue)
02684     _TRACE_CREATION_DETAILED(env, msg->array_ep());
02685 
02686   CmiUInt8 id;
02687   if (lookupID(idx, id)) {
02688     env->setRecipientID(ck::ObjID(mgr, id));
02689     deliverMsg(msg, mgr, id, &idx, type, opts);
02690     return;
02691   }
02692 
02693   env->setRecipientID(ck::ObjID(mgr, 0));
02694 
02695   int home = homePe(idx);
02696   if (home != CkMyPe()) {
02697     if (bufferedIndexMsgs.find(idx) == bufferedIndexMsgs.end())
02698       thisProxy[home].requestLocation(idx, CkMyPe(), false, msg->array_ifNotThere(), _entryTable[env->getEpIdx()]->chareIdx, mgr);
02699     bufferedIndexMsgs[idx].push_back(msg);
02700 
02701     return;
02702   }
02703 
02704   
02705   
02706   if (managers.find(mgr) == managers.end()) {
02707     
02708     if (CkInRestarting()) {
02709       
02710       delete msg;
02711     } else {
02712       
02713       
02714       
02715       
02716       bufferedIndexMsgs[idx].push_back(msg);
02717     }
02718     return;
02719   }
02720 
02721   
02722   if (opts & CK_MSG_KEEP)
02723     msg = (CkArrayMessage *)CkCopyMsg((void **)&msg);
02724 
02725   
02726   bufferedIndexMsgs[idx].push_back(msg);
02727 
02728 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
02729   envelope *env = UsrToEnv(msg);
02730   env->sender = CpvAccess(_currentObj)->mlogData->objID;
02731 #endif
02732 
02733   
02734   if (msg->array_ifNotThere()!=CkArray_IfNotThere_buffer) {
02735     demandCreateElement(msg, idx, -1, type);
02736   }
02737 }
02738 
02740 void CkLocMgr::deliverUnknown(CkArrayMessage *msg, const CkArrayIndex* idx, CkDeliver_t type, int opts)
02741 {
02742   CK_MAGICNUMBER_CHECK
02743   CmiUInt8 id = msg->array_element_id();
02744   int home;
02745   if (idx) home = homePe(*idx);
02746   else home = homePe(id);
02747 
02748   if (home != CkMyPe()) {
02749     id2pe[id] = home;
02750     if (UsrToEnv(msg)->getTotalsize() < _messageBufferingThreshold) {
02751       DEBM((AA "Forwarding message for unknown %u to home %d \n" AB, id, home));
02752       msg->array_hops()++;
02753       CkArrayManagerDeliver(home, msg, opts);
02754     } else {
02755       DEBM((AA "Buffering message for unknown %u, home %d \n" AB, id, home));
02756       if (bufferedRemoteMsgs.find(id) == bufferedRemoteMsgs.end())
02757         thisProxy[home].requestLocation(id, CkMyPe(), false);
02758       bufferedRemoteMsgs[id].push_back(msg);
02759     }
02760   } else { 
02761     
02762     
02763     if (managers.find(UsrToEnv((void*)msg)->getArrayMgr()) == managers.end()) {
02764       if (CkInRestarting()) {
02765         
02766         delete msg;
02767       } else {
02768         CkArrayManagerDeliver(CkMyPe(),msg);
02769       }
02770     } else { 
02771       
02772       if (opts & CK_MSG_KEEP)
02773         msg = (CkArrayMessage *)CkCopyMsg((void **)&msg);
02774       
02775       bufferedMsgs[id].push_back(msg);
02776 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
02777       envelope *env = UsrToEnv(msg);
02778       env->sender = CpvAccess(_currentObj)->mlogData->objID;
02779 #endif
02780       
02781       if (msg->array_ifNotThere()!=CkArray_IfNotThere_buffer) {
02782         CkAbort("Demand creation of elements is currently unimplemented");
02783       }
02784     }
02785   }
02786 }
02787 
02788 void CkLocMgr::demandCreateElement(const CkArrayIndex &idx, int chareType, int onPe, CkArrayID mgr)
02789 {
02790   int ctor=_chareTable[chareType]->getDefaultCtor();
02791   if (ctor==-1) CkAbort("Can't create array element to handle message--\n"
02792                         "The element has no default constructor in the .ci file!\n");
02793 
02794   
02795   DEBC((AA "Demand-creating element %s on pe %d\n" AB,idx2str(idx),onPe));
02796   inform(idx, getNewObjectID(idx), onPe);
02797   CProxy_CkArray(mgr)[onPe].demandCreateElement(idx, ctor, CkDeliver_inline);
02798 }
02799 
02800 bool CkLocMgr::demandCreateElement(CkArrayMessage *msg, const CkArrayIndex &idx, int onPe,CkDeliver_t type)
02801 {
02802     CK_MAGICNUMBER_CHECK
02803     int chareType=_entryTable[msg->array_ep()]->chareIdx;
02804     int ctor=_chareTable[chareType]->getDefaultCtor();
02805     if (ctor==-1) CkAbort("Can't create array element to handle message--\n"
02806                   "The element has no default constructor in the .ci file!\n");
02807     if (onPe==-1) 
02808     { 
02809         if (msg->array_ifNotThere()==CkArray_IfNotThere_createhere) 
02810             onPe=UsrToEnv(msg)->getsetArraySrcPe();
02811         else 
02812             onPe=homePe(idx);
02813     }
02814     
02815     
02816     DEBC((AA "Demand-creating element %s on pe %d\n" AB,idx2str(idx),onPe));
02817     CProxy_CkArray(UsrToEnv((void *)msg)->getArrayMgr())[onPe].demandCreateElement(idx, ctor, type);
02818         return onPe == CkMyPe();
02819 }
02820 
02821 
02822 void CkLocMgr::multiHop(CkArrayMessage *msg)
02823 {
02824     CK_MAGICNUMBER_CHECK
02825     int srcPe=msg->array_getSrcPe();
02826     if (srcPe==CkMyPe())
02827           DEB((AA "Odd routing: local element %u is %d hops away!\n" AB, msg->array_element_id(),msg->array_hops()));
02828     else
02829     {
02830           DEBS((AA "Sending update back to %d for element %u\n" AB, srcPe, msg->array_element_id()));
02831           thisProxy[srcPe].updateLocation(msg->array_element_id(), CkMyPe());
02832     }
02833 }
02834 
02835 void CkLocMgr::checkInBounds(const CkArrayIndex &idx)
02836 {
02837 #if CMK_ERROR_CHECKING
02838   if (bounds.nInts > 0) {
02839     CkAssert(idx.dimension == bounds.dimension);
02840     bool shorts = idx.dimension > 3;
02841 
02842     for (int i = 0; i < idx.dimension; ++i) {
02843       unsigned int thisDim = shorts ? idx.indexShorts[i] : idx.index[i];
02844       unsigned int thatDim = shorts ? bounds.indexShorts[i] : bounds.index[i];
02845       CkAssert(thisDim < thatDim);
02846     }
02847   }
02848 #endif
02849 }
02850 
02851 
02852 CkLocation::CkLocation(CkLocMgr *mgr_, CkLocRec *rec_)
02853     :mgr(mgr_), rec(rec_) {}
02854     
02855 const CkArrayIndex &CkLocation::getIndex(void) const {
02856     return rec->getIndex();
02857 }
02858 
02859 CmiUInt8 CkLocation::getID() const {
02860     return rec->getID();
02861 }
02862 
02863 void CkLocation::destroyAll() {
02864     mgr->callMethod(rec, &CkMigratable::ckDestroy);
02865 }
02866 
02867 void CkLocation::pup(PUP::er &p) {
02868     mgr->pupElementsFor(p,rec,CkElementCreation_migrate);
02869 }
02870 
02871 CkLocIterator::~CkLocIterator() {}
02872 
02874 void CkLocMgr::iterate(CkLocIterator &dest) {
02875   
02876   CmiImmediateLock(hashImmLock);
02877   for (LocRecHash::iterator it = hash.begin(); it != hash.end(); it++) {
02878     CkLocation loc(this,it->second);
02879     dest.addLocation(loc);
02880   }
02881   CmiImmediateUnlock(hashImmLock);
02882 }
02883 
02884 
02885 
02886 
02887 
02888 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
02889 void CkLocMgr::pupElementsFor(PUP::er &p,CkLocRec *rec,
02890         CkElementCreation_t type, bool create, int dummy)
02891 {
02892     p.comment("-------- Array Location --------");
02893     std::vector<CkMigratable *> dummyElts;
02894 
02895     for (auto itr = managers.begin(); itr != managers.end(); ++itr) {
02896         int elCType;
02897         if (!p.isUnpacking())
02898         { 
02899             CkMigratable *elt = itr->second->getEltFromArrMgr(rec->getIndex());
02900             if (elt) elCType=elt->ckGetChareType();
02901             else elCType=-1; 
02902         }
02903         p(elCType);
02904         if (p.isUnpacking() && elCType!=-1) {
02905             CkMigratable *elt = itr->second->allocateMigrated(elCType,rec->getIndex(),type);
02906             int migCtorIdx=_chareTable[elCType]->getMigCtor();
02907                 if(!dummy){
02908             if(create)
02909                             if (!addElementToRec(rec, itr->second, elt, migCtorIdx, NULL)) return;
02910                 }else{
02911                     CkMigratable_initInfo &i=CkpvAccess(mig_initInfo);
02912                     i.locRec=rec;
02913                     i.chareType=_entryTable[migCtorIdx]->chareIdx;
02914                     dummyElts.push_back(elt);
02915                     if (!rec->invokeEntry(elt,NULL,migCtorIdx,true)) return ;
02916                 }
02917         }
02918     }
02919     if(!dummy){
02920         for (auto itr = managers.begin(); itr != managers.end(); ++itr) {
02921             CkMigratable *elt = itr->second->getEltFromArrMgr(rec->getIndex());
02922             if (elt!=NULL)
02923                 {
02924                        elt->virtual_pup(p);
02925                 }
02926         }
02927     }else{
02928             for(int i=0;i<dummyElts.size();i++){
02929                 CkMigratable *elt = dummyElts[i];
02930                 if (elt!=NULL){
02931             elt->virtual_pup(p);
02932                 }
02933                 delete elt;
02934             }
02935             for (auto itr = managers.begin(); itr != managers.end(); ++itr) {
02936                 itr->second->eraseEltFromArrMgr(rec->getIndex());
02937             }
02938     }
02939 }
02940 #else
02941 void CkLocMgr::pupElementsFor(PUP::er &p,CkLocRec *rec,
02942         CkElementCreation_t type,bool rebuild)
02943 {
02944     p.comment("-------- Array Location --------");
02945 
02946     
02947     
02948     for (auto itr = managers.begin(); itr != managers.end(); ++itr) {
02949         int elCType;
02950                 CkArray *arr = itr->second;
02951         if (!p.isUnpacking())
02952         { 
02953             CkMigratable *elt = arr->getEltFromArrMgr(rec->getID());
02954             if (elt) elCType=elt->ckGetChareType();
02955             else elCType=-1; 
02956         }
02957         p(elCType);
02958         if (p.isUnpacking() && elCType!=-1) {
02959             
02960             CkMigratable *elt = arr->allocateMigrated(elCType, type);
02961             int migCtorIdx=_chareTable[elCType]->getMigCtor();
02962             
02963             if (!addElementToRec(rec,arr,elt,migCtorIdx,NULL)) return;
02964                         if (type==CkElementCreation_resume)
02965                         { 
02966                           
02967                           arr->stampListenerData(elt);
02968                         }
02969         }
02970     }
02971     
02972     for (auto itr = managers.begin(); itr != managers.end(); ++itr) {
02973         CkMigratable *elt = itr->second->getEltFromArrMgr(rec->getID());
02974         if (elt!=NULL)
02975                 {
02976                         elt->virtual_pup(p);
02977 #if CMK_ERROR_CHECKING
02978                         if (p.isUnpacking()) elt->sanitycheck();
02979 #endif
02980                 }
02981     }
02982 #if CMK_MEM_CHECKPOINT
02983     if(rebuild){
02984       ArrayElement *elt;
02985       std::vector<CkMigratable *> list;
02986       migratableList(rec, list);
02987       CmiAssert(!list.empty());
02988       for (int l=0; l<list.size(); l++) {
02989         
02990         
02991         for (int i=0; i<CK_ARRAYLISTENER_MAXLEN; i++) {
02992             ArrayElement * elt = (ArrayElement *)list[l];
02993           contributorInfo *c=(contributorInfo *)&elt->listenerData[i];
02994           if (c) c->redNo = 0;
02995         }
02996       }
02997         
02998     }
02999 #endif
03000 }
03001 #endif
03002 
03004 void CkLocMgr::callMethod(CkLocRec *rec,CkMigratable_voidfn_t fn)
03005 {
03006     for (auto itr = managers.begin(); itr != managers.end(); ++itr) {
03007         CkMigratable *el = itr->second->getEltFromArrMgr(rec->getID());
03008         if (el) (el->* fn)();
03009     }
03010 }
03011 
03013 void CkLocMgr::callMethod(CkLocRec *rec,CkMigratable_voidfn_arg_t fn,     void * data)
03014 {
03015     for (auto itr = managers.begin(); itr != managers.end(); ++itr) {
03016         CkMigratable *el = itr->second->getEltFromArrMgr(rec->getID());
03017         if (el) (el->* fn)(data);
03018     }
03019 }
03020 
03022 void CkLocMgr::migratableList(CkLocRec *rec, std::vector<CkMigratable *> &list)
03023 {
03024         for (auto itr = managers.begin(); itr != managers.end(); ++itr) {
03025                 CkMigratable *elt = itr->second->getEltFromArrMgr(rec->getID());
03026                 if (elt) list.push_back(elt);
03027         }
03028 }
03029 
03031 void CkLocMgr::emigrate(CkLocRec *rec,int toPe)
03032 {
03033     CK_MAGICNUMBER_CHECK
03034     if (toPe==CkMyPe()) return; 
03035 
03036 #if CMK_FAULT_EVAC
03037     
03038 
03039 
03040 
03041     if(!CmiNodeAlive(toPe)){
03042         return;
03043     }
03044 #endif
03045 
03046     CkArrayIndex idx=rec->getIndex();
03047         CmiUInt8 id = rec->getID();
03048 
03049 #if CMK_OUT_OF_CORE
03050     
03051     for (auto itr = managers.begin(); itr != managers.end(); ++itr) {
03052         CkMigratable *el = itr->second->getEltFromArrMgr(rec->getIndex());
03053         if (el) if (!el->isInCore) CooBringIn(el->prefetchObjID);
03054     }
03055 #endif
03056 
03057     
03058     callMethod(rec,&CkMigratable::ckAboutToMigrate);
03059     
03060 
03061 
03062     size_t bufSize;
03063     {
03064         PUP::sizer p;
03065         pupElementsFor(p,rec,CkElementCreation_migrate);
03066         bufSize=p.size(); 
03067     }
03068 #if CMK_ERROR_CHECKING
03069     if (bufSize > std::numeric_limits<int>::max()) {
03070         CmiPrintf("Cannot migrate an object with size greater than %zu bytes!\n", std::numeric_limits<int>::max());
03071         CmiAbort("");
03072     }
03073 #endif
03074 
03075 
03076     CkArrayElementMigrateMessage *msg = new (bufSize, 0) CkArrayElementMigrateMessage(idx, id,
03077 #if CMK_LBDB_ON
03078         rec->isAsyncMigrate(),
03079 #else
03080         false,
03081 #endif
03082         bufSize, managers.size(),
03083 #if CMK_FAULT_EVAC
03084     rec->isBounced()
03085 #else
03086     false
03087 #endif
03088     );
03089 
03090 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_)) 
03091     msg->gid = ckGetGroupID();
03092 #endif
03093     {
03094         PUP::toMem p(msg->packData); 
03095         p.becomeDeleting(); 
03096         pupElementsFor(p,rec,CkElementCreation_migrate);
03097         if (p.size()!=bufSize) {
03098             CkError("ERROR! Array element claimed it was %d bytes to a "
03099                 "sizing PUP::er, but copied %d bytes into the packing PUP::er!\n",
03100                 bufSize,p.size());
03101             CkAbort("Array element's pup routine has a direction mismatch.\n");
03102         }
03103     }
03104 
03105     DEBM((AA "Migrated index size %s to %d \n" AB,idx2str(idx),toPe));  
03106 
03107 
03108 
03109 
03110 
03111     
03112     thisProxy[toPe].immigrate(msg);
03113 
03114 
03115     duringMigration=true;
03116     for (auto itr = managers.begin(); itr != managers.end(); ++itr) {
03117         itr->second->deleteElt(id);
03118     }
03119     duringMigration=false;
03120 
03121     
03122     inform(idx, id, toPe);
03123 
03124 
03125     informHome(idx,toPe);
03126 
03127 
03128 #if !CMK_LBDB_ON && CMK_GLOBAL_LOCATION_UPDATE
03129         DEBM((AA "Global location update. idx %s " 
03130               "assigned to %d \n" AB,idx2str(idx),toPe));
03131         thisProxy.updateLocation(id, toPe);
03132 #endif
03133 
03134     CK_MAGICNUMBER_CHECK
03135 }
03136 
03137 #if CMK_LBDB_ON
03138 void CkLocMgr::informLBPeriod(CkLocRec *rec, int lb_ideal_period) {
03139     callMethod(rec,&CkMigratable::recvLBPeriod, (void *)&lb_ideal_period);
03140 }
03141 
03142 void CkLocMgr::metaLBCallLB(CkLocRec *rec) {
03143     callMethod(rec, &CkMigratable::metaLBCallLB);
03144 }
03145 #endif
03146 
03150 void CkLocMgr::immigrate(CkArrayElementMigrateMessage *msg)
03151 {
03152     const CkArrayIndex &idx=msg->idx;
03153         
03154     PUP::fromMem p(msg->packData); 
03155     
03156     if (msg->nManagers < managers.size())
03157         CkAbort("Array element arrived from location with fewer managers!\n");
03158     if (msg->nManagers > managers.size()) {
03159         
03160         DEBM((AA "Busy-waiting for array registration on migrating %s\n" AB,idx2str(idx)));
03161         thisProxy[CkMyPe()].immigrate(msg);
03162         return;
03163     }
03164 
03165     insertID(idx,msg->id);
03166 
03167     
03168 
03169 
03170     CkLocRec *rec=createLocal(idx,true,msg->ignoreArrival,false  );
03171 
03172 
03173 
03174     
03175     
03176     pupElementsFor(p,rec,CkElementCreation_migrate);
03177     if (p.size()!=msg->length) {
03178         CkError("ERROR! Array element claimed it was %d bytes to a"
03179             "packing PUP::er, but %d bytes in the unpacking PUP::er!\n",
03180             msg->length,p.size());
03181         CkError("(I have %d managers; he claims %d managers)\n",
03182             managers.size(), msg->nManagers);
03183         
03184         CkAbort("Array element's pup routine has a direction mismatch.\n");
03185     }
03186 
03187 #if CMK_FAULT_EVAC
03188     
03189 
03190 
03191 
03192 
03193     if(msg->bounced){
03194         callMethod(rec,&CkMigratable::ResumeFromSync);
03195     }
03196 #endif
03197 
03198     
03199     callMethod(rec,&CkMigratable::ckJustMigrated);
03200 
03201 #if CMK_FAULT_EVAC
03202     
03203 
03204 
03205 
03206 
03207 
03208     if(CkpvAccess(startedEvac)){
03209         int newhomePE = getNextPE(idx);
03210         DEBM((AA "Migrated into failed processor index size %s resent to %d \n" AB,idx2str(idx),newhomePE));    
03211         int targetPE=getNextPE(idx);
03212         
03213         
03214         rec->AsyncMigrate(true);
03215         rec->Bounced(true);
03216         emigrate(rec,targetPE);
03217     }
03218 #endif
03219 
03220     delete msg;
03221 }
03222 
03223 void CkLocMgr::restore(const CkArrayIndex &idx, CmiUInt8 id, PUP::er &p)
03224 {
03225     insertID(idx,id);
03226 
03227     
03228     
03229     
03230 #if CMK_ERROR_CHECKING
03231     if(_BgOutOfCoreFlag!=2)
03232         CmiAbort("CkLocMgr::restore should only be used in out-of-core emulation for BigSim and be called when object is brought into memory!\n");
03233 #endif
03234     CkLocRec *rec=createLocal(idx,false,false,false);
03235     
03236     
03237     
03238 
03239     
03240     pupElementsFor(p,rec,CkElementCreation_restore);
03241 
03242     callMethod(rec,&CkMigratable::ckJustRestored);
03243 }
03244 
03245 
03247 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
03248 void CkLocMgr::resume(const CkArrayIndex &idx, CmiUInt8 id, PUP::er &p, bool create, int dummy)
03249 {
03250     insertID(idx,id);
03251 
03252     CkLocRec *rec;
03253 
03254     if(create){
03255         rec = createLocal(idx,false,false,true && !dummy ,dummy );
03256     }else{
03257         rec = elementNrec(idx);
03258         if(rec == NULL) 
03259             CmiAbort("Local object not found");
03260     }
03261         
03262     pupElementsFor(p,rec,CkElementCreation_resume,create,dummy);
03263 
03264     if(!dummy){
03265         callMethod(rec,&CkMigratable::ckJustMigrated);
03266     }
03267 }
03268 #else
03269 void CkLocMgr::resume(const CkArrayIndex &idx, CmiUInt8 id, PUP::er &p, bool notify,bool rebuild)
03270 {
03271     insertID(idx,id);
03272 
03273     CkLocRec *rec=createLocal(idx,false,false,notify  );
03274 
03275     
03276     pupElementsFor(p,rec,CkElementCreation_resume,rebuild);
03277 
03278     callMethod(rec,&CkMigratable::ckJustMigrated);
03279 }
03280 #endif
03281 
03282 
03283 void CkMagicNumber_impl::badMagicNumber(
03284     int expected,const char *file,int line,void *obj) const
03285 {
03286     CkError("FAILURE on pe %d, %s:%d> Expected %p's magic number "
03287         "to be 0x%08x; but found 0x%08x!\n", CkMyPe(),file,line,obj,
03288         expected, magic);
03289     CkAbort("Bad magic number detected!  This implies either\n"
03290         "the heap or a message was corrupted!\n");
03291 }
03292 CkMagicNumber_impl::CkMagicNumber_impl(int m) :magic(m) { }
03293 
03294 int CkLocMgr::whichPE(const CkArrayIndex &idx) const
03295 {
03296   CmiUInt8 id;
03297   if (!lookupID(idx, id))
03298     return -1;
03299 
03300   IdPeMap::const_iterator itr = id2pe.find(id);
03301   return (itr != id2pe.end() ? itr->second : -1);
03302 }
03303 
03304 int CkLocMgr::whichPE(const CmiUInt8 id) const
03305 {
03306   IdPeMap::const_iterator itr = id2pe.find(id);
03307   return (itr != id2pe.end() ? itr->second : -1);
03308 }
03309 
03310 
03311 int CkLocMgr::lastKnown(const CkArrayIndex &idx) {
03312     CkLocMgr *vthis=(CkLocMgr *)this;
03313     int pe = whichPE(idx);
03314     if (pe==-1) return homePe(idx);
03315     else{
03316 #if CMK_FAULT_EVAC
03317         if(!CmiNodeAlive(pe)){
03318             CkAbort("Last known PE is no longer alive");
03319         }
03320 #endif
03321         return pe;
03322     }   
03323 }
03324 
03325 
03326 int CkLocMgr::lastKnown(CmiUInt8 id) {
03327   int pe = whichPE(id);
03328   if (pe==-1) return homePe(id);
03329   else{
03330 #if CMK_FAULT_EVAC
03331     if(!CmiNodeAlive(pe)){
03332       CkAbort("Last known PE is no longer alive");
03333     }
03334 #endif
03335     return pe;
03336   } 
03337 }
03338 
03340 bool CkLocMgr::isRemote(const CkArrayIndex &idx,int *onPe) const
03341 {
03342     int pe = whichPE(idx);
03343     
03344     if (pe == -1 || pe == CkMyPe())
03345         return false;
03346     
03347     *onPe = pe;
03348     return true;
03349 }
03350 
03351 static const char *rec2str[]={
03352     "base (INVALID)",
03353     "local",
03354 };
03355 
03356 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
03357 void CkLocMgr::setDuringMigration(bool _duringMigration){
03358     duringMigration = _duringMigration;
03359 }
03360 #endif
03361 
03362 
03363 
03364 void CkLocMgr::setDuringDestruction(bool _duringDestruction) {
03365   duringDestruction = (_duringDestruction && managers.size() == 1);
03366 }
03367 
03368 
03369 void CkLocMgr::insertRec(CkLocRec *rec, const CmiUInt8 &id) {
03370     CkLocRec *old_rec = elementNrec(id);
03371     CmiImmediateLock(hashImmLock);
03372     hash[id] = rec;
03373     CmiImmediateUnlock(hashImmLock);
03374     delete old_rec;
03375 }
03376 
03377 
03378 static void abort_out_of_bounds(const CkArrayIndex &idx)
03379 {
03380   CkPrintf("ERROR! Unknown array index: %s\n",idx2str(idx));
03381   CkAbort("Array index out of bounds\n");
03382 }
03383 
03384 
03385 
03386 CkLocRec *CkLocMgr::elementRec(const CkArrayIndex &idx) {
03387 #if ! CMK_ERROR_CHECKING
03388 
03389   return hash[lookupID(idx)];
03390 #else
03391 
03392   CmiUInt8 id;
03393   CkLocRec *rec = NULL;
03394   if (lookupID(idx, id) && (rec = elementNrec(id))) {
03395     return rec;
03396   } else {
03397     if (rec==NULL) abort_out_of_bounds(idx);
03398     return NULL;
03399   }
03400 #endif
03401 }
03402 
03403 
03404 CkLocRec *CkLocMgr::elementNrec(const CmiUInt8 id) {
03405   LocRecHash::iterator it = hash.find(id);
03406   return it == hash.end() ? NULL : it->second;
03407 }
03408 
03409 struct LocalElementCounter :  public CkLocIterator
03410 {
03411     unsigned int count;
03412     LocalElementCounter() : count(0) {}
03413     void addLocation(CkLocation &loc)
03414     { ++count; }
03415 };
03416 
03417 unsigned int CkLocMgr::numLocalElements()
03418 {
03419     LocalElementCounter c;
03420     iterate(c);
03421     return c.count;
03422 }
03423 
03424 
03425 
03426 
03427 #if !CMK_LBDB_ON
03428 
03429 void CkLocMgr::initLB(CkGroupID lbdbID_, CkGroupID metalbID_) {}
03430 void CkLocMgr::startInserting(void) {}
03431 void CkLocMgr::doneInserting(void) {}
03432 void CkLocMgr::dummyAtSync(void) {}
03433 #endif
03434 
03435 
03436 #if CMK_LBDB_ON
03437 void CkLocMgr::initLB(CkGroupID lbdbID_, CkGroupID metalbID_)
03438 { 
03439     the_lbdb = (LBDatabase *)CkLocalBranch(lbdbID_);
03440     if (the_lbdb == 0)
03441         CkAbort("LBDatabase not yet created?\n");
03442     DEBL((AA "Connected to load balancer %p\n" AB,the_lbdb));
03443     if(_lb_args.metaLbOn()){
03444       the_metalb = (MetaBalancer *)CkLocalBranch(metalbID_);
03445       if (the_metalb == 0)
03446           CkAbort("MetaBalancer not yet created?\n");
03447     }
03448     
03449     LDOMid myId;
03450     myId.id = thisgroup;
03451     LDCallbacks myCallbacks;
03452     myCallbacks.migrate = (LDMigrateFn)CkLocRec::staticMigrate;
03453     myCallbacks.setStats = NULL;
03454     myCallbacks.queryEstLoad = NULL;
03455   myCallbacks.metaLBResumeWaitingChares =
03456       (LDMetaLBResumeWaitingCharesFn)CkLocRec::staticMetaLBResumeWaitingChares;
03457   myCallbacks.metaLBCallLBOnChares =
03458       (LDMetaLBCallLBOnCharesFn)CkLocRec::staticMetaLBCallLBOnChares;
03459     myLBHandle = the_lbdb->RegisterOM(myId,this,myCallbacks);
03460 
03461     
03462     the_lbdb->RegisteringObjects(myLBHandle);
03463 
03464     
03465 
03466 
03467 
03468     lbBarrierReceiver = the_lbdb->AddLocalBarrierReceiver(
03469         (LDBarrierFn)staticRecvAtSync,(void*)(this));
03470     dummyBarrierHandle = the_lbdb->AddLocalBarrierClient(
03471         (LDResumeFn)staticDummyResumeFromSync,(void*)(this));
03472     dummyAtSync();
03473 }
03474 void CkLocMgr::dummyAtSync(void)
03475 {
03476     DEBL((AA "dummyAtSync called\n" AB));
03477     the_lbdb->AtLocalBarrier(dummyBarrierHandle);
03478 }
03479 
03480 void CkLocMgr::staticDummyResumeFromSync(void* data)
03481 {      ((CkLocMgr*)data)->dummyResumeFromSync(); }
03482 void CkLocMgr::dummyResumeFromSync()
03483 {
03484     DEBL((AA "DummyResumeFromSync called\n" AB));
03485     the_lbdb->DoneRegisteringObjects(myLBHandle);
03486     dummyAtSync();
03487 }
03488 void CkLocMgr::staticRecvAtSync(void* data)
03489 {      ((CkLocMgr*)data)->recvAtSync(); }
03490 void CkLocMgr::recvAtSync()
03491 {
03492     DEBL((AA "recvAtSync called\n" AB));
03493     the_lbdb->RegisteringObjects(myLBHandle);
03494 }
03495 
03496 void CkLocMgr::startInserting(void)
03497 {
03498     the_lbdb->RegisteringObjects(myLBHandle);
03499 }
03500 void CkLocMgr::doneInserting(void)
03501 {
03502     the_lbdb->DoneRegisteringObjects(myLBHandle);
03503 }
03504 #endif
03505 
03506 #include "CkLocation.def.h"
03507 
03508