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