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