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