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