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