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