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