8e5604c021ada31be531478abffb97bca2260dc6
[charm.git] / src / ck-core / cklocation.C
1 /** \file cklocation.C
2  *  \addtogroup CkArrayImpl
3  *
4  *  The location manager keeps track of an indexed set of migratable objects.
5  *  It is used by the array manager to locate array elements, interact with the
6  *  load balancer, and perform migrations.
7  *
8  *  Orion Sky Lawlor, olawlor@acm.org 9/29/2001
9  */
10
11 #include "hilbert.h"
12 #include "partitioning_strategies.h"
13 #include "charm++.h"
14 #include "register.h"
15 #include "ck.h"
16 #include "trace.h"
17 #include "TopoManager.h"
18 #include <vector>
19 #include <algorithm>
20 #include<sstream>
21
22 #if CMK_LBDB_ON
23 #include "LBDatabase.h"
24 #include "MetaBalancer.h"
25 #if CMK_GLOBAL_LOCATION_UPDATE
26 #include "BaseLB.h"
27 #include "init.h"
28 #endif
29 #endif // CMK_LBDB_ON
30
31 #if CMK_GRID_QUEUE_AVAILABLE
32 CpvExtern(void *, CkGridObject);
33 #endif
34
35 static const char *idx2str(const CkArrayMessage *m) {
36   return idx2str(((CkArrayMessage *)m)->array_index());
37 }
38
39 #define ARRAY_DEBUG_OUTPUT 0
40
41 #if ARRAY_DEBUG_OUTPUT 
42 #   define DEB(x) CkPrintf x  //General debug messages
43 #   define DEBI(x) CkPrintf x  //Index debug messages
44 #   define DEBC(x) CkPrintf x  //Construction debug messages
45 #   define DEBS(x) CkPrintf x  //Send/recv/broadcast debug messages
46 #   define DEBM(x) CkPrintf x  //Migration debug messages
47 #   define DEBL(x) CkPrintf x  //Load balancing debug messages
48 #   define DEBK(x) CkPrintf x  //Spring Cleaning debug messages
49 #   define DEBB(x) CkPrintf x  //Broadcast debug messages
50 #   define AA "LocMgr on %d: "
51 #   define AB ,CkMyPe()
52 #   define DEBUG(x) CkPrintf x
53 #   define DEBAD(x) CkPrintf x
54 #else
55 #   define DEB(X) /*CkPrintf x*/
56 #   define DEBI(X) /*CkPrintf x*/
57 #   define DEBC(X) /*CkPrintf x*/
58 #   define DEBS(x) /*CkPrintf x*/
59 #   define DEBM(X) /*CkPrintf x*/
60 #   define DEBL(X) /*CkPrintf x*/
61 #   define DEBK(x) /*CkPrintf x*/
62 #   define DEBB(x) /*CkPrintf x*/
63 #   define str(x) /**/
64 #   define DEBUG(x)   /**/
65 #   define DEBAD(x) /*CkPrintf x*/
66 #endif
67
68 //whether to use block mapping in the SMP node level
69 bool useNodeBlkMapping;
70
71 #if CMK_LBDB_ON
72 /*LBDB object handles are fixed-sized, and not necc.
73 the same size as ArrayIndices.
74 */
75 LDObjid idx2LDObjid(const CkArrayIndex &idx)
76 {
77   LDObjid r;
78   int i;
79   const int *data=idx.data();
80   if (OBJ_ID_SZ>=idx.nInts) {
81     for (i=0;i<idx.nInts;i++)
82       r.id[i]=data[i];
83     for (i=idx.nInts;i<OBJ_ID_SZ;i++)
84       r.id[i]=0;
85   } else {
86     //Must hash array index into LBObjid
87     int j;
88     for (j=0;j<OBJ_ID_SZ;j++)
89         r.id[j]=data[j];
90     for (i=0;i<idx.nInts;i++)
91       for (j=0;j<OBJ_ID_SZ;j++)
92         r.id[j]+=circleShift(data[i],22+11*i*(j+1))+
93           circleShift(data[i],21-9*i*(j+1));
94   }
95
96 #if CMK_GLOBAL_LOCATION_UPDATE
97   r.dimension = idx.dimension;
98   r.nInts = idx.nInts; 
99   r.isArrayElement = 1; 
100 #endif
101
102   return r;
103 }
104
105 #if CMK_GLOBAL_LOCATION_UPDATE
106 void UpdateLocation(MigrateInfo& migData) {
107
108   if (migData.obj.id.isArrayElement == 0) {
109     return;
110   }
111
112   CkArrayIndex idx; 
113   idx.dimension = migData.obj.id.dimension; 
114   idx.nInts = migData.obj.id.nInts; 
115
116   for (int i = 0; i < idx.nInts; i++) {
117     idx.data()[i] = migData.obj.id.id[i];    
118   }
119
120   CkGroupID locMgrGid;
121   locMgrGid.idx = migData.obj.id.locMgrGid;
122   CkLocMgr *localLocMgr = (CkLocMgr *) CkLocalBranch(locMgrGid);
123   localLocMgr->updateLocation(idx, migData.to_pe); 
124 }
125 #endif
126
127 #endif
128
129 /*********************** Array Messages ************************/
130 CkArrayIndex &CkArrayMessage::array_index(void)
131 {
132     return UsrToEnv((void *)this)->getsetArrayIndex();
133 }
134 unsigned short &CkArrayMessage::array_ep(void)
135 {
136         return UsrToEnv((void *)this)->getsetArrayEp();
137 }
138 unsigned short &CkArrayMessage::array_ep_bcast(void)
139 {
140         return UsrToEnv((void *)this)->getsetArrayBcastEp();
141 }
142 unsigned char &CkArrayMessage::array_hops(void)
143 {
144         return UsrToEnv((void *)this)->getsetArrayHops();
145 }
146 unsigned int CkArrayMessage::array_getSrcPe(void)
147 {
148         return UsrToEnv((void *)this)->getsetArraySrcPe();
149 }
150 unsigned int CkArrayMessage::array_ifNotThere(void)
151 {
152         return UsrToEnv((void *)this)->getArrayIfNotThere();
153 }
154 void CkArrayMessage::array_setIfNotThere(unsigned int i)
155 {
156         UsrToEnv((void *)this)->setArrayIfNotThere(i);
157 }
158
159 /*********************** Array Map ******************
160 Given an array element index, an array map tells us 
161 the index's "home" Pe.  This is the Pe the element will
162 be created on, and also where messages to this element will
163 be forwarded by default.
164 */
165
166 CkArrayMap::CkArrayMap(void) { }
167 CkArrayMap::~CkArrayMap() { }
168 int CkArrayMap::registerArray(const CkArrayIndex& numElements, CkArrayID aid)
169 {return 0;}
170 void CkArrayMap::unregisterArray(int idx)
171 { }
172
173 #define CKARRAYMAP_POPULATE_INITIAL(POPULATE_CONDITION) \
174         int i; \
175         for (int i1=0; i1<numElements.data()[0]; i1++) { \
176           if (numElements.dimension == 1) { \
177             /* Make 1D indices */ \
178             i = i1; \
179             CkArrayIndex1D idx(i1); \
180             if (POPULATE_CONDITION) \
181               mgr->insertInitial(idx,CkCopyMsg(&ctorMsg)); \
182           } else { \
183             /* higher dimensionality */ \
184             for (int i2=0; i2<numElements.data()[1]; i2++) { \
185               if (numElements.dimension == 2) { \
186                 /* Make 2D indices */ \
187                 i = i1 * numElements.data()[1] + i2; \
188                 CkArrayIndex2D idx(i1, i2); \
189                 if (POPULATE_CONDITION) \
190                   mgr->insertInitial(idx,CkCopyMsg(&ctorMsg)); \
191               } else { \
192                 /* higher dimensionality */ \
193                 CkAssert(numElements.dimension == 3); \
194                 for (int i3=0; i3<numElements.data()[2]; i3++) { \
195                   /* Make 3D indices */ \
196                   i = (i1 * numElements.data()[1] + i2) * numElements.data()[2] + i3; \
197                   CkArrayIndex3D idx(i1, i2, i3 ); \
198                   if (POPULATE_CONDITION) \
199                     mgr->insertInitial(idx,CkCopyMsg(&ctorMsg)); \
200                 } \
201               } \
202             } \
203           } \
204         }
205
206 void CkArrayMap::populateInitial(int arrayHdl,CkArrayIndex& numElements,void *ctorMsg,CkArrMgr *mgr)
207 {
208         if (numElements.nInts==0) {
209           CkFreeMsg(ctorMsg);
210           return;
211         }
212         int thisPe=CkMyPe();
213         /* The CkArrayIndex is supposed to have at most 3 dimensions, which
214            means that all the fields are ints, and numElements.nInts represents
215            how many of them are used */
216         CKARRAYMAP_POPULATE_INITIAL(procNum(arrayHdl,idx)==thisPe);
217
218 #if CMK_BIGSIM_CHARM
219         BgEntrySplit("split-array-new-end");
220 #endif
221
222         mgr->doneInserting();
223         CkFreeMsg(ctorMsg);
224 }
225
226 CkGroupID _defaultArrayMapID;
227 CkGroupID _fastArrayMapID;
228
229 class RRMap : public CkArrayMap
230 {
231 public:
232   RRMap(void)
233   {
234           DEBC((AA"Creating RRMap\n"AB));
235   }
236   RRMap(CkMigrateMessage *m):CkArrayMap(m){}
237   int procNum(int /*arrayHdl*/, const CkArrayIndex &i)
238   {
239 #if 1
240     if (i.nInts==1) {
241       //Map 1D integer indices in simple round-robin fashion
242       int ans= (i.data()[0])%CkNumPes();
243       while(!CmiNodeAlive(ans) || (ans == CkMyPe() && CkpvAccess(startedEvac))){
244         ans = (ans +1 )%CkNumPes();
245       }
246       return ans;
247     }
248     else 
249 #endif
250       {
251         //Map other indices based on their hash code, mod a big prime.
252         unsigned int hash=(i.hash()+739)%1280107;
253         int ans = (hash % CkNumPes());
254         while(!CmiNodeAlive(ans)){
255                 ans = (ans +1 )%CkNumPes();
256         }
257         return ans;
258
259       }
260   }
261 };
262
263 /** 
264  * Class used to store the dimensions of the array and precalculate numChares,
265  * binSize and other values for the DefaultArrayMap -- ASB
266  */
267 class arrayMapInfo {
268 public:
269   CkArrayIndex _nelems;
270   int _binSizeFloor;            /* floor of numChares/numPes */
271   int _binSizeCeil;             /* ceiling of numChares/numPes */
272   int _numChares;               /* initial total number of chares */
273   int _remChares;               /* numChares % numPes -- equals the number of
274                                    processors in the first set */
275   int _numFirstSet;             /* _remChares X (_binSize + 1) -- number of
276                                    chares in the first set */
277
278   int _nBinSizeFloor;           /* floor of numChares/numNodes */
279   int _nRemChares;              /* numChares % numNodes -- equals the number of
280                                    nodes in the first set */
281   int _nNumFirstSet;            /* _remChares X (_binSize + 1) -- number of
282                                    chares in the first set of nodes */
283
284   /** All processors are divided into two sets. Processors in the first set
285    *  have one chare more than the processors in the second set. */
286
287   arrayMapInfo(void) { }
288
289   arrayMapInfo(const CkArrayIndex& n) : _nelems(n), _numChares(0) {
290     compute_binsize();
291   }
292
293   ~arrayMapInfo() {}
294   
295   void compute_binsize()
296   {
297     int numPes = CkNumPes();
298     //Now assuming homogenous nodes where each node has the same number of PEs
299     int numNodes = CkNumNodes();
300
301     if (_nelems.nInts == 1) {
302       _numChares = _nelems.data()[0];
303     } else if (_nelems.nInts == 2) {
304       _numChares = _nelems.data()[0] * _nelems.data()[1];
305     } else if (_nelems.nInts == 3) {
306       _numChares = _nelems.data()[0] * _nelems.data()[1] * _nelems.data()[2];
307     }
308
309     _remChares = _numChares % numPes;
310     _binSizeFloor = (int)floor((double)_numChares/(double)numPes);
311     _binSizeCeil = (int)ceil((double)_numChares/(double)numPes);
312     _numFirstSet = _remChares * (_binSizeFloor + 1);
313
314     _nRemChares = _numChares % numNodes;
315     _nBinSizeFloor = _numChares/numNodes;
316     _nNumFirstSet = _nRemChares * (_nBinSizeFloor +1);
317   }
318
319   void pup(PUP::er& p){
320     p|_nelems;
321     p|_binSizeFloor;
322     p|_binSizeCeil;
323     p|_numChares;
324     p|_remChares;
325     p|_numFirstSet;
326     p|_nRemChares;
327     p|_nBinSizeFloor;
328     p|_nNumFirstSet;
329   }
330 };
331
332
333 /**
334  * The default map object -- This does blocked mapping in the general case and
335  * calls the round-robin procNum for the dynamic insertion case -- ASB
336  */
337 class DefaultArrayMap : public RRMap
338 {
339 public:
340   /** This array stores information about different chare arrays in a Charm
341    *  program (dimensions, binsize, numChares etc ... ) */
342   CkPupPtrVec<arrayMapInfo> amaps;
343
344 public:
345   DefaultArrayMap(void) {
346     DEBC((AA"Creating DefaultArrayMap\n"AB));
347   }
348
349   DefaultArrayMap(CkMigrateMessage *m) : RRMap(m){}
350
351   int registerArray(const CkArrayIndex& numElements, CkArrayID aid)
352   {
353     int idx = amaps.size();
354     amaps.resize(idx+1);
355     amaps[idx] = new arrayMapInfo(numElements);
356     return idx;
357   }
358
359   void unregisterArray(int idx)
360   {
361     delete amaps[idx];
362     amaps[idx] = NULL;
363   }
364  
365   int procNum(int arrayHdl, const CkArrayIndex &i) {
366     int flati;
367     if (amaps[arrayHdl]->_nelems.nInts == 0) {
368       return RRMap::procNum(arrayHdl, i);
369     }
370
371     if (i.nInts == 1) {
372       flati = i.data()[0];
373     } else if (i.nInts == 2) {
374       flati = i.data()[0] * amaps[arrayHdl]->_nelems.data()[1] + i.data()[1];
375     } else if (i.nInts == 3) {
376       flati = (i.data()[0] * amaps[arrayHdl]->_nelems.data()[1] + i.data()[1]) * amaps[arrayHdl]->_nelems.data()[2] + i.data()[2];
377     }
378 #if CMK_ERROR_CHECKING
379     else {
380       CkAbort("CkArrayIndex has more than 3 integers!");
381     }
382 #endif
383
384     if(useNodeBlkMapping){
385       if(flati < amaps[arrayHdl]->_numChares){
386         int numCharesOnNode = amaps[arrayHdl]->_nBinSizeFloor;
387         int startNodeID, offsetInNode;
388         if(flati < amaps[arrayHdl]->_nNumFirstSet){
389           numCharesOnNode++;
390           startNodeID = flati/numCharesOnNode;
391           offsetInNode = flati%numCharesOnNode;
392         }else{
393           startNodeID = amaps[arrayHdl]->_nRemChares+(flati-amaps[arrayHdl]->_nNumFirstSet)/numCharesOnNode;
394           offsetInNode = (flati-amaps[arrayHdl]->_nNumFirstSet)%numCharesOnNode;
395         }
396         int nodeSize = CkMyNodeSize(); //assuming every node has same number of PEs
397         int elemsPerPE = numCharesOnNode/nodeSize;
398         int remElems = numCharesOnNode%nodeSize;
399         int firstSetPEs = remElems*(elemsPerPE+1);
400         if(offsetInNode<firstSetPEs){
401           return CkNodeFirst(startNodeID)+offsetInNode/(elemsPerPE+1);
402         }else{
403           return CkNodeFirst(startNodeID)+remElems+(offsetInNode-firstSetPEs)/elemsPerPE;
404         }
405       } else
406           return (flati % CkNumPes());
407     }
408     //regular PE-based block mapping
409     if(flati < amaps[arrayHdl]->_numFirstSet)
410       return (flati / (amaps[arrayHdl]->_binSizeFloor + 1));
411     else if (flati < amaps[arrayHdl]->_numChares)
412       return (amaps[arrayHdl]->_remChares + (flati - amaps[arrayHdl]->_numFirstSet) / (amaps[arrayHdl]->_binSizeFloor));
413     else
414       return (flati % CkNumPes());
415   }
416
417   void pup(PUP::er& p){
418     RRMap::pup(p);
419     int npes = CkNumPes();
420     p|npes;
421     p|amaps;
422     if (p.isUnpacking() && npes != CkNumPes())  {   // binSize needs update
423       for (int i=0; i<amaps.size(); i++)
424         amaps[i]->compute_binsize();
425     }
426   }
427 };
428
429 /**
430  *  A fast map for chare arrays which do static insertions and promise NOT
431  *  to do late insertions -- ASB
432  */
433 class FastArrayMap : public DefaultArrayMap
434 {
435 public:
436   FastArrayMap(void) {
437     DEBC((AA"Creating FastArrayMap\n"AB));
438   }
439
440   FastArrayMap(CkMigrateMessage *m) : DefaultArrayMap(m){}
441
442   int registerArray(const CkArrayIndex& numElements, CkArrayID aid)
443   {
444     int idx;
445     idx = DefaultArrayMap::registerArray(numElements, aid);
446
447     return idx;
448   }
449
450   int procNum(int arrayHdl, const CkArrayIndex &i) {
451     int flati = 0;
452     if (amaps[arrayHdl]->_nelems.nInts == 0) {
453       return RRMap::procNum(arrayHdl, i);
454     }
455
456     if (i.nInts == 1) {
457       flati = i.data()[0];
458     } else if (i.nInts == 2) {
459       flati = i.data()[0] * amaps[arrayHdl]->_nelems.data()[1] + i.data()[1];
460     } else if (i.nInts == 3) {
461       flati = (i.data()[0] * amaps[arrayHdl]->_nelems.data()[1] + i.data()[1]) * amaps[arrayHdl]->_nelems.data()[2] + i.data()[2];
462     }
463 #if CMK_ERROR_CHECKING
464     else {
465       CkAbort("CkArrayIndex has more than 3 integers!");
466     }
467 #endif
468
469     /** binSize used in DefaultArrayMap is the floor of numChares/numPes
470      *  but for this FastArrayMap, we need the ceiling */
471     return (flati / amaps[arrayHdl]->_binSizeCeil);
472   }
473
474   void pup(PUP::er& p){
475     DefaultArrayMap::pup(p);
476   }
477 };
478
479 /* *
480  * Hilbert map object -- This does hilbert mapping.
481  * Convert array indices into 1D fashion according to their Hilbert filling curve 
482  */
483
484 typedef struct {
485     int intIndex;
486     std::vector<int> coords;
487 }hilbert_pair;
488
489 bool operator== ( hilbert_pair p1, hilbert_pair p2) 
490 {
491     return p1.intIndex == p2.intIndex;
492 }
493
494 bool myCompare(hilbert_pair p1, hilbert_pair p2)
495 {
496     return p1.intIndex < p2.intIndex;
497 }
498
499 class HilbertArrayMap: public DefaultArrayMap
500 {
501     std::vector<hilbert_pair> allpairs;
502     int *procList;
503 public:
504   HilbertArrayMap(void) {
505     procList = new int[CkNumPes()]; 
506     DEBC((AA"Creating HilbertArrayMap\n"AB));
507   }
508
509   HilbertArrayMap(CkMigrateMessage *m) : DefaultArrayMap(m){}
510
511   ~HilbertArrayMap()
512   {
513       if(procList)
514           delete []procList;
515   }
516
517   int registerArray(const CkArrayIndex& i, CkArrayID aid)
518   {
519     int idx;
520     idx = DefaultArrayMap::registerArray(i, aid);
521    
522     if (i.nInts == 1) {
523       CkPrintf("1D %d\n", amaps[idx]->_nelems.data()[0]); 
524     } else if (i.nInts == 2) {
525       CkPrintf("2D %d:%d\n", amaps[idx]->_nelems.data()[0], amaps[idx]->_nelems.data()[1]); 
526       int dims = 2;
527       int nDim0 = amaps[idx]->_nelems.data()[0];
528       int nDim1 = amaps[idx]->_nelems.data()[1];
529       int index;
530       int counter = 0;
531       allpairs.resize(nDim0*nDim1);
532       for(int i=0; i<nDim0; i++)
533           for(int j=0; j<nDim1; j++)
534           {
535               allpairs[counter].coords.resize(2);
536               allpairs[counter].coords[0] = i;
537               allpairs[counter].coords[1] = j;
538               index = Hilbert_to_int( allpairs[counter].coords, dims);
539               //CkPrintf("(%d:%d)----------> %d \n", i, j, index);
540               allpairs[counter].intIndex = index;
541               counter++;
542           }
543       std::sort(allpairs.begin(), allpairs.end(), myCompare);
544     } else if (i.nInts == 3) {
545       CkPrintf("3D %d:%d:%d\n", amaps[idx]->_nelems.data()[0], amaps[idx]->_nelems.data()[1], amaps[idx]->_nelems.data()[2]); 
546       int dims = 3;
547       int nDim0 = amaps[idx]->_nelems.data()[0];
548       int nDim1 = amaps[idx]->_nelems.data()[1];
549       int nDim2 = amaps[idx]->_nelems.data()[2];
550       int index;
551       int counter = 0;
552       allpairs.resize(nDim0*nDim1*nDim2);
553       for(int i=0; i<nDim0; i++)
554           for(int j=0; j<nDim1; j++)
555               for(int k=0; k<nDim2; k++)
556           {
557               allpairs[counter].coords.resize(3);
558               allpairs[counter].coords[0] = i;
559               allpairs[counter].coords[1] = j;
560               allpairs[counter].coords[2] = k;
561               index = Hilbert_to_int( allpairs[counter].coords, dims);
562               //CkPrintf("(%d:%d)----------> %d \n", i, j, index);
563               allpairs[counter].intIndex = index;
564               counter++;
565           }
566       std::sort(allpairs.begin(), allpairs.end(), myCompare);
567
568     }
569    
570     //for(int i=0; i<allpairs.size(); i++)
571     //    CkPrintf(" %d (%d:%d --- %d)\n ", i, allpairs[i].coords[0], allpairs[i].coords[1], allpairs[i].intIndex);
572
573     return idx;
574   }
575
576   int procNum(int arrayHdl, const CkArrayIndex &i) {
577     int flati = 0;
578     int myInt;
579     int dest;
580     if (amaps[arrayHdl]->_nelems.nInts == 0) {
581       return RRMap::procNum(arrayHdl, i);
582     }
583     if (i.nInts == 1) {
584       flati = i.data()[0];
585     } else if (i.nInts == 2) {
586         hilbert_pair mypair;
587         mypair.coords.resize(2);
588         mypair.coords[0] = i.data()[0];
589         mypair.coords[1] = i.data()[1];
590         myInt = Hilbert_to_int(mypair.coords, 2);
591         mypair.intIndex = myInt;
592         flati = std::distance(allpairs.begin(), std::find(allpairs.begin(), allpairs.end(), mypair));
593         //CkPrintf("(%d:%d) my realIndex is %d  %d \n", i.data()[0], i.data()[1], flati, myInt);
594     } else if (i.nInts == 3) {
595         hilbert_pair mypair;
596         mypair.coords.resize(3);
597         mypair.coords[0] = i.data()[0];
598         mypair.coords[1] = i.data()[1];
599         mypair.coords[2] = i.data()[2];
600         myInt = Hilbert_to_int(mypair.coords, 3);
601         mypair.intIndex = myInt;
602         flati = std::distance(allpairs.begin(), std::find(allpairs.begin(), allpairs.end(), mypair));
603         //CkPrintf("(%d:%d:%d) my realIndex is %d  %d \n", i.data()[0], i.data()[1], i.data()[2], flati, myInt);
604
605     }
606 #if CMK_ERROR_CHECKING
607     else {
608       CkAbort("CkArrayIndex has more than 3 integers!");
609     }
610 #endif
611
612     /** binSize used in DefaultArrayMap is the floor of numChares/numPes
613      *  but for this FastArrayMap, we need the ceiling */
614     getHilbertList(procList);
615     int block = flati / amaps[arrayHdl]->_binSizeCeil;
616     //for(int i=0; i<CkNumPes(); i++)
617     //    CkPrintf("(%d:%d) ", i, procList[i]);
618     //CkPrintf("\n");
619     //CkPrintf("block [%d:%d]\n", block, procList[block]);
620     return procList[block];
621   }
622
623   void pup(PUP::er& p){
624     DefaultArrayMap::pup(p);
625   }
626 };
627
628
629 /**
630  * This map can be used for topology aware mapping when the mapping is provided
631  * through a file -- ASB
632  */
633 class ReadFileMap : public DefaultArrayMap
634 {
635 private:
636   CkVec<int> mapping;
637
638 public:
639   ReadFileMap(void) {
640     DEBC((AA"Creating ReadFileMap\n"AB));
641   }
642
643   ReadFileMap(CkMigrateMessage *m) : DefaultArrayMap(m){}
644
645   int registerArray(const CkArrayIndex& numElements, CkArrayID aid)
646   {
647     int idx;
648     idx = DefaultArrayMap::registerArray(numElements, aid);
649
650     if(mapping.size() == 0) {
651       int numChares;
652
653       if (amaps[idx]->_nelems.nInts == 1) {
654         numChares = amaps[idx]->_nelems.data()[0];
655       } else if (amaps[idx]->_nelems.nInts == 2) {
656         numChares = amaps[idx]->_nelems.data()[0] * amaps[idx]->_nelems.data()[1];
657       } else if (amaps[idx]->_nelems.nInts == 3) {
658         numChares = amaps[idx]->_nelems.data()[0] * amaps[idx]->_nelems.data()[1] * amaps[idx]->_nelems.data()[2];
659       } else {
660         CkAbort("CkArrayIndex has more than 3 integers!");
661       }
662
663       mapping.resize(numChares);
664       FILE *mapf = fopen("mapfile", "r");
665       TopoManager tmgr;
666       int x, y, z, t;
667
668       for(int i=0; i<numChares; i++) {
669         (void) fscanf(mapf, "%d %d %d %d", &x, &y, &z, &t);
670         mapping[i] = tmgr.coordinatesToRank(x, y, z, t);
671       }
672       fclose(mapf);
673     }
674
675     return idx;
676   }
677
678   int procNum(int arrayHdl, const CkArrayIndex &i) {
679     int flati;
680
681     if (i.nInts == 1) {
682       flati = i.data()[0];
683     } else if (i.nInts == 2) {
684       flati = i.data()[0] * amaps[arrayHdl]->_nelems.data()[1] + i.data()[1];
685     } else if (i.nInts == 3) {
686       flati = (i.data()[0] * amaps[arrayHdl]->_nelems.data()[1] + i.data()[1]) * amaps[arrayHdl]->_nelems.data()[2] + i.data()[2];
687     } else {
688       CkAbort("CkArrayIndex has more than 3 integers!");
689     }
690
691     return mapping[flati];
692   }
693
694   void pup(PUP::er& p){
695     DefaultArrayMap::pup(p);
696     p|mapping;
697   }
698 };
699
700 class BlockMap : public RRMap
701 {
702 public:
703   BlockMap(void){
704         DEBC((AA"Creating BlockMap\n"AB));
705   }
706   BlockMap(CkMigrateMessage *m):RRMap(m){ }
707   void populateInitial(int arrayHdl,CkArrayIndex& numElements,void *ctorMsg,CkArrMgr *mgr){
708         if (numElements.nInts==0) {
709           CkFreeMsg(ctorMsg);
710           return;
711         }
712         int thisPe=CkMyPe();
713         int numPes=CkNumPes();
714         int binSize;
715         if (numElements.nInts == 1) {
716           binSize = (int)ceil((double)numElements.data()[0]/(double)numPes);
717         } else if (numElements.nInts == 2) {
718           binSize = (int)ceil((double)(numElements.data()[0]*numElements.data()[1])/(double)numPes);
719         } else if (numElements.nInts == 3) {
720           binSize = (int)ceil((double)(numElements.data()[0]*numElements.data()[1]*numElements.data()[2])/(double)numPes);
721         } else {
722           CkAbort("CkArrayIndex has more than 3 integers!");
723         }
724         CKARRAYMAP_POPULATE_INITIAL(i/binSize==thisPe);
725
726         /*
727         CkArrayIndex idx;
728         for (idx=numElements.begin(); idx<numElements; idx.getNext(numElements)) {
729           //for (int i=0;i<numElements;i++) {
730                 int binSize = (int)ceil((double)numElements.getCombinedCount()/(double)numPes);
731                 if (i/binSize==thisPe)
732                         mgr->insertInitial(idx,CkCopyMsg(&ctorMsg));
733         }*/
734         mgr->doneInserting();
735         CkFreeMsg(ctorMsg);
736   }
737 };
738
739 /**
740  * map object-- use seed load balancer.  
741  */
742 class CldMap : public CkArrayMap
743 {
744 public:
745   CldMap(void)
746   {
747           DEBC((AA"Creating CldMap\n"AB));
748   }
749   CldMap(CkMigrateMessage *m):CkArrayMap(m){}
750   int homePe(int /*arrayHdl*/, const CkArrayIndex &i)
751   {
752     if (i.nInts==1) {
753       //Map 1D integer indices in simple round-robin fashion
754       return (i.data()[0])%CkNumPes();
755     }
756     else 
757       {
758         //Map other indices based on their hash code, mod a big prime.
759         unsigned int hash=(i.hash()+739)%1280107;
760         return (hash % CkNumPes());
761       }
762   }
763   int procNum(int arrayHdl, const CkArrayIndex &i)
764   {
765      return CLD_ANYWHERE;   // -1
766   }
767   void populateInitial(int arrayHdl,CkArrayIndex& numElements,void *ctorMsg,CkArrMgr *mgr)  {
768         if (numElements.nInts==0) {
769           CkFreeMsg(ctorMsg);
770           return;
771         }
772         int thisPe=CkMyPe();
773         int numPes=CkNumPes();
774         //CkArrayIndex idx;
775
776         CKARRAYMAP_POPULATE_INITIAL(i%numPes==thisPe);
777         /*for (idx=numElements.begin(); idx<numElements; idx.getNext(numElements)) {
778           //for (int i=0;i<numElements;i++)
779                         if((idx.getRank(numElements))%numPes==thisPe)
780                                 mgr->insertInitial(CkArrayIndex1D(i),CkCopyMsg(&ctorMsg),0);
781         }*/
782         mgr->doneInserting();
783         CkFreeMsg(ctorMsg);
784   }
785
786 };
787
788
789 /// A class responsible for parsing the command line arguments for the PE
790 /// to extract the format string passed in with +ConfigurableRRMap
791 class ConfigurableRRMapLoader {
792 public:
793   
794   int *locations;
795   int objs_per_block;
796   int PE_per_block;
797
798   /// labels for states used when parsing the ConfigurableRRMap from ARGV
799   enum ConfigurableRRMapLoadStatus{
800     not_loaded,
801     loaded_found,
802     loaded_not_found
803   };
804   
805   enum ConfigurableRRMapLoadStatus state;
806   
807   ConfigurableRRMapLoader(){
808     state = not_loaded;
809     locations = NULL;
810     objs_per_block = 0;
811     PE_per_block = 0;
812   }
813   
814   /// load configuration if possible, and return whether a valid configuration exists
815   bool haveConfiguration() {
816     if(state == not_loaded) {
817       DEBUG(("[%d] loading ConfigurableRRMap configuration\n", CkMyPe()));
818       char **argv=CkGetArgv();
819       char *configuration = NULL;
820       bool found = CmiGetArgString(argv, "+ConfigurableRRMap", &configuration);
821       if(!found){
822         DEBUG(("Couldn't find +ConfigurableRRMap command line argument\n"));
823         state = loaded_not_found;
824         return false;
825       } else {
826
827         DEBUG(("Found +ConfigurableRRMap command line argument in %p=\"%s\"\n", configuration, configuration));
828
829         std::istringstream instream(configuration);
830         CkAssert(instream.good());
831          
832         // Example line:
833         // 10 8 0 1 2 3 4 5 6 7 7 7 7
834         // Map 10 objects to 8 PEs, with each object's index among the 8 PEs.
835         
836         // extract first integer
837         instream >> objs_per_block >> PE_per_block;
838         CkAssert(instream.good());
839         CkAssert(objs_per_block > 0);
840         CkAssert(PE_per_block > 0);
841         locations = new int[objs_per_block];
842         for(int i=0;i<objs_per_block;i++){
843           locations[i] = 0;
844           CkAssert(instream.good());
845           instream >> locations[i];
846           CkAssert(locations[i] < PE_per_block);
847         }
848         state = loaded_found;
849         return true;
850       }
851
852     } else {
853       DEBUG(("[%d] ConfigurableRRMap has already been loaded\n", CkMyPe()));
854       return state == loaded_found;
855     }      
856      
857   }
858   
859 };
860
861 CkpvDeclare(ConfigurableRRMapLoader, myConfigRRMapState);
862
863 void _initConfigurableRRMap(){
864   CkpvInitialize(ConfigurableRRMapLoader, myConfigRRMapState);
865 }
866
867
868 /// Try to load the command line arguments for ConfigurableRRMap
869 bool haveConfigurableRRMap(){
870   DEBUG(("haveConfigurableRRMap()\n"));
871   ConfigurableRRMapLoader &loader =  CkpvAccess(myConfigRRMapState);
872   return loader.haveConfiguration();
873 }
874
875 class ConfigurableRRMap : public RRMap
876 {
877 public:
878   ConfigurableRRMap(void){
879         DEBC((AA"Creating ConfigurableRRMap\n"AB));
880   }
881   ConfigurableRRMap(CkMigrateMessage *m):RRMap(m){ }
882
883
884   void populateInitial(int arrayHdl,CkArrayIndex& numElements,void *ctorMsg,CkArrMgr *mgr){
885     // Try to load the configuration from command line argument
886     CkAssert(haveConfigurableRRMap());
887     ConfigurableRRMapLoader &loader =  CkpvAccess(myConfigRRMapState);
888     if (numElements.nInts==0) {
889       CkFreeMsg(ctorMsg);
890       return;
891     }
892     int thisPe=CkMyPe();
893     int maxIndex = numElements.data()[0];
894     DEBUG(("[%d] ConfigurableRRMap: index=%d,%d,%d\n", CkMyPe(),(int)numElements.data()[0], (int)numElements.data()[1], (int)numElements.data()[2]));
895
896     if (numElements.nInts != 1) {
897       CkAbort("ConfigurableRRMap only supports dimension 1!");
898     }
899         
900     for (int index=0; index<maxIndex; index++) {        
901       CkArrayIndex1D idx(index);                
902       
903       int cyclic_block = index / loader.objs_per_block;
904       int cyclic_local = index % loader.objs_per_block;
905       int l = loader.locations[ cyclic_local ];
906       int PE = (cyclic_block*loader.PE_per_block + l) % CkNumPes();
907
908       DEBUG(("[%d] ConfigurableRRMap: index=%d is located on PE %d l=%d\n", CkMyPe(), (int)index, (int)PE, l));
909
910       if(PE == thisPe)
911         mgr->insertInitial(idx,CkCopyMsg(&ctorMsg));
912
913     }
914     //        CKARRAYMAP_POPULATE_INITIAL(PE == thisPe);
915         
916     mgr->doneInserting();
917     CkFreeMsg(ctorMsg);
918   }
919 };
920
921
922 CkpvStaticDeclare(double*, rem);
923
924 class arrInfo {
925  private:
926    CkArrayIndex _nelems;
927    int *_map;
928    void distrib(int *speeds);
929  public:
930    arrInfo(void):_map(NULL){}
931    arrInfo(const CkArrayIndex& n, int *speeds)
932    {
933      _nelems = n;
934      _map = new int[_nelems.getCombinedCount()];
935      distrib(speeds);
936    }
937    ~arrInfo() { delete[] _map; }
938    int getMap(const CkArrayIndex &i);
939    void pup(PUP::er& p){
940      p|_nelems;
941      int totalElements = _nelems.getCombinedCount();
942      if(p.isUnpacking()){
943        _map = new int[totalElements];
944      }
945      p(_map,totalElements);
946    }
947 };
948
949 static int cmp(const void *first, const void *second)
950 {
951   int fi = *((const int *)first);
952   int si = *((const int *)second);
953   return ((CkpvAccess(rem)[fi]==CkpvAccess(rem)[si]) ?
954           0 :
955           ((CkpvAccess(rem)[fi]<CkpvAccess(rem)[si]) ?
956           1 : (-1)));
957 }
958
959 void
960 arrInfo::distrib(int *speeds)
961 {
962   int _nelemsCount = _nelems.getCombinedCount();
963   double total = 0.0;
964   int npes = CkNumPes();
965   int i,j,k;
966   for(i=0;i<npes;i++)
967     total += (double) speeds[i];
968   double *nspeeds = new double[npes];
969   for(i=0;i<npes;i++)
970     nspeeds[i] = (double) speeds[i] / total;
971   int *cp = new int[npes];
972   for(i=0;i<npes;i++)
973     cp[i] = (int) (nspeeds[i]*_nelemsCount);
974   int nr = 0;
975   for(i=0;i<npes;i++)
976     nr += cp[i];
977   nr = _nelemsCount - nr;
978   if(nr != 0)
979   {
980     CkpvAccess(rem) = new double[npes];
981     for(i=0;i<npes;i++)
982       CkpvAccess(rem)[i] = (double)_nelemsCount*nspeeds[i] - cp[i];
983     int *pes = new int[npes];
984     for(i=0;i<npes;i++)
985       pes[i] = i;
986     qsort(pes, npes, sizeof(int), cmp);
987     for(i=0;i<nr;i++)
988       cp[pes[i]]++;
989     delete[] pes;
990     delete[] CkpvAccess(rem);
991   }
992   k = 0;
993   for(i=0;i<npes;i++)
994   {
995     for(j=0;j<cp[i];j++)
996       _map[k++] = i;
997   }
998   delete[] cp;
999   delete[] nspeeds;
1000 }
1001
1002 int
1003 arrInfo::getMap(const CkArrayIndex &i)
1004 {
1005   if(i.nInts==1)
1006     return _map[i.data()[0]];
1007   else
1008     return _map[((i.hash()+739)%1280107)%_nelems.getCombinedCount()];
1009 }
1010
1011 //Speeds maps processor number to "speed" (some sort of iterations per second counter)
1012 // It is initialized by processor 0.
1013 static int* speeds;
1014
1015 #if CMK_USE_PROP_MAP
1016 typedef struct _speedmsg
1017 {
1018   char hdr[CmiMsgHeaderSizeBytes];
1019   int node;
1020   int speed;
1021 } speedMsg;
1022
1023 static void _speedHdlr(void *m)
1024 {
1025   speedMsg *msg=(speedMsg *)m;
1026   if (CmiMyRank()==0)
1027     for (int pe=0;pe<CmiNodeSize(msg->node);pe++)
1028       speeds[CmiNodeFirst(msg->node)+pe] = msg->speed;  
1029   CmiFree(m);
1030 }
1031
1032 // initnode call
1033 void _propMapInit(void)
1034 {
1035   speeds = new int[CkNumPes()];
1036   int hdlr = CkRegisterHandler((CmiHandler)_speedHdlr);
1037   CmiPrintf("[%d]Measuring processor speed for prop. mapping...\n", CkMyPe());
1038   int s = LDProcessorSpeed();
1039   speedMsg msg;
1040   CmiSetHandler(&msg, hdlr);
1041   msg.node = CkMyNode();
1042   msg.speed = s;
1043   CmiSyncBroadcastAllAndFree(sizeof(msg), &msg);
1044   for(int i=0;i<CkNumNodes();i++)
1045     CmiDeliverSpecificMsg(hdlr);
1046 }
1047 #else
1048 void _propMapInit(void)
1049 {
1050   speeds = new int[CkNumPes()];
1051   int i;
1052   for(i=0;i<CkNumPes();i++)
1053     speeds[i] = 1;
1054 }
1055 #endif
1056 /**
1057  * A proportional map object-- tries to map more objects to
1058  * faster processors and fewer to slower processors.  Also
1059  * attempts to ensure good locality by mapping nearby elements
1060  * together.
1061  */
1062 class PropMap : public CkArrayMap
1063 {
1064 private:
1065   CkPupPtrVec<arrInfo> arrs;
1066 public:
1067   PropMap(void)
1068   {
1069     CkpvInitialize(double*, rem);
1070     DEBC((AA"Creating PropMap\n"AB));
1071   }
1072   PropMap(CkMigrateMessage *m) {}
1073   int registerArray(const CkArrayIndex& numElements, CkArrayID aid)
1074   {
1075     int idx = arrs.size();
1076     arrs.resize(idx+1);
1077     arrs[idx] = new arrInfo(numElements, speeds);
1078     return idx;
1079   }
1080   void unregisterArray(int idx)
1081   {
1082     arrs[idx].destroy();
1083   }
1084   int procNum(int arrayHdl, const CkArrayIndex &i)
1085   {
1086     return arrs[arrayHdl]->getMap(i);
1087   }
1088   void pup(PUP::er& p){
1089     p|arrs;
1090   }
1091 };
1092
1093 class CkMapsInit : public Chare
1094 {
1095 public:
1096         CkMapsInit(CkArgMsg *msg) {
1097                 //_defaultArrayMapID = CProxy_HilbertArrayMap::ckNew();
1098                 _defaultArrayMapID = CProxy_DefaultArrayMap::ckNew();
1099                 _fastArrayMapID = CProxy_FastArrayMap::ckNew();
1100                 delete msg;
1101         }
1102
1103         CkMapsInit(CkMigrateMessage *m) {}
1104 };
1105
1106 // given an envelope of a Charm msg, find the recipient object pointer
1107 CkMigratable * CkArrayMessageObjectPtr(envelope *env) {
1108   if (env->getMsgtype() != ForArrayEltMsg && env->getMsgtype() != ForIDedObjMsg)
1109       return NULL;   // not an array msg
1110
1111   ///@todo: Delegate this to the array manager which can then deal with ForArrayEltMsg or ForIDedObjMsg
1112   CkArrayID aid = env->getArrayMgr();
1113   CkArray *mgr=(CkArray *)_localBranch(aid);
1114   if (mgr) {
1115     CkLocMgr *locMgr = mgr->getLocMgr();
1116     if (locMgr) {
1117       return locMgr->lookup(env->getsetArrayIndex(),aid);
1118     }
1119   }
1120   return NULL;
1121 }
1122
1123 /****************************** Out-of-Core support ********************/
1124
1125 #if CMK_OUT_OF_CORE
1126 CooPrefetchManager CkArrayElementPrefetcher;
1127 CkpvDeclare(int,CkSaveRestorePrefetch);
1128
1129 /**
1130  * Return the out-of-core objid (from CooRegisterObject)
1131  * that this Converse message will access.  If the message
1132  * will not access an object, return -1.
1133  */
1134 int CkArrayPrefetch_msg2ObjId(void *msg) {
1135   envelope *env=(envelope *)msg;
1136   CkMigratable *elt = CkArrayMessageObjectPtr(env);
1137   return elt?elt->prefetchObjID:-1;
1138 }
1139
1140 /**
1141  * Write this object (registered with RegisterObject)
1142  * to this writable file.
1143  */
1144 void CkArrayPrefetch_writeToSwap(FILE *swapfile,void *objptr) {
1145   CkMigratable *elt=(CkMigratable *)objptr;
1146
1147   //Save the element's data to disk:
1148   PUP::toDisk p(swapfile);
1149   elt->pup(p);
1150
1151   //Call the element's destructor in-place (so pointer doesn't change)
1152   CkpvAccess(CkSaveRestorePrefetch)=1;
1153   elt->~CkMigratable(); //< because destuctor is virtual, destroys user class too.
1154   CkpvAccess(CkSaveRestorePrefetch)=0;
1155 }
1156         
1157 /**
1158  * Read this object (registered with RegisterObject)
1159  * from this readable file.
1160  */
1161 void CkArrayPrefetch_readFromSwap(FILE *swapfile,void *objptr) {
1162   CkMigratable *elt=(CkMigratable *)objptr;
1163   //Call the element's migration constructor in-place
1164   CkpvAccess(CkSaveRestorePrefetch)=1;
1165   int ctorIdx=_chareTable[elt->thisChareType]->migCtor;
1166   elt->myRec->invokeEntry(elt,(CkMigrateMessage *)0,ctorIdx,true);
1167   CkpvAccess(CkSaveRestorePrefetch)=0;
1168   
1169   //Restore the element's data from disk:
1170   PUP::fromDisk p(swapfile);
1171   elt->pup(p);
1172 }
1173
1174 static void _CkMigratable_prefetchInit(void) 
1175 {
1176   CkpvExtern(int,CkSaveRestorePrefetch);
1177   CkpvAccess(CkSaveRestorePrefetch)=0;
1178   CkArrayElementPrefetcher.msg2ObjId=CkArrayPrefetch_msg2ObjId;
1179   CkArrayElementPrefetcher.writeToSwap=CkArrayPrefetch_writeToSwap;
1180   CkArrayElementPrefetcher.readFromSwap=CkArrayPrefetch_readFromSwap;
1181   CooRegisterManager(&CkArrayElementPrefetcher, _charmHandlerIdx);
1182 }
1183 #endif
1184
1185 /****************************** CkMigratable ***************************/
1186 /**
1187  * This tiny class is used to convey information to the 
1188  * newly created CkMigratable object when its constructor is called.
1189  */
1190 class CkMigratable_initInfo {
1191 public:
1192         CkLocRec_local *locRec;
1193         int chareType;
1194         bool forPrefetch; /* If true, this creation is only a prefetch restore-from-disk.*/
1195 };
1196
1197 CkpvStaticDeclare(CkMigratable_initInfo,mig_initInfo);
1198
1199
1200 void _CkMigratable_initInfoInit(void) {
1201   CkpvInitialize(CkMigratable_initInfo,mig_initInfo);
1202 #if CMK_OUT_OF_CORE
1203   _CkMigratable_prefetchInit();
1204 #endif
1205 }
1206
1207 void CkMigratable::commonInit(void) {
1208         CkMigratable_initInfo &i=CkpvAccess(mig_initInfo);
1209 #if CMK_OUT_OF_CORE
1210         isInCore=true;
1211         if (CkpvAccess(CkSaveRestorePrefetch))
1212                 return; /* Just restoring from disk--don't touch object */
1213         prefetchObjID=-1; //Unregistered
1214 #endif
1215         myRec=i.locRec;
1216         thisIndexMax=myRec->getIndex();
1217         thisChareType=i.chareType;
1218         usesAtSync=false;
1219         usesAutoMeasure=true;
1220         barrierRegistered=false;
1221
1222   local_state = OFF;
1223   prev_load = 0.0;
1224   can_reset = false;
1225
1226 #if CMK_LBDB_ON
1227   if (_lb_args.metaLbOn()) {
1228     atsync_iteration = myRec->getMetaBalancer()->get_iteration();
1229   }
1230 #endif
1231
1232         /*
1233         FAULT_EVAC
1234         */
1235         AsyncEvacuate(true);
1236 }
1237
1238 CkMigratable::CkMigratable(void) {
1239         DEBC((AA"In CkMigratable constructor\n"AB));
1240         commonInit();
1241 }
1242 CkMigratable::CkMigratable(CkMigrateMessage *m): Chare(m) {
1243         commonInit();
1244 }
1245
1246 int CkMigratable::ckGetChareType(void) const {return thisChareType;}
1247
1248 void CkMigratable::pup(PUP::er &p) {
1249         DEBM((AA"In CkMigratable::pup %s\n"AB,idx2str(thisIndexMax)));
1250         Chare::pup(p);
1251         p|thisIndexMax;
1252         p(usesAtSync);
1253   p(can_reset);
1254         p(usesAutoMeasure);
1255 #if CMK_LBDB_ON 
1256         int readyMigrate = 0;
1257         if (p.isPacking()) readyMigrate = myRec->isReadyMigrate();
1258         p|readyMigrate;
1259         if (p.isUnpacking()) myRec->ReadyMigrate(readyMigrate);
1260 #endif
1261         if(p.isUnpacking()) barrierRegistered=false;
1262         /*
1263                 FAULT_EVAC
1264         */
1265         p | asyncEvacuate;
1266         if(p.isUnpacking()){myRec->AsyncEvacuate(asyncEvacuate);}
1267         
1268         ckFinishConstruction();
1269 }
1270
1271 void CkMigratable::ckDestroy(void) {
1272         DEBC((AA"In CkMigratable::ckDestroy %s\n"AB,idx2str(thisIndexMax)));
1273         myRec->destroy();
1274 }
1275
1276 void CkMigratable::ckAboutToMigrate(void) { }
1277 void CkMigratable::ckJustMigrated(void) { }
1278 void CkMigratable::ckJustRestored(void) { }
1279
1280 CkMigratable::~CkMigratable() {
1281         DEBC((AA"In CkMigratable::~CkMigratable %s\n"AB,idx2str(thisIndexMax)));
1282 #if CMK_OUT_OF_CORE
1283         isInCore=false;
1284         if (CkpvAccess(CkSaveRestorePrefetch)) 
1285                 return; /* Just saving to disk--don't deregister anything. */
1286         /* We're really leaving or dying-- unregister from the ooc system*/
1287         if (prefetchObjID!=-1) {
1288                 CooDeregisterObject(prefetchObjID);
1289                 prefetchObjID=-1;
1290         }
1291 #endif
1292         /*Might want to tell myRec about our doom here--
1293         it's difficult to avoid some kind of circular-delete, though.
1294         */
1295 #if CMK_LBDB_ON 
1296         if (barrierRegistered) {
1297           DEBL((AA"Removing barrier for element %s\n"AB,idx2str(thisIndexMax)));
1298           if (usesAtSync)
1299                 myRec->getLBDB()->RemoveLocalBarrierClient(ldBarrierHandle);
1300           else
1301                 myRec->getLBDB()->RemoveLocalBarrierReceiver(ldBarrierRecvHandle);
1302         }
1303 #endif
1304         //To detect use-after-delete
1305         thisIndexMax.nInts=-12345;
1306         thisIndexMax.dimension=-12345;
1307 }
1308
1309 void CkMigratable::CkAbort(const char *why) const {
1310         CkError("CkMigratable '%s' aborting:\n",_chareTable[thisChareType]->name);
1311         ::CkAbort(why);
1312 }
1313
1314 void CkMigratable::ResumeFromSync(void)
1315 {
1316 //      CkAbort("::ResumeFromSync() not defined for this array element!\n");
1317 }
1318
1319 void CkMigratable::UserSetLBLoad() {
1320         CkAbort("::UserSetLBLoad() not defined for this array element!\n");
1321 }
1322
1323 #if CMK_LBDB_ON  //For load balancing:
1324 // user can call this helper function to set obj load (for model-based lb)
1325 void CkMigratable::setObjTime(double cputime) {
1326         myRec->setObjTime(cputime);
1327 }
1328 double CkMigratable::getObjTime() {
1329         return myRec->getObjTime();
1330 }
1331
1332 void CkMigratable::clearMetaLBData() {
1333 //  if (can_reset) {
1334     local_state = OFF;
1335     atsync_iteration = -1;
1336     prev_load = 0.0;
1337     can_reset = false;
1338 //  }
1339 }
1340
1341 void CkMigratable::recvLBPeriod(void *data) {
1342   if (atsync_iteration < 0) {
1343     return;
1344   }
1345   int lb_period = *((int *) data);
1346  DEBAD(("\t[obj %s] Received the LB Period %d current iter %d state %d on PE %d\n",
1347      idx2str(thisIndexMax), lb_period, atsync_iteration, local_state, CkMyPe()));
1348
1349   bool is_tentative;
1350   if (local_state == LOAD_BALANCE) {
1351     CkAssert(lb_period == myRec->getMetaBalancer()->getPredictedLBPeriod(is_tentative));
1352     return;
1353   }
1354
1355   if (local_state == PAUSE) {
1356     if (atsync_iteration < lb_period) {
1357       local_state = DECIDED;
1358       ResumeFromSync();
1359       return;
1360     }
1361     local_state = LOAD_BALANCE;
1362
1363     can_reset = true;
1364     //myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
1365     return;
1366   }
1367   local_state = DECIDED;
1368 }
1369
1370 void CkMigratable::metaLBCallLB() {
1371         myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
1372 }
1373
1374 void CkMigratable::ckFinishConstruction(void)
1375 {
1376 //      if ((!usesAtSync) || barrierRegistered) return;
1377         myRec->setMeasure(usesAutoMeasure);
1378         if (barrierRegistered) return;
1379         DEBL((AA"Registering barrier client for %s\n"AB,idx2str(thisIndexMax)));
1380         if (usesAtSync)
1381           ldBarrierHandle = myRec->getLBDB()->AddLocalBarrierClient(
1382                 (LDBarrierFn)staticResumeFromSync,(void*)(this));
1383         else
1384           ldBarrierRecvHandle = myRec->getLBDB()->AddLocalBarrierReceiver(
1385                 (LDBarrierFn)staticResumeFromSync,(void*)(this));
1386         barrierRegistered=true;
1387 }
1388
1389 void CkMigratable::AtSync(int waitForMigration)
1390 {
1391         if (!usesAtSync)
1392                 CkAbort("You must set usesAtSync=true in your array element constructor to use AtSync!\n");
1393 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1394         mlogData->toResumeOrNot=1;
1395 #endif
1396         myRec->AsyncMigrate(!waitForMigration);
1397         if (waitForMigration) ReadyMigrate(true);
1398         ckFinishConstruction();
1399   DEBL((AA"Element %s going to sync\n"AB,idx2str(thisIndexMax)));
1400   // model-based load balancing, ask user to provide cpu load
1401   if (usesAutoMeasure == false) UserSetLBLoad();
1402
1403   if (!_lb_args.metaLbOn()) {
1404     myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
1405     return;
1406   }
1407
1408   // When MetaBalancer is turned on
1409
1410   if (atsync_iteration == -1) {
1411     can_reset = false;
1412     local_state = OFF;
1413     prev_load = 0.0;
1414   }
1415
1416   atsync_iteration++;
1417   //CkPrintf("[pe %s] atsync_iter %d && predicted period %d state: %d\n",
1418   //    idx2str(thisIndexMax), atsync_iteration,
1419   //    myRec->getMetaBalancer()->getPredictedLBPeriod(), local_state);
1420   double tmp = prev_load;
1421   prev_load = myRec->getObjTime();
1422   double current_load = prev_load - tmp;
1423   if (atsync_iteration <= myRec->getMetaBalancer()->get_finished_iteration()) {
1424     CkPrintf("[%d:%s] Error!! Contributing to iter %d < current iter %d\n",
1425       CkMyPe(), idx2str(thisIndexMax), atsync_iteration,
1426       myRec->getMetaBalancer()->get_finished_iteration());
1427     CkAbort("Not contributing to the right iteration\n");
1428   }
1429
1430   if (atsync_iteration != 0) {
1431     myRec->getMetaBalancer()->AddLoad(atsync_iteration, current_load);
1432   }
1433
1434   bool is_tentative;
1435   if (atsync_iteration < myRec->getMetaBalancer()->getPredictedLBPeriod(is_tentative)) {
1436     ResumeFromSync();
1437   } else if (is_tentative) {
1438     local_state = PAUSE;
1439   } else if (local_state == DECIDED) {
1440     DEBAD(("[%d:%s] Went to load balance iter %d\n", CkMyPe(), idx2str(thisIndexMax), atsync_iteration));
1441     local_state = LOAD_BALANCE;
1442     can_reset = true;
1443     //myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
1444   } else {
1445     DEBAD(("[%d:%s] Went to pause state iter %d\n", CkMyPe(), idx2str(thisIndexMax), atsync_iteration));
1446     local_state = PAUSE;
1447   }
1448 }
1449
1450 void CkMigratable::ReadyMigrate(bool ready)
1451 {
1452         myRec->ReadyMigrate(ready);
1453 }
1454
1455 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1456     extern int globalResumeCount;
1457 #endif
1458
1459 void CkMigratable::staticResumeFromSync(void* data)
1460 {
1461         CkMigratable *el=(CkMigratable *)data;
1462 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1463     if(el->mlogData->toResumeOrNot ==0 || el->mlogData->resumeCount >= globalResumeCount){
1464         return;
1465     }
1466 #endif
1467         DEBL((AA"Element %s resuming from sync\n"AB,idx2str(el->thisIndexMax)));
1468 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1469     CpvAccess(_currentObj) = el;
1470 #endif
1471
1472   if (_lb_args.metaLbOn()) {
1473         el->clearMetaLBData();
1474         }
1475         el->ResumeFromSync();
1476 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1477     el->mlogData->resumeCount++;
1478 #endif
1479 }
1480 void CkMigratable::setMigratable(int migratable) 
1481 {
1482         myRec->setMigratable(migratable);
1483 }
1484
1485 struct CkArrayThreadListener {
1486         struct CthThreadListener base;
1487         CkMigratable *mig;
1488 };
1489
1490 extern "C"
1491 void CkArrayThreadListener_suspend(struct CthThreadListener *l)
1492 {
1493         CkArrayThreadListener *a=(CkArrayThreadListener *)l;
1494         a->mig->ckStopTiming();
1495 }
1496
1497 extern "C"
1498 void CkArrayThreadListener_resume(struct CthThreadListener *l)
1499 {
1500         CkArrayThreadListener *a=(CkArrayThreadListener *)l;
1501         a->mig->ckStartTiming();
1502 }
1503
1504 extern "C"
1505 void CkArrayThreadListener_free(struct CthThreadListener *l)
1506 {
1507         CkArrayThreadListener *a=(CkArrayThreadListener *)l;
1508         delete a;
1509 }
1510
1511 void CkMigratable::CkAddThreadListeners(CthThread tid, void *msg)
1512 {
1513         Chare::CkAddThreadListeners(tid, msg);   // for trace
1514         CthSetThreadID(tid, thisIndexMax.data()[0], thisIndexMax.data()[1], 
1515                        thisIndexMax.data()[2]);
1516         CkArrayThreadListener *a=new CkArrayThreadListener;
1517         a->base.suspend=CkArrayThreadListener_suspend;
1518         a->base.resume=CkArrayThreadListener_resume;
1519         a->base.free=CkArrayThreadListener_free;
1520         a->mig=this;
1521         CthAddListener(tid,(struct CthThreadListener *)a);
1522 }
1523 #else
1524 void CkMigratable::setObjTime(double cputime) {}
1525 double CkMigratable::getObjTime() {return 0.0;}
1526
1527 /* no load balancer: need dummy implementations to prevent link error */
1528 void CkMigratable::CkAddThreadListeners(CthThread tid, void *msg)
1529 {
1530 }
1531 #endif
1532
1533
1534 /*CkMigratableList*/
1535 CkMigratableList::CkMigratableList() {}
1536 CkMigratableList::~CkMigratableList() {}
1537
1538 void CkMigratableList::setSize(int s) {
1539         el.resize(s);
1540 }
1541
1542 void CkMigratableList::put(CkMigratable *v,int atIdx) {
1543 #if CMK_ERROR_CHECKING
1544         if (atIdx>=length())
1545                 CkAbort("Internal array manager error (CkMigrableList::put index out of bounds)");
1546 #endif
1547         el[atIdx]=v;
1548 }
1549
1550
1551 /************************** Location Records: *********************************/
1552
1553 //---------------- Base type:
1554 void CkLocRec::weAreObsolete(const CkArrayIndex &idx) {}
1555 CkLocRec::~CkLocRec() { }
1556 void CkLocRec::beenReplaced(void)
1557     {/*Default: ignore replacement*/}
1558
1559 //Return the represented array element; or NULL if there is none
1560 CkMigratable *CkLocRec::lookupElement(CkArrayID aid) {return NULL;}
1561
1562 //Return the last known processor; or -1 if none
1563 int CkLocRec::lookupProcessor(void) {return -1;}
1564
1565
1566 /*----------------- Local:
1567 Matches up the array index with the local index, an
1568 interfaces with the load balancer on behalf of the
1569 represented array elements.
1570 */
1571 CkLocRec_local::CkLocRec_local(CkLocMgr *mgr,bool fromMigration,
1572   bool ignoreArrival, const CkArrayIndex &idx_,int localIdx_)
1573         :CkLocRec(mgr),idx(idx_),localIdx(localIdx_),
1574          running(false),deletedMarker(NULL)
1575 {
1576 #if CMK_LBDB_ON
1577         DEBL((AA"Registering element %s with load balancer\n"AB,idx2str(idx)));
1578         //BIGSIM_OOC DEBUGGING
1579         //CkPrintf("LocMgr on %d: Registering element %s with load balancer\n", CkMyPe(), idx2str(idx));
1580         nextPe = -1;
1581         asyncMigrate = false;
1582         readyMigrate = true;
1583         enable_measure = true;
1584         bounced  = false;
1585         the_lbdb=mgr->getLBDB();
1586         the_metalb=mgr->getMetaBalancer();
1587         LDObjid ldid = idx2LDObjid(idx);
1588 #if CMK_GLOBAL_LOCATION_UPDATE
1589         ldid.locMgrGid = mgr->getGroupID().idx;
1590 #endif        
1591         ldHandle=the_lbdb->RegisterObj(mgr->getOMHandle(),
1592                 ldid,(void *)this,1);
1593         if (fromMigration) {
1594                 DEBL((AA"Element %s migrated in\n"AB,idx2str(idx)));
1595                 if (!ignoreArrival)  {
1596                         the_lbdb->Migrated(ldHandle, true);
1597                   // load balancer should ignore this objects movement
1598                 //  AsyncMigrate(true);
1599                 }
1600         }
1601 #endif
1602         /*
1603                 FAULT_EVAC
1604         */
1605         asyncEvacuate = true;
1606 }
1607 CkLocRec_local::~CkLocRec_local()
1608 {
1609         if (deletedMarker!=NULL) *deletedMarker=true;
1610         myLocMgr->reclaim(idx,localIdx);
1611 #if CMK_LBDB_ON
1612         stopTiming();
1613         DEBL((AA"Unregistering element %s from load balancer\n"AB,idx2str(idx)));
1614         the_lbdb->UnregisterObj(ldHandle);
1615 #endif
1616 }
1617 void CkLocRec_local::migrateMe(int toPe) //Leaving this processor
1618 {
1619         //This will pack us up, send us off, and delete us
1620 //      printf("[%d] migrating migrateMe to %d \n",CkMyPe(),toPe);
1621         myLocMgr->emigrate(this,toPe);
1622 }
1623
1624 #if CMK_LBDB_ON
1625 void CkLocRec_local::informIdealLBPeriod(int lb_ideal_period) {
1626   myLocMgr->informLBPeriod(this, lb_ideal_period);
1627 }
1628
1629 void CkLocRec_local::metaLBCallLB() {
1630         myLocMgr->metaLBCallLB(this);
1631 }
1632
1633 void CkLocRec_local::startTiming(int ignore_running) {
1634         if (!ignore_running) running=true;
1635         DEBL((AA"Start timing for %s at %.3fs {\n"AB,idx2str(idx),CkWallTimer()));
1636         if (enable_measure) the_lbdb->ObjectStart(ldHandle);
1637 }
1638 void CkLocRec_local::stopTiming(int ignore_running) {
1639         DEBL((AA"} Stop timing for %s at %.3fs\n"AB,idx2str(idx),CkWallTimer()));
1640         if ((ignore_running || running) && enable_measure) the_lbdb->ObjectStop(ldHandle);
1641         if (!ignore_running) running=false;
1642 }
1643 void CkLocRec_local::setObjTime(double cputime) {
1644         the_lbdb->EstObjLoad(ldHandle, cputime);
1645 }
1646 double CkLocRec_local::getObjTime() {
1647         LBRealType walltime, cputime;
1648         the_lbdb->GetObjLoad(ldHandle, walltime, cputime);
1649         return walltime;
1650 }
1651 #endif
1652
1653 void CkLocRec_local::destroy(void) //User called destructor
1654 {
1655         //Our destructor does all the needed work
1656         delete this;
1657 }
1658 //Return the represented array element; or NULL if there is none
1659 CkMigratable *CkLocRec_local::lookupElement(CkArrayID aid) {
1660         return myLocMgr->lookupLocal(localIdx,aid);
1661 }
1662
1663 //Return the last known processor; or -1 if none
1664 int CkLocRec_local::lookupProcessor(void) {
1665         return CkMyPe();
1666 }
1667
1668 CkLocRec::RecType CkLocRec_local::type(void)
1669 {
1670         return local;
1671 }
1672
1673 void CkLocRec_local::addedElement(void) 
1674 {
1675         //Push everything in the half-created queue into the system--
1676         // anything not ready yet will be put back in.
1677         while (!halfCreated.isEmpty()) 
1678                 CkArrayManagerDeliver(CkMyPe(),halfCreated.deq());
1679 }
1680
1681 bool CkLocRec_local::isObsolete(int nSprings,const CkArrayIndex &idx_)
1682
1683         int len=halfCreated.length();
1684         if (len!=0) {
1685                 /* This is suspicious-- the halfCreated queue should be extremely
1686                  transient.  It's possible we just looked at the wrong time, though;
1687                  so this is only a warning. 
1688                 */
1689                 CkPrintf("CkLoc WARNING> %d messages still around for uncreated element %s!\n",
1690                          len,idx2str(idx));
1691         }
1692         //A local element never expires
1693         return false;
1694 }
1695
1696 /**********Added for cosmology (inline function handling without parameter marshalling)***********/
1697
1698 LDObjHandle CkMigratable::timingBeforeCall(int* objstopped){
1699         LDObjHandle objHandle;
1700 #if CMK_LBDB_ON
1701         if (getLBDB()->RunningObject(&objHandle)) {
1702                 *objstopped = 1;
1703                 getLBDB()->ObjectStop(objHandle);
1704         }
1705         myRec->startTiming(1);
1706 #endif
1707
1708   return objHandle;
1709 }
1710
1711 void CkMigratable::timingAfterCall(LDObjHandle objHandle,int *objstopped){
1712         myRec->stopTiming(1);
1713 #if CMK_LBDB_ON
1714         if (*objstopped) {
1715                  getLBDB()->ObjectStart(objHandle);
1716         }
1717 #endif
1718
1719  return;
1720 }
1721 /****************************************************************************/
1722
1723
1724 bool CkLocRec_local::invokeEntry(CkMigratable *obj,void *msg,
1725         int epIdx,bool doFree) 
1726 {
1727
1728         DEBS((AA"   Invoking entry %d on element %s\n"AB,epIdx,idx2str(idx)));
1729         bool isDeleted=false; //Enables us to detect deletion during processing
1730         deletedMarker=&isDeleted;
1731         startTiming();
1732
1733
1734 #if CMK_TRACE_ENABLED
1735         if (msg) { /* Tracing: */
1736                 envelope *env=UsrToEnv(msg);
1737         //      CkPrintf("ckLocation.C beginExecuteDetailed %d %d \n",env->getEvent(),env->getsetArraySrcPe());
1738                 if (_entryTable[epIdx]->traceEnabled)
1739         {
1740             _TRACE_BEGIN_EXECUTE_DETAILED(env->getEvent(),
1741                                                       ForChareMsg,epIdx,env->getsetArraySrcPe(), env->getTotalsize(), idx.getProjectionID(env->getArrayMgrIdx()));
1742             if(_entryTable[epIdx]->appWork)
1743                 _TRACE_BEGIN_APPWORK();
1744         }
1745         }
1746 #endif
1747
1748         if (doFree) 
1749            CkDeliverMessageFree(epIdx,msg,obj);
1750         else /* !doFree */
1751            CkDeliverMessageReadonly(epIdx,msg,obj);
1752
1753
1754 #if CMK_TRACE_ENABLED
1755         if (msg) { /* Tracing: */
1756                 if (_entryTable[epIdx]->traceEnabled)
1757         {
1758             if(_entryTable[epIdx]->appWork)
1759                 _TRACE_END_APPWORK();
1760                         _TRACE_END_EXECUTE();
1761         }
1762         }
1763 #endif
1764 #if CMK_LBDB_ON
1765         if (!isDeleted) checkBufferedMigration();   // check if should migrate
1766 #endif
1767         if (isDeleted) return false;//We were deleted
1768         deletedMarker=NULL;
1769         stopTiming();
1770         return true;
1771 }
1772
1773 bool CkLocRec_local::deliver(CkArrayMessage *msg,CkDeliver_t type,int opts)
1774 {
1775
1776         if (type==CkDeliver_queue) { /*Send via the message queue */
1777                 if (opts & CK_MSG_KEEP)
1778                         msg = (CkArrayMessage *)CkCopyMsg((void **)&msg);
1779                 CkArrayManagerDeliver(CkMyPe(),msg,opts);
1780                 return true;
1781         }
1782         else
1783         {
1784                 CkMigratable *obj=myLocMgr->lookupLocal(localIdx,
1785                         UsrToEnv(msg)->getArrayMgr());
1786                 if (obj==NULL) {//That sibling of this object isn't created yet!
1787                         if (opts & CK_MSG_KEEP)
1788                                 msg = (CkArrayMessage *)CkCopyMsg((void **)&msg);
1789                         if (msg->array_ifNotThere()!=CkArray_IfNotThere_buffer) {
1790                                 return myLocMgr->demandCreateElement(msg,CkMyPe(),type);
1791                         }
1792                         else {
1793                                 DEBS((AA"   BUFFERING message for nonexistent element %s!\n"AB,idx2str(this->idx)));
1794                                 halfCreated.enq(msg);
1795                                 return true;
1796                         }
1797                 }
1798                         
1799                 if (msg->array_hops()>1)
1800                         myLocMgr->multiHop(msg);
1801                 bool doFree = (bool)!(opts & CK_MSG_KEEP);
1802 #if CMK_LBDB_ON
1803                 // if there is a running obj being measured, stop it temporarily
1804                 LDObjHandle objHandle;
1805                 int objstopped = 0;
1806                 if (the_lbdb->RunningObject(&objHandle)) {
1807                         objstopped = 1;
1808                         the_lbdb->ObjectStop(objHandle);
1809                 }
1810 #endif
1811 #if CMK_GRID_QUEUE_AVAILABLE
1812                 // retain a pointer to the sending object (needed later)
1813                 CpvAccess(CkGridObject) = obj;
1814 #endif
1815
1816         bool status = invokeEntry(obj,(void *)msg,msg->array_ep(),doFree);
1817         
1818 #if CMK_GRID_QUEUE_AVAILABLE
1819                 CpvAccess(CkGridObject) = NULL;
1820 #endif
1821 #if CMK_LBDB_ON
1822                 if (objstopped) the_lbdb->ObjectStart(objHandle);
1823 #endif
1824                 return status;
1825         }
1826
1827
1828 }
1829
1830 #if CMK_LBDB_ON
1831
1832 void CkLocRec_local::staticMetaLBResumeWaitingChares(LDObjHandle h, int lb_ideal_period) {
1833         CkLocRec_local *el=(CkLocRec_local *)LDObjUserData(h);
1834         DEBL((AA"MetaBalancer wants to resume waiting chare %s\n"AB,idx2str(el->idx)));
1835         el->metaLBResumeWaitingChares(lb_ideal_period);
1836 }
1837
1838 void CkLocRec_local::metaLBResumeWaitingChares(int lb_ideal_period) {
1839   informIdealLBPeriod(lb_ideal_period);
1840 }
1841
1842 void CkLocRec_local::staticMetaLBCallLBOnChares(LDObjHandle h) {
1843         CkLocRec_local *el=(CkLocRec_local *)LDObjUserData(h);
1844         DEBL((AA"MetaBalancer wants to call LoadBalance on chare %s\n"AB,idx2str(el->idx)));
1845         el->metaLBCallLBOnChares();
1846 }
1847
1848 void CkLocRec_local::metaLBCallLBOnChares() {
1849   metaLBCallLB();
1850 }
1851
1852 void CkLocRec_local::staticMigrate(LDObjHandle h, int dest)
1853 {
1854         CkLocRec_local *el=(CkLocRec_local *)LDObjUserData(h);
1855         DEBL((AA"Load balancer wants to migrate %s to %d\n"AB,idx2str(el->idx),dest));
1856         el->recvMigrate(dest);
1857 }
1858
1859 void CkLocRec_local::recvMigrate(int toPe)
1860 {
1861         // we are in the mode of delaying actual migration
1862         // till readyMigrate()
1863         if (readyMigrate) { migrateMe(toPe); }
1864         else nextPe = toPe;
1865 }
1866
1867 void CkLocRec_local::AsyncMigrate(bool use)  
1868 {
1869         asyncMigrate = use; 
1870         the_lbdb->UseAsyncMigrate(ldHandle, use);
1871 }
1872
1873 bool CkLocRec_local::checkBufferedMigration()
1874 {
1875         // we don't migrate in user's code when calling ReadyMigrate(true)
1876         // we postphone the action to here until we exit from the user code.
1877         if (readyMigrate && nextPe != -1) {
1878             int toPe = nextPe;
1879             nextPe = -1;
1880             // don't migrate inside the object call
1881             migrateMe(toPe);
1882             // don't do anything
1883             return true;
1884         }
1885         return false;
1886 }
1887
1888 int CkLocRec_local::MigrateToPe()
1889 {
1890         int pe = nextPe;
1891         nextPe = -1;
1892         return pe;
1893 }
1894
1895 void CkLocRec_local::setMigratable(int migratable)
1896 {
1897         if (migratable)
1898           the_lbdb->Migratable(ldHandle);
1899         else
1900           the_lbdb->NonMigratable(ldHandle);
1901 }
1902 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1903 void CkLocRec_local::Migrated(){
1904     the_lbdb->Migrated(ldHandle, true);
1905 }
1906 #endif
1907 #endif
1908
1909 /**
1910  * Represents a deleted array element (and prevents re-use).
1911  * These are a debugging aid, usable only by uncommenting a line in
1912  * the element destruction code.
1913  */
1914 class CkLocRec_dead:public CkLocRec {
1915 public:
1916         CkLocRec_dead(CkLocMgr *Narr):CkLocRec(Narr) {}
1917   
1918         virtual RecType type(void) {return dead;}
1919   
1920         virtual bool deliver(CkArrayMessage *msg,CkDeliver_t type,int opts=0) {
1921                 CkPrintf("Dead array element is %s.\n",idx2str(msg->array_index()));
1922                 CkAbort("Send to dead array element!\n");
1923                 return false;
1924         }
1925         virtual void beenReplaced(void) 
1926                 {CkAbort("Can't re-use dead array element!\n");}
1927   
1928         //Return if this element is now obsolete (it isn't)
1929         virtual bool isObsolete(int nSprings,const CkArrayIndex &idx) {return false;}   
1930 };
1931
1932 /**
1933  * This is the abstract superclass of arrayRecs that keep track of their age,
1934  * and eventually expire. Its kids are remote and buffering.
1935  */
1936 class CkLocRec_aging:public CkLocRec {
1937 private:
1938         int lastAccess;//Age when last accessed
1939 protected:
1940         //Update our access time
1941         inline void access(void) {
1942                 lastAccess=myLocMgr->getSpringCount();
1943         }
1944         //Return if we are "stale"-- we were last accessed a while ago
1945         bool isStale(void) {
1946                 if (myLocMgr->getSpringCount()-lastAccess>3) return true;
1947                 else return false;
1948         }
1949 public:
1950         CkLocRec_aging(CkLocMgr *Narr):CkLocRec(Narr) {
1951                 lastAccess=myLocMgr->getSpringCount();
1952         }
1953         //Return if this element is now obsolete
1954         virtual bool isObsolete(int nSprings,const CkArrayIndex &idx)=0;
1955         //virtual void pup(PUP::er &p) { CkLocRec::pup(p); p(lastAccess); }
1956 };
1957
1958
1959 /**
1960  * Represents a remote array element.  This is just a PE number.
1961  */
1962 class CkLocRec_remote:public CkLocRec_aging {
1963 private:
1964         int onPe;//The last known Pe for this element
1965 public:
1966         CkLocRec_remote(CkLocMgr *Narr,int NonPe)
1967                 :CkLocRec_aging(Narr)
1968                 {
1969                         onPe=NonPe;
1970 #if CMK_ERROR_CHECKING
1971                         if (onPe==CkMyPe())
1972                                 CkAbort("ERROR!  'remote' array element on this Pe!\n");
1973 #endif
1974                 }
1975         //Return the last known processor for this element
1976         int lookupProcessor(void) {
1977                 return onPe;
1978         }  
1979         virtual RecType type(void) {return remote;}
1980   
1981         //Send a message for this element.
1982         virtual bool deliver(CkArrayMessage *msg,CkDeliver_t type,int opts=0) {
1983                 /*FAULT_EVAC*/
1984                 int destPE = onPe;
1985                 if((!CmiNodeAlive(onPe) && onPe != allowMessagesOnly)){
1986 //                      printf("Delivery failed because process %d is invalid\n",onPe);
1987                         /*
1988                                 Send it to its home processor instead
1989                         */
1990                         const CkArrayIndex &idx=msg->array_index();
1991                         destPE = getNextPE(idx);
1992                 }
1993                 access();//Update our modification date
1994                 msg->array_hops()++;
1995                 DEBS((AA"   Forwarding message for element %s to %d (REMOTE)\n"AB,
1996                       idx2str(msg->array_index()),destPE));
1997                 if (opts & CK_MSG_KEEP)
1998                         msg = (CkArrayMessage *)CkCopyMsg((void **)&msg);
1999                 CkArrayManagerDeliver(destPE,msg,opts);
2000                 return true;
2001         }
2002         //Return if this element is now obsolete
2003         virtual bool isObsolete(int nSprings,const CkArrayIndex &idx) {
2004                 if (myLocMgr->isHome(idx)) 
2005                         //Home elements never become obsolete
2006                         // if they did, we couldn't deliver messages to that element.
2007                         return false;
2008                 else if (isStale())
2009                         return true;//We haven't been used in a long time
2010                 else
2011                         return false;//We're fairly recent
2012         }
2013         //virtual void pup(PUP::er &p) { CkLocRec_aging::pup(p); p(onPe); }
2014 };
2015
2016
2017 /**
2018  * Buffers messages until record is replaced in the hash table, 
2019  * then delivers all messages to the replacing record.  This is 
2020  * used when a message arrives for a local element that has not
2021  * yet been created, buffering messages until the new element finally
2022  * checks in.
2023  *
2024  * It's silly to send a message to an element you won't ever create,
2025  * so this kind of record causes an abort "Stale array manager message!"
2026  * if it's left undelivered too long.
2027  */
2028 class CkLocRec_buffering:public CkLocRec_aging {
2029 private:
2030         CkQ<CkArrayMessage *> buffer;//Buffered messages.
2031 public:
2032         CkLocRec_buffering(CkLocMgr *Narr):CkLocRec_aging(Narr) {}
2033         virtual ~CkLocRec_buffering() {
2034                 if (0!=buffer.length()) {
2035                         CkPrintf("[%d] Warning: Messages abandoned in array manager buffer!\n", CkMyPe());
2036                         CkArrayMessage *m;
2037                         while (NULL!=(m=buffer.deq()))  {
2038                                 delete m;
2039                         }
2040                 }
2041         }
2042   
2043         virtual RecType type(void) {return buffering;}
2044   
2045         //Buffer a message for this element.
2046         virtual bool deliver(CkArrayMessage *msg,CkDeliver_t type,int opts=0) {
2047                 DEBS((AA" Queued message for %s\n"AB,idx2str(msg->array_index())));
2048                 if (opts & CK_MSG_KEEP)
2049                         msg = (CkArrayMessage *)CkCopyMsg((void **)&msg);
2050                 buffer.enq(msg);
2051 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2052                 envelope *env = UsrToEnv(msg);
2053                 env->sender = CpvAccess(_currentObj)->mlogData->objID;
2054 #endif
2055                 return true;
2056         }
2057  
2058         //This is called when this ArrayRec is about to be replaced.
2059         // We dump all our buffered messages off on the next guy,
2060         // who should know what to do with them.
2061         virtual void beenReplaced(void) {
2062                 DEBS((AA" Delivering queued messages:\n"AB));
2063                 CkArrayMessage *m;
2064                 while (NULL!=(m=buffer.deq())) {
2065 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))         
2066                 DEBUG(CmiPrintf("[%d] buffered message being sent\n",CmiMyPe()));
2067                 envelope *env = UsrToEnv(m);
2068                 Chare *oldObj = CpvAccess(_currentObj);
2069                 CpvAccess(_currentObj) =(Chare *) env->sender.getObject();
2070                 env->sender.type = TypeInvalid;
2071 #endif
2072                 DEBS((AA"Sending buffered message to %s\n"AB,idx2str(m->array_index())));
2073                 myLocMgr->deliverViaQueue(m);
2074 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))         
2075                 CpvAccess(_currentObj) = oldObj;
2076 #endif
2077                 }
2078         }
2079   
2080         //Return if this element is now obsolete
2081         virtual bool isObsolete(int nSprings,const CkArrayIndex &idx) {
2082                 if (isStale() && buffer.length()>0) {
2083                         /*This indicates something is seriously wrong--
2084                           buffers should be short-lived.*/
2085                         CkPrintf("[%d] WARNING: %d stale array message(s) found!\n",CkMyPe(),buffer.length());
2086                         CkArrayMessage *msg=buffer[0];
2087                         CkPrintf("Addressed to: ");
2088                         CkPrintEntryMethod(msg->array_ep());
2089                         CkPrintf(" index %s\n",idx2str(idx));
2090                         if (myLocMgr->isHome(idx)) 
2091                                 CkPrintf("is this an out-of-bounds array index, or was it never created?\n");
2092                         else //Idx is a remote-home index
2093                                 CkPrintf("why weren't they forwarded?\n");
2094                         
2095                         // CkAbort("Stale array manager message(s)!\n");
2096                 }
2097                 return false;
2098         }
2099   
2100 /*  virtual void pup(PUP::er &p) {
2101     CkLocRec_aging::pup(p);
2102     CkArray::pupArrayMsgQ(buffer, p);
2103     }*/
2104 };
2105
2106 /*********************** Spring Cleaning *****************/
2107 /**
2108  * Used to periodically flush out unused remote element pointers.
2109  *
2110  * Cleaning often will free up memory quickly, but slow things
2111  * down because the cleaning takes time and some not-recently-referenced
2112  * remote element pointers might be valid and used some time in 
2113  * the future.
2114  *
2115  * Also used to determine if buffered messages have become stale.
2116  */
2117 inline void CkLocMgr::springCleaning(void)
2118 {
2119   nSprings++;
2120
2121   //Poke through the hash table for old ArrayRecs.
2122   void *objp;
2123   void *keyp;
2124   
2125   CkHashtableIterator *it=hash.iterator();
2126   CmiImmediateLock(hashImmLock);
2127   while (NULL!=(objp=it->next(&keyp))) {
2128     CkLocRec *rec=*(CkLocRec **)objp;
2129     CkArrayIndex &idx=*(CkArrayIndex *)keyp;
2130     if (rec->isObsolete(nSprings,idx)) {
2131       //This record is obsolete-- remove it from the table
2132       DEBK((AA"Cleaning out old record %s\n"AB,idx2str(idx)));
2133       hash.remove(*(CkArrayIndex *)&idx);
2134       delete rec;
2135       it->seek(-1);//retry this hash slot
2136     }
2137   }
2138   CmiImmediateUnlock(hashImmLock);
2139   delete it;
2140
2141   setupSpringCleaning();
2142 }
2143 void CkLocMgr::staticSpringCleaning(void *forWhom,double curWallTime) {
2144         DEBK((AA"Starting spring cleaning at %.2f\n"AB,CkWallTimer()));
2145         ((CkLocMgr *)forWhom)->springCleaning();
2146 }
2147 //doesn't delete if there is extra pe
2148 void CkLocMgr::flushLocalRecs(void)
2149 {
2150   void *objp;
2151   void *keyp;
2152   CkHashtableIterator *it=hash.iterator();
2153   CmiImmediateLock(hashImmLock);
2154   while (NULL!=(objp=it->next(&keyp))) {
2155     CkLocRec *rec=*(CkLocRec **)objp;
2156     CkArrayIndex &idx=*(CkArrayIndex *)keyp;
2157     if (rec->type() == CkLocRec::local) {
2158         callMethod((CkLocRec_local*)rec, &CkMigratable::ckDestroy);
2159         it->seek(-1);//retry this hash slot
2160     }
2161   }
2162   delete it;
2163   CmiImmediateUnlock(hashImmLock);
2164 }
2165
2166 // clean all buffer'ed messages and also free local objects
2167 void CkLocMgr::flushAllRecs(void)
2168 {
2169   void *objp;
2170   void *keyp;
2171   CkHashtableIterator *it=hash.iterator();
2172   CmiImmediateLock(hashImmLock);
2173   while (NULL!=(objp=it->next(&keyp))) {
2174     CkLocRec *rec=*(CkLocRec **)objp;
2175     CkArrayIndex &idx=*(CkArrayIndex *)keyp;
2176     if (rec->type() != CkLocRec::local) {
2177       //In the case of taking core out of memory (in BigSim's emulation)
2178       //the meta data in the location manager are not deleted so we need
2179       //this condition
2180       
2181       if(_BgOutOfCoreFlag!=1){
2182         hash.remove(*(CkArrayIndex *)&idx);
2183         delete rec;
2184         it->seek(-1);//retry this hash slot
2185       }
2186     }
2187     else {
2188         callMethod((CkLocRec_local*)rec, &CkMigratable::ckDestroy);
2189         it->seek(-1);//retry this hash slot
2190     }
2191   }
2192   delete it;
2193   CmiImmediateUnlock(hashImmLock);
2194 }
2195
2196
2197 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2198 void CkLocMgr::callForAllRecords(CkLocFn fnPointer,CkArray *arr,void *data){
2199         void *objp;
2200         void *keyp;
2201
2202         CkHashtableIterator *it = hash.iterator();
2203         while (NULL!=(objp=it->next(&keyp))) {
2204                 CkLocRec *rec=*(CkLocRec **)objp;
2205                 CkArrayIndex &idx=*(CkArrayIndex *)keyp;
2206                 fnPointer(arr,data,rec,&idx);
2207         }
2208
2209         // releasing iterator memory
2210         delete it;
2211 }
2212 #endif
2213
2214 /*************************** LocMgr: CREATION *****************************/
2215 CkLocMgr::CkLocMgr(CkArrayOptions opts)
2216         :thisProxy(thisgroup),thislocalproxy(thisgroup,CkMyPe()),
2217          hash(17,0.3)
2218 #if CMK_ERROR_CHECKING
2219         , bounds(opts.getBounds())
2220 #endif
2221 {
2222         DEBC((AA"Creating new location manager %d\n"AB,thisgroup));
2223 // moved to _CkMigratable_initInfoInit()
2224 //      CkpvInitialize(CkMigratable_initInfo,mig_initInfo);
2225
2226         managers.init();
2227         nManagers=0;
2228         firstManager=NULL;
2229         firstFree=localLen=0;
2230         duringMigration=false;
2231         nSprings=0;
2232         setupSpringCleaning();
2233
2234 //Register with the map object
2235         mapID = opts.getMap();
2236         map=(CkArrayMap *)CkLocalBranch(mapID);
2237         if (map==NULL) CkAbort("ERROR!  Local branch of array map is NULL!");
2238         mapHandle=map->registerArray(opts.getNumInitial(), thisgroup);
2239
2240         // Figure out the mapping from indices to object IDs if one is possible
2241         compressor = ck::FixedArrayIndexCompressor::make(opts.getBounds());
2242
2243 //Find and register with the load balancer
2244 #if CMK_LBDB_ON
2245         lbdbID = _lbdb;
2246         metalbID = _metalb;
2247 #endif
2248         initLB(lbdbID, metalbID);
2249         hashImmLock = CmiCreateImmediateLock();
2250 }
2251
2252 CkLocMgr::CkLocMgr(CkMigrateMessage* m)
2253         :IrrGroup(m),thisProxy(thisgroup),thislocalproxy(thisgroup,CkMyPe()),hash(17,0.3)
2254 {
2255         managers.init();
2256         nManagers=0;
2257         firstManager=NULL;
2258         firstFree=localLen=0;
2259         duringMigration=false;
2260         nSprings=0;
2261         setupSpringCleaning();
2262         hashImmLock = CmiCreateImmediateLock();
2263 }
2264
2265 void CkLocMgr::setupSpringCleaning() {
2266 #if !CMK_GLOBAL_LOCATION_UPDATE
2267         springCleaningCcd = CcdCallOnConditionOnPE(CcdPERIODIC_1minute,staticSpringCleaning,(void *)this, CkMyPe());
2268 #endif
2269 }
2270
2271 CkLocMgr::~CkLocMgr() {
2272 #if CMK_LBDB_ON
2273   the_lbdb->RemoveLocalBarrierClient(dummyBarrierHandle);
2274   the_lbdb->RemoveLocalBarrierReceiver(lbBarrierReceiver);
2275   the_lbdb->UnregisterOM(myLBHandle);
2276 #endif
2277   CcdCancelCallOnCondition(CcdPERIODIC_1minute, springCleaningCcd);
2278   map->unregisterArray(mapHandle);
2279   CmiDestroyLock(hashImmLock);
2280 }
2281
2282 void CkLocMgr::pup(PUP::er &p){
2283         IrrGroup::pup(p);
2284         p|mapID;
2285         p|mapHandle;
2286         p|lbdbID;
2287   p|metalbID;
2288         mapID = _defaultArrayMapID;
2289         if(p.isUnpacking()){
2290                 thisProxy=thisgroup;
2291                 CProxyElement_CkLocMgr newlocalproxy(thisgroup,CkMyPe());
2292                 thislocalproxy=newlocalproxy;
2293                 //Register with the map object
2294                 map=(CkArrayMap *)CkLocalBranch(mapID);
2295                 if (map==NULL) CkAbort("ERROR!  Local branch of array map is NULL!");
2296                 CkArrayIndex emptyIndex;
2297                 map->registerArray(emptyIndex,thisgroup);
2298                 // _lbdb is the fixed global groupID
2299                 initLB(lbdbID, metalbID);
2300 #if __FAULT__
2301         int count = 0;
2302         p | count;
2303         DEBUG(CmiPrintf("[%d] Unpacking Locmgr %d has %d home elements\n",CmiMyPe(),thisgroup.idx,count));
2304 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))    
2305         homeElementCount = count;
2306 #endif
2307         for(int i=0;i<count;i++){
2308             CkArrayIndex idx;
2309             int pe = 0;
2310             idx.pup(p);
2311             p | pe;
2312   //          CmiPrintf("[%d] idx %s is a home element exisiting on pe %d\n",CmiMyPe(),idx2str(idx),pe);
2313             inform(idx,pe);
2314             CkLocRec *rec = elementNrec(idx);
2315             CmiAssert(rec!=NULL);
2316             CmiAssert(lastKnown(idx) == pe);
2317         }
2318 #endif
2319                 // delay doneInserting when it is unpacking during restart.
2320                 // to prevent load balancing kicking in
2321                 if (!CkInRestarting()) 
2322                         doneInserting();
2323         }else{
2324  /**
2325  * pack the indexes of elements which have their homes on this processor
2326  * but dont exist on it.. needed for broadcast after a restart
2327  * indexes of local elements dont need to be packed
2328  * since they will be recreated later anyway
2329  */
2330 #if __FAULT__
2331                 int count=0,count1=0;
2332         void *objp;
2333         void *keyp;
2334         CkVec<int> pe_list;
2335         CkVec<CkArrayIndex> idx_list;
2336         CkHashtableIterator *it = hash.iterator();
2337       while (NULL!=(objp=it->next(&keyp))) {
2338           CkLocRec *rec=*(CkLocRec **)objp;
2339           CkArrayIndex &idx=*(CkArrayIndex *)keyp;
2340             if(rec->type() != CkLocRec::local){
2341                 if(homePe(idx) == CmiMyPe()){
2342                   int pe;
2343                   CkArrayIndex max = idx;
2344                   pe = rec->lookupProcessor();
2345                   idx_list.push_back(max);
2346                   pe_list.push_back(pe);
2347                     count++;
2348                 }
2349             }
2350         }
2351         p | count;
2352
2353                 // releasing iterator memory
2354                 delete it;
2355
2356       for(int i=0;i<pe_list.length();i++){
2357         CkArrayIndex max = idx_list[i];
2358         max.pup(p);
2359         p|pe_list[i];
2360       }
2361     /*    it = hash.iterator();
2362       while (NULL!=(objp=it->next(&keyp))) {
2363       CkLocRec *rec=*(CkLocRec **)objp;
2364         CkArrayIndex &idx=*(CkArrayIndex *)keyp;
2365             CkArrayIndex max = idx;
2366             if(rec->type() != CkLocRec::local){
2367                 if(homePe(idx) == CmiMyPe()){
2368                     int pe;
2369                     max.pup(p);
2370                     pe = rec->lookupProcessor();
2371                     p | pe;
2372                     count1++;
2373                 }
2374             }
2375         }
2376       //  CmiAssert(count == count1);
2377
2378                 // releasing iterator memory
2379                 delete it;*/
2380
2381 #endif
2382
2383         }
2384 }
2385
2386 void _CkLocMgrInit(void) {
2387   /* Don't trace our deliver method--it does its own tracing */
2388   CkDisableTracing(CkIndex_CkLocMgr::deliverInline(0));
2389 }
2390
2391 /// Add a new local array manager to our list.
2392 /// Returns a new CkMigratableList for the manager to store his
2393 /// elements in.
2394 CkMigratableList *CkLocMgr::addManager(CkArrayID id,CkArrMgr *mgr)
2395 {
2396         CK_MAGICNUMBER_CHECK
2397         DEBC((AA"Adding new array manager\n"AB));
2398         //Link new manager into list
2399         ManagerRec *n=new ManagerRec;
2400         managers.find(id)=n;
2401         n->next=firstManager;
2402         n->mgr=mgr;
2403         n->elts.setSize(localLen);
2404         nManagers++;
2405         firstManager=n;
2406         return &n->elts;
2407 }
2408
2409 void CkLocMgr::deleteManager(CkArrayID id, CkArrMgr *mgr) {
2410   ManagerRec *&rec = managers.find(id);
2411
2412   ManagerRec **prev = &firstManager;
2413   ManagerRec *cur = firstManager;
2414   while (cur->mgr != mgr) {
2415     prev = &cur->next;
2416     ++cur;
2417   }
2418
2419   CkAssert(cur);
2420   CkAssert(cur == rec);
2421
2422   *prev = cur->next;
2423   nManagers--;
2424   delete cur;
2425   rec = NULL; // Would like to remove the entry entirely, but it's in a direct-mapped array
2426
2427   if (nManagers == 0)
2428     delete this;
2429 }
2430
2431 /// Return the next unused local element index.
2432 int CkLocMgr::nextFree(void) {
2433         if (firstFree>=localLen)
2434         {//Need more space in the local index arrays-- enlarge them
2435                 int oldLen=localLen;
2436                 localLen=localLen*2+8;
2437                 DEBC((AA"Growing the local list from %d to %d...\n"AB,oldLen,localLen));
2438                 for (ManagerRec *m=firstManager;m!=NULL;m=m->next)
2439                         m->elts.setSize(localLen);
2440                 //Update the free list
2441                 freeList.resize(localLen);
2442                 for (int i=oldLen;i<localLen;i++)
2443                         freeList[i]=i+1;
2444         }
2445         int localIdx=firstFree;
2446         if (localIdx==-1) CkAbort("CkLocMgr free list corrupted!");
2447         firstFree=freeList[localIdx];
2448         freeList[localIdx]=-1; //Mark as used
2449         return localIdx;
2450 }
2451
2452 CkLocRec_remote *CkLocMgr::insertRemote(const CkArrayIndex &idx,int nowOnPe)
2453 {
2454         DEBS((AA"Remote element %s lives on %d\n"AB,idx2str(idx),nowOnPe));
2455         CkLocRec_remote *rem=new CkLocRec_remote(this,nowOnPe);
2456         insertRec(rem,idx);
2457         return rem;
2458 }
2459
2460 //This element now lives on the given Pe
2461 void CkLocMgr::inform(const CkArrayIndex &idx,int nowOnPe)
2462 {
2463         if (nowOnPe==CkMyPe())
2464                 return; //Never insert a "remote" record pointing here
2465         CkLocRec *rec=elementNrec(idx);
2466         if (rec!=NULL && rec->type()==CkLocRec::local){
2467 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2468         CmiPrintf("[%d]WARNING!!! Element %d:%s is local but is being told it exists on %d\n",CkMyPe(),idx.dimension,idx2str(idx), nowOnPe);
2469 #endif
2470                 return; //Never replace a local element's record!
2471         }
2472         insertRemote(idx,nowOnPe);
2473 }
2474
2475 //Tell this element's home processor it now lives "there"
2476 void CkLocMgr::informHome(const CkArrayIndex &idx,int nowOnPe)
2477 {
2478         int home=homePe(idx);
2479         if (home!=CkMyPe() && home!=nowOnPe) {
2480                 //Let this element's home Pe know it lives here now
2481                 DEBC((AA"  Telling %s's home %d that it lives on %d.\n"AB,idx2str(idx),home,nowOnPe));
2482 //#if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2483 //#if defined(_FAULT_MLOG_)
2484 //        informLocationHome(thisgroup,idx,home,CkMyPe());
2485 //#else
2486                 thisProxy[home].updateLocation(idx,nowOnPe);
2487 //#endif
2488         }
2489 }
2490
2491 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2492 CkLocRec_local *CkLocMgr::createLocal(const CkArrayIndex &idx,
2493         bool forMigration, bool ignoreArrival,
2494         bool notifyHome,int dummy)
2495 {
2496     int localIdx=nextFree();
2497     DEBC((AA"Adding new record for element %s at local index %d\n"AB,idx2str(idx),localIdx));
2498     CkLocRec_local *rec=new CkLocRec_local(this,forMigration,ignoreArrival,idx,localIdx);
2499     if(!dummy){
2500         insertRec(rec,idx); //Add to global hashtable
2501     }   
2502     if (notifyHome) informHome(idx,CkMyPe());
2503     return rec; 
2504 }
2505 #else
2506 CkLocRec_local *CkLocMgr::createLocal(const CkArrayIndex &idx, 
2507                 bool forMigration, bool ignoreArrival,
2508                 bool notifyHome)
2509 {
2510         int localIdx=nextFree();
2511         DEBC((AA"Adding new record for element %s at local index %d\n"AB,idx2str(idx),localIdx));
2512         CkLocRec_local *rec=new CkLocRec_local(this,forMigration,ignoreArrival,idx,localIdx);
2513         insertRec(rec,idx); //Add to global hashtable
2514
2515
2516         if (notifyHome) informHome(idx,CkMyPe());
2517         return rec;
2518 }
2519 #endif
2520
2521 //Add a new local array element, calling element's constructor
2522 bool CkLocMgr::addElement(CkArrayID id,const CkArrayIndex &idx,
2523                 CkMigratable *elt,int ctorIdx,void *ctorMsg)
2524 {
2525         CK_MAGICNUMBER_CHECK
2526         CkLocRec *oldRec=elementNrec(idx);
2527         CkLocRec_local *rec;
2528         if (oldRec==NULL||oldRec->type()!=CkLocRec::local) 
2529         { //This is the first we've heard of that element-- add new local record
2530                 rec=createLocal(idx,false,false,true);
2531 #if CMK_GLOBAL_LOCATION_UPDATE
2532                 if (homePe(idx) != CkMyPe()) {
2533                   DEBC((AA"Global location broadcast for new element idx %s "
2534                         "assigned to %d \n"AB, idx2str(idx), CkMyPe()));
2535                   thisProxy.updateLocation(idx, CkMyPe());  
2536                 }
2537 #endif
2538                 
2539         } else 
2540         { //rec is *already* local-- must not be the first insertion    
2541                 rec=((CkLocRec_local *)oldRec);
2542                 rec->addedElement();
2543         }
2544         if (!addElementToRec(rec,managers.find(id),elt,ctorIdx,ctorMsg)) return false;
2545         elt->ckFinishConstruction();
2546         return true;
2547 }
2548
2549 //As above, but shared with the migration code
2550 bool CkLocMgr::addElementToRec(CkLocRec_local *rec,ManagerRec *m,
2551                 CkMigratable *elt,int ctorIdx,void *ctorMsg)
2552 {//Insert the new element into its manager's local list
2553         int localIdx=rec->getLocalIndex();
2554         if (m->elts.get(localIdx)!=NULL) CkAbort("Cannot insert array element twice!");
2555         m->elts.put(elt,localIdx); //Local element table
2556
2557 //Call the element's constructor
2558         DEBC((AA"Constructing element %s of array\n"AB,idx2str(rec->getIndex())));
2559         CkMigratable_initInfo &i=CkpvAccess(mig_initInfo);
2560         i.locRec=rec;
2561         i.chareType=_entryTable[ctorIdx]->chareIdx;
2562         if (!rec->invokeEntry(elt,ctorMsg,ctorIdx,true)) return false;
2563
2564 #if CMK_OUT_OF_CORE
2565         /* Register new element with out-of-core */
2566         PUP::sizer p_getSize; elt->pup(p_getSize);
2567         elt->prefetchObjID=CooRegisterObject(&CkArrayElementPrefetcher,p_getSize.size(),elt);
2568 #endif
2569         
2570         return true;
2571 }
2572
2573 void CkLocMgr::requestLocation(const CkArrayIndex &idx, const int peToTell,
2574                                bool suppressIfHere) {
2575   int onPe = -1;
2576
2577   if (peToTell == CkMyPe())
2578     return;
2579
2580   onPe = lastKnown(idx);
2581   CkAssert(onPe != -1);
2582
2583   if (suppressIfHere && onPe == CkMyPe())
2584     return;
2585
2586   thisProxy[peToTell].updateLocation(idx, onPe);
2587 }
2588
2589 void CkLocMgr::updateLocation(const CkArrayIndex &idx, int nowOnPe) {
2590   inform(idx, nowOnPe);
2591 }
2592
2593 /*************************** LocMgr: DELETION *****************************/
2594 /// This index will no longer be used-- delete the associated elements
2595 void CkLocMgr::reclaim(const CkArrayIndex &idx,int localIdx) {
2596         CK_MAGICNUMBER_CHECK
2597         DEBC((AA"Destroying element %s (local %d)\n"AB,idx2str(idx),localIdx));
2598         //Delete, and mark as empty, each array element
2599         for (ManagerRec *m=firstManager;m!=NULL;m=m->next) {
2600                 delete m->elts.get(localIdx);
2601                 m->elts.empty(localIdx);
2602         }
2603         
2604         removeFromTable(idx);
2605         
2606         //Link local index into free list
2607         freeList[localIdx]=firstFree;
2608         firstFree=localIdx;
2609         
2610                 
2611         if (!duringMigration) 
2612         { //This is a local element dying a natural death
2613             #if CMK_BIGSIM_CHARM
2614                 //After migration, reclaimRemote will be called through 
2615                 //the CkRemoveArrayElement in the pupping routines for those 
2616                 //objects that are not on the home processors. However,
2617                 //those remote records should not be deleted since the corresponding
2618                 //objects are not actually deleted but on disk. If deleted, msgs
2619                 //that seeking where is the object will be accumulated (a circular
2620                 //msg chain) and causes the program no progress
2621                 if(_BgOutOfCoreFlag==1) return; 
2622             #endif
2623                 int home=homePe(idx);
2624                 if (home!=CkMyPe())
2625 #if CMK_MEM_CHECKPOINT
2626                 if (!CkInRestarting()) // all array elements are removed anyway
2627 #endif
2628                         thisProxy[home].reclaimRemote(idx,CkMyPe());
2629         /*      //Install a zombie to keep the living from re-using this index.
2630                 insertRecN(new CkLocRec_dead(this),idx); */
2631         }
2632 }
2633
2634 void CkLocMgr::reclaimRemote(const CkArrayIndex &idx,int deletedOnPe) {
2635         DEBC((AA"Our element %s died on PE %d\n"AB,idx2str(idx),deletedOnPe));
2636         CkLocRec *rec=elementNrec(idx);
2637         if (rec==NULL) return; //We never knew him
2638         if (rec->type()==CkLocRec::local) return; //He's already been reborn
2639         removeFromTable(idx);
2640         delete rec;
2641 }
2642 void CkLocMgr::removeFromTable(const CkArrayIndex &idx) {
2643 #if CMK_ERROR_CHECKING
2644         //Make sure it's actually in the table before we delete it
2645         if (NULL==elementNrec(idx))
2646                 CkAbort("CkLocMgr::removeFromTable called on invalid index!");
2647 #endif
2648         CmiImmediateLock(hashImmLock);
2649         hash.remove(*(CkArrayIndex *)&idx);
2650         CmiImmediateUnlock(hashImmLock);
2651 #if CMK_ERROR_CHECKING
2652         //Make sure it's really gone
2653         if (NULL!=elementNrec(idx))
2654                 CkAbort("CkLocMgr::removeFromTable called, but element still there!");
2655 #endif
2656 }
2657
2658 /************************** LocMgr: MESSAGING *************************/
2659 /// Deliver message to this element, going via the scheduler if local
2660 /// @return 0 if object local, 1 if not
2661 int CkLocMgr::deliver(CkMessage *m,CkDeliver_t type,int opts) {
2662         DEBS((AA"deliver \n"AB));
2663         CK_MAGICNUMBER_CHECK
2664         CkArrayMessage *msg=(CkArrayMessage *)m;
2665
2666
2667         const CkArrayIndex &idx=msg->array_index();
2668         DEBS((AA"deliver %s\n"AB,idx2str(idx)));
2669         if (type==CkDeliver_queue)
2670                 _TRACE_CREATION_DETAILED(UsrToEnv(m),msg->array_ep());
2671         CkLocRec *rec=elementNrec(idx);
2672         if(rec != NULL){
2673                 DEBS((AA"deliver %s of type %d \n"AB,idx2str(idx),rec->type()));
2674         }else{
2675                 DEBS((AA"deliver %s rec is null\n"AB,idx2str(idx)));
2676         }
2677 //#if (!defined(_FAULT_MLOG_) && !defined(_FAULT_CAUSAL_))
2678 //#if !defined(_FAULT_MLOG_)
2679 #if CMK_LBDB_ON
2680
2681         LDObjid ldid = idx2LDObjid(idx);
2682 #if CMK_GLOBAL_LOCATION_UPDATE
2683         ldid.locMgrGid = thisgroup.idx;
2684 #endif        
2685         if (type==CkDeliver_queue) {
2686                 if (!(opts & CK_MSG_LB_NOTRACE) && the_lbdb->CollectingCommStats()) {
2687                 if(rec!=NULL) the_lbdb->Send(myLBHandle,ldid,UsrToEnv(msg)->getTotalsize(), rec->lookupProcessor(), 1);
2688                 else /*rec==NULL*/ the_lbdb->Send(myLBHandle,ldid,UsrToEnv(msg)->getTotalsize(),homePe(msg->array_index()), 1);
2689                 }
2690         }
2691 #endif
2692 //#endif
2693 #if CMK_GRID_QUEUE_AVAILABLE
2694         int gridSrcPE;
2695         int gridSrcCluster;
2696         int gridDestPE;
2697         int gridDestCluster;
2698         CkMigratable *obj;
2699         ArrayElement *obj2;
2700         CkGroupID gid;
2701         int *data;
2702
2703         obj = (CkMigratable *) CpvAccess(CkGridObject);   // CkGridObject is a pointer to the sending object (retained earlier)
2704         if (obj != NULL) {
2705           obj2 = dynamic_cast<ArrayElement *> (obj);
2706           if (obj2 > 0) {
2707             // Get the sending object's array gid and indexes.
2708             // These are guaranteed to exist due to the succeeding dynamic cast above.
2709             gid = obj2->ckGetArrayID ();
2710             data = obj2->thisIndexMax.data ();
2711
2712             // Get the source PE and destination PE.
2713             gridSrcPE = CkMyPe ();
2714             if (rec != NULL) {
2715               gridDestPE = rec->lookupProcessor ();
2716             } else {
2717               gridDestPE = homePe (msg->array_index ());
2718             }
2719
2720             // Get the source cluster and destination cluster.
2721             gridSrcCluster = CmiGetCluster (gridSrcPE);
2722             gridDestCluster = CmiGetCluster (gridDestPE);
2723
2724             // If the Grid queue interval is greater than zero, it means that the more complicated
2725             // technique for registering border objects that exceed a specified threshold of
2726             // cross-cluster messages within a specified interval (and deregistering border objects
2727             // that do not meet this threshold) is used.  Otherwise a much simpler technique is used
2728             // where a border object is registered immediately upon sending a single cross-cluster
2729             // message (and deregistered when load balancing takes place).
2730             if (obj2->grid_queue_interval > 0) {
2731               // Increment the sending object's count of all messages.
2732               obj2->msg_count += 1;
2733
2734               // If the source cluster and destination cluster differ, this is a Grid message.
2735               // (Increment the count of all Grid messages.)
2736               if (gridSrcCluster != gridDestCluster) {
2737                 obj2->msg_count_grid += 1;
2738               }
2739
2740               // If the number of messages exceeds the interval, check to see if the object has
2741               // sent enough cross-cluster messages to qualify as a border object.
2742               if (obj2->msg_count >= obj2->grid_queue_interval) {
2743                 if (obj2->msg_count_grid >= obj2->grid_queue_threshold) {
2744                   // The object is a border object; if it is not already registered, register it.
2745                   if (!obj2->border_flag) {
2746                     CmiGridQueueRegister (gid.idx, obj2->thisIndexMax.nInts, data[0], data[1], data[2]);
2747                   }
2748                   obj2->border_flag = 1;
2749                 } else {
2750                   // The object is not a border object; if it is registered, deregister it.
2751                   if (obj2->border_flag) {
2752                     CmiGridQueueDeregister (gid.idx, obj2->thisIndexMax.nInts, data[0], data[1], data[2]);
2753                   }
2754                   obj2->border_flag = 0;
2755                 }
2756                 // Reset the counts.
2757                 obj2->msg_count = 0;
2758                 obj2->msg_count_grid = 0;
2759               }
2760             } else {
2761               if (gridSrcCluster != gridDestCluster) {
2762                 CmiGridQueueRegister (gid.idx, obj2->thisIndexMax.nInts, data[0], data[1], data[2]);
2763               }
2764             }
2765           }
2766
2767           // Reset the CkGridObject pointer.
2768           CpvAccess(CkGridObject) = NULL;
2769         }
2770 #endif
2771         /**FAULT_EVAC*/
2772         if (rec!=NULL){
2773                 bool result = rec->deliver(msg,type,opts);
2774                 // if result is false, than rec is not valid anymore, as the object
2775                 // the message was just delivered to has died or migrated out.
2776                 // Therefore rec->type() cannot be invoked!
2777                 if (result==true && rec->type()==CkLocRec::local) return 0;
2778                 else return 1;
2779                 /*if(!result){
2780                         //DEBS((AA"deliver %s failed type %d \n"AB,idx2str(idx),rec->type()));
2781                         DEBS((AA"deliver %s failed \n"AB,idx2str(idx)));
2782                         if(rec->type() == CkLocRec::remote){
2783                                 if (opts & CK_MSG_KEEP)
2784                                         msg = (CkArrayMessage *)CkCopyMsg((void **)&msg);
2785                                 deliverUnknown(msg,type);
2786                         }
2787                 }*/
2788         }else /* rec==NULL*/ {
2789                 if (opts & CK_MSG_KEEP)
2790                         msg = (CkArrayMessage *)CkCopyMsg((void **)&msg);
2791                 deliverUnknown(msg,type,opts);
2792                 return 1;
2793         }
2794
2795 }
2796
2797 /// This index is not hashed-- somehow figure out what to do.
2798 bool CkLocMgr::deliverUnknown(CkArrayMessage *msg,CkDeliver_t type,int opts)
2799 {
2800         CK_MAGICNUMBER_CHECK
2801         const CkArrayIndex &idx=msg->array_index();
2802         int onPe=homePe(idx);
2803         if (onPe!=CkMyPe()) 
2804         {// Forward the message to its home processor
2805                 DEBM((AA"Forwarding message for unknown %s to home %d \n"AB,idx2str(idx),onPe));
2806                 msg->array_hops()++;
2807                 CkArrayManagerDeliver(onPe,msg,opts);
2808                 return true;
2809         }
2810         else
2811         { // We *are* the home processor:
2812         //Check if the element's array manager has been registered yet:
2813           CkArrMgr *mgr=managers.find(UsrToEnv((void *)msg)->getArrayMgr())->mgr;
2814           if (!mgr) { //No manager yet-- postpone the message (stupidly)
2815             if (CkInRestarting()) {
2816               // during restarting, this message should be ignored
2817               delete msg;
2818             }
2819             else {
2820               CkArrayManagerDeliver(CkMyPe(),msg); 
2821             }
2822           }
2823           else { // Has a manager-- must buffer the message
2824             DEBC((AA"Adding buffer for unknown element %s\n"AB,idx2str(idx)));
2825             CkLocRec *rec=new CkLocRec_buffering(this);
2826             insertRecN(rec,idx);
2827             rec->deliver(msg,type);
2828           
2829             if (msg->array_ifNotThere()!=CkArray_IfNotThere_buffer) 
2830             { //Demand-create the element:
2831               return demandCreateElement(msg,-1,type);
2832             }
2833           }
2834           return true;
2835         }
2836 }
2837
2838 bool CkLocMgr::demandCreateElement(CkArrayMessage *msg,int onPe,CkDeliver_t type)
2839 {
2840         CK_MAGICNUMBER_CHECK
2841         const CkArrayIndex &idx=msg->array_index();
2842         int chareType=_entryTable[msg->array_ep()]->chareIdx;
2843         int ctor=_chareTable[chareType]->getDefaultCtor();
2844         if (ctor==-1) CkAbort("Can't create array element to handle message--\n"
2845                               "The element has no default constructor in the .ci file!\n");
2846         if (onPe==-1) 
2847         { //Decide where element needs to live
2848                 if (msg->array_ifNotThere()==CkArray_IfNotThere_createhere) 
2849                         onPe=UsrToEnv(msg)->getsetArraySrcPe();
2850                 else //Createhome
2851                         onPe=homePe(idx);
2852         }
2853         
2854         //Find the manager and build the element
2855         DEBC((AA"Demand-creating element %s on pe %d\n"AB,idx2str(idx),onPe));
2856         CkArrMgr *mgr=managers.find(UsrToEnv((void *)msg)->getArrayMgr())->mgr;
2857         if (!mgr) CkAbort("Tried to demand-create for nonexistent arrMgr");
2858         return mgr->demandCreateElement(idx,onPe,ctor,type);
2859 }
2860
2861 //This message took several hops to reach us-- fix it
2862 void CkLocMgr::multiHop(CkArrayMessage *msg)
2863 {
2864
2865         CK_MAGICNUMBER_CHECK
2866         int srcPe=msg->array_getSrcPe();
2867         if (srcPe==CkMyPe())
2868                 DEB((AA"Odd routing: local element %s is %d hops away!\n"AB,idx2str(msg),msg->array_hops()));
2869         else
2870         {//Send a routing message letting original sender know new element location
2871                 DEBS((AA"Sending update back to %d for element\n"AB,srcPe,idx2str(msg)));
2872                 thisProxy[srcPe].updateLocation(msg->array_index(),CkMyPe());
2873         }
2874 }
2875
2876 void CkLocMgr::checkInBounds(const CkArrayIndex &idx)
2877 {
2878 #if CMK_ERROR_CHECKING
2879   if (bounds.nInts > 0) {
2880     CkAssert(idx.dimension == bounds.dimension);
2881     bool shorts = idx.dimension > 3;
2882
2883     for (int i = 0; i < idx.dimension; ++i) {
2884       unsigned int thisDim = shorts ? idx.indexShorts[i] : idx.index[i];
2885       unsigned int thatDim = shorts ? bounds.indexShorts[i] : bounds.index[i];
2886       CkAssert(thisDim < thatDim);
2887     }
2888   }
2889 #endif
2890 }
2891
2892 /************************** LocMgr: ITERATOR *************************/
2893 CkLocation::CkLocation(CkLocMgr *mgr_, CkLocRec_local *rec_)
2894         :mgr(mgr_), rec(rec_) {}
2895         
2896 const CkArrayIndex &CkLocation::getIndex(void) const {
2897         return rec->getIndex();
2898 }
2899
2900 void CkLocation::destroyAll() {
2901         mgr->callMethod(rec, &CkMigratable::ckDestroy);
2902 }
2903
2904 void CkLocation::pup(PUP::er &p) {
2905         mgr->pupElementsFor(p,rec,CkElementCreation_migrate);
2906 }
2907
2908 CkLocIterator::~CkLocIterator() {}
2909
2910 /// Iterate over our local elements:
2911 void CkLocMgr::iterate(CkLocIterator &dest) {
2912   //Poke through the hash table for local ArrayRecs.
2913   void *objp;
2914   CkHashtableIterator *it=hash.iterator();
2915   CmiImmediateLock(hashImmLock);
2916
2917   while (NULL!=(objp=it->next())) {
2918     CkLocRec *rec=*(CkLocRec **)objp;
2919     if (rec->type()==CkLocRec::local) {
2920       CkLocation loc(this,(CkLocRec_local *)rec);
2921       dest.addLocation(loc);
2922     }
2923   }
2924   CmiImmediateUnlock(hashImmLock);
2925   delete it;
2926 }
2927
2928
2929
2930
2931 /************************** LocMgr: MIGRATION *************************/
2932 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2933 void CkLocMgr::pupElementsFor(PUP::er &p,CkLocRec_local *rec,
2934         CkElementCreation_t type, bool create, int dummy)
2935 {
2936     p.comment("-------- Array Location --------");
2937     register ManagerRec *m;
2938     int localIdx=rec->getLocalIndex();
2939     CkVec<CkMigratable *> dummyElts;
2940
2941     for (m=firstManager;m!=NULL;m=m->next) {
2942         int elCType;
2943         if (!p.isUnpacking())
2944         { //Need to find the element's existing type
2945             CkMigratable *elt=m->element(localIdx);
2946             if (elt) elCType=elt->ckGetChareType();
2947             else elCType=-1; //Element hasn't been created
2948         }
2949         p(elCType);
2950         if (p.isUnpacking() && elCType!=-1) {
2951             CkMigratable *elt=m->mgr->allocateMigrated(elCType,rec->getIndex(),type);
2952             int migCtorIdx=_chareTable[elCType]->getMigCtor();
2953                 if(!dummy){
2954                         if(create)
2955                                 if (!addElementToRec(rec,m,elt,migCtorIdx,NULL)) return;
2956                                 }else{
2957                     CkMigratable_initInfo &i=CkpvAccess(mig_initInfo);
2958                     i.locRec=rec;
2959                     i.chareType=_entryTable[migCtorIdx]->chareIdx;
2960                     dummyElts.push_back(elt);
2961                     if (!rec->invokeEntry(elt,NULL,migCtorIdx,true)) return ;
2962                 }
2963         }
2964     }
2965     if(!dummy){
2966         for (m=firstManager;m!=NULL;m=m->next) {
2967             CkMigratable *elt=m->element(localIdx);
2968             if (elt!=NULL)
2969                 {
2970                        elt->pup(p);
2971                 }
2972         }
2973     }else{
2974             for(int i=0;i<dummyElts.size();i++){
2975                 CkMigratable *elt = dummyElts[i];
2976                 if (elt!=NULL){
2977             elt->pup(p);
2978                         }
2979                 delete elt;
2980             }
2981                         for (ManagerRec *m=firstManager;m!=NULL;m=m->next) {
2982                 m->elts.empty(localIdx);
2983             }
2984         freeList[localIdx]=firstFree;
2985         firstFree=localIdx;
2986     }
2987 }
2988 #else
2989 void CkLocMgr::pupElementsFor(PUP::er &p,CkLocRec_local *rec,
2990                 CkElementCreation_t type,bool rebuild)
2991 {
2992         p.comment("-------- Array Location --------");
2993         register ManagerRec *m;
2994         int localIdx=rec->getLocalIndex();
2995
2996         //First pup the element types
2997         // (A separate loop so ckLocal works even in element pup routines)
2998         for (m=firstManager;m!=NULL;m=m->next) {
2999                 int elCType;
3000                 if (!p.isUnpacking())
3001                 { //Need to find the element's existing type
3002                         CkMigratable *elt=m->element(localIdx);
3003                         if (elt) elCType=elt->ckGetChareType();
3004                         else elCType=-1; //Element hasn't been created
3005                 }
3006                 p(elCType);
3007                 if (p.isUnpacking() && elCType!=-1) {
3008                         //Create the element
3009                         CkMigratable *elt=m->mgr->allocateMigrated(elCType,rec->getIndex(),type);
3010                         int migCtorIdx=_chareTable[elCType]->getMigCtor();
3011                         //Insert into our tables and call migration constructor
3012                         if (!addElementToRec(rec,m,elt,migCtorIdx,NULL)) return;
3013                 }
3014         }
3015         //Next pup the element data
3016         for (m=firstManager;m!=NULL;m=m->next) {
3017                 CkMigratable *elt=m->element(localIdx);
3018                 if (elt!=NULL)
3019                 {
3020                         elt->pup(p);
3021 #if CMK_ERROR_CHECKING
3022                         if (p.isUnpacking()) elt->sanitycheck();
3023 #endif
3024                 }
3025         }
3026 #if CMK_MEM_CHECKPOINT
3027         if(rebuild){
3028           ArrayElement *elt;
3029           CkVec<CkMigratable *> list;
3030           migratableList(rec, list);
3031           CmiAssert(list.length() > 0);
3032           for (int l=0; l<list.length(); l++) {
3033                 //    reset, may not needed now
3034                 // for now.
3035                 for (int i=0; i<CK_ARRAYLISTENER_MAXLEN; i++) {
3036                         ArrayElement * elt = (ArrayElement *)list[l];
3037                   contributorInfo *c=(contributorInfo *)&elt->listenerData[i];
3038                   if (c) c->redNo = 0;
3039                 }
3040           }
3041                 
3042         }
3043 #endif
3044 }
3045 #endif
3046
3047 /// Call this member function on each element of this location:
3048 void CkLocMgr::callMethod(CkLocRec_local *rec,CkMigratable_voidfn_t fn)
3049 {
3050         int localIdx=rec->getLocalIndex();
3051         for (ManagerRec *m=firstManager;m!=NULL;m=m->next) {
3052                 CkMigratable *el=m->element(localIdx);
3053                 if (el) (el->* fn)();
3054         }
3055 }
3056
3057 /// Call this member function on each element of this location:
3058 void CkLocMgr::callMethod(CkLocRec_local *rec,CkMigratable_voidfn_arg_t fn,     void * data)
3059 {
3060         int localIdx=rec->getLocalIndex();
3061         for (ManagerRec *m=firstManager;m!=NULL;m=m->next) {
3062                 CkMigratable *el=m->element(localIdx);
3063                 if (el) (el->* fn)(data);
3064         }
3065 }
3066
3067 /// return a list of migratables in this local record
3068 void CkLocMgr::migratableList(CkLocRec_local *rec, CkVec<CkMigratable *> &list)
3069 {
3070         register ManagerRec *m;
3071         int localIdx=rec->getLocalIndex();
3072
3073         for (m=firstManager;m!=NULL;m=m->next) {
3074                 CkMigratable *elt=m->element(localIdx);
3075                 if (elt) list.push_back(elt);
3076         }
3077 }
3078
3079 /// Migrate this local element away to another processor.
3080 void CkLocMgr::emigrate(CkLocRec_local *rec,int toPe)
3081 {
3082         CK_MAGICNUMBER_CHECK
3083         if (toPe==CkMyPe()) return; //You're already there!
3084         /*
3085                 FAULT_EVAC
3086                 if the toProcessor is already marked as invalid, dont emigrate
3087                 Shouldn't happen but might
3088         */
3089         if(!CmiNodeAlive(toPe)){
3090                 return;
3091         }
3092         CkArrayIndex idx=rec->getIndex();
3093
3094 #if CMK_OUT_OF_CORE
3095         int localIdx=rec->getLocalIndex();
3096         /* Load in any elements that are out-of-core */
3097         for (ManagerRec *m=firstManager;m!=NULL;m=m->next) {
3098                 CkMigratable *el=m->element(localIdx);
3099                 if (el) if (!el->isInCore) CooBringIn(el->prefetchObjID);
3100         }
3101 #endif
3102
3103         //Let all the elements know we're leaving
3104         callMethod(rec,&CkMigratable::ckAboutToMigrate);
3105         /*EVAC*/
3106
3107 //First pass: find size of migration message
3108         size_t bufSize;
3109         {
3110                 PUP::sizer p;
3111                 pupElementsFor(p,rec,CkElementCreation_migrate);
3112                 bufSize=p.size(); 
3113         }
3114
3115 //Allocate and pack into message
3116         CkArrayElementMigrateMessage *msg = 
3117                 new (bufSize, 0) CkArrayElementMigrateMessage;
3118         msg->idx=idx;
3119         msg->length=bufSize;
3120         msg->nManagers = nManagers;
3121 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_)) 
3122     msg->gid = ckGetGroupID();
3123 #endif
3124 #if CMK_LBDB_ON
3125         msg->ignoreArrival = rec->isAsyncMigrate()?1:0;
3126 #endif
3127         /*
3128                 FAULT_EVAC
3129         */
3130         msg->bounced = rec->isBounced();
3131         {
3132                 PUP::toMem p(msg->packData); 
3133                 p.becomeDeleting(); 
3134                 pupElementsFor(p,rec,CkElementCreation_migrate);
3135                 if (p.size()!=bufSize) {
3136                         CkError("ERROR! Array element claimed it was %d bytes to a "
3137                                 "sizing PUP::er, but copied %d bytes into the packing PUP::er!\n",
3138                                 bufSize,p.size());
3139                         CkAbort("Array element's pup routine has a direction mismatch.\n");
3140                 }
3141         }
3142
3143         DEBM((AA"Migrated index size %s to %d \n"AB,idx2str(idx),toPe));        
3144
3145 //#if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
3146 //#if defined(_FAULT_MLOG_)
3147 //    sendMlogLocation(toPe,UsrToEnv(msg));
3148 //#else
3149         //Send off message and delete old copy
3150         thisProxy[toPe].immigrate(msg);
3151 //#endif
3152
3153         duringMigration=true;
3154         delete rec; //Removes elements, hashtable entries, local index
3155         
3156         
3157         duringMigration=false;
3158         //The element now lives on another processor-- tell ourselves and its home
3159         inform(idx,toPe);
3160 //#if (!defined(_FAULT_MLOG_) && !defined(_FAULT_CAUSAL_))    
3161 //#if !defined(_FAULT_MLOG_)    
3162         informHome(idx,toPe);
3163 //#endif
3164
3165 #if !CMK_LBDB_ON && CMK_GLOBAL_LOCATION_UPDATE
3166         DEBM((AA"Global location update. idx %s " 
3167               "assigned to %d \n"AB,idx2str(idx),toPe));
3168         thisProxy.updateLocation(idx, toPe);                        
3169 #endif
3170
3171         CK_MAGICNUMBER_CHECK
3172 }
3173
3174 #if CMK_LBDB_ON
3175 void CkLocMgr::informLBPeriod(CkLocRec_local *rec, int lb_ideal_period) {
3176         callMethod(rec,&CkMigratable::recvLBPeriod, (void *)&lb_ideal_period);
3177 }
3178
3179 void CkLocMgr::metaLBCallLB(CkLocRec_local *rec) {
3180         callMethod(rec, &CkMigratable::metaLBCallLB);
3181 }
3182 #endif
3183
3184 /**
3185   Migrating array element is arriving on this processor.
3186 */
3187 void CkLocMgr::immigrate(CkArrayElementMigrateMessage *msg)
3188 {
3189         const CkArrayIndex &idx=msg->idx;
3190                 
3191         PUP::fromMem p(msg->packData); 
3192         
3193         if (msg->nManagers < nManagers)
3194                 CkAbort("Array element arrived from location with fewer managers!\n");
3195         if (msg->nManagers > nManagers) {
3196                 //Some array managers haven't registered yet-- throw it back
3197                 DEBM((AA"Busy-waiting for array registration on migrating %s\n"AB,idx2str(idx)));
3198                 thisProxy[CkMyPe()].immigrate(msg);
3199                 return;
3200         }
3201
3202         //Create a record for this element
3203 //#if (!defined(_FAULT_MLOG_) && !defined(_FAULT_CAUSAL_))    
3204 //#if !defined(_FAULT_MLOG_)     
3205         CkLocRec_local *rec=createLocal(idx,true,msg->ignoreArrival,false /* home told on departure */ );
3206 //#else
3207 //    CkLocRec_local *rec=createLocal(idx,true,true,false /* home told on departure */ );
3208 //#endif
3209         
3210         //Create the new elements as we unpack the message
3211         pupElementsFor(p,rec,CkElementCreation_migrate);
3212         if (p.size()!=msg->length) {
3213                 CkError("ERROR! Array element claimed it was %d bytes to a"
3214                         "packing PUP::er, but %d bytes in the unpacking PUP::er!\n",
3215                         msg->length,p.size());
3216                 CkError("(I have %d managers; he claims %d managers)\n",
3217                         nManagers, msg->nManagers);
3218                 
3219                 CkAbort("Array element's pup routine has a direction mismatch.\n");
3220         }
3221         /*
3222                 FAULT_EVAC
3223                         if this element came in as a result of being bounced off some other process,
3224                         then it needs to be resumed. It is assumed that it was bounced because load 
3225                         balancing caused it to move into a processor which later crashed
3226         */
3227         if(msg->bounced){
3228                 callMethod(rec,&CkMigratable::ResumeFromSync);
3229         }
3230         
3231         //Let all the elements know we've arrived
3232         callMethod(rec,&CkMigratable::ckJustMigrated);
3233         /*FAULT_EVAC
3234                 If this processor has started evacuating array elements on it 
3235                 dont let new immigrants in. If they arrive send them to what
3236                 would be their correct homePE.
3237                 Leave a record here mentioning the processor where it got sent
3238         */
3239         
3240         if(CkpvAccess(startedEvac)){
3241                 int newhomePE = getNextPE(idx);
3242                 DEBM((AA"Migrated into failed processor index size %s resent to %d \n"AB,idx2str(idx),newhomePE));      
3243                 CkLocMgr *mgr = rec->getLocMgr();
3244                 int targetPE=getNextPE(idx);
3245                 //set this flag so that load balancer is not informed when
3246                 //this element migrates
3247                 rec->AsyncMigrate(true);
3248                 rec->Bounced(true);
3249                 mgr->emigrate(rec,targetPE);
3250                 
3251         }
3252
3253         delete msg;
3254 }
3255
3256 void CkLocMgr::restore(const CkArrayIndex &idx, PUP::er &p)
3257 {
3258         //This is in broughtIntoMem during out-of-core emulation in BigSim,
3259         //informHome should not be called since such information is already
3260         //immediately updated real migration
3261 #if CMK_ERROR_CHECKING
3262         if(_BgOutOfCoreFlag!=2)
3263             CmiAbort("CkLocMgr::restore should only be used in out-of-core emulation for BigSim and be called when object is brought into memory!\n");
3264 #endif
3265         CkLocRec_local *rec=createLocal(idx,false,false,false);
3266         
3267         //BIGSIM_OOC DEBUGGING
3268         //CkPrintf("Proc[%d]: Registering element %s with LDB\n", CkMyPe(), idx2str(idx));
3269
3270         //Create the new elements as we unpack the message
3271         pupElementsFor(p,rec,CkElementCreation_restore);
3272
3273         callMethod(rec,&CkMigratable::ckJustRestored);
3274 }
3275
3276
3277 /// Insert and unpack this array element from this checkpoint (e.g., from CkLocation::pup)
3278 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
3279 void CkLocMgr::resume(const CkArrayIndex &idx, PUP::er &p, bool create, int dummy)
3280 {
3281         CkLocRec_local *rec;
3282         CkLocRec *recGlobal;    
3283
3284         if(create){
3285                 rec = createLocal(idx,false,false,true && !dummy /* home doesn't know yet */,dummy );
3286         }else{
3287                 recGlobal = elementNrec(idx);
3288                 if(recGlobal == NULL) 
3289                         CmiAbort("Local object not found");
3290                 if(recGlobal->type() != CkLocRec::local)
3291                         CmiAbort("Local object not local, :P");
3292                 rec = (CkLocRec_local *)recGlobal;
3293         }
3294         
3295     pupElementsFor(p,rec,CkElementCreation_resume,create,dummy);
3296
3297     if(!dummy){
3298         callMethod(rec,&CkMigratable::ckJustMigrated);
3299     }
3300 }
3301 #else
3302 void CkLocMgr::resume(const CkArrayIndex &idx, PUP::er &p, bool notify,bool rebuild)
3303 {
3304         CkLocRec_local *rec=createLocal(idx,false,false,notify /* home doesn't know yet */ );
3305
3306         //Create the new elements as we unpack the message
3307         pupElementsFor(p,rec,CkElementCreation_resume,rebuild);
3308
3309         callMethod(rec,&CkMigratable::ckJustMigrated);
3310 }
3311 #endif
3312
3313 /********************* LocMgr: UTILITY ****************/
3314 void CkMagicNumber_impl::badMagicNumber(
3315         int expected,const char *file,int line,void *obj) const
3316 {
3317         CkError("FAILURE on pe %d, %s:%d> Expected %p's magic number "
3318                 "to be 0x%08x; but found 0x%08x!\n", CkMyPe(),file,line,obj,
3319                 expected, magic);
3320         CkAbort("Bad magic number detected!  This implies either\n"
3321                 "the heap or a message was corrupted!\n");
3322 }
3323 CkMagicNumber_impl::CkMagicNumber_impl(int m) :magic(m) { }
3324
3325 //Look up the object with this array index, or return NULL
3326 CkMigratable *CkLocMgr::lookup(const CkArrayIndex &idx,CkArrayID aid) {
3327         CkLocRec *rec=elementNrec(idx);
3328         if (rec==NULL) return NULL;
3329         else return rec->lookupElement(aid);
3330 }
3331 //"Last-known" location (returns a processor number)
3332 int CkLocMgr::lastKnown(const CkArrayIndex &idx) {
3333         CkLocMgr *vthis=(CkLocMgr *)this;//Cast away "const"
3334         CkLocRec *rec=vthis->elementNrec(idx);
3335         int pe=-1;
3336         if (rec!=NULL) pe=rec->lookupProcessor();
3337         if (pe==-1) return homePe(idx);
3338         else{
3339                 /*
3340                         FAULT_EVAC
3341                         if the lastKnownPE is invalid return homePE and delete this record
3342                 */
3343                 if(!CmiNodeAlive(pe)){
3344                         removeFromTable(idx);
3345                         return homePe(idx);
3346                 }
3347                 return pe;
3348         }       
3349 }
3350 /// Return true if this array element lives on another processor
3351 bool CkLocMgr::isRemote(const CkArrayIndex &idx,int *onPe) const
3352 {
3353         CkLocMgr *vthis=(CkLocMgr *)this;//Cast away "const"
3354         CkLocRec *rec=vthis->elementNrec(idx);
3355         if (rec==NULL || rec->type()!=CkLocRec::remote) 
3356                 return false; /* not definitely a remote element */
3357         else /* element is indeed remote */
3358         {
3359                 *onPe=rec->lookupProcessor();
3360                 return true;
3361         }
3362 }
3363
3364 static const char *rec2str[]={
3365     "base (INVALID)",//Base class (invalid type)
3366     "local",//Array element that lives on this Pe
3367     "remote",//Array element that lives on some other Pe
3368     "buffering",//Array element that was just created
3369     "dead"//Deleted element (for debugging)
3370 };
3371
3372 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
3373 void CkLocMgr::setDuringMigration(bool _duringMigration){
3374     duringMigration = _duringMigration;
3375 }
3376 #endif
3377
3378
3379 //Add given element array record at idx, replacing the existing record
3380 void CkLocMgr::insertRec(CkLocRec *rec,const CkArrayIndex &idx) {
3381         CkLocRec *old=elementNrec(idx);
3382         insertRecN(rec,idx);
3383         if (old!=NULL) {
3384                 DEBC((AA"  replaces old rec(%s) for %s\n"AB,rec2str[old->type()],idx2str(idx)));
3385                 //There was an old element at this location
3386                 if (old->type()==CkLocRec::local && rec->type()==CkLocRec::local) {
3387                     if (!CkInRestarting()) {    // ok if it is restarting
3388                         CkPrintf("ERROR! Duplicate array index: %s\n",idx2str(idx));
3389                         CkAbort("Duplicate array index used");
3390                     }
3391                 }
3392                 old->beenReplaced();
3393                 delete old;
3394         }
3395 }
3396
3397 //Add given record, when there is guarenteed to be no prior record
3398 void CkLocMgr::insertRecN(CkLocRec *rec,const CkArrayIndex &idx) {
3399         DEBC((AA"  adding new rec(%s) for %s\n"AB,rec2str[rec->type()],idx2str(idx)));
3400         checkInBounds(idx);
3401         CmiImmediateLock(hashImmLock);
3402         hash.put(*(CkArrayIndex *)&idx)=rec;
3403         CmiImmediateUnlock(hashImmLock);
3404 }
3405
3406 //Call this on an unrecognized array index
3407 static void abort_out_of_bounds(const CkArrayIndex &idx)
3408 {
3409   CkPrintf("ERROR! Unknown array index: %s\n",idx2str(idx));
3410   CkAbort("Array index out of bounds\n");
3411 }
3412
3413 //Look up array element in hash table.  Index out-of-bounds if not found.
3414 CkLocRec *CkLocMgr::elementRec(const CkArrayIndex &idx) {
3415 #if ! CMK_ERROR_CHECKING
3416 //Assume the element will be found
3417         return hash.getRef(idx);
3418 #else
3419 //Include an out-of-bounds check if the element isn't found
3420         CkLocRec *rec=elementNrec(idx);
3421         if (rec==NULL) abort_out_of_bounds(idx);
3422         return rec;
3423 #endif
3424 }
3425
3426 //Look up array element in hash table.  Return NULL if not there.
3427 CkLocRec *CkLocMgr::elementNrec(const CkArrayIndex &idx) {
3428         return hash.get(idx);
3429 }
3430
3431 struct LocalElementCounter :  public CkLocIterator
3432 {
3433     unsigned int count;
3434     LocalElementCounter() : count(0) {}
3435     void addLocation(CkLocation &loc)
3436         { ++count; }
3437 };
3438
3439 unsigned int CkLocMgr::numLocalElements()
3440 {
3441     LocalElementCounter c;
3442     iterate(c);
3443     return c.count;
3444 }
3445
3446
3447 /********************* LocMgr: LOAD BALANCE ****************/
3448
3449 #if !CMK_LBDB_ON
3450 //Empty versions of all load balancer calls
3451 void CkLocMgr::initLB(CkGroupID lbdbID_, CkGroupID metalbID_) {}
3452 void CkLocMgr::startInserting(void) {}
3453 void CkLocMgr::doneInserting(void) {}
3454 void CkLocMgr::dummyAtSync(void) {}
3455 #endif
3456
3457
3458 #if CMK_LBDB_ON
3459 void CkLocMgr::initLB(CkGroupID lbdbID_, CkGroupID metalbID_)
3460 { //Find and register with the load balancer
3461         the_lbdb = (LBDatabase *)CkLocalBranch(lbdbID_);
3462         if (the_lbdb == 0)
3463                 CkAbort("LBDatabase not yet created?\n");
3464         DEBL((AA"Connected to load balancer %p\n"AB,the_lbdb));
3465         the_metalb = (MetaBalancer *)CkLocalBranch(metalbID_);
3466         if (the_metalb == 0)
3467                 CkAbort("MetaBalancer not yet created?\n");
3468
3469         // Register myself as an object manager
3470         LDOMid myId;
3471         myId.id = thisgroup;
3472         LDCallbacks myCallbacks;
3473         myCallbacks.migrate = (LDMigrateFn)CkLocRec_local::staticMigrate;
3474         myCallbacks.setStats = NULL;
3475         myCallbacks.queryEstLoad = NULL;
3476   myCallbacks.metaLBResumeWaitingChares =
3477       (LDMetaLBResumeWaitingCharesFn)CkLocRec_local::staticMetaLBResumeWaitingChares;
3478   myCallbacks.metaLBCallLBOnChares =
3479       (LDMetaLBCallLBOnCharesFn)CkLocRec_local::staticMetaLBCallLBOnChares;
3480         myLBHandle = the_lbdb->RegisterOM(myId,this,myCallbacks);
3481
3482         // Tell the lbdb that I'm registering objects
3483         the_lbdb->RegisteringObjects(myLBHandle);
3484
3485         /*Set up the dummy barrier-- the load balancer needs
3486           us to call Registering/DoneRegistering during each AtSync,
3487           and this is the only way to do so.
3488         */
3489         lbBarrierReceiver = the_lbdb->AddLocalBarrierReceiver(
3490                 (LDBarrierFn)staticRecvAtSync,(void*)(this));
3491         dummyBarrierHandle = the_lbdb->AddLocalBarrierClient(
3492                 (LDResumeFn)staticDummyResumeFromSync,(void*)(this));
3493         dummyAtSync();
3494 }
3495 void CkLocMgr::dummyAtSync(void)
3496 {
3497         DEBL((AA"dummyAtSync called\n"AB));
3498         the_lbdb->AtLocalBarrier(dummyBarrierHandle);
3499 }
3500
3501 void CkLocMgr::staticDummyResumeFromSync(void* data)
3502 {      ((CkLocMgr*)data)->dummyResumeFromSync(); }
3503 void CkLocMgr::dummyResumeFromSync()
3504 {
3505         DEBL((AA"DummyResumeFromSync called\n"AB));
3506         the_lbdb->DoneRegisteringObjects(myLBHandle);
3507         dummyAtSync();
3508 }
3509 void CkLocMgr::staticRecvAtSync(void* data)
3510 {      ((CkLocMgr*)data)->recvAtSync(); }
3511 void CkLocMgr::recvAtSync()
3512 {
3513         DEBL((AA"recvAtSync called\n"AB));
3514         the_lbdb->RegisteringObjects(myLBHandle);
3515 }
3516
3517 void CkLocMgr::startInserting(void)
3518 {
3519         the_lbdb->RegisteringObjects(myLBHandle);
3520 }
3521 void CkLocMgr::doneInserting(void)
3522 {
3523         the_lbdb->DoneRegisteringObjects(myLBHandle);
3524 }
3525 #endif
3526
3527 #include "CkLocation.def.h"
3528
3529