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