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