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