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