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