fix bug for ending and clean up commits
[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()) 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         p | chkp_cb;
1104         p | atsync_chkp_iter;   
1105         if(p.isUnpacking()){
1106                 resetForChkp();
1107         }
1108
1109         ckFinishConstruction();
1110 }
1111
1112 void CkMigratable::ckDestroy(void) {
1113         DEBC((AA"In CkMigratable::ckDestroy %s\n"AB,idx2str(thisIndexMax)));
1114         myRec->destroy();
1115 }
1116
1117 void CkMigratable::ckAboutToMigrate(void) { }
1118 void CkMigratable::ckJustMigrated(void) { }
1119 void CkMigratable::ckJustRestored(void) { }
1120
1121 CkMigratable::~CkMigratable() {
1122         DEBC((AA"In CkMigratable::~CkMigratable %s\n"AB,idx2str(thisIndexMax)));
1123 #if CMK_OUT_OF_CORE
1124         isInCore=CmiFalse;
1125         if (CkpvAccess(CkSaveRestorePrefetch)) 
1126                 return; /* Just saving to disk--don't deregister anything. */
1127         /* We're really leaving or dying-- unregister from the ooc system*/
1128         if (prefetchObjID!=-1) {
1129                 CooDeregisterObject(prefetchObjID);
1130                 prefetchObjID=-1;
1131         }
1132 #endif
1133         /*Might want to tell myRec about our doom here--
1134         it's difficult to avoid some kind of circular-delete, though.
1135         */
1136 #if CMK_LBDB_ON 
1137         if (barrierRegistered) {
1138           DEBL((AA"Removing barrier for element %s\n"AB,idx2str(thisIndexMax)));
1139           //CkPrintf("Removing barrier for element %s\n",idx2str(thisIndexMax));
1140           if (usesAtSync)
1141                 myRec->getLBDB()->RemoveLocalBarrierClient(ldBarrierHandle);
1142           else
1143                 myRec->getLBDB()->RemoveLocalBarrierReceiver(ldBarrierRecvHandle);
1144         }
1145 #endif
1146         //To detect use-after-delete
1147         thisIndexMax.nInts=-12345;
1148         thisIndexMax.dimension=-12345;
1149 }
1150
1151 void CkMigratable::CkAbort(const char *why) const {
1152         CkError("CkMigratable '%s' aborting:\n",_chareTable[thisChareType]->name);
1153         ::CkAbort(why);
1154 }
1155
1156 void CkMigratable::ResumeFromSync(void)
1157 {
1158 //      CkAbort("::ResumeFromSync() not defined for this array element!\n");
1159 }
1160
1161 void CkMigratable::UserSetLBLoad() {
1162         CkAbort("::UserSetLBLoad() not defined for this array element!\n");
1163 }
1164
1165 #if CMK_LBDB_ON  //For load balancing:
1166 // user can call this helper function to set obj load (for model-based lb)
1167 void CkMigratable::setObjTime(double cputime) {
1168         myRec->setObjTime(cputime);
1169 }
1170 double CkMigratable::getObjTime() {
1171         return myRec->getObjTime();
1172 }
1173
1174 void CkMigratable::clearMetaLBData() {
1175 //  if (can_reset) {
1176     local_state = OFF;
1177     atsync_iteration = -1;
1178     prev_load = 0.0;
1179     can_reset = false;
1180 //  }
1181 }
1182
1183 void CkMigratable::recvLBPeriod(void *data) {
1184   if (atsync_iteration < 0) {
1185     return;
1186   }
1187   int lb_period = *((int *) data);
1188  DEBAD(("\t[obj %s] Received the LB Period %d current iter %d state %d on PE %d\n",
1189      idx2str(thisIndexMax), lb_period, atsync_iteration, local_state, CkMyPe()));
1190
1191   bool is_tentative;
1192   if (local_state == LOAD_BALANCE) {
1193     CkAssert(lb_period == myRec->getMetaBalancer()->getPredictedLBPeriod(is_tentative));
1194     return;
1195   }
1196
1197   if (local_state == PAUSE) {
1198     if (atsync_iteration < lb_period) {
1199       local_state = DECIDED;
1200       ResumeFromSync();
1201       return;
1202     }
1203     local_state = LOAD_BALANCE;
1204
1205     can_reset = true;
1206     //myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
1207     return;
1208   }
1209   local_state = DECIDED;
1210 }
1211
1212 void CkMigratable::metaLBCallLB() {
1213         myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
1214 }
1215
1216 void CkMigratable::ckFinishConstruction(void)
1217 {
1218 //      if ((!usesAtSync) || barrierRegistered) return;
1219         myRec->setMeasure(usesAutoMeasure);
1220         if (barrierRegistered) return;
1221         DEBL((AA"Registering barrier client for %s\n"AB,idx2str(thisIndexMax)));
1222         //CkPrintf("Registering barrier client for %s\n",idx2str(thisIndexMax));
1223         if (usesAtSync)
1224           ldBarrierHandle = myRec->getLBDB()->AddLocalBarrierClient(
1225                 (LDBarrierFn)staticResumeFromSync,(void*)(this));
1226         else
1227           ldBarrierRecvHandle = myRec->getLBDB()->AddLocalBarrierReceiver(
1228                 (LDBarrierFn)staticResumeFromSync,(void*)(this));
1229         barrierRegistered=CmiTrue;
1230 }
1231
1232
1233 void CkMigratable::setChkpResumeClient(CkCallback & _cb)
1234 {
1235         chkp_cb = _cb;
1236         nextChkpIter = -1;
1237         nextChkpDecided = false;
1238         atsync_chkp_iter = -1;
1239         local_chkp_pause = false;
1240         usesChkpAtSync = CmiTrue;
1241 }
1242
1243 void CkMigratable::AtChkpSync()
1244 {
1245         if(usesChkpAtSync){
1246                 if(CmiNumPartition()==1){
1247                         chkp_cb.send();
1248                         return;
1249                 }
1250                 atsync_chkp_iter++;
1251                 myRec->getChkpMgr()->recvIter(atsync_chkp_iter);
1252                 //reduction to decide the current maximum
1253                 if(nextChkpDecided){
1254                         if(atsync_chkp_iter<nextChkpIter){
1255                                 chkp_cb.send();
1256                         }else if(atsync_chkp_iter == nextChkpIter){
1257                                 resetForChkp();
1258                                 myRec->getChkpMgr()->reachChkpIter();
1259                         }else{
1260                                 CkAbort("Impossible state\n");
1261                         }
1262                 }
1263                 else if(myRec->getChkpMgr()->localDecided){
1264                         int localIter = myRec->getChkpMgr()->localMaxIter;
1265                         if(atsync_chkp_iter==localIter){
1266                                 local_chkp_pause = true;
1267                         }
1268                         else if(atsync_chkp_iter<localIter){
1269                                 chkp_cb.send();
1270                         }
1271                         else{
1272                                 CkAbort("local Impossible state\n");
1273                         }
1274                 }       
1275                 else{
1276                         chkp_cb.send();
1277                 }
1278         }
1279 }
1280
1281 void CkMigratable::resetForChkp(){
1282         nextChkpDecided = false;
1283         local_chkp_pause = false;
1284 }
1285
1286 void CkMigratable::ResumeFromChkp(){
1287 //      if(!chkp_cb.isInvalid())
1288         if(usesChkpAtSync){     
1289                 chkp_cb.send();
1290         }
1291 }
1292
1293 void CkMigratable::recvChkpIter(void * _iter){
1294         if(usesChkpAtSync){
1295                 int iter = *(int *)_iter;
1296                 nextChkpIter = iter;
1297                 nextChkpDecided = true;
1298                 if(atsync_chkp_iter>nextChkpIter){
1299                         CkAbort("impossible state in notify\n");
1300                 }
1301                 else if(atsync_chkp_iter==nextChkpIter){
1302                         resetForChkp();
1303                         myRec->getChkpMgr()->reachChkpIter();
1304                 }
1305                 else{
1306                         if(local_chkp_pause){
1307                                 if(!chkp_cb.isInvalid())
1308                                         chkp_cb.send(); 
1309                         }
1310                 }
1311         }
1312 }
1313
1314 void CkMigratable::AtSync(int waitForMigration)
1315 {
1316         if (!usesAtSync)
1317                 CkAbort("You must set usesAtSync=CmiTrue in your array element constructor to use AtSync!\n");
1318 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1319         mlogData->toResumeOrNot=1;
1320 #endif
1321         myRec->AsyncMigrate(!waitForMigration);
1322         if (waitForMigration) ReadyMigrate(CmiTrue);
1323         ckFinishConstruction();
1324   //DEBL((AA"Element %s going to sync\n"AB,idx2str(thisIndexMax)));
1325   //if(CmiMyPartition()==1)
1326 //      CkPrintf("Element %s going to sync\n",idx2str(thisIndexMax));
1327   // model-based load balancing, ask user to provide cpu load
1328   if (usesAutoMeasure == CmiFalse) UserSetLBLoad();
1329
1330   if (!_lb_args.metaLbOn()) {
1331     myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
1332     return;
1333   }
1334
1335   // When MetaBalancer is turned on
1336
1337   if (atsync_iteration == -1) {
1338     can_reset = false;
1339     local_state = OFF;
1340     prev_load = 0.0;
1341   }
1342
1343   atsync_iteration++;
1344   //CkPrintf("[pe %s] atsync_iter %d && predicted period %d state: %d\n",
1345   //    idx2str(thisIndexMax), atsync_iteration,
1346   //    myRec->getMetaBalancer()->getPredictedLBPeriod(), local_state);
1347   double tmp = prev_load;
1348   prev_load = myRec->getObjTime();
1349   double current_load = prev_load - tmp;
1350   if (atsync_iteration <= myRec->getMetaBalancer()->get_finished_iteration()) {
1351     CkPrintf("[%d:%s] Error!! Contributing to iter %d < current iter %d\n",
1352       CkMyPe(), idx2str(thisIndexMax), atsync_iteration,
1353       myRec->getMetaBalancer()->get_finished_iteration());
1354     CkAbort("Not contributing to the right iteration\n");
1355   }
1356
1357   if (atsync_iteration != 0) {
1358     myRec->getMetaBalancer()->AddLoad(atsync_iteration, current_load);
1359   }
1360
1361   bool is_tentative;
1362   if (atsync_iteration < myRec->getMetaBalancer()->getPredictedLBPeriod(is_tentative)) {
1363     ResumeFromSync();
1364   } else if (is_tentative) {
1365     local_state = PAUSE;
1366   } else if (local_state == DECIDED) {
1367     DEBAD(("[%d:%s] Went to load balance iter %d\n", CkMyPe(), idx2str(thisIndexMax), atsync_iteration));
1368     local_state = LOAD_BALANCE;
1369     can_reset = true;
1370     //myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
1371   } else {
1372     DEBAD(("[%d:%s] Went to pause state iter %d\n", CkMyPe(), idx2str(thisIndexMax), atsync_iteration));
1373     local_state = PAUSE;
1374   }
1375 }
1376
1377 void CkMigratable::ReadyMigrate(CmiBool ready)
1378 {
1379         myRec->ReadyMigrate(ready);
1380 }
1381
1382 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1383     extern int globalResumeCount;
1384 #endif
1385
1386 void CkMigratable::staticResumeFromSync(void* data)
1387 {
1388         CkMigratable *el=(CkMigratable *)data;
1389 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1390     if(el->mlogData->toResumeOrNot ==0 || el->mlogData->resumeCount >= globalResumeCount){
1391         return;
1392     }
1393 #endif
1394         DEBL((AA"Element %s resuming from sync\n"AB,idx2str(el->thisIndexMax)));
1395 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1396     CpvAccess(_currentObj) = el;
1397 #endif
1398
1399   if (_lb_args.metaLbOn()) {
1400         el->clearMetaLBData();
1401         }
1402         el->ResumeFromSync();
1403 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1404     el->mlogData->resumeCount++;
1405 #endif
1406 }
1407 void CkMigratable::setMigratable(int migratable) 
1408 {
1409         myRec->setMigratable(migratable);
1410 }
1411
1412 struct CkArrayThreadListener {
1413         struct CthThreadListener base;
1414         CkMigratable *mig;
1415 };
1416
1417 extern "C"
1418 void CkArrayThreadListener_suspend(struct CthThreadListener *l)
1419 {
1420         CkArrayThreadListener *a=(CkArrayThreadListener *)l;
1421         a->mig->ckStopTiming();
1422 }
1423
1424 extern "C"
1425 void CkArrayThreadListener_resume(struct CthThreadListener *l)
1426 {
1427         CkArrayThreadListener *a=(CkArrayThreadListener *)l;
1428         a->mig->ckStartTiming();
1429 }
1430
1431 extern "C"
1432 void CkArrayThreadListener_free(struct CthThreadListener *l)
1433 {
1434         CkArrayThreadListener *a=(CkArrayThreadListener *)l;
1435         delete a;
1436 }
1437
1438 void CkMigratable::CkAddThreadListeners(CthThread tid, void *msg)
1439 {
1440         Chare::CkAddThreadListeners(tid, msg);   // for trace
1441         CthSetThreadID(tid, thisIndexMax.data()[0], thisIndexMax.data()[1], 
1442                        thisIndexMax.data()[2]);
1443         CkArrayThreadListener *a=new CkArrayThreadListener;
1444         a->base.suspend=CkArrayThreadListener_suspend;
1445         a->base.resume=CkArrayThreadListener_resume;
1446         a->base.free=CkArrayThreadListener_free;
1447         a->mig=this;
1448         CthAddListener(tid,(struct CthThreadListener *)a);
1449 }
1450 #else
1451 void CkMigratable::setObjTime(double cputime) {}
1452 double CkMigratable::getObjTime() {return 0.0;}
1453
1454 /* no load balancer: need dummy implementations to prevent link error */
1455 void CkMigratable::CkAddThreadListeners(CthThread tid, void *msg)
1456 {
1457 }
1458 #endif
1459
1460
1461 /*CkMigratableList*/
1462 CkMigratableList::CkMigratableList() {}
1463 CkMigratableList::~CkMigratableList() {}
1464
1465 void CkMigratableList::setSize(int s) {
1466         el.resize(s);
1467 }
1468
1469 void CkMigratableList::put(CkMigratable *v,int atIdx) {
1470 #if CMK_ERROR_CHECKING
1471         if (atIdx>=length())
1472                 CkAbort("Internal array manager error (CkMigrableList::put index out of bounds)");
1473 #endif
1474         el[atIdx]=v;
1475 }
1476
1477
1478 /************************** Location Records: *********************************/
1479
1480 //---------------- Base type:
1481 void CkLocRec::weAreObsolete(const CkArrayIndex &idx) {}
1482 CkLocRec::~CkLocRec() { }
1483 void CkLocRec::beenReplaced(void)
1484     {/*Default: ignore replacement*/}
1485
1486 //Return the represented array element; or NULL if there is none
1487 CkMigratable *CkLocRec::lookupElement(CkArrayID aid) {return NULL;}
1488
1489 //Return the last known processor; or -1 if none
1490 int CkLocRec::lookupProcessor(void) {return -1;}
1491
1492
1493 /*----------------- Local:
1494 Matches up the array index with the local index, an
1495 interfaces with the load balancer on behalf of the
1496 represented array elements.
1497 */
1498 CkLocRec_local::CkLocRec_local(CkLocMgr *mgr,CmiBool fromMigration,
1499   CmiBool ignoreArrival, const CkArrayIndex &idx_,int localIdx_)
1500         :CkLocRec(mgr),idx(idx_),localIdx(localIdx_),
1501          running(CmiFalse),deletedMarker(NULL)
1502 {
1503 #if CMK_LBDB_ON
1504         DEBL((AA"Registering element %s with load balancer\n"AB,idx2str(idx)));
1505         //BIGSIM_OOC DEBUGGING
1506         //CkPrintf("LocMgr on %d: Registering element %s with load balancer\n", CkMyPe(), idx2str(idx));
1507         nextPe = -1;
1508         asyncMigrate = CmiFalse;
1509         readyMigrate = CmiTrue;
1510         enable_measure = CmiTrue;
1511         bounced  = CmiFalse;
1512         the_lbdb=mgr->getLBDB();
1513         the_metalb=mgr->getMetaBalancer();
1514         the_chkp = mgr->getChkpMgr();
1515         LDObjid ldid = idx2LDObjid(idx);
1516 #if CMK_GLOBAL_LOCATION_UPDATE
1517         ldid.locMgrGid = mgr->getGroupID().idx;
1518 #endif        
1519         ldHandle=the_lbdb->RegisterObj(mgr->getOMHandle(),
1520                 ldid,(void *)this,1);
1521         if (fromMigration) {
1522                 DEBL((AA"Element %s migrated in\n"AB,idx2str(idx)));
1523                 if (!ignoreArrival)  {
1524                         the_lbdb->Migrated(ldHandle, CmiTrue);
1525                   // load balancer should ignore this objects movement
1526                 //  AsyncMigrate(CmiTrue);
1527                 }
1528         }
1529 #endif
1530         the_chkp = mgr->getChkpMgr();
1531         /*
1532                 FAULT_EVAC
1533         */
1534         asyncEvacuate = CmiTrue;
1535 }
1536 CkLocRec_local::~CkLocRec_local()
1537 {
1538         if (deletedMarker!=NULL) *deletedMarker=CmiTrue;
1539         myLocMgr->reclaim(idx,localIdx);
1540 #if CMK_LBDB_ON
1541         stopTiming();
1542         DEBL((AA"Unregistering element %s from load balancer\n"AB,idx2str(idx)));
1543         the_lbdb->UnregisterObj(ldHandle);
1544 #endif
1545 }
1546 void CkLocRec_local::migrateMe(int toPe) //Leaving this processor
1547 {
1548         //This will pack us up, send us off, and delete us
1549 //      printf("[%d] migrating migrateMe to %d \n",CkMyPe(),toPe);
1550         myLocMgr->emigrate(this,toPe);
1551 }
1552
1553 #if CMK_LBDB_ON
1554 void CkLocRec_local::informIdealLBPeriod(int lb_ideal_period) {
1555   myLocMgr->informLBPeriod(this, lb_ideal_period);
1556 }
1557
1558 void CkLocRec_local::metaLBCallLB() {
1559         myLocMgr->metaLBCallLB(this);
1560 }
1561
1562 void CkLocRec_local::startTiming(int ignore_running) {
1563         if (!ignore_running) running=CmiTrue;
1564         DEBL((AA"Start timing for %s at %.3fs {\n"AB,idx2str(idx),CkWallTimer()));
1565         if (enable_measure) the_lbdb->ObjectStart(ldHandle);
1566 }
1567 void CkLocRec_local::stopTiming(int ignore_running) {
1568         DEBL((AA"} Stop timing for %s at %.3fs\n"AB,idx2str(idx),CkWallTimer()));
1569         if ((ignore_running || running) && enable_measure) the_lbdb->ObjectStop(ldHandle);
1570         if (!ignore_running) running=CmiFalse;
1571 }
1572 void CkLocRec_local::setObjTime(double cputime) {
1573         the_lbdb->EstObjLoad(ldHandle, cputime);
1574 }
1575 double CkLocRec_local::getObjTime() {
1576         LBRealType walltime, cputime;
1577         the_lbdb->GetObjLoad(ldHandle, walltime, cputime);
1578         return walltime;
1579 }
1580 #endif
1581
1582 void CkLocRec_local::destroy(void) //User called destructor
1583 {
1584         //Our destructor does all the needed work
1585         delete this;
1586 }
1587 //Return the represented array element; or NULL if there is none
1588 CkMigratable *CkLocRec_local::lookupElement(CkArrayID aid) {
1589         return myLocMgr->lookupLocal(localIdx,aid);
1590 }
1591
1592 //Return the last known processor; or -1 if none
1593 int CkLocRec_local::lookupProcessor(void) {
1594         return CkMyPe();
1595 }
1596
1597 CkLocRec::RecType CkLocRec_local::type(void)
1598 {
1599         return local;
1600 }
1601
1602 void CkLocRec_local::addedElement(void) 
1603 {
1604         //Push everything in the half-created queue into the system--
1605         // anything not ready yet will be put back in.
1606         while (!halfCreated.isEmpty()) 
1607                 CkArrayManagerDeliver(CkMyPe(),halfCreated.deq());
1608 }
1609
1610 CmiBool CkLocRec_local::isObsolete(int nSprings,const CkArrayIndex &idx_)
1611
1612         int len=halfCreated.length();
1613         if (len!=0) {
1614                 /* This is suspicious-- the halfCreated queue should be extremely
1615                  transient.  It's possible we just looked at the wrong time, though;
1616                  so this is only a warning. 
1617                 */
1618                 CkPrintf("CkLoc WARNING> %d messages still around for uncreated element %s!\n",
1619                          len,idx2str(idx));
1620         }
1621         //A local element never expires
1622         return CmiFalse;
1623 }
1624
1625 /**********Added for cosmology (inline function handling without parameter marshalling)***********/
1626
1627 LDObjHandle CkMigratable::timingBeforeCall(int* objstopped){
1628
1629         LDObjHandle objHandle;
1630 #if CMK_LBDB_ON
1631         if (getLBDB()->RunningObject(&objHandle)) {
1632                 *objstopped = 1;
1633                 getLBDB()->ObjectStop(objHandle);
1634         }
1635         myRec->startTiming(1);
1636 #endif
1637
1638   //DEBS((AA"   Invoking entry %d on element %s\n"AB,epIdx,idx2str(idx)));
1639         //CmiBool isDeleted=CmiFalse; //Enables us to detect deletion during processing
1640         //deletedMarker=&isDeleted;
1641 /*#ifndef CMK_OPTIMIZE
1642         if (msg) {  Tracing: 
1643                 envelope *env=UsrToEnv(msg);
1644         //      CkPrintf("ckLocation.C beginExecuteDetailed %d %d \n",env->getEvent(),env->getsetArraySrcPe());
1645                 if (_entryTable[epIdx]->traceEnabled)
1646                         _TRACE_BEGIN_EXECUTE_DETAILED(env->getEvent(),
1647                                  ForChareMsg,epIdx,env->getsetArraySrcPe(), env->getTotalsize(), idx.getProjectionID(((CkGroupID)env->getsetArrayMgr())).idx);
1648         }
1649 #endif*/
1650
1651   return objHandle;
1652 }
1653
1654 void CkMigratable::timingAfterCall(LDObjHandle objHandle,int *objstopped){
1655   
1656 /*#ifndef CMK_OPTIMIZE
1657         if (msg) {  Tracing: 
1658                 if (_entryTable[epIdx]->traceEnabled)
1659                         _TRACE_END_EXECUTE();
1660         }
1661 #endif*/
1662 //#if CMK_LBDB_ON
1663 //        if (!isDeleted) checkBufferedMigration();   // check if should migrate
1664 //#endif
1665 //      if (isDeleted) return CmiFalse;//We were deleted
1666 //      deletedMarker=NULL;
1667 //      return CmiTrue;
1668         myRec->stopTiming(1);
1669 #if CMK_LBDB_ON
1670         if (*objstopped) {
1671                  getLBDB()->ObjectStart(objHandle);
1672         }
1673 #endif
1674
1675  return;
1676 }
1677 /****************************************************************************/
1678
1679
1680 CmiBool CkLocRec_local::invokeEntry(CkMigratable *obj,void *msg,
1681         int epIdx,CmiBool doFree) 
1682 {
1683
1684         DEBS((AA"   Invoking entry %d on element %s\n"AB,epIdx,idx2str(idx)));
1685         CmiBool isDeleted=CmiFalse; //Enables us to detect deletion during processing
1686         deletedMarker=&isDeleted;
1687         startTiming();
1688
1689
1690 #if CMK_TRACE_ENABLED
1691         if (msg) { /* Tracing: */
1692                 envelope *env=UsrToEnv(msg);
1693         //      CkPrintf("ckLocation.C beginExecuteDetailed %d %d \n",env->getEvent(),env->getsetArraySrcPe());
1694                 if (_entryTable[epIdx]->traceEnabled)
1695                         _TRACE_BEGIN_EXECUTE_DETAILED(env->getEvent(),
1696                                  ForChareMsg,epIdx,env->getsetArraySrcPe(), env->getTotalsize(), idx.getProjectionID((((CkGroupID)env->getsetArrayMgr())).idx));
1697         }
1698 #endif
1699
1700         if (doFree) 
1701            CkDeliverMessageFree(epIdx,msg,obj);
1702         else /* !doFree */
1703            CkDeliverMessageReadonly(epIdx,msg,obj);
1704
1705
1706 #if CMK_TRACE_ENABLED
1707         if (msg) { /* Tracing: */
1708                 if (_entryTable[epIdx]->traceEnabled)
1709                         _TRACE_END_EXECUTE();
1710         }
1711 #endif
1712 #if CMK_LBDB_ON
1713         if (!isDeleted) checkBufferedMigration();   // check if should migrate
1714 #endif
1715         if (isDeleted) return CmiFalse;//We were deleted
1716         deletedMarker=NULL;
1717         stopTiming();
1718         return CmiTrue;
1719 }
1720
1721 CmiBool CkLocRec_local::deliver(CkArrayMessage *msg,CkDeliver_t type,int opts)
1722 {
1723
1724         if (type==CkDeliver_queue) { /*Send via the message queue */
1725                 if (opts & CK_MSG_KEEP)
1726                         msg = (CkArrayMessage *)CkCopyMsg((void **)&msg);
1727                 CkArrayManagerDeliver(CkMyPe(),msg,opts);
1728                 return CmiTrue;
1729         }
1730         else
1731         {
1732                 CkMigratable *obj=myLocMgr->lookupLocal(localIdx,
1733                         UsrToEnv(msg)->getsetArrayMgr());
1734                 if (obj==NULL) {//That sibling of this object isn't created yet!
1735                         if (opts & CK_MSG_KEEP)
1736                                 msg = (CkArrayMessage *)CkCopyMsg((void **)&msg);
1737                         if (msg->array_ifNotThere()!=CkArray_IfNotThere_buffer) {
1738                                 return myLocMgr->demandCreateElement(msg,CkMyPe(),type);
1739                         }
1740                         else {
1741                                 DEBS((AA"   BUFFERING message for nonexistent element %s!\n"AB,idx2str(this->idx)));
1742                                 halfCreated.enq(msg);
1743                                 return CmiTrue;
1744                         }
1745                 }
1746                         
1747                 if (msg->array_hops()>1)
1748                         myLocMgr->multiHop(msg);
1749                 CmiBool doFree = (CmiBool)!(opts & CK_MSG_KEEP);
1750 #if CMK_LBDB_ON
1751                 // if there is a running obj being measured, stop it temporarily
1752                 LDObjHandle objHandle;
1753                 int objstopped = 0;
1754                 if (the_lbdb->RunningObject(&objHandle)) {
1755                         objstopped = 1;
1756                         the_lbdb->ObjectStop(objHandle);
1757                 }
1758 #endif
1759 #if CMK_GRID_QUEUE_AVAILABLE
1760                 // retain a pointer to the sending object (needed later)
1761                 CpvAccess(CkGridObject) = obj;
1762 #endif
1763
1764         CmiBool status = invokeEntry(obj,(void *)msg,msg->array_ep(),doFree);
1765         
1766 #if CMK_GRID_QUEUE_AVAILABLE
1767                 CpvAccess(CkGridObject) = NULL;
1768 #endif
1769 #if CMK_LBDB_ON
1770                 if (objstopped) the_lbdb->ObjectStart(objHandle);
1771 #endif
1772                 return status;
1773         }
1774
1775
1776 }
1777
1778 #if CMK_LBDB_ON
1779
1780 void CkLocRec_local::staticMetaLBResumeWaitingChares(LDObjHandle h, int lb_ideal_period) {
1781         CkLocRec_local *el=(CkLocRec_local *)LDObjUserData(h);
1782         DEBL((AA"MetaBalancer wants to resume waiting chare %s\n"AB,idx2str(el->idx)));
1783         el->metaLBResumeWaitingChares(lb_ideal_period);
1784 }
1785
1786 void CkLocRec_local::metaLBResumeWaitingChares(int lb_ideal_period) {
1787   informIdealLBPeriod(lb_ideal_period);
1788 }
1789
1790 void CkLocRec_local::staticMetaLBCallLBOnChares(LDObjHandle h) {
1791         CkLocRec_local *el=(CkLocRec_local *)LDObjUserData(h);
1792         DEBL((AA"MetaBalancer wants to call LoadBalance on chare %s\n"AB,idx2str(el->idx)));
1793         el->metaLBCallLBOnChares();
1794 }
1795
1796 void CkLocRec_local::metaLBCallLBOnChares() {
1797   metaLBCallLB();
1798 }
1799
1800 void CkLocRec_local::staticMigrate(LDObjHandle h, int dest)
1801 {
1802         CkLocRec_local *el=(CkLocRec_local *)LDObjUserData(h);
1803         DEBL((AA"Load balancer wants to migrate %s to %d\n"AB,idx2str(el->idx),dest));
1804         el->recvMigrate(dest);
1805 }
1806
1807 void CkLocRec_local::recvMigrate(int toPe)
1808 {
1809         // we are in the mode of delaying actual migration
1810         // till readyMigrate()
1811         if (readyMigrate) { migrateMe(toPe); }
1812         else nextPe = toPe;
1813 }
1814
1815 void CkLocRec_local::AsyncMigrate(CmiBool use)  
1816 {
1817         asyncMigrate = use; 
1818         the_lbdb->UseAsyncMigrate(ldHandle, use);
1819 }
1820
1821 CmiBool CkLocRec_local::checkBufferedMigration()
1822 {
1823         // we don't migrate in user's code when calling ReadyMigrate(true)
1824         // we postphone the action to here until we exit from the user code.
1825         if (readyMigrate && nextPe != -1) {
1826             int toPe = nextPe;
1827             nextPe = -1;
1828             // don't migrate inside the object call
1829             migrateMe(toPe);
1830             // don't do anything
1831             return CmiTrue;
1832         }
1833         return CmiFalse;
1834 }
1835
1836 int CkLocRec_local::MigrateToPe()
1837 {
1838         int pe = nextPe;
1839         nextPe = -1;
1840         return pe;
1841 }
1842
1843 void CkLocRec_local::setMigratable(int migratable)
1844 {
1845         if (migratable)
1846           the_lbdb->Migratable(ldHandle);
1847         else
1848           the_lbdb->NonMigratable(ldHandle);
1849 }
1850 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1851 void CkLocRec_local::Migrated(){
1852     the_lbdb->Migrated(ldHandle, CmiTrue);
1853 }
1854 #endif
1855 #endif
1856
1857 /**
1858  * Represents a deleted array element (and prevents re-use).
1859  * These are a debugging aid, usable only by uncommenting a line in
1860  * the element destruction code.
1861  */
1862 class CkLocRec_dead:public CkLocRec {
1863 public:
1864         CkLocRec_dead(CkLocMgr *Narr):CkLocRec(Narr) {}
1865   
1866         virtual RecType type(void) {return dead;}
1867   
1868         virtual CmiBool deliver(CkArrayMessage *msg,CkDeliver_t type,int opts=0) {
1869                 CkPrintf("Dead array element is %s.\n",idx2str(msg->array_index()));
1870                 CkAbort("Send to dead array element!\n");
1871                 return CmiFalse;
1872         }
1873         virtual void beenReplaced(void) 
1874                 {CkAbort("Can't re-use dead array element!\n");}
1875   
1876         //Return if this element is now obsolete (it isn't)
1877         virtual CmiBool isObsolete(int nSprings,const CkArrayIndex &idx) {return CmiFalse;}     
1878 };
1879
1880 /**
1881  * This is the abstract superclass of arrayRecs that keep track of their age,
1882  * and eventually expire. Its kids are remote and buffering.
1883  */
1884 class CkLocRec_aging:public CkLocRec {
1885 private:
1886         int lastAccess;//Age when last accessed
1887 protected:
1888         //Update our access time
1889         inline void access(void) {
1890                 lastAccess=myLocMgr->getSpringCount();
1891         }
1892         //Return if we are "stale"-- we were last accessed a while ago
1893         CmiBool isStale(void) {
1894                 if (myLocMgr->getSpringCount()-lastAccess>3) return CmiTrue;
1895                 else return CmiFalse;
1896         }
1897 public:
1898         CkLocRec_aging(CkLocMgr *Narr):CkLocRec(Narr) {
1899                 lastAccess=myLocMgr->getSpringCount();
1900         }
1901         //Return if this element is now obsolete
1902         virtual CmiBool isObsolete(int nSprings,const CkArrayIndex &idx)=0;
1903         //virtual void pup(PUP::er &p) { CkLocRec::pup(p); p(lastAccess); }
1904 };
1905
1906
1907 /**
1908  * Represents a remote array element.  This is just a PE number.
1909  */
1910 class CkLocRec_remote:public CkLocRec_aging {
1911 private:
1912         int onPe;//The last known Pe for this element
1913 public:
1914         CkLocRec_remote(CkLocMgr *Narr,int NonPe)
1915                 :CkLocRec_aging(Narr)
1916                 {
1917                         onPe=NonPe;
1918 #if CMK_ERROR_CHECKING
1919                         if (onPe==CkMyPe())
1920                                 CkAbort("ERROR!  'remote' array element on this Pe!\n");
1921 #endif
1922                 }
1923         //Return the last known processor for this element
1924         int lookupProcessor(void) {
1925                 return onPe;
1926         }  
1927         virtual RecType type(void) {return remote;}
1928   
1929         //Send a message for this element.
1930         virtual CmiBool deliver(CkArrayMessage *msg,CkDeliver_t type,int opts=0) {
1931                 /*FAULT_EVAC*/
1932                 int destPE = onPe;
1933                 if((!CmiNodeAlive(onPe) && onPe != allowMessagesOnly)){
1934 //                      printf("Delivery failed because process %d is invalid\n",onPe);
1935                         /*
1936                                 Send it to its home processor instead
1937                         */
1938                         const CkArrayIndex &idx=msg->array_index();
1939                         destPE = getNextPE(idx);
1940                 }
1941                 access();//Update our modification date
1942                 msg->array_hops()++;
1943                 DEBS((AA"   Forwarding message for element %s to %d (REMOTE)\n"AB,
1944                       idx2str(msg->array_index()),destPE));
1945                 if (opts & CK_MSG_KEEP)
1946                         msg = (CkArrayMessage *)CkCopyMsg((void **)&msg);
1947                 CkArrayManagerDeliver(destPE,msg,opts);
1948                 return CmiTrue;
1949         }
1950         //Return if this element is now obsolete
1951         virtual CmiBool isObsolete(int nSprings,const CkArrayIndex &idx) {
1952                 if (myLocMgr->isHome(idx)) 
1953                         //Home elements never become obsolete
1954                         // if they did, we couldn't deliver messages to that element.
1955                         return CmiFalse;
1956                 else if (isStale())
1957                         return CmiTrue;//We haven't been used in a long time
1958                 else
1959                         return CmiFalse;//We're fairly recent
1960         }
1961         //virtual void pup(PUP::er &p) { CkLocRec_aging::pup(p); p(onPe); }
1962 };
1963
1964
1965 /**
1966  * Buffers messages until record is replaced in the hash table, 
1967  * then delivers all messages to the replacing record.  This is 
1968  * used when a message arrives for a local element that has not
1969  * yet been created, buffering messages until the new element finally
1970  * checks in.
1971  *
1972  * It's silly to send a message to an element you won't ever create,
1973  * so this kind of record causes an abort "Stale array manager message!"
1974  * if it's left undelivered too long.
1975  */
1976 class CkLocRec_buffering:public CkLocRec_aging {
1977 private:
1978         CkQ<CkArrayMessage *> buffer;//Buffered messages.
1979 public:
1980         CkLocRec_buffering(CkLocMgr *Narr):CkLocRec_aging(Narr) {}
1981         virtual ~CkLocRec_buffering() {
1982                 if (0!=buffer.length()) {
1983                         CkPrintf("[%d] Warning: Messages abandoned in array manager buffer!\n", CkMyPe());
1984                         CkArrayMessage *m;
1985                         while (NULL!=(m=buffer.deq()))  {
1986                                 delete m;
1987                         }
1988                 }
1989         }
1990   
1991         virtual RecType type(void) {return buffering;}
1992   
1993         //Buffer a message for this element.
1994         virtual CmiBool deliver(CkArrayMessage *msg,CkDeliver_t type,int opts=0) {
1995                 DEBS((AA" Queued message for %s\n"AB,idx2str(msg->array_index())));
1996                 if (opts & CK_MSG_KEEP)
1997                         msg = (CkArrayMessage *)CkCopyMsg((void **)&msg);
1998                 buffer.enq(msg);
1999 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2000                 envelope *env = UsrToEnv(msg);
2001                 env->sender = CpvAccess(_currentObj)->mlogData->objID;
2002 #endif
2003                 return CmiTrue;
2004         }
2005  
2006         //This is called when this ArrayRec is about to be replaced.
2007         // We dump all our buffered messages off on the next guy,
2008         // who should know what to do with them.
2009         virtual void beenReplaced(void) {
2010                 DEBS((AA" Delivering queued messages:\n"AB));
2011                 CkArrayMessage *m;
2012                 while (NULL!=(m=buffer.deq())) {
2013 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))         
2014                 DEBUG(CmiPrintf("[%d] buffered message being sent\n",CmiMyPe()));
2015                 envelope *env = UsrToEnv(m);
2016                 Chare *oldObj = CpvAccess(_currentObj);
2017                 CpvAccess(_currentObj) =(Chare *) env->sender.getObject();
2018                 env->sender.type = TypeInvalid;
2019 #endif
2020                 DEBS((AA"Sending buffered message to %s\n"AB,idx2str(m->array_index())));
2021                 myLocMgr->deliverViaQueue(m);
2022 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))         
2023                 CpvAccess(_currentObj) = oldObj;
2024 #endif
2025                 }
2026         }
2027   
2028         //Return if this element is now obsolete
2029         virtual CmiBool isObsolete(int nSprings,const CkArrayIndex &idx) {
2030                 if (isStale() && buffer.length()>0) {
2031                         /*This indicates something is seriously wrong--
2032                           buffers should be short-lived.*/
2033                         CkPrintf("[%d] WARNING: %d stale array message(s) found!\n",CkMyPe(),buffer.length());
2034                         CkArrayMessage *msg=buffer[0];
2035                         CkPrintf("Addressed to: ");
2036                         CkPrintEntryMethod(msg->array_ep());
2037                         CkPrintf(" index %s\n",idx2str(idx));
2038                         if (myLocMgr->isHome(idx)) 
2039                                 CkPrintf("is this an out-of-bounds array index, or was it never created?\n");
2040                         else //Idx is a remote-home index
2041                                 CkPrintf("why weren't they forwarded?\n");
2042                         
2043                         // CkAbort("Stale array manager message(s)!\n");
2044                 }
2045                 return CmiFalse;
2046         }
2047   
2048 /*  virtual void pup(PUP::er &p) {
2049     CkLocRec_aging::pup(p);
2050     CkArray::pupArrayMsgQ(buffer, p);
2051     }*/
2052 };
2053
2054 /*********************** Spring Cleaning *****************/
2055 /**
2056  * Used to periodically flush out unused remote element pointers.
2057  *
2058  * Cleaning often will free up memory quickly, but slow things
2059  * down because the cleaning takes time and some not-recently-referenced
2060  * remote element pointers might be valid and used some time in 
2061  * the future.
2062  *
2063  * Also used to determine if buffered messages have become stale.
2064  */
2065 inline void CkLocMgr::springCleaning(void)
2066 {
2067   nSprings++;
2068
2069   //Poke through the hash table for old ArrayRecs.
2070   void *objp;
2071   void *keyp;
2072   
2073   CkHashtableIterator *it=hash.iterator();
2074   CmiImmediateLock(hashImmLock);
2075   while (NULL!=(objp=it->next(&keyp))) {
2076     CkLocRec *rec=*(CkLocRec **)objp;
2077     CkArrayIndex &idx=*(CkArrayIndex *)keyp;
2078     if (rec->isObsolete(nSprings,idx)) {
2079       //This record is obsolete-- remove it from the table
2080       DEBK((AA"Cleaning out old record %s\n"AB,idx2str(idx)));
2081       hash.remove(*(CkArrayIndex *)&idx);
2082       delete rec;
2083       it->seek(-1);//retry this hash slot
2084     }
2085   }
2086   CmiImmediateUnlock(hashImmLock);
2087   delete it;
2088 }
2089 void CkLocMgr::staticSpringCleaning(void *forWhom,double curWallTime) {
2090         DEBK((AA"Starting spring cleaning at %.2f\n"AB,CkWallTimer()));
2091         ((CkLocMgr *)forWhom)->springCleaning();
2092 }
2093 //doesn't delete if there is extra pe
2094 void CkLocMgr::flushLocalRecs(void)
2095 {
2096   void *objp;
2097   void *keyp;
2098   CkHashtableIterator *it=hash.iterator();
2099   CmiImmediateLock(hashImmLock);
2100   while (NULL!=(objp=it->next(&keyp))) {
2101     CkLocRec *rec=*(CkLocRec **)objp;
2102     CkArrayIndex &idx=*(CkArrayIndex *)keyp;
2103     if (rec->type() == CkLocRec::local) {
2104         callMethod((CkLocRec_local*)rec, &CkMigratable::ckDestroy);
2105         it->seek(-1);//retry this hash slot
2106     }
2107   }
2108   delete it;
2109   CmiImmediateUnlock(hashImmLock);
2110 }
2111
2112 void CkLocMgr::recvChkpIter(int iter)
2113 {
2114   void *objp;
2115   void *keyp;
2116   CkHashtableIterator *it=hash.iterator();
2117   CmiImmediateLock(hashImmLock);
2118   while (NULL!=(objp=it->next(&keyp))) {
2119     CkLocRec *rec=*(CkLocRec **)objp;
2120     CkArrayIndex &idx=*(CkArrayIndex *)keyp;
2121     if (rec->type() == CkLocRec::local) {
2122         callMethod((CkLocRec_local*)rec, &CkMigratable::recvChkpIter,&iter);
2123     }
2124   }
2125   delete it;
2126   CmiImmediateUnlock(hashImmLock);
2127 }
2128
2129 void CkLocMgr::resumeFromChkp(){
2130   void *objp;
2131   void *keyp;
2132   CkHashtableIterator *it=hash.iterator();
2133   CmiImmediateLock(hashImmLock);
2134   while (NULL!=(objp=it->next(&keyp))) {
2135     CkLocRec *rec=*(CkLocRec **)objp;
2136     CkArrayIndex &idx=*(CkArrayIndex *)keyp;
2137     if (rec->type() == CkLocRec::local) {
2138         callMethod((CkLocRec_local*)rec, &CkMigratable::ResumeFromChkp);
2139     }
2140   }
2141   delete it;
2142   CmiImmediateUnlock(hashImmLock);
2143 }
2144
2145 // clean all buffer'ed messages and also free local objects
2146 void CkLocMgr::flushAllRecs(void)
2147 {
2148   void *objp;
2149   void *keyp;
2150   CkHashtableIterator *it=hash.iterator();
2151   CmiImmediateLock(hashImmLock);
2152   while (NULL!=(objp=it->next(&keyp))) {
2153     CkLocRec *rec=*(CkLocRec **)objp;
2154     CkArrayIndex &idx=*(CkArrayIndex *)keyp;
2155     if (rec->type() != CkLocRec::local) {
2156       //In the case of taking core out of memory (in BigSim's emulation)
2157       //the meta data in the location manager are not deleted so we need
2158       //this condition
2159       
2160       if(_BgOutOfCoreFlag!=1){
2161         hash.remove(*(CkArrayIndex *)&idx);
2162         delete rec;
2163         it->seek(-1);//retry this hash slot
2164       }
2165     }
2166     else {
2167         callMethod((CkLocRec_local*)rec, &CkMigratable::ckDestroy);
2168         it->seek(-1);//retry this hash slot
2169     }
2170   }
2171   delete it;
2172   CmiImmediateUnlock(hashImmLock);
2173 }
2174
2175
2176 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2177 void CkLocMgr::callForAllRecords(CkLocFn fnPointer,CkArray *arr,void *data){
2178         void *objp;
2179         void *keyp;
2180
2181         CkHashtableIterator *it = hash.iterator();
2182         while (NULL!=(objp=it->next(&keyp))) {
2183                 CkLocRec *rec=*(CkLocRec **)objp;
2184                 CkArrayIndex &idx=*(CkArrayIndex *)keyp;
2185                 fnPointer(arr,data,rec,&idx);
2186         }
2187
2188         // releasing iterator memory
2189         delete it;
2190 }
2191 #endif
2192
2193 /*************************** LocMgr: CREATION *****************************/
2194 CkLocMgr::CkLocMgr(CkGroupID mapID_,CkGroupID lbdbID_,CkGroupID metalbID_,CkArrayIndex& numInitial)
2195         :thisProxy(thisgroup),thislocalproxy(thisgroup,CkMyPe()),
2196          hash(17,0.3)
2197 {
2198         DEBC((AA"Creating new location manager %d\n"AB,thisgroup));
2199 // moved to _CkMigratable_initInfoInit()
2200 //      CkpvInitialize(CkMigratable_initInfo,mig_initInfo);
2201
2202         managers.init();
2203         nManagers=0;
2204         firstManager=NULL;
2205         firstFree=localLen=0;
2206         duringMigration=CmiFalse;
2207         nSprings=0;
2208 #if !CMK_GLOBAL_LOCATION_UPDATE
2209         CcdCallOnConditionKeepOnPE(CcdPERIODIC_1minute,staticSpringCleaning,(void *)this, CkMyPe());
2210 #endif
2211
2212 //Register with the map object
2213         mapID=mapID_;
2214         map=(CkArrayMap *)CkLocalBranch(mapID);
2215         if (map==NULL) CkAbort("ERROR!  Local branch of array map is NULL!");
2216         mapHandle=map->registerArray(numInitial,thisgroup);
2217
2218 //Find and register with the load balancer
2219         lbdbID = lbdbID_;
2220   metalbID = metalbID_;
2221         initLB(lbdbID_, metalbID_);
2222         hashImmLock = CmiCreateImmediateLock();
2223         chkpID = ckCheckPTGroupID;
2224         the_chkp = (CkMemCheckPT *)CkLocalBranch(chkpID);
2225 }
2226
2227 CkLocMgr::CkLocMgr(CkGroupID mapID_,CkGroupID lbdbID_,CkArrayIndex& numInitial)
2228         :thisProxy(thisgroup),thislocalproxy(thisgroup,CkMyPe()),
2229          hash(17,0.3)
2230 {
2231 #if !CMK_LBDB_ON
2232         CkGroupID _metalb;
2233 #endif
2234         CkLocMgr(mapID_, lbdbID_, _metalb, numInitial);
2235 }
2236
2237
2238 CkLocMgr::CkLocMgr(CkMigrateMessage* m)
2239         :IrrGroup(m),thisProxy(thisgroup),thislocalproxy(thisgroup,CkMyPe()),hash(17,0.3)
2240 {
2241         managers.init();
2242         nManagers=0;
2243         firstManager=NULL;
2244         firstFree=localLen=0;
2245         duringMigration=CmiFalse;
2246         nSprings=0;
2247 #if !CMK_GLOBAL_LOCATION_UPDATE
2248         CcdCallOnConditionKeepOnPE(CcdPERIODIC_1minute,staticSpringCleaning,(void *)this, CkMyPe());
2249 #endif
2250         hashImmLock = CmiCreateImmediateLock();
2251 }
2252
2253 void CkLocMgr::pup(PUP::er &p){
2254         IrrGroup::pup(p);
2255         p|mapID;
2256         p|mapHandle;
2257         p|lbdbID;
2258   p|metalbID;
2259    p|chkpID;
2260         mapID = _defaultArrayMapID;
2261         if(p.isUnpacking()){
2262                 thisProxy=thisgroup;
2263                 CProxyElement_CkLocMgr newlocalproxy(thisgroup,CkMyPe());
2264                 thislocalproxy=newlocalproxy;
2265                 //Register with the map object
2266                 map=(CkArrayMap *)CkLocalBranch(mapID);
2267                 if (map==NULL) CkAbort("ERROR!  Local branch of array map is NULL!");
2268                 CkArrayIndex emptyIndex;
2269                 map->registerArray(emptyIndex,thisgroup);
2270                 // _lbdb is the fixed global groupID
2271                 initLB(lbdbID, metalbID);
2272                 the_chkp = (CkMemCheckPT *)CkLocalBranch(chkpID);
2273 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_)) ||CMK_MEM_CHECKPOINT    
2274         int count;
2275         p | count;
2276         DEBUG(CmiPrintf("[%d] Unpacking Locmgr %d has %d home elements\n",CmiMyPe(),thisgroup.idx,count));
2277 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))    
2278         homeElementCount = count;
2279 #endif
2280         for(int i=0;i<count;i++){
2281             CkArrayIndex idx;
2282             int pe;
2283             idx.pup(p);
2284             p | pe;
2285   //          CmiPrintf("[%d] idx %s is a home element exisiting on pe %d\n",CmiMyPe(),idx2str(idx),pe);
2286             inform(idx,pe);
2287             CkLocRec *rec = elementNrec(idx);
2288             CmiAssert(rec!=NULL);
2289             CmiAssert(lastKnown(idx) == pe);
2290         }
2291 #endif
2292                 // delay doneInserting when it is unpacking during restart.
2293                 // to prevent load balancing kicking in
2294                 if (!CkInRestarting()) 
2295                         doneInserting();
2296         }else{
2297  /**
2298  * pack the indexes of elements which have their homes on this processor
2299  * but dont exist on it.. needed for broadcast after a restart
2300  * indexes of local elements dont need to be packed
2301  * since they will be recreated later anyway
2302  */
2303 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))  || CMK_MEM_CHECKPOINT   
2304                 int count=0,count1=0;
2305         void *objp;
2306         void *keyp;
2307         CkVec<int> pe_list;
2308         CkVec<CkArrayIndex> idx_list;
2309         CkHashtableIterator *it = hash.iterator();
2310       while (NULL!=(objp=it->next(&keyp))) {
2311           CkLocRec *rec=*(CkLocRec **)objp;
2312           CkArrayIndex &idx=*(CkArrayIndex *)keyp;
2313             if(rec->type() != CkLocRec::local){
2314                 if(homePe(idx) == CmiMyPe()){
2315                   int pe;
2316                   CkArrayIndex max = idx;
2317                   pe = rec->lookupProcessor();
2318                   idx_list.push_back(max);
2319                   pe_list.push_back(pe);
2320                     count++;
2321                 }
2322             }
2323         }
2324         p | count;
2325
2326                 // releasing iterator memory
2327                 delete it;
2328
2329       for(int i=0;i<pe_list.length();i++){
2330         CkArrayIndex max = idx_list[i];
2331         max.pup(p);
2332         p|pe_list[i];
2333       }
2334     /*    it = hash.iterator();
2335       while (NULL!=(objp=it->next(&keyp))) {
2336       CkLocRec *rec=*(CkLocRec **)objp;
2337         CkArrayIndex &idx=*(CkArrayIndex *)keyp;
2338             CkArrayIndex max = idx;
2339             if(rec->type() != CkLocRec::local){
2340                 if(homePe(idx) == CmiMyPe()){
2341                     int pe;
2342                     max.pup(p);
2343                     pe = rec->lookupProcessor();
2344                     p | pe;
2345                     count1++;
2346                 }
2347             }
2348         }
2349       //  CmiAssert(count == count1);
2350
2351                 // releasing iterator memory
2352                 delete it;*/
2353
2354 #endif
2355
2356         }
2357 }
2358
2359 void _CkLocMgrInit(void) {
2360   /* Don't trace our deliver method--it does its own tracing */
2361   CkDisableTracing(CkIndex_CkLocMgr::deliverInline(0));
2362 }
2363
2364 /// Add a new local array manager to our list.
2365 /// Returns a new CkMigratableList for the manager to store his
2366 /// elements in.
2367 CkMigratableList *CkLocMgr::addManager(CkArrayID id,CkArrMgr *mgr)
2368 {
2369         CK_MAGICNUMBER_CHECK
2370         DEBC((AA"Adding new array manager\n"AB));
2371         //Link new manager into list
2372         ManagerRec *n=new ManagerRec;
2373         managers.find(id)=n;
2374         n->next=firstManager;
2375         n->mgr=mgr;
2376         n->elts.setSize(localLen);
2377         nManagers++;
2378         firstManager=n;
2379         return &n->elts;
2380 }
2381
2382 /// Return the next unused local element index.
2383 int CkLocMgr::nextFree(void) {
2384         if (firstFree>=localLen)
2385         {//Need more space in the local index arrays-- enlarge them
2386                 int oldLen=localLen;
2387                 localLen=localLen*2+8;
2388                 DEBC((AA"Growing the local list from %d to %d...\n"AB,oldLen,localLen));
2389                 for (ManagerRec *m=firstManager;m!=NULL;m=m->next)
2390                         m->elts.setSize(localLen);
2391                 //Update the free list
2392                 freeList.resize(localLen);
2393                 for (int i=oldLen;i<localLen;i++)
2394                         freeList[i]=i+1;
2395         }
2396         int localIdx=firstFree;
2397         if (localIdx==-1) CkAbort("CkLocMgr free list corrupted!");
2398         firstFree=freeList[localIdx];
2399         freeList[localIdx]=-1; //Mark as used
2400         return localIdx;
2401 }
2402
2403 CkLocRec_remote *CkLocMgr::insertRemote(const CkArrayIndex &idx,int nowOnPe)
2404 {
2405         DEBS((AA"Remote element %s lives on %d\n"AB,idx2str(idx),nowOnPe));
2406         CkLocRec_remote *rem=new CkLocRec_remote(this,nowOnPe);
2407         insertRec(rem,idx);
2408         return rem;
2409 }
2410
2411 //This element now lives on the given Pe
2412 void CkLocMgr::inform(const CkArrayIndex &idx,int nowOnPe)
2413 {
2414         if (nowOnPe==CkMyPe())
2415                 return; //Never insert a "remote" record pointing here
2416         CkLocRec *rec=elementNrec(idx);
2417         if (rec!=NULL && rec->type()==CkLocRec::local){
2418 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2419         CmiPrintf("[%d]WARNING!!! Element %d:%s is local but is being told it exists on %d\n",CkMyPe(),idx.dimension,idx2str(idx), nowOnPe);
2420 #endif
2421                 return; //Never replace a local element's record!
2422         }
2423         insertRemote(idx,nowOnPe);
2424 }
2425
2426 //Tell this element's home processor it now lives "there"
2427 void CkLocMgr::informHome(const CkArrayIndex &idx,int nowOnPe)
2428 {
2429         int home=homePe(idx);
2430         if (home!=CkMyPe() && home!=nowOnPe) {
2431                 //Let this element's home Pe know it lives here now
2432                 DEBC((AA"  Telling %s's home %d that it lives on %d.\n"AB,idx2str(idx),home,nowOnPe));
2433 //#if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2434 //#if defined(_FAULT_MLOG_)
2435 //        informLocationHome(thisgroup,idx,home,CkMyPe());
2436 //#else
2437                 thisProxy[home].updateLocation(idx,nowOnPe);
2438 //#endif
2439         }
2440 }
2441
2442 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2443 CkLocRec_local *CkLocMgr::createLocal(const CkArrayIndex &idx,
2444         CmiBool forMigration, CmiBool ignoreArrival,
2445         CmiBool notifyHome,int dummy)
2446 {
2447     int localIdx=nextFree();
2448     DEBC((AA"Adding new record for element %s at local index %d\n"AB,idx2str(idx),localIdx));
2449     CkLocRec_local *rec=new CkLocRec_local(this,forMigration,ignoreArrival,idx,localIdx);
2450     if(!dummy){
2451         insertRec(rec,idx); //Add to global hashtable
2452     }   
2453     if (notifyHome) informHome(idx,CkMyPe());
2454     return rec; 
2455 }
2456 #else
2457 CkLocRec_local *CkLocMgr::createLocal(const CkArrayIndex &idx, 
2458                 CmiBool forMigration, CmiBool ignoreArrival,
2459                 CmiBool notifyHome)
2460 {
2461         //CkPrintf("Adding new record for element %s\n",idx2str(idx));
2462         int localIdx=nextFree();
2463         DEBC((AA"Adding new record for element %s at local index %d\n"AB,idx2str(idx),localIdx));
2464         //CkPrintf("Adding new record for element %s at local index %d\n",idx2str(idx),localIdx);
2465         CkLocRec_local *rec=new CkLocRec_local(this,forMigration,ignoreArrival,idx,localIdx);
2466         insertRec(rec,idx); //Add to global hashtable
2467         if (notifyHome) informHome(idx,CkMyPe());
2468         return rec;
2469 }
2470 #endif
2471
2472 //Add a new local array element, calling element's constructor
2473 CmiBool CkLocMgr::addElement(CkArrayID id,const CkArrayIndex &idx,
2474                 CkMigratable *elt,int ctorIdx,void *ctorMsg)
2475 {
2476         CK_MAGICNUMBER_CHECK
2477         CkLocRec *oldRec=elementNrec(idx);
2478         CkLocRec_local *rec;
2479         if (oldRec==NULL||oldRec->type()!=CkLocRec::local) 
2480         { //This is the first we've heard of that element-- add new local record
2481                 rec=createLocal(idx,CmiFalse,CmiFalse,CmiTrue);
2482 #if CMK_GLOBAL_LOCATION_UPDATE
2483                 if (homePe(idx) != CkMyPe()) {
2484                   DEBC((AA"Global location broadcast for new element idx %s "
2485                         "assigned to %d \n"AB, idx2str(idx), CkMyPe()));
2486                   thisProxy.updateLocation(idx, CkMyPe());  
2487                 }
2488 #endif
2489                 
2490         } else 
2491         { //rec is *already* local-- must not be the first insertion    
2492                 rec=((CkLocRec_local *)oldRec);
2493                 rec->addedElement();
2494         }
2495         if (!addElementToRec(rec,managers.find(id),elt,ctorIdx,ctorMsg)) return CmiFalse;
2496         elt->ckFinishConstruction();
2497         return CmiTrue;
2498 }
2499
2500 //As above, but shared with the migration code
2501 CmiBool CkLocMgr::addElementToRec(CkLocRec_local *rec,ManagerRec *m,
2502                 CkMigratable *elt,int ctorIdx,void *ctorMsg)
2503 {//Insert the new element into its manager's local list
2504         int localIdx=rec->getLocalIndex();
2505         if (m->elts.get(localIdx)!=NULL) CkAbort("Cannot insert array element twice!");
2506         m->elts.put(elt,localIdx); //Local element table
2507
2508 //Call the element's constructor
2509         DEBC((AA"Constructing element %s of array\n"AB,idx2str(rec->getIndex())));
2510         CkMigratable_initInfo &i=CkpvAccess(mig_initInfo);
2511         i.locRec=rec;
2512         i.chareType=_entryTable[ctorIdx]->chareIdx;
2513         if (!rec->invokeEntry(elt,ctorMsg,ctorIdx,CmiTrue)) return CmiFalse;
2514
2515 #if CMK_OUT_OF_CORE
2516         /* Register new element with out-of-core */
2517         PUP::sizer p_getSize; elt->pup(p_getSize);
2518         elt->prefetchObjID=CooRegisterObject(&CkArrayElementPrefetcher,p_getSize.size(),elt);
2519 #endif
2520         
2521         return CmiTrue;
2522 }
2523 void CkLocMgr::updateLocation(const CkArrayIndex &idx,int nowOnPe) {
2524   inform(idx,nowOnPe);
2525         CProxy_CkMemCheckPT checkptMgr(ckCheckPTGroupID);
2526 }
2527
2528 /*************************** LocMgr: DELETION *****************************/
2529 /// This index will no longer be used-- delete the associated elements
2530 void CkLocMgr::reclaim(const CkArrayIndex &idx,int localIdx) {
2531         CK_MAGICNUMBER_CHECK
2532         DEBC((AA"Destroying element %s (local %d)\n"AB,idx2str(idx),localIdx));
2533         //Delete, and mark as empty, each array element
2534         for (ManagerRec *m=firstManager;m!=NULL;m=m->next) {
2535                 delete m->elts.get(localIdx);
2536                 m->elts.empty(localIdx);
2537         }
2538         
2539         removeFromTable(idx);
2540         
2541         //Link local index into free list
2542         freeList[localIdx]=firstFree;
2543         firstFree=localIdx;
2544         
2545                 
2546         if (!duringMigration) 
2547         { //This is a local element dying a natural death
2548             #if CMK_BIGSIM_CHARM
2549                 //After migration, reclaimRemote will be called through 
2550                 //the CkRemoveArrayElement in the pupping routines for those 
2551                 //objects that are not on the home processors. However,
2552                 //those remote records should not be deleted since the corresponding
2553                 //objects are not actually deleted but on disk. If deleted, msgs
2554                 //that seeking where is the object will be accumulated (a circular
2555                 //msg chain) and causes the program no progress
2556                 if(_BgOutOfCoreFlag==1) return; 
2557             #endif
2558                 int home=homePe(idx);
2559                 if (home!=CkMyPe())
2560 #if CMK_MEM_CHECKPOINT
2561                 if (!CkInRestarting()) // all array elements are removed anyway
2562 #endif
2563                         thisProxy[home].reclaimRemote(idx,CkMyPe());
2564         /*      //Install a zombie to keep the living from re-using this index.
2565                 insertRecN(new CkLocRec_dead(this),idx); */
2566         }
2567 }
2568
2569 void CkLocMgr::reclaimRemote(const CkArrayIndex &idx,int deletedOnPe) {
2570         DEBC((AA"Our element %s died on PE %d\n"AB,idx2str(idx),deletedOnPe));
2571         CkLocRec *rec=elementNrec(idx);
2572         if (rec==NULL) return; //We never knew him
2573         if (rec->type()==CkLocRec::local) return; //He's already been reborn
2574         removeFromTable(idx);
2575         delete rec;
2576 }
2577 void CkLocMgr::removeFromTable(const CkArrayIndex &idx) {
2578 #if CMK_ERROR_CHECKING
2579         //Make sure it's actually in the table before we delete it
2580         if (NULL==elementNrec(idx))
2581                 CkAbort("CkLocMgr::removeFromTable called on invalid index!");
2582 #endif
2583         CmiImmediateLock(hashImmLock);
2584         hash.remove(*(CkArrayIndex *)&idx);
2585         CmiImmediateUnlock(hashImmLock);
2586 #if CMK_ERROR_CHECKING
2587         //Make sure it's really gone
2588         if (NULL!=elementNrec(idx))
2589                 CkAbort("CkLocMgr::removeFromTable called, but element still there!");
2590 #endif
2591 }
2592
2593 /************************** LocMgr: MESSAGING *************************/
2594 /// Deliver message to this element, going via the scheduler if local
2595 /// @return 0 if object local, 1 if not
2596 int CkLocMgr::deliver(CkMessage *m,CkDeliver_t type,int opts) {
2597         DEBS((AA"deliver \n"AB));
2598         CK_MAGICNUMBER_CHECK
2599         CkArrayMessage *msg=(CkArrayMessage *)m;
2600
2601
2602         const CkArrayIndex &idx=msg->array_index();
2603         DEBS((AA"deliver %s\n"AB,idx2str(idx)));
2604         if (type==CkDeliver_queue)
2605                 _TRACE_CREATION_DETAILED(UsrToEnv(m),msg->array_ep());
2606         CkLocRec *rec=elementNrec(idx);
2607         if(rec != NULL){
2608                 DEBS((AA"deliver %s of type %d \n"AB,idx2str(idx),rec->type()));
2609         }else{
2610                 DEBS((AA"deliver %s rec is null\n"AB,idx2str(idx)));
2611         }
2612 //#if (!defined(_FAULT_MLOG_) && !defined(_FAULT_CAUSAL_))
2613 //#if !defined(_FAULT_MLOG_)
2614 #if CMK_LBDB_ON
2615
2616         LDObjid ldid = idx2LDObjid(idx);
2617 #if CMK_GLOBAL_LOCATION_UPDATE
2618         ldid.locMgrGid = thisgroup.idx;
2619 #endif        
2620         if (type==CkDeliver_queue) {
2621                 if (!(opts & CK_MSG_LB_NOTRACE) && the_lbdb->CollectingCommStats()) {
2622                 if(rec!=NULL) the_lbdb->Send(myLBHandle,ldid,UsrToEnv(msg)->getTotalsize(), rec->lookupProcessor(), 1);
2623                 else /*rec==NULL*/ the_lbdb->Send(myLBHandle,ldid,UsrToEnv(msg)->getTotalsize(),homePe(msg->array_index()), 1);
2624                 }
2625         }
2626 #endif
2627 //#endif
2628 #if CMK_GRID_QUEUE_AVAILABLE
2629         int gridSrcPE;
2630         int gridSrcCluster;
2631         int gridDestPE;
2632         int gridDestCluster;
2633         CkMigratable *obj;
2634         ArrayElement *obj2;
2635         CkGroupID gid;
2636         int *data;
2637
2638         obj = (CkMigratable *) CpvAccess(CkGridObject);   // CkGridObject is a pointer to the sending object (retained earlier)
2639         if (obj != NULL) {
2640           obj2 = dynamic_cast<ArrayElement *> (obj);
2641           if (obj2 > 0) {
2642             // Get the sending object's array gid and indexes.
2643             // These are guaranteed to exist due to the succeeding dynamic cast above.
2644             gid = obj2->ckGetArrayID ();
2645             data = obj2->thisIndexMax.data ();
2646
2647             // Get the source PE and destination PE.
2648             gridSrcPE = CkMyPe ();
2649             if (rec != NULL) {
2650               gridDestPE = rec->lookupProcessor ();
2651             } else {
2652               gridDestPE = homePe (msg->array_index ());
2653             }
2654
2655             // Get the source cluster and destination cluster.
2656             gridSrcCluster = CmiGetCluster (gridSrcPE);
2657             gridDestCluster = CmiGetCluster (gridDestPE);
2658
2659             // If the Grid queue interval is greater than zero, it means that the more complicated
2660             // technique for registering border objects that exceed a specified threshold of
2661             // cross-cluster messages within a specified interval (and deregistering border objects
2662             // that do not meet this threshold) is used.  Otherwise a much simpler technique is used
2663             // where a border object is registered immediately upon sending a single cross-cluster
2664             // message (and deregistered when load balancing takes place).
2665             if (obj2->grid_queue_interval > 0) {
2666               // Increment the sending object's count of all messages.
2667               obj2->msg_count += 1;
2668
2669               // If the source cluster and destination cluster differ, this is a Grid message.
2670               // (Increment the count of all Grid messages.)
2671               if (gridSrcCluster != gridDestCluster) {
2672                 obj2->msg_count_grid += 1;
2673               }
2674
2675               // If the number of messages exceeds the interval, check to see if the object has
2676               // sent enough cross-cluster messages to qualify as a border object.
2677               if (obj2->msg_count >= obj2->grid_queue_interval) {
2678                 if (obj2->msg_count_grid >= obj2->grid_queue_threshold) {
2679                   // The object is a border object; if it is not already registered, register it.
2680                   if (!obj2->border_flag) {
2681                     CmiGridQueueRegister (gid.idx, obj2->thisIndexMax.nInts, data[0], data[1], data[2]);
2682                   }
2683                   obj2->border_flag = 1;
2684                 } else {
2685                   // The object is not a border object; if it is registered, deregister it.
2686                   if (obj2->border_flag) {
2687                     CmiGridQueueDeregister (gid.idx, obj2->thisIndexMax.nInts, data[0], data[1], data[2]);
2688                   }
2689                   obj2->border_flag = 0;
2690                 }
2691                 // Reset the counts.
2692                 obj2->msg_count = 0;
2693                 obj2->msg_count_grid = 0;
2694               }
2695             } else {
2696               if (gridSrcCluster != gridDestCluster) {
2697                 CmiGridQueueRegister (gid.idx, obj2->thisIndexMax.nInts, data[0], data[1], data[2]);
2698               }
2699             }
2700           }
2701
2702           // Reset the CkGridObject pointer.
2703           CpvAccess(CkGridObject) = NULL;
2704         }
2705 #endif
2706         /**FAULT_EVAC*/
2707         if (rec!=NULL){
2708                 CmiBool result = rec->deliver(msg,type,opts);
2709                 // if result is CmiFalse, than rec is not valid anymore, as the object
2710                 // the message was just delivered to has died or migrated out.
2711                 // Therefore rec->type() cannot be invoked!
2712                 if (result==CmiTrue && rec->type()==CkLocRec::local) return 0;
2713                 else return 1;
2714                 /*if(!result){
2715                         //DEBS((AA"deliver %s failed type %d \n"AB,idx2str(idx),rec->type()));
2716                         DEBS((AA"deliver %s failed \n"AB,idx2str(idx)));
2717                         if(rec->type() == CkLocRec::remote){
2718                                 if (opts & CK_MSG_KEEP)
2719                                         msg = (CkArrayMessage *)CkCopyMsg((void **)&msg);
2720                                 deliverUnknown(msg,type);
2721                         }
2722                 }*/
2723         }else /* rec==NULL*/ {
2724                 if (opts & CK_MSG_KEEP)
2725                         msg = (CkArrayMessage *)CkCopyMsg((void **)&msg);
2726                 deliverUnknown(msg,type,opts);
2727                 return 1;
2728         }
2729
2730 }
2731
2732 /// This index is not hashed-- somehow figure out what to do.
2733 CmiBool CkLocMgr::deliverUnknown(CkArrayMessage *msg,CkDeliver_t type,int opts)
2734 {
2735         CK_MAGICNUMBER_CHECK
2736         const CkArrayIndex &idx=msg->array_index();
2737         int onPe=homePe(idx);
2738         if (onPe!=CkMyPe()) 
2739         {// Forward the message to its home processor
2740                 DEBM((AA"Forwarding message for unknown %s to home %d \n"AB,idx2str(idx),onPe));
2741                 msg->array_hops()++;
2742                 CkArrayManagerDeliver(onPe,msg,opts);
2743                 return CmiTrue;
2744         }
2745         else
2746         { // We *are* the home processor:
2747         //Check if the element's array manager has been registered yet:
2748           CkArrMgr *mgr=managers.find(UsrToEnv((void *)msg)->getsetArrayMgr())->mgr;
2749           if (!mgr) { //No manager yet-- postpone the message (stupidly)
2750             if (CkInRestarting()) {
2751               // during restarting, this message should be ignored
2752               delete msg;
2753             }
2754             else {
2755               CkArrayManagerDeliver(CkMyPe(),msg); 
2756             }
2757           }
2758           else { // Has a manager-- must buffer the message
2759             DEBC((AA"Adding buffer for unknown element %s\n"AB,idx2str(idx)));
2760             CkLocRec *rec=new CkLocRec_buffering(this);
2761             insertRecN(rec,idx);
2762             rec->deliver(msg,type);
2763           
2764             if (msg->array_ifNotThere()!=CkArray_IfNotThere_buffer) 
2765             { //Demand-create the element:
2766               return demandCreateElement(msg,-1,type);
2767             }
2768           }
2769           return CmiTrue;
2770         }
2771 }
2772
2773 CmiBool CkLocMgr::demandCreateElement(CkArrayMessage *msg,int onPe,CkDeliver_t type)
2774 {
2775         CK_MAGICNUMBER_CHECK
2776         const CkArrayIndex &idx=msg->array_index();
2777         int chareType=_entryTable[msg->array_ep()]->chareIdx;
2778         int ctor=_chareTable[chareType]->getDefaultCtor();
2779         if (ctor==-1) CkAbort("Can't create array element to handle message--\n"
2780                               "The element has no default constructor in the .ci file!\n");
2781         if (onPe==-1) 
2782         { //Decide where element needs to live
2783                 if (msg->array_ifNotThere()==CkArray_IfNotThere_createhere) 
2784                         onPe=UsrToEnv(msg)->getsetArraySrcPe();
2785                 else //Createhome
2786                         onPe=homePe(idx);
2787         }
2788         
2789         //Find the manager and build the element
2790         DEBC((AA"Demand-creating element %s on pe %d\n"AB,idx2str(idx),onPe));
2791         CkArrMgr *mgr=managers.find(UsrToEnv((void *)msg)->getsetArrayMgr())->mgr;
2792         if (!mgr) CkAbort("Tried to demand-create for nonexistent arrMgr");
2793         return mgr->demandCreateElement(idx,onPe,ctor,type);
2794 }
2795
2796 //This message took several hops to reach us-- fix it
2797 void CkLocMgr::multiHop(CkArrayMessage *msg)
2798 {
2799
2800         CK_MAGICNUMBER_CHECK
2801         int srcPe=msg->array_getSrcPe();
2802         if (srcPe==CkMyPe())
2803                 DEB((AA"Odd routing: local element %s is %d hops away!\n"AB,idx2str(msg),msg->array_hops()));
2804         else
2805         {//Send a routing message letting original sender know new element location
2806                 DEBS((AA"Sending update back to %d for element\n"AB,srcPe,idx2str(msg)));
2807                 thisProxy[srcPe].updateLocation(msg->array_index(),CkMyPe());
2808         }
2809 }
2810
2811 /************************** LocMgr: ITERATOR *************************/
2812 CkLocation::CkLocation(CkLocMgr *mgr_, CkLocRec_local *rec_)
2813         :mgr(mgr_), rec(rec_) {}
2814         
2815 const CkArrayIndex &CkLocation::getIndex(void) const {
2816         return rec->getIndex();
2817 }
2818
2819 void CkLocation::destroyAll() {
2820         mgr->callMethod(rec, &CkMigratable::ckDestroy);
2821 }
2822
2823 void CkLocation::pup(PUP::er &p) {
2824         mgr->pupElementsFor(p,rec,CkElementCreation_migrate);
2825 }
2826
2827 CkLocIterator::~CkLocIterator() {}
2828
2829 /// Iterate over our local elements:
2830 void CkLocMgr::iterate(CkLocIterator &dest) {
2831   //Poke through the hash table for local ArrayRecs.
2832   void *objp;
2833   CkHashtableIterator *it=hash.iterator();
2834   CmiImmediateLock(hashImmLock);
2835
2836   while (NULL!=(objp=it->next())) {
2837     CkLocRec *rec=*(CkLocRec **)objp;
2838     if (rec->type()==CkLocRec::local) {
2839       CkLocation loc(this,(CkLocRec_local *)rec);
2840       dest.addLocation(loc);
2841     }
2842   }
2843   CmiImmediateUnlock(hashImmLock);
2844   delete it;
2845 }
2846
2847
2848 void CkLocMgr::iterateChkpSync(CkLocIterator &dest) {
2849   //Poke through the hash table for local ArrayRecs.
2850   void *objp;
2851   CkHashtableIterator *it=hash.iterator();
2852   CmiImmediateLock(hashImmLock);
2853
2854   while (NULL!=(objp=it->next())) {
2855     CkLocRec *rec=*(CkLocRec **)objp;
2856     if (rec->type()==CkLocRec::local) {
2857       CkLocation loc(this,(CkLocRec_local *)rec);
2858           int localIdx=((CkLocRec_local *)rec)->getLocalIndex();
2859           for (ManagerRec *m=firstManager;m!=NULL;m=m->next) {
2860                 CkMigratable *el=m->element(localIdx);
2861         if(el->getChkpSync()==CmiTrue){
2862                         dest.addLocation(loc);
2863                         break;
2864                 }
2865           }
2866     }
2867   }
2868   CmiImmediateUnlock(hashImmLock);
2869   delete it;
2870 }
2871
2872
2873 /************************** LocMgr: MIGRATION *************************/
2874 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2875 void CkLocMgr::pupElementsFor(PUP::er &p,CkLocRec_local *rec,
2876         CkElementCreation_t type, CmiBool create, int dummy)
2877 {
2878     p.comment("-------- Array Location --------");
2879     register ManagerRec *m;
2880     int localIdx=rec->getLocalIndex();
2881     CkVec<CkMigratable *> dummyElts;
2882     for (m=firstManager;m!=NULL;m=m->next) {
2883         int elCType;
2884         if (!p.isUnpacking())
2885         { //Need to find the element's existing type
2886             CkMigratable *elt=m->element(localIdx);
2887             if (elt) elCType=elt->ckGetChareType();
2888             else elCType=-1; //Element hasn't been created
2889         }
2890         p(elCType);
2891         if (p.isUnpacking() && elCType!=-1) {
2892             CkMigratable *elt=m->mgr->allocateMigrated(elCType,rec->getIndex(),type);
2893             int migCtorIdx=_chareTable[elCType]->getMigCtor();
2894                         if(!dummy){
2895                                 if(create)
2896                                 if (!addElementToRec(rec,m,elt,migCtorIdx,NULL)) return;
2897                                 }else{
2898                     CkMigratable_initInfo &i=CkpvAccess(mig_initInfo);
2899                     i.locRec=rec;
2900                     i.chareType=_entryTable[migCtorIdx]->chareIdx;
2901                     dummyElts.push_back(elt);
2902                     if (!rec->invokeEntry(elt,NULL,migCtorIdx,CmiTrue)) return ;
2903                 }
2904         }
2905         }
2906     if(!dummy){
2907         for (m=firstManager;m!=NULL;m=m->next) {
2908             CkMigratable *elt=m->element(localIdx);
2909             if (elt!=NULL)
2910                 {
2911                        elt->pup(p);
2912                 }
2913         }
2914     }else{
2915             for(int i=0;i<dummyElts.size();i++){
2916                 CkMigratable *elt = dummyElts[i];
2917                 if (elt!=NULL){
2918             elt->pup(p);
2919                         }
2920                 delete elt;
2921             }
2922                         for (ManagerRec *m=firstManager;m!=NULL;m=m->next) {
2923                 m->elts.empty(localIdx);
2924             }
2925         freeList[localIdx]=firstFree;
2926         firstFree=localIdx;
2927     }
2928 }
2929 #else
2930 void CkLocMgr::pupElementsFor(PUP::er &p,CkLocRec_local *rec,
2931                 CkElementCreation_t type,CmiBool rebuild,CmiBool create)
2932 {
2933         p.comment("-------- Array Location --------");
2934         register ManagerRec *m;
2935         int localIdx=rec->getLocalIndex();
2936
2937         //First pup the element types
2938         // (A separate loop so ckLocal works even in element pup routines)
2939         for (m=firstManager;m!=NULL;m=m->next) {
2940                 int elCType;
2941                 if (!p.isUnpacking()&&!p.isChecking())
2942                 { //Need to find the element's existing type
2943                         CkMigratable *elt=m->element(localIdx);
2944                         if (elt) elCType=elt->ckGetChareType();
2945                         else elCType=-1; //Element hasn't been created
2946                 }
2947
2948                 p(elCType);
2949                 if (p.isUnpacking() && elCType!=-1) {
2950                         //Create the element
2951                         CkMigratable *elt=m->mgr->allocateMigrated(elCType,rec->getIndex(),type);
2952                         int migCtorIdx=_chareTable[elCType]->getMigCtor();
2953                         //Insert into our tables and call migration constructor
2954                         if(create)
2955                                 if (!addElementToRec(rec,m,elt,migCtorIdx,NULL)) return;
2956                 }
2957         }
2958
2959         //Next pup the element data
2960         for (m=firstManager;m!=NULL;m=m->next) {
2961                 CkMigratable *elt=m->element(localIdx);
2962                 if (elt!=NULL)
2963                 {
2964                         elt->pup(p);
2965 #if CMK_ERROR_CHECKING
2966                         if (p.isUnpacking()) elt->sanitycheck();
2967 #endif
2968                 }
2969         }
2970
2971 #if CMK_MEM_CHECKPOINT
2972         if(rebuild){
2973           ArrayElement *elt;
2974           CkVec<CkMigratable *> list;
2975           migratableList(rec, list);
2976           CmiAssert(list.length() > 0);
2977           for (int l=0; l<list.length(); l++) {
2978                 //    reset, may not needed now
2979                 // for now.
2980                 for (int i=0; i<CK_ARRAYLISTENER_MAXLEN; i++) {
2981                         ArrayElement * elt = (ArrayElement *)list[l];
2982                   contributorInfo *c=(contributorInfo *)&elt->listenerData[i];
2983                   if (c) c->redNo = 0;
2984                 }
2985           }
2986         }
2987 #endif
2988 }
2989 #endif
2990
2991 /// Call this member function on each element of this location:
2992 void CkLocMgr::callMethod(CkLocRec_local *rec,CkMigratable_voidfn_t fn)
2993 {
2994         int localIdx=rec->getLocalIndex();
2995         for (ManagerRec *m=firstManager;m!=NULL;m=m->next) {
2996                 CkMigratable *el=m->element(localIdx);
2997                 if (el) (el->* fn)();
2998         }
2999 }
3000
3001 /// Call this member function on each element of this location:
3002 void CkLocMgr::callMethod(CkLocRec_local *rec,CkMigratable_voidfn_arg_t fn,     void * data)
3003 {
3004         int localIdx=rec->getLocalIndex();
3005         for (ManagerRec *m=firstManager;m!=NULL;m=m->next) {
3006                 CkMigratable *el=m->element(localIdx);
3007                 if (el) (el->* fn)(data);
3008         }
3009 }
3010
3011 /// return a list of migratables in this local record
3012 void CkLocMgr::migratableList(CkLocRec_local *rec, CkVec<CkMigratable *> &list)
3013 {
3014         register ManagerRec *m;
3015         int localIdx=rec->getLocalIndex();
3016
3017         for (m=firstManager;m!=NULL;m=m->next) {
3018                 CkMigratable *elt=m->element(localIdx);
3019                 if (elt) list.push_back(elt);
3020         }
3021 }
3022
3023 /// Migrate this local element away to another processor.
3024 void CkLocMgr::emigrate(CkLocRec_local *rec,int toPe)
3025 {
3026         CK_MAGICNUMBER_CHECK
3027         if (toPe==CkMyPe()) return; //You're already there!
3028         /*
3029                 FAULT_EVAC
3030                 if the toProcessor is already marked as invalid, dont emigrate
3031                 Shouldn't happen but might
3032         */
3033         if(!CmiNodeAlive(toPe)){
3034                 return;
3035         }
3036         CkArrayIndex idx=rec->getIndex();
3037
3038 #if CMK_OUT_OF_CORE
3039         int localIdx=rec->getLocalIndex();
3040         /* Load in any elements that are out-of-core */
3041         for (ManagerRec *m=firstManager;m!=NULL;m=m->next) {
3042                 CkMigratable *el=m->element(localIdx);
3043                 if (el) if (!el->isInCore) CooBringIn(el->prefetchObjID);
3044         }
3045 #endif
3046
3047         //Let all the elements know we're leaving
3048         callMethod(rec,&CkMigratable::ckAboutToMigrate);
3049         /*EVAC*/
3050
3051 //First pass: find size of migration message
3052         int bufSize;
3053         {
3054                 PUP::sizer p;
3055                 p(nManagers);
3056                 pupElementsFor(p,rec,CkElementCreation_migrate);
3057                 bufSize=p.size(); 
3058         }
3059
3060 //Allocate and pack into message
3061         int doubleSize=bufSize/sizeof(double)+1;
3062         CkArrayElementMigrateMessage *msg = 
3063                 new (doubleSize, 0) CkArrayElementMigrateMessage;
3064         msg->idx=idx;
3065         msg->length=bufSize;
3066 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_)) 
3067     msg->gid = ckGetGroupID();
3068 #endif
3069 #if CMK_LBDB_ON
3070         msg->ignoreArrival = rec->isAsyncMigrate()?1:0;
3071 #endif
3072         /*
3073                 FAULT_EVAC
3074         */
3075         msg->bounced = rec->isBounced();
3076         {
3077                 PUP::toMem p(msg->packData); 
3078                 p.becomeDeleting(); 
3079                 p(nManagers);
3080                 pupElementsFor(p,rec,CkElementCreation_migrate);
3081                 if (p.size()!=bufSize) {
3082                         CkError("ERROR! Array element claimed it was %d bytes to a "
3083                                 "sizing PUP::er, but copied %d bytes into the packing PUP::er!\n",
3084                                 bufSize,p.size());
3085                         CkAbort("Array element's pup routine has a direction mismatch.\n");
3086                 }
3087         }
3088
3089         DEBM((AA"Migrated index size %s to %d \n"AB,idx2str(idx),toPe));        
3090
3091 //#if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
3092 //#if defined(_FAULT_MLOG_)
3093 //    sendMlogLocation(toPe,UsrToEnv(msg));
3094 //#else
3095         //Send off message and delete old copy
3096         thisProxy[toPe].immigrate(msg);
3097 //#endif
3098
3099         duringMigration=CmiTrue;
3100         delete rec; //Removes elements, hashtable entries, local index
3101         
3102         
3103         duringMigration=CmiFalse;
3104         //The element now lives on another processor-- tell ourselves and its home
3105         inform(idx,toPe);
3106 //#if (!defined(_FAULT_MLOG_) && !defined(_FAULT_CAUSAL_))    
3107 //#if !defined(_FAULT_MLOG_)    
3108         informHome(idx,toPe);
3109 //#endif
3110
3111 #if !CMK_LBDB_ON && CMK_GLOBAL_LOCATION_UPDATE
3112         DEBM((AA"Global location update. idx %s " 
3113               "assigned to %d \n"AB,idx2str(idx),toPe));
3114         thisProxy.updateLocation(idx, toPe);                        
3115 #endif
3116
3117         CK_MAGICNUMBER_CHECK
3118 }
3119
3120 #if CMK_LBDB_ON
3121 void CkLocMgr::informLBPeriod(CkLocRec_local *rec, int lb_ideal_period) {
3122         callMethod(rec,&CkMigratable::recvLBPeriod, (void *)&lb_ideal_period);
3123 }
3124
3125 void CkLocMgr::metaLBCallLB(CkLocRec_local *rec) {
3126         callMethod(rec, &CkMigratable::metaLBCallLB);
3127 }
3128 #endif
3129
3130 /**
3131   Migrating array element is arriving on this processor.
3132 */
3133 void CkLocMgr::immigrate(CkArrayElementMigrateMessage *msg)
3134 {
3135         const CkArrayIndex &idx=msg->idx;
3136                 
3137         PUP::fromMem p(msg->packData); 
3138         
3139         int nMsgMan;
3140         p(nMsgMan);
3141         if (nMsgMan<nManagers)
3142                 CkAbort("Array element arrived from location with fewer managers!\n");
3143         if (nMsgMan>nManagers) {
3144                 //Some array managers haven't registered yet-- throw it back
3145                 DEBM((AA"Busy-waiting for array registration on migrating %s\n"AB,idx2str(idx)));
3146                 thisProxy[CkMyPe()].immigrate(msg);
3147                 return;
3148         }
3149
3150         //Create a record for this element
3151 //#if (!defined(_FAULT_MLOG_) && !defined(_FAULT_CAUSAL_))    
3152 //#if !defined(_FAULT_MLOG_)     
3153         CkLocRec_local *rec=createLocal(idx,CmiTrue,msg->ignoreArrival,CmiFalse /* home told on departure */ );
3154 //#else
3155 //    CkLocRec_local *rec=createLocal(idx,CmiTrue,CmiTrue,CmiFalse /* home told on departure */ );
3156 //#endif
3157         
3158         //Create the new elements as we unpack the message
3159         pupElementsFor(p,rec,CkElementCreation_migrate);
3160         if (p.size()!=msg->length) {
3161                 CkError("ERROR! Array element claimed it was %d bytes to a"
3162                         "packing PUP::er, but %d bytes in the unpacking PUP::er!\n",
3163                         msg->length,p.size());
3164                 CkError("(I have %d managers; he claims %d managers)\n",
3165                         nManagers,nMsgMan);
3166                 
3167                 CkAbort("Array element's pup routine has a direction mismatch.\n");
3168         }
3169         /*
3170                 FAULT_EVAC
3171                         if this element came in as a result of being bounced off some other process,
3172                         then it needs to be resumed. It is assumed that it was bounced because load 
3173                         balancing caused it to move into a processor which later crashed
3174         */
3175         if(msg->bounced){
3176                 callMethod(rec,&CkMigratable::ResumeFromSync);
3177         }
3178         
3179         //Let all the elements know we've arrived
3180         callMethod(rec,&CkMigratable::ckJustMigrated);
3181         /*FAULT_EVAC
3182                 If this processor has started evacuating array elements on it 
3183                 dont let new immigrants in. If they arrive send them to what
3184                 would be their correct homePE.
3185                 Leave a record here mentioning the processor where it got sent
3186         */
3187         
3188         if(CkpvAccess(startedEvac)){
3189                 int newhomePE = getNextPE(idx);
3190                 DEBM((AA"Migrated into failed processor index size %s resent to %d \n"AB,idx2str(idx),newhomePE));      
3191                 CkLocMgr *mgr = rec->getLocMgr();
3192                 int targetPE=getNextPE(idx);
3193                 //set this flag so that load balancer is not informed when
3194                 //this element migrates
3195                 rec->AsyncMigrate(CmiTrue);
3196                 rec->Bounced(CmiTrue);
3197                 mgr->emigrate(rec,targetPE);
3198                 
3199         }
3200
3201         delete msg;
3202 }
3203
3204 void CkLocMgr::restore(const CkArrayIndex &idx, PUP::er &p)
3205 {
3206         //This is in broughtIntoMem during out-of-core emulation in BigSim,
3207         //informHome should not be called since such information is already
3208         //immediately updated real migration
3209 #if CMK_ERROR_CHECKING
3210         if(_BgOutOfCoreFlag!=2)
3211             CmiAbort("CkLocMgr::restore should only be used in out-of-core emulation for BigSim and be called when object is brought into memory!\n");
3212 #endif
3213         CkLocRec_local *rec=createLocal(idx,CmiFalse,CmiFalse,CmiFalse);
3214         
3215         //BIGSIM_OOC DEBUGGING
3216         //CkPrintf("Proc[%d]: Registering element %s with LDB\n", CkMyPe(), idx2str(idx));
3217
3218         //Create the new elements as we unpack the message
3219         pupElementsFor(p,rec,CkElementCreation_restore);
3220
3221         callMethod(rec,&CkMigratable::ckJustRestored);
3222 }
3223
3224
3225 /// Insert and unpack this array element from this checkpoint (e.g., from CkLocation::pup)
3226 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
3227 void CkLocMgr::resume(const CkArrayIndex &idx, PUP::er &p, CmiBool create, int dummy)
3228 {
3229         CkLocRec_local *rec;
3230         CkLocRec *recGlobal;    
3231
3232         if(create){
3233                 rec = createLocal(idx,CmiFalse,CmiFalse,CmiTrue && !dummy /* home doesn't know yet */,dummy );
3234         }else{
3235                 recGlobal = elementNrec(idx);
3236                 if(recGlobal == NULL) 
3237                         CmiAbort("Local object not found");
3238                 if(recGlobal->type() != CkLocRec::local)
3239                         CmiAbort("Local object not local, :P");
3240                 rec = (CkLocRec_local *)recGlobal;
3241         }
3242         
3243     pupElementsFor(p,rec,CkElementCreation_resume,create,dummy);
3244
3245     if(!dummy){
3246         callMethod(rec,&CkMigratable::ckJustMigrated);
3247     }
3248 }
3249 #else
3250 void CkLocMgr::resume(const CkArrayIndex &idx, PUP::er &p, CmiBool notify,CmiBool rebuild,CmiBool create)
3251 {
3252         CkLocRec_local *rec;
3253         CkLocRec *recGlobal;    
3254
3255         if(create){
3256                 //Create the new elements as we unpack the message
3257                 rec=createLocal(idx,CmiFalse,CmiFalse,notify /* home doesn't know yet */ );
3258         }else{
3259                 recGlobal = elementNrec(idx);
3260                 if(recGlobal == NULL) 
3261                         CmiAbort("Local object not found");
3262                 if(recGlobal->type() != CkLocRec::local)
3263                         CmiAbort("Local object not local, :P");
3264                 rec = (CkLocRec_local *)recGlobal;
3265         }
3266         pupElementsFor(p,rec,CkElementCreation_resume,rebuild,create);
3267         if(!p.isChecking())
3268                 callMethod(rec,&CkMigratable::ckJustMigrated);
3269 }
3270 #endif
3271
3272 /********************* LocMgr: UTILITY ****************/
3273 void CkMagicNumber_impl::badMagicNumber(
3274         int expected,const char *file,int line,void *obj) const
3275 {
3276         CkError("FAILURE on pe %d, %s:%d> Expected %p's magic number "
3277                 "to be 0x%08x; but found 0x%08x!\n", CkMyPe(),file,line,obj,
3278                 expected, magic);
3279         CkAbort("Bad magic number detected!  This implies either\n"
3280                 "the heap or a message was corrupted!\n");
3281 }
3282 CkMagicNumber_impl::CkMagicNumber_impl(int m) :magic(m) { }
3283
3284 //Look up the object with this array index, or return NULL
3285 CkMigratable *CkLocMgr::lookup(const CkArrayIndex &idx,CkArrayID aid) {
3286         CkLocRec *rec=elementNrec(idx);
3287         if (rec==NULL) return NULL;
3288         else return rec->lookupElement(aid);
3289 }
3290 //"Last-known" location (returns a processor number)
3291 int CkLocMgr::lastKnown(const CkArrayIndex &idx) {
3292         CkLocMgr *vthis=(CkLocMgr *)this;//Cast away "const"
3293         CkLocRec *rec=vthis->elementNrec(idx);
3294         int pe=-1;
3295         if (rec!=NULL) pe=rec->lookupProcessor();
3296         if (pe==-1) return homePe(idx);
3297         else{
3298                 /*
3299                         FAULT_EVAC
3300                         if the lastKnownPE is invalid return homePE and delete this record
3301                 */
3302                 if(!CmiNodeAlive(pe)){
3303                         removeFromTable(idx);
3304                         return homePe(idx);
3305                 }
3306                 return pe;
3307         }       
3308 }
3309 /// Return true if this array element lives on another processor
3310 bool CkLocMgr::isRemote(const CkArrayIndex &idx,int *onPe) const
3311 {
3312         CkLocMgr *vthis=(CkLocMgr *)this;//Cast away "const"
3313         CkLocRec *rec=vthis->elementNrec(idx);
3314         if (rec==NULL || rec->type()!=CkLocRec::remote) 
3315                 return false; /* not definitely a remote element */
3316         else /* element is indeed remote */
3317         {
3318                 *onPe=rec->lookupProcessor();
3319                 return true;
3320         }
3321 }
3322
3323 static const char *rec2str[]={
3324     "base (INVALID)",//Base class (invalid type)
3325     "local",//Array element that lives on this Pe
3326     "remote",//Array element that lives on some other Pe
3327     "buffering",//Array element that was just created
3328     "dead"//Deleted element (for debugging)
3329 };
3330
3331 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
3332 void CkLocMgr::setDuringMigration(CmiBool _duringMigration){
3333     duringMigration = _duringMigration;
3334 }
3335 #endif
3336
3337
3338 //Add given element array record at idx, replacing the existing record
3339 void CkLocMgr::insertRec(CkLocRec *rec,const CkArrayIndex &idx) {
3340         CkLocRec *old=elementNrec(idx);
3341         insertRecN(rec,idx);
3342         if (old!=NULL) {
3343                 DEBC((AA"  replaces old rec(%s) for %s\n"AB,rec2str[old->type()],idx2str(idx)));
3344                 //There was an old element at this location
3345                 if (old->type()==CkLocRec::local && rec->type()==CkLocRec::local) {
3346                     if (!CkInRestarting()) {    // ok if it is restarting
3347                         CkPrintf("ERROR! Duplicate array index: %s\n",idx2str(idx));
3348                         CkAbort("Duplicate array index used");
3349                     }
3350                 }
3351                 old->beenReplaced();
3352                 delete old;
3353         }
3354 }
3355
3356 //Add given record, when there is guarenteed to be no prior record
3357 void CkLocMgr::insertRecN(CkLocRec *rec,const CkArrayIndex &idx) {
3358         DEBC((AA"  adding new rec(%s) for %s\n"AB,rec2str[rec->type()],idx2str(idx)));
3359         CmiImmediateLock(hashImmLock);
3360         hash.put(*(CkArrayIndex *)&idx)=rec;
3361         CmiImmediateUnlock(hashImmLock);
3362 }
3363
3364 //Call this on an unrecognized array index
3365 static void abort_out_of_bounds(const CkArrayIndex &idx)
3366 {
3367   CkPrintf("ERROR! Unknown array index: %s\n",idx2str(idx));
3368   CkAbort("Array index out of bounds\n");
3369 }
3370
3371 //Look up array element in hash table.  Index out-of-bounds if not found.
3372 CkLocRec *CkLocMgr::elementRec(const CkArrayIndex &idx) {
3373 #if ! CMK_ERROR_CHECKING
3374 //Assume the element will be found
3375         return hash.getRef(*(CkArrayIndex *)&idx);
3376 #else
3377 //Include an out-of-bounds check if the element isn't found
3378         CkLocRec *rec=elementNrec(idx);
3379         if (rec==NULL) abort_out_of_bounds(idx);
3380         return rec;
3381 #endif
3382 }
3383
3384 //Look up array element in hash table.  Return NULL if not there.
3385 CkLocRec *CkLocMgr::elementNrec(const CkArrayIndex &idx) {
3386         return hash.get(*(CkArrayIndex *)&idx);
3387 }
3388
3389 struct LocalElementCounter :  public CkLocIterator
3390 {
3391     unsigned int count;
3392     LocalElementCounter() : count(0) {}
3393     void addLocation(CkLocation &loc)
3394         { ++count; }
3395 };
3396
3397 unsigned int CkLocMgr::numLocalElements()
3398 {
3399     LocalElementCounter c;
3400     iterate(c);
3401     return c.count;
3402 }
3403
3404
3405 /********************* LocMgr: LOAD BALANCE ****************/
3406
3407 #if !CMK_LBDB_ON
3408 //Empty versions of all load balancer calls
3409 void CkLocMgr::initLB(CkGroupID lbdbID_, CkGroupID metalbID_) {}
3410 void CkLocMgr::startInserting(void) {}
3411 void CkLocMgr::doneInserting(void) {}
3412 void CkLocMgr::dummyAtSync(void) {}
3413 #endif
3414
3415
3416 #if CMK_LBDB_ON
3417 void CkLocMgr::initLB(CkGroupID lbdbID_, CkGroupID metalbID_)
3418 { //Find and register with the load balancer
3419         the_lbdb = (LBDatabase *)CkLocalBranch(lbdbID_);
3420         if (the_lbdb == 0)
3421                 CkAbort("LBDatabase not yet created?\n");
3422         DEBL((AA"Connected to load balancer %p\n"AB,the_lbdb));
3423         the_metalb = (MetaBalancer *)CkLocalBranch(metalbID_);
3424         if (the_metalb == 0)
3425                 CkAbort("MetaBalancer not yet created?\n");
3426
3427         // Register myself as an object manager
3428         LDOMid myId;
3429         myId.id = thisgroup;
3430         LDCallbacks myCallbacks;
3431         myCallbacks.migrate = (LDMigrateFn)CkLocRec_local::staticMigrate;
3432         myCallbacks.setStats = NULL;
3433         myCallbacks.queryEstLoad = NULL;
3434   myCallbacks.metaLBResumeWaitingChares =
3435       (LDMetaLBResumeWaitingCharesFn)CkLocRec_local::staticMetaLBResumeWaitingChares;
3436   myCallbacks.metaLBCallLBOnChares =
3437       (LDMetaLBCallLBOnCharesFn)CkLocRec_local::staticMetaLBCallLBOnChares;
3438         myLBHandle = the_lbdb->RegisterOM(myId,this,myCallbacks);
3439
3440         // Tell the lbdb that I'm registering objects
3441         the_lbdb->RegisteringObjects(myLBHandle);
3442
3443         /*Set up the dummy barrier-- the load balancer needs
3444           us to call Registering/DoneRegistering during each AtSync,
3445           and this is the only way to do so.
3446         */
3447         the_lbdb->AddLocalBarrierReceiver(
3448                 (LDBarrierFn)staticRecvAtSync,(void*)(this));
3449         dummyBarrierHandle = the_lbdb->AddLocalBarrierClient(
3450                 (LDResumeFn)staticDummyResumeFromSync,(void*)(this));
3451         dummyAtSync();
3452 }
3453 void CkLocMgr::dummyAtSync(void)
3454 {
3455         DEBL((AA"dummyAtSync called\n"AB));
3456         the_lbdb->AtLocalBarrier(dummyBarrierHandle);
3457 }
3458
3459 void CkLocMgr::staticDummyResumeFromSync(void* data)
3460 {      ((CkLocMgr*)data)->dummyResumeFromSync(); }
3461 void CkLocMgr::dummyResumeFromSync()
3462 {
3463         DEBL((AA"DummyResumeFromSync called\n"AB));
3464         the_lbdb->DoneRegisteringObjects(myLBHandle);
3465         dummyAtSync();
3466 }
3467 void CkLocMgr::staticRecvAtSync(void* data)
3468 {      ((CkLocMgr*)data)->recvAtSync(); }
3469 void CkLocMgr::recvAtSync()
3470 {
3471         DEBL((AA"recvAtSync called\n"AB));
3472         the_lbdb->RegisteringObjects(myLBHandle);
3473 }
3474
3475 void CkLocMgr::startInserting(void)
3476 {
3477         the_lbdb->RegisteringObjects(myLBHandle);
3478 }
3479 void CkLocMgr::doneInserting(void)
3480 {
3481         the_lbdb->DoneRegisteringObjects(myLBHandle);
3482 }
3483 #endif
3484
3485 #include "CkLocation.def.h"
3486
3487