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