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