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