Merge branch 'charm' of charmgit:charm into charm
[charm.git] / src / ck-core / cklocation.C
1 /** \file cklocation.C
2  *  \addtogroup CkArrayImpl
3  *
4  *  The location manager keeps track of an indexed set of migratable objects.
5  *  It is used by the array manager to locate array elements, interact with the
6  *  load balancer, and perform migrations.
7  *
8  *  Orion Sky Lawlor, olawlor@acm.org 9/29/2001
9  */
10
11 #include "charm++.h"
12 #include "register.h"
13 #include "ck.h"
14 #include "trace.h"
15 #include "TopoManager.h"
16
17 #include<sstream>
18
19 #if CMK_LBDB_ON
20 #include "LBDatabase.h"
21 #endif // CMK_LBDB_ON
22
23 #if CMK_GRID_QUEUE_AVAILABLE
24 CpvExtern(void *, CkGridObject);
25 #endif
26
27 static const char *idx2str(const CkArrayMessage *m) {
28   return idx2str(((CkArrayMessage *)m)->array_index());
29 }
30
31 #define ARRAY_DEBUG_OUTPUT 0
32
33 #if ARRAY_DEBUG_OUTPUT 
34 #   define DEB(x) CkPrintf x  //General debug messages
35 #   define DEBI(x) CkPrintf x  //Index debug messages
36 #   define DEBC(x) CkPrintf x  //Construction debug messages
37 #   define DEBS(x) CkPrintf x  //Send/recv/broadcast debug messages
38 #   define DEBM(x) CkPrintf x  //Migration debug messages
39 #   define DEBL(x) CkPrintf x  //Load balancing debug messages
40 #   define DEBK(x) //CkPrintf x  //Spring Cleaning debug messages
41 #   define DEBB(x) CkPrintf x  //Broadcast debug messages
42 #   define AA "LocMgr on %d: "
43 #   define AB ,CkMyPe()
44 #   define DEBUG(x) CkPrintf x
45 #else
46 #   define DEB(X) /*CkPrintf x*/
47 #   define DEBI(X) /*CkPrintf x*/
48 #   define DEBC(X) /*CkPrintf x*/
49 #   define DEBS(x) /*CkPrintf x*/
50 #   define DEBM(X) /*CkPrintf x*/
51 #   define DEBL(X) /*CkPrintf x*/
52 #   define DEBK(x) /*CkPrintf x*/
53 #   define DEBB(x) /*CkPrintf x*/
54 #   define str(x) /**/
55 #   define DEBUG(x)   /**/
56 #endif
57
58 //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         // releasing iterator memory
1865         delete it;
1866 }
1867 #endif
1868
1869 /*************************** LocMgr: CREATION *****************************/
1870 CkLocMgr::CkLocMgr(CkGroupID mapID_,CkGroupID lbdbID_,CkArrayIndex& numInitial)
1871         :thisProxy(thisgroup),thislocalproxy(thisgroup,CkMyPe()),
1872          hash(17,0.3)
1873 {
1874         DEBC((AA"Creating new location manager %d\n"AB,thisgroup));
1875 // moved to _CkMigratable_initInfoInit()
1876 //      CkpvInitialize(CkMigratable_initInfo,mig_initInfo);
1877
1878         managers.init();
1879         nManagers=0;
1880         firstManager=NULL;
1881         firstFree=localLen=0;
1882         duringMigration=CmiFalse;
1883         nSprings=0;
1884         CcdCallOnConditionKeepOnPE(CcdPERIODIC_1minute,staticSpringCleaning,(void *)this, CkMyPe());
1885
1886 //Register with the map object
1887         mapID=mapID_;
1888         map=(CkArrayMap *)CkLocalBranch(mapID);
1889         if (map==NULL) CkAbort("ERROR!  Local branch of array map is NULL!");
1890         mapHandle=map->registerArray(numInitial,thisgroup);
1891
1892 //Find and register with the load balancer
1893         lbdbID = lbdbID_;
1894         initLB(lbdbID_);
1895         hashImmLock = CmiCreateImmediateLock();
1896 }
1897
1898 CkLocMgr::CkLocMgr(CkMigrateMessage* m)
1899         :IrrGroup(m),thisProxy(thisgroup),thislocalproxy(thisgroup,CkMyPe()),hash(17,0.3)
1900 {
1901         managers.init();
1902         nManagers=0;
1903         firstManager=NULL;
1904         firstFree=localLen=0;
1905         duringMigration=CmiFalse;
1906         nSprings=0;
1907         CcdCallOnConditionKeepOnPE(CcdPERIODIC_1minute,staticSpringCleaning,(void *)this, CkMyPe());
1908         hashImmLock = CmiCreateImmediateLock();
1909 }
1910
1911 void CkLocMgr::pup(PUP::er &p){
1912         IrrGroup::pup(p);
1913         p|mapID;
1914         p|mapHandle;
1915         p|lbdbID;
1916         mapID = _defaultArrayMapID;
1917         if(p.isUnpacking()){
1918                 thisProxy=thisgroup;
1919                 CProxyElement_CkLocMgr newlocalproxy(thisgroup,CkMyPe());
1920                 thislocalproxy=newlocalproxy;
1921                 //Register with the map object
1922                 map=(CkArrayMap *)CkLocalBranch(mapID);
1923                 if (map==NULL) CkAbort("ERROR!  Local branch of array map is NULL!");
1924                 CkArrayIndex emptyIndex;
1925                 map->registerArray(emptyIndex,thisgroup);
1926                 // _lbdb is the fixed global groupID
1927                 initLB(lbdbID);
1928
1929 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))     
1930         int count;
1931         p | count;
1932         DEBUG(CmiPrintf("[%d] Unpacking Locmgr %d has %d home elements\n",CmiMyPe(),thisgroup.idx,count));
1933         homeElementCount = count;
1934
1935         for(int i=0;i<count;i++){
1936             CkArrayIndex idx;
1937             int pe;
1938             idx.pup(p);
1939             p | pe;
1940             DEBUG(CmiPrintf("[%d] idx %s is a home element exisiting on pe %d\n",CmiMyPe(),idx2str(idx),pe));
1941             inform(idx,pe);
1942             CkLocRec *rec = elementNrec(idx);
1943             CmiAssert(rec!=NULL);
1944             CmiAssert(lastKnown(idx) == pe);
1945         }
1946 #endif
1947                 // delay doneInserting when it is unpacking during restart.
1948                 // to prevent load balancing kicking in
1949                 if (!CkInRestarting()) 
1950                         doneInserting();
1951         }else{
1952  /**
1953  * pack the indexes of elements which have their homes on this processor
1954  * but dont exist on it.. needed for broadcast after a restart
1955  * indexes of local elements dont need to be packed
1956  * since they will be recreated later anyway
1957  */
1958 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))     
1959         int count=0,count1=0;
1960         void *objp;
1961         void *keyp;
1962         CkHashtableIterator *it = hash.iterator();
1963       while (NULL!=(objp=it->next(&keyp))) {
1964       CkLocRec *rec=*(CkLocRec **)objp;
1965         CkArrayIndex &idx=*(CkArrayIndex *)keyp;
1966             if(rec->type() != CkLocRec::local){
1967                 if(homePe(idx) == CmiMyPe()){
1968                     count++;
1969                 }
1970             }
1971         }
1972         p | count;
1973         DEBUG(CmiPrintf("[%d] Packing Locmgr %d has %d home elements\n",CmiMyPe(),thisgroup.idx,count));
1974
1975                 // releasing iterator memory
1976                 delete it;
1977
1978         it = hash.iterator();
1979       while (NULL!=(objp=it->next(&keyp))) {
1980       CkLocRec *rec=*(CkLocRec **)objp;
1981         CkArrayIndex &idx=*(CkArrayIndex *)keyp;
1982             CkArrayIndex max = idx;
1983             if(rec->type() != CkLocRec::local){
1984                 if(homePe(idx) == CmiMyPe()){
1985                     int pe;
1986                     max.pup(p);
1987                     pe = rec->lookupProcessor();
1988                     p | pe;
1989                     count1++;
1990                 }
1991             }
1992         }
1993         CmiAssert(count == count1);
1994
1995                 // releasing iterator memory
1996                 delete it;
1997
1998 #endif
1999
2000         }
2001 }
2002
2003 void _CkLocMgrInit(void) {
2004   /* Don't trace our deliver method--it does its own tracing */
2005   CkDisableTracing(CkIndex_CkLocMgr::deliverInline(0));
2006 }
2007
2008 /// Add a new local array manager to our list.
2009 /// Returns a new CkMigratableList for the manager to store his
2010 /// elements in.
2011 CkMigratableList *CkLocMgr::addManager(CkArrayID id,CkArrMgr *mgr)
2012 {
2013         CK_MAGICNUMBER_CHECK
2014         DEBC((AA"Adding new array manager\n"AB));
2015         //Link new manager into list
2016         ManagerRec *n=new ManagerRec;
2017         managers.find(id)=n;
2018         n->next=firstManager;
2019         n->mgr=mgr;
2020         n->elts.setSize(localLen);
2021         nManagers++;
2022         firstManager=n;
2023         return &n->elts;
2024 }
2025
2026 /// Return the next unused local element index.
2027 int CkLocMgr::nextFree(void) {
2028         if (firstFree>=localLen)
2029         {//Need more space in the local index arrays-- enlarge them
2030                 int oldLen=localLen;
2031                 localLen=localLen*2+8;
2032                 DEBC((AA"Growing the local list from %d to %d...\n"AB,oldLen,localLen));
2033                 for (ManagerRec *m=firstManager;m!=NULL;m=m->next)
2034                         m->elts.setSize(localLen);
2035                 //Update the free list
2036                 freeList.resize(localLen);
2037                 for (int i=oldLen;i<localLen;i++)
2038                         freeList[i]=i+1;
2039         }
2040         int localIdx=firstFree;
2041         if (localIdx==-1) CkAbort("CkLocMgr free list corrupted!");
2042         firstFree=freeList[localIdx];
2043         freeList[localIdx]=-1; //Mark as used
2044         return localIdx;
2045 }
2046
2047 CkLocRec_remote *CkLocMgr::insertRemote(const CkArrayIndex &idx,int nowOnPe)
2048 {
2049         DEBS((AA"Remote element %s lives on %d\n"AB,idx2str(idx),nowOnPe));
2050         CkLocRec_remote *rem=new CkLocRec_remote(this,nowOnPe);
2051         insertRec(rem,idx);
2052         return rem;
2053 }
2054
2055 //This element now lives on the given Pe
2056 void CkLocMgr::inform(const CkArrayIndex &idx,int nowOnPe)
2057 {
2058         if (nowOnPe==CkMyPe())
2059                 return; //Never insert a "remote" record pointing here
2060         CkLocRec *rec=elementNrec(idx);
2061         if (rec!=NULL && rec->type()==CkLocRec::local){
2062 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2063         CmiPrintf("[%d]WARNING!!! Element %d:%s is local but is being told it exists on %d\n",CkMyPe(),idx.dimension,idx2str(idx), nowOnPe);
2064 #endif
2065                 return; //Never replace a local element's record!
2066         }
2067         insertRemote(idx,nowOnPe);
2068 }
2069
2070 //Tell this element's home processor it now lives "there"
2071 void CkLocMgr::informHome(const CkArrayIndex &idx,int nowOnPe)
2072 {
2073         int home=homePe(idx);
2074         if (home!=CkMyPe() && home!=nowOnPe) {
2075                 //Let this element's home Pe know it lives here now
2076                 DEBC((AA"  Telling %s's home %d that it lives on %d.\n"AB,idx2str(idx),home,nowOnPe));
2077 //#if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2078 #if defined(_FAULT_MLOG_)
2079         informLocationHome(thisgroup,idx,home,CkMyPe());
2080 #else
2081                 thisProxy[home].updateLocation(idx,nowOnPe);
2082 #endif
2083         }
2084 }
2085
2086 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2087 CkLocRec_local *CkLocMgr::createLocal(const CkArrayIndex &idx,
2088         CmiBool forMigration, CmiBool ignoreArrival,
2089         CmiBool notifyHome,int dummy)
2090 {
2091     int localIdx=nextFree();
2092     DEBC((AA"Adding new record for element %s at local index %d\n"AB,idx2str(idx),localIdx));
2093     CkLocRec_local *rec=new CkLocRec_local(this,forMigration,ignoreArrival,idx,localIdx);
2094     if(!dummy){
2095         insertRec(rec,idx); //Add to global hashtable
2096     }   
2097     if (notifyHome) informHome(idx,CkMyPe());
2098     return rec; 
2099 }
2100 #else
2101 CkLocRec_local *CkLocMgr::createLocal(const CkArrayIndex &idx, 
2102                 CmiBool forMigration, CmiBool ignoreArrival,
2103                 CmiBool notifyHome)
2104 {
2105         int localIdx=nextFree();
2106         DEBC((AA"Adding new record for element %s at local index %d\n"AB,idx2str(idx),localIdx));
2107         CkLocRec_local *rec=new CkLocRec_local(this,forMigration,ignoreArrival,idx,localIdx);
2108         insertRec(rec,idx); //Add to global hashtable
2109
2110
2111         if (notifyHome) informHome(idx,CkMyPe());
2112         return rec;
2113 }
2114 #endif
2115
2116 //Add a new local array element, calling element's constructor
2117 CmiBool CkLocMgr::addElement(CkArrayID id,const CkArrayIndex &idx,
2118                 CkMigratable *elt,int ctorIdx,void *ctorMsg)
2119 {
2120         CK_MAGICNUMBER_CHECK
2121         CkLocRec *oldRec=elementNrec(idx);
2122         CkLocRec_local *rec;
2123         if (oldRec==NULL||oldRec->type()!=CkLocRec::local) 
2124         { //This is the first we've heard of that element-- add new local record
2125                 rec=createLocal(idx,CmiFalse,CmiFalse,CmiTrue);
2126         } else 
2127         { //rec is *already* local-- must not be the first insertion    
2128                 rec=((CkLocRec_local *)oldRec);
2129                 rec->addedElement();
2130         }
2131         if (!addElementToRec(rec,managers.find(id),elt,ctorIdx,ctorMsg)) return CmiFalse;
2132         elt->ckFinishConstruction();
2133         return CmiTrue;
2134 }
2135
2136 //As above, but shared with the migration code
2137 CmiBool CkLocMgr::addElementToRec(CkLocRec_local *rec,ManagerRec *m,
2138                 CkMigratable *elt,int ctorIdx,void *ctorMsg)
2139 {//Insert the new element into its manager's local list
2140         int localIdx=rec->getLocalIndex();
2141         if (m->elts.get(localIdx)!=NULL) CkAbort("Cannot insert array element twice!");
2142         m->elts.put(elt,localIdx); //Local element table
2143
2144 //Call the element's constructor
2145         DEBC((AA"Constructing element %s of array\n"AB,idx2str(rec->getIndex())));
2146         CkMigratable_initInfo &i=CkpvAccess(mig_initInfo);
2147         i.locRec=rec;
2148         i.chareType=_entryTable[ctorIdx]->chareIdx;
2149         if (!rec->invokeEntry(elt,ctorMsg,ctorIdx,CmiTrue)) return CmiFalse;
2150
2151 #if CMK_OUT_OF_CORE
2152         /* Register new element with out-of-core */
2153         PUP::sizer p_getSize; elt->pup(p_getSize);
2154         elt->prefetchObjID=CooRegisterObject(&CkArrayElementPrefetcher,p_getSize.size(),elt);
2155 #endif
2156         
2157         return CmiTrue;
2158 }
2159 void CkLocMgr::updateLocation(const CkArrayIndex &idx,int nowOnPe) {
2160         inform(idx,nowOnPe);
2161 }
2162
2163 /*************************** LocMgr: DELETION *****************************/
2164 /// This index will no longer be used-- delete the associated elements
2165 void CkLocMgr::reclaim(const CkArrayIndex &idx,int localIdx) {
2166         CK_MAGICNUMBER_CHECK
2167         DEBC((AA"Destroying element %s (local %d)\n"AB,idx2str(idx),localIdx));
2168         //Delete, and mark as empty, each array element
2169         for (ManagerRec *m=firstManager;m!=NULL;m=m->next) {
2170                 delete m->elts.get(localIdx);
2171                 m->elts.empty(localIdx);
2172         }
2173         
2174         removeFromTable(idx);
2175         
2176         //Link local index into free list
2177         freeList[localIdx]=firstFree;
2178         firstFree=localIdx;
2179         
2180                 
2181         if (!duringMigration) 
2182         { //This is a local element dying a natural death
2183             #if CMK_BIGSIM_CHARM
2184                 //After migration, reclaimRemote will be called through 
2185                 //the CkRemoveArrayElement in the pupping routines for those 
2186                 //objects that are not on the home processors. However,
2187                 //those remote records should not be deleted since the corresponding
2188                 //objects are not actually deleted but on disk. If deleted, msgs
2189                 //that seeking where is the object will be accumulated (a circular
2190                 //msg chain) and causes the program no progress
2191                 if(_BgOutOfCoreFlag==1) return; 
2192             #endif
2193                 int home=homePe(idx);
2194                 if (home!=CkMyPe())
2195 #if CMK_MEM_CHECKPOINT
2196                 if (!CkInRestarting()) // all array elements are removed anyway
2197 #endif
2198                         thisProxy[home].reclaimRemote(idx,CkMyPe());
2199         /*      //Install a zombie to keep the living from re-using this index.
2200                 insertRecN(new CkLocRec_dead(this),idx); */
2201         }
2202 }
2203
2204 void CkLocMgr::reclaimRemote(const CkArrayIndex &idx,int deletedOnPe) {
2205         DEBC((AA"Our element %s died on PE %d\n"AB,idx2str(idx),deletedOnPe));
2206         CkLocRec *rec=elementNrec(idx);
2207         if (rec==NULL) return; //We never knew him
2208         if (rec->type()==CkLocRec::local) return; //He's already been reborn
2209         removeFromTable(idx);
2210         delete rec;
2211 }
2212 void CkLocMgr::removeFromTable(const CkArrayIndex &idx) {
2213 #if CMK_ERROR_CHECKING
2214         //Make sure it's actually in the table before we delete it
2215         if (NULL==elementNrec(idx))
2216                 CkAbort("CkLocMgr::removeFromTable called on invalid index!");
2217 #endif
2218         CmiImmediateLock(hashImmLock);
2219         hash.remove(*(CkArrayIndex *)&idx);
2220         CmiImmediateUnlock(hashImmLock);
2221 #if CMK_ERROR_CHECKING
2222         //Make sure it's really gone
2223         if (NULL!=elementNrec(idx))
2224                 CkAbort("CkLocMgr::removeFromTable called, but element still there!");
2225 #endif
2226 }
2227
2228 /************************** LocMgr: MESSAGING *************************/
2229 /// Deliver message to this element, going via the scheduler if local
2230 /// @return 0 if object local, 1 if not
2231 int CkLocMgr::deliver(CkMessage *m,CkDeliver_t type,int opts) {
2232         DEBS((AA"deliver \n"AB));
2233         CK_MAGICNUMBER_CHECK
2234         CkArrayMessage *msg=(CkArrayMessage *)m;
2235
2236
2237         const CkArrayIndex &idx=msg->array_index();
2238         DEBS((AA"deliver %s\n"AB,idx2str(idx)));
2239         if (type==CkDeliver_queue)
2240                 _TRACE_CREATION_DETAILED(UsrToEnv(m),msg->array_ep());
2241         CkLocRec *rec=elementNrec(idx);
2242         if(rec != NULL){
2243                 DEBS((AA"deliver %s of type %d \n"AB,idx2str(idx),rec->type()));
2244         }else{
2245                 DEBS((AA"deliver %s rec is null\n"AB,idx2str(idx)));
2246         }
2247 //#if (!defined(_FAULT_MLOG_) && !defined(_FAULT_CAUSAL_))
2248 #if !defined(_FAULT_MLOG_)
2249 #if CMK_LBDB_ON
2250         if (type==CkDeliver_queue) {
2251                 if (!(opts & CK_MSG_LB_NOTRACE) && the_lbdb->CollectingCommStats()) {
2252                 if(rec!=NULL) the_lbdb->Send(myLBHandle,idx2LDObjid(idx),UsrToEnv(msg)->getTotalsize(), rec->lookupProcessor(), 1);
2253                 else /*rec==NULL*/ the_lbdb->Send(myLBHandle,idx2LDObjid(idx),UsrToEnv(msg)->getTotalsize(),homePe(msg->array_index()), 1);
2254                 }
2255         }
2256 #endif
2257 #endif
2258 #if CMK_GRID_QUEUE_AVAILABLE
2259         int gridSrcPE;
2260         int gridSrcCluster;
2261         int gridDestPE;
2262         int gridDestCluster;
2263         CkMigratable *obj;
2264         ArrayElement *obj2;
2265         CkGroupID gid;
2266         int *data;
2267
2268         obj = (CkMigratable *) CpvAccess(CkGridObject);   // CkGridObject is a pointer to the sending object (retained earlier)
2269         if (obj != NULL) {
2270           obj2 = dynamic_cast<ArrayElement *> (obj);
2271           if (obj2 > 0) {
2272             // Get the sending object's array gid and indexes.
2273             // These are guaranteed to exist due to the succeeding dynamic cast above.
2274             gid = obj2->ckGetArrayID ();
2275             data = obj2->thisIndexMax.data ();
2276
2277             // Get the source PE and destination PE.
2278             gridSrcPE = CkMyPe ();
2279             if (rec != NULL) {
2280               gridDestPE = rec->lookupProcessor ();
2281             } else {
2282               gridDestPE = homePe (msg->array_index ());
2283             }
2284
2285             // Get the source cluster and destination cluster.
2286             gridSrcCluster = CmiGetCluster (gridSrcPE);
2287             gridDestCluster = CmiGetCluster (gridDestPE);
2288
2289             // If the Grid queue interval is greater than zero, it means that the more complicated
2290             // technique for registering border objects that exceed a specified threshold of
2291             // cross-cluster messages within a specified interval (and deregistering border objects
2292             // that do not meet this threshold) is used.  Otherwise a much simpler technique is used
2293             // where a border object is registered immediately upon sending a single cross-cluster
2294             // message (and deregistered when load balancing takes place).
2295             if (obj2->grid_queue_interval > 0) {
2296               // Increment the sending object's count of all messages.
2297               obj2->msg_count += 1;
2298
2299               // If the source cluster and destination cluster differ, this is a Grid message.
2300               // (Increment the count of all Grid messages.)
2301               if (gridSrcCluster != gridDestCluster) {
2302                 obj2->msg_count_grid += 1;
2303               }
2304
2305               // If the number of messages exceeds the interval, check to see if the object has
2306               // sent enough cross-cluster messages to qualify as a border object.
2307               if (obj2->msg_count >= obj2->grid_queue_interval) {
2308                 if (obj2->msg_count_grid >= obj2->grid_queue_threshold) {
2309                   // The object is a border object; if it is not already registered, register it.
2310                   if (!obj2->border_flag) {
2311                     CmiGridQueueRegister (gid.idx, obj2->thisIndexMax.nInts, data[0], data[1], data[2]);
2312                   }
2313                   obj2->border_flag = 1;
2314                 } else {
2315                   // The object is not a border object; if it is registered, deregister it.
2316                   if (obj2->border_flag) {
2317                     CmiGridQueueDeregister (gid.idx, obj2->thisIndexMax.nInts, data[0], data[1], data[2]);
2318                   }
2319                   obj2->border_flag = 0;
2320                 }
2321                 // Reset the counts.
2322                 obj2->msg_count = 0;
2323                 obj2->msg_count_grid = 0;
2324               }
2325             } else {
2326               if (gridSrcCluster != gridDestCluster) {
2327                 CmiGridQueueRegister (gid.idx, obj2->thisIndexMax.nInts, data[0], data[1], data[2]);
2328               }
2329             }
2330           }
2331
2332           // Reset the CkGridObject pointer.
2333           CpvAccess(CkGridObject) = NULL;
2334         }
2335 #endif
2336         /**FAULT_EVAC*/
2337         if (rec!=NULL){
2338                 CmiBool result = rec->deliver(msg,type,opts);
2339                 // if result is CmiFalse, than rec is not valid anymore, as the object
2340                 // the message was just delivered to has died or migrated out.
2341                 // Therefore rec->type() cannot be invoked!
2342                 if (result==CmiTrue && rec->type()==CkLocRec::local) return 0;
2343                 else return 1;
2344                 /*if(!result){
2345                         //DEBS((AA"deliver %s failed type %d \n"AB,idx2str(idx),rec->type()));
2346                         DEBS((AA"deliver %s failed \n"AB,idx2str(idx)));
2347                         if(rec->type() == CkLocRec::remote){
2348                                 if (opts & CK_MSG_KEEP)
2349                                         msg = (CkArrayMessage *)CkCopyMsg((void **)&msg);
2350                                 deliverUnknown(msg,type);
2351                         }
2352                 }*/
2353         }else /* rec==NULL*/ {
2354                 if (opts & CK_MSG_KEEP)
2355                         msg = (CkArrayMessage *)CkCopyMsg((void **)&msg);
2356                 deliverUnknown(msg,type,opts);
2357                 return 1;
2358         }
2359
2360 }
2361
2362 /// This index is not hashed-- somehow figure out what to do.
2363 CmiBool CkLocMgr::deliverUnknown(CkArrayMessage *msg,CkDeliver_t type,int opts)
2364 {
2365         CK_MAGICNUMBER_CHECK
2366         const CkArrayIndex &idx=msg->array_index();
2367         int onPe=homePe(idx);
2368         if (onPe!=CkMyPe()) 
2369         {// Forward the message to its home processor
2370                 DEBM((AA"Forwarding message for unknown %s to home %d \n"AB,idx2str(idx),onPe));
2371                 msg->array_hops()++;
2372                 CkArrayManagerDeliver(onPe,msg,opts);
2373                 return CmiTrue;
2374         }
2375         else
2376         { // We *are* the home processor:
2377         //Check if the element's array manager has been registered yet:
2378           CkArrMgr *mgr=managers.find(UsrToEnv((void *)msg)->getsetArrayMgr())->mgr;
2379           if (!mgr) { //No manager yet-- postpone the message (stupidly)
2380             if (CkInRestarting()) {
2381               // during restarting, this message should be ignored
2382               delete msg;
2383             }
2384             else {
2385               CkArrayManagerDeliver(CkMyPe(),msg); 
2386             }
2387           }
2388           else { // Has a manager-- must buffer the message
2389             DEBC((AA"Adding buffer for unknown element %s\n"AB,idx2str(idx)));
2390             CkLocRec *rec=new CkLocRec_buffering(this);
2391             insertRecN(rec,idx);
2392             rec->deliver(msg,type);
2393           
2394             if (msg->array_ifNotThere()!=CkArray_IfNotThere_buffer) 
2395             { //Demand-create the element:
2396               return demandCreateElement(msg,-1,type);
2397             }
2398           }
2399           return CmiTrue;
2400         }
2401 }
2402
2403 CmiBool CkLocMgr::demandCreateElement(CkArrayMessage *msg,int onPe,CkDeliver_t type)
2404 {
2405         CK_MAGICNUMBER_CHECK
2406         const CkArrayIndex &idx=msg->array_index();
2407         int chareType=_entryTable[msg->array_ep()]->chareIdx;
2408         int ctor=_chareTable[chareType]->getDefaultCtor();
2409         if (ctor==-1) CkAbort("Can't create array element to handle message--\n"
2410                               "The element has no default constructor in the .ci file!\n");
2411         if (onPe==-1) 
2412         { //Decide where element needs to live
2413                 if (msg->array_ifNotThere()==CkArray_IfNotThere_createhere) 
2414                         onPe=UsrToEnv(msg)->getsetArraySrcPe();
2415                 else //Createhome
2416                         onPe=homePe(idx);
2417         }
2418         
2419         //Find the manager and build the element
2420         DEBC((AA"Demand-creating element %s on pe %d\n"AB,idx2str(idx),onPe));
2421         CkArrMgr *mgr=managers.find(UsrToEnv((void *)msg)->getsetArrayMgr())->mgr;
2422         if (!mgr) CkAbort("Tried to demand-create for nonexistent arrMgr");
2423         return mgr->demandCreateElement(idx,onPe,ctor,type);
2424 }
2425
2426 //This message took several hops to reach us-- fix it
2427 void CkLocMgr::multiHop(CkArrayMessage *msg)
2428 {
2429         CK_MAGICNUMBER_CHECK
2430         int srcPe=msg->array_getSrcPe();
2431         if (srcPe==CkMyPe())
2432                 DEB((AA"Odd routing: local element %s is %d hops away!\n"AB,idx2str(msg),msg->array_hops()));
2433         else
2434         {//Send a routing message letting original sender know new element location
2435                 DEBS((AA"Sending update back to %d for element\n"AB,srcPe,idx2str(msg)));
2436                 thisProxy[srcPe].updateLocation(msg->array_index(),CkMyPe());
2437         }
2438 }
2439
2440 /************************** LocMgr: ITERATOR *************************/
2441 CkLocation::CkLocation(CkLocMgr *mgr_, CkLocRec_local *rec_)
2442         :mgr(mgr_), rec(rec_) {}
2443         
2444 const CkArrayIndex &CkLocation::getIndex(void) const {
2445         return rec->getIndex();
2446 }
2447
2448 void CkLocation::destroyAll() {
2449         mgr->callMethod(rec, &CkMigratable::ckDestroy);
2450 }
2451
2452 void CkLocation::pup(PUP::er &p) {
2453         mgr->pupElementsFor(p,rec,CkElementCreation_migrate);
2454 }
2455
2456 CkLocIterator::~CkLocIterator() {}
2457
2458 /// Iterate over our local elements:
2459 void CkLocMgr::iterate(CkLocIterator &dest) {
2460   //Poke through the hash table for local ArrayRecs.
2461   void *objp;
2462   CkHashtableIterator *it=hash.iterator();
2463   CmiImmediateLock(hashImmLock);
2464
2465   while (NULL!=(objp=it->next())) {
2466     CkLocRec *rec=*(CkLocRec **)objp;
2467     if (rec->type()==CkLocRec::local) {
2468       CkLocation loc(this,(CkLocRec_local *)rec);
2469       dest.addLocation(loc);
2470     }
2471   }
2472   CmiImmediateUnlock(hashImmLock);
2473   delete it;
2474 }
2475
2476
2477
2478
2479 /************************** LocMgr: MIGRATION *************************/
2480 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2481 void CkLocMgr::pupElementsFor(PUP::er &p,CkLocRec_local *rec,
2482         CkElementCreation_t type, CmiBool create, int dummy)
2483 {
2484     p.comment("-------- Array Location --------");
2485     register ManagerRec *m;
2486     int localIdx=rec->getLocalIndex();
2487     CkVec<CkMigratable *> dummyElts;
2488
2489     for (m=firstManager;m!=NULL;m=m->next) {
2490         int elCType;
2491         if (!p.isUnpacking())
2492         { //Need to find the element's existing type
2493             CkMigratable *elt=m->element(localIdx);
2494             if (elt) elCType=elt->ckGetChareType();
2495             else elCType=-1; //Element hasn't been created
2496         }
2497         p(elCType);
2498         if (p.isUnpacking() && elCType!=-1) {
2499             CkMigratable *elt=m->mgr->allocateMigrated(elCType,rec->getIndex(),type);
2500             int migCtorIdx=_chareTable[elCType]->getMigCtor();
2501                 if(!dummy){
2502                         if(create)
2503                                 if (!addElementToRec(rec,m,elt,migCtorIdx,NULL)) return;
2504                                 }else{
2505                     CkMigratable_initInfo &i=CkpvAccess(mig_initInfo);
2506                     i.locRec=rec;
2507                     i.chareType=_entryTable[migCtorIdx]->chareIdx;
2508                     dummyElts.push_back(elt);
2509                     if (!rec->invokeEntry(elt,NULL,migCtorIdx,CmiTrue)) return ;
2510                 }
2511         }
2512     }
2513     if(!dummy){
2514         for (m=firstManager;m!=NULL;m=m->next) {
2515             CkMigratable *elt=m->element(localIdx);
2516             if (elt!=NULL)
2517                 {
2518                        elt->pup(p);
2519                 }
2520         }
2521     }else{
2522             for(int i=0;i<dummyElts.size();i++){
2523                 CkMigratable *elt = dummyElts[i];
2524                 if (elt!=NULL){
2525             elt->pup(p);
2526                         }
2527                 delete elt;
2528             }
2529                         for (ManagerRec *m=firstManager;m!=NULL;m=m->next) {
2530                 m->elts.empty(localIdx);
2531             }
2532         freeList[localIdx]=firstFree;
2533         firstFree=localIdx;
2534     }
2535 }
2536 #else
2537 void CkLocMgr::pupElementsFor(PUP::er &p,CkLocRec_local *rec,
2538                 CkElementCreation_t type)
2539 {
2540         p.comment("-------- Array Location --------");
2541         register ManagerRec *m;
2542         int localIdx=rec->getLocalIndex();
2543
2544         //First pup the element types
2545         // (A separate loop so ckLocal works even in element pup routines)
2546         for (m=firstManager;m!=NULL;m=m->next) {
2547                 int elCType;
2548                 if (!p.isUnpacking())
2549                 { //Need to find the element's existing type
2550                         CkMigratable *elt=m->element(localIdx);
2551                         if (elt) elCType=elt->ckGetChareType();
2552                         else elCType=-1; //Element hasn't been created
2553                 }
2554                 p(elCType);
2555                 if (p.isUnpacking() && elCType!=-1) {
2556                         //Create the element
2557                         CkMigratable *elt=m->mgr->allocateMigrated(elCType,rec->getIndex(),type);
2558                         int migCtorIdx=_chareTable[elCType]->getMigCtor();
2559                         //Insert into our tables and call migration constructor
2560                         if (!addElementToRec(rec,m,elt,migCtorIdx,NULL)) return;
2561                 }
2562         }
2563         //Next pup the element data
2564         for (m=firstManager;m!=NULL;m=m->next) {
2565                 CkMigratable *elt=m->element(localIdx);
2566                 if (elt!=NULL)
2567                 {
2568                         elt->pup(p);
2569 #if CMK_ERROR_CHECKING
2570                         if (p.isUnpacking()) elt->sanitycheck();
2571 #endif
2572                 }
2573         }
2574 }
2575 #endif
2576
2577 /// Call this member function on each element of this location:
2578 void CkLocMgr::callMethod(CkLocRec_local *rec,CkMigratable_voidfn_t fn)
2579 {
2580         int localIdx=rec->getLocalIndex();
2581         for (ManagerRec *m=firstManager;m!=NULL;m=m->next) {
2582                 CkMigratable *el=m->element(localIdx);
2583                 if (el) (el->* fn)();
2584         }
2585 }
2586
2587 /// return a list of migratables in this local record
2588 void CkLocMgr::migratableList(CkLocRec_local *rec, CkVec<CkMigratable *> &list)
2589 {
2590         register ManagerRec *m;
2591         int localIdx=rec->getLocalIndex();
2592
2593         for (m=firstManager;m!=NULL;m=m->next) {
2594                 CkMigratable *elt=m->element(localIdx);
2595                 if (elt) list.push_back(elt);
2596         }
2597 }
2598
2599 /// Migrate this local element away to another processor.
2600 void CkLocMgr::emigrate(CkLocRec_local *rec,int toPe)
2601 {
2602         CK_MAGICNUMBER_CHECK
2603         if (toPe==CkMyPe()) return; //You're already there!
2604         /*
2605                 FAULT_EVAC
2606                 if the toProcessor is already marked as invalid, dont emigrate
2607                 Shouldn't happen but might
2608         */
2609         if(!CmiNodeAlive(toPe)){
2610                 return;
2611         }
2612         CkArrayIndex idx=rec->getIndex();
2613
2614 #if CMK_OUT_OF_CORE
2615         int localIdx=rec->getLocalIndex();
2616         /* Load in any elements that are out-of-core */
2617         for (ManagerRec *m=firstManager;m!=NULL;m=m->next) {
2618                 CkMigratable *el=m->element(localIdx);
2619                 if (el) if (!el->isInCore) CooBringIn(el->prefetchObjID);
2620         }
2621 #endif
2622
2623         //Let all the elements know we're leaving
2624         callMethod(rec,&CkMigratable::ckAboutToMigrate);
2625         /*EVAC*/
2626
2627 //First pass: find size of migration message
2628         int bufSize;
2629         {
2630                 PUP::sizer p;
2631                 p(nManagers);
2632                 pupElementsFor(p,rec,CkElementCreation_migrate);
2633                 bufSize=p.size(); 
2634         }
2635
2636 //Allocate and pack into message
2637         int doubleSize=bufSize/sizeof(double)+1;
2638         CkArrayElementMigrateMessage *msg = 
2639                 new (doubleSize, 0) CkArrayElementMigrateMessage;
2640         msg->idx=idx;
2641         msg->length=bufSize;
2642 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_)) 
2643     msg->gid = ckGetGroupID();
2644 #endif
2645 #if CMK_LBDB_ON
2646         msg->ignoreArrival = rec->isAsyncMigrate()?1:0;
2647 #endif
2648         /*
2649                 FAULT_EVAC
2650         */
2651         msg->bounced = rec->isBounced();
2652         {
2653                 PUP::toMem p(msg->packData); 
2654                 p.becomeDeleting(); 
2655                 p(nManagers);
2656                 pupElementsFor(p,rec,CkElementCreation_migrate);
2657                 if (p.size()!=bufSize) {
2658                         CkError("ERROR! Array element claimed it was %d bytes to a "
2659                                 "sizing PUP::er, but copied %d bytes into the packing PUP::er!\n",
2660                                 bufSize,p.size());
2661                         CkAbort("Array element's pup routine has a direction mismatch.\n");
2662                 }
2663         }
2664
2665         DEBM((AA"Migrated index size %s to %d \n"AB,idx2str(idx),toPe));        
2666
2667 //#if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2668 #if defined(_FAULT_MLOG_)
2669     sendMlogLocation(toPe,UsrToEnv(msg));
2670 #else
2671         //Send off message and delete old copy
2672         thisProxy[toPe].immigrate(msg);
2673 #endif
2674
2675         duringMigration=CmiTrue;
2676         delete rec; //Removes elements, hashtable entries, local index
2677         
2678         
2679         duringMigration=CmiFalse;
2680         //The element now lives on another processor-- tell ourselves and its home
2681         inform(idx,toPe);
2682 //#if (!defined(_FAULT_MLOG_) && !defined(_FAULT_CAUSAL_))    
2683 #if !defined(_FAULT_MLOG_)    
2684         informHome(idx,toPe);
2685 #endif
2686
2687 #if CMK_GLOBAL_LOCATION_UPDATE
2688         DEBM((AA"Global location update! idx %s to %d \n"AB,idx2str(idx),toPe));
2689         thisProxy.updateLocation(idx, toPe);                        
2690 #endif
2691
2692         CK_MAGICNUMBER_CHECK
2693 }
2694
2695 /**
2696   Migrating array element is arriving on this processor.
2697 */
2698 void CkLocMgr::immigrate(CkArrayElementMigrateMessage *msg)
2699 {
2700         const CkArrayIndex &idx=msg->idx;
2701                 
2702         PUP::fromMem p(msg->packData); 
2703         
2704         int nMsgMan;
2705         p(nMsgMan);
2706         if (nMsgMan<nManagers)
2707                 CkAbort("Array element arrived from location with fewer managers!\n");
2708         if (nMsgMan>nManagers) {
2709                 //Some array managers haven't registered yet-- throw it back
2710                 DEBM((AA"Busy-waiting for array registration on migrating %s\n"AB,idx2str(idx)));
2711                 thisProxy[CkMyPe()].immigrate(msg);
2712                 return;
2713         }
2714
2715         //Create a record for this element
2716 //#if (!defined(_FAULT_MLOG_) && !defined(_FAULT_CAUSAL_))    
2717 #if !defined(_FAULT_MLOG_)     
2718         CkLocRec_local *rec=createLocal(idx,CmiTrue,msg->ignoreArrival,CmiFalse /* home told on departure */ );
2719 #else
2720     CkLocRec_local *rec=createLocal(idx,CmiTrue,CmiTrue,CmiFalse /* home told on departure */ );
2721 #endif
2722         
2723         //Create the new elements as we unpack the message
2724         pupElementsFor(p,rec,CkElementCreation_migrate);
2725         if (p.size()!=msg->length) {
2726                 CkError("ERROR! Array element claimed it was %d bytes to a"
2727                         "packing PUP::er, but %d bytes in the unpacking PUP::er!\n",
2728                         msg->length,p.size());
2729                 CkError("(I have %d managers; he claims %d managers)\n",
2730                         nManagers,nMsgMan);
2731                 
2732                 CkAbort("Array element's pup routine has a direction mismatch.\n");
2733         }
2734         /*
2735                 FAULT_EVAC
2736                         if this element came in as a result of being bounced off some other process,
2737                         then it needs to be resumed. It is assumed that it was bounced because load 
2738                         balancing caused it to move into a processor which later crashed
2739         */
2740         if(msg->bounced){
2741                 callMethod(rec,&CkMigratable::ResumeFromSync);
2742         }
2743         
2744         //Let all the elements know we've arrived
2745         callMethod(rec,&CkMigratable::ckJustMigrated);
2746         /*FAULT_EVAC
2747                 If this processor has started evacuating array elements on it 
2748                 dont let new immigrants in. If they arrive send them to what
2749                 would be their correct homePE.
2750                 Leave a record here mentioning the processor where it got sent
2751         */
2752         
2753         if(CkpvAccess(startedEvac)){
2754                 int newhomePE = getNextPE(idx);
2755                 DEBM((AA"Migrated into failed processor index size %s resent to %d \n"AB,idx2str(idx),newhomePE));      
2756                 CkLocMgr *mgr = rec->getLocMgr();
2757                 int targetPE=getNextPE(idx);
2758                 //set this flag so that load balancer is not informed when
2759                 //this element migrates
2760                 rec->AsyncMigrate(CmiTrue);
2761                 rec->Bounced(CmiTrue);
2762                 mgr->emigrate(rec,targetPE);
2763                 
2764         }
2765
2766         delete msg;
2767 }
2768
2769 void CkLocMgr::restore(const CkArrayIndex &idx, PUP::er &p)
2770 {
2771         //This is in broughtIntoMem during out-of-core emulation in BigSim,
2772         //informHome should not be called since such information is already
2773         //immediately updated real migration
2774 #if CMK_ERROR_CHECKING
2775         if(_BgOutOfCoreFlag!=2)
2776             CmiAbort("CkLocMgr::restore should only be used in out-of-core emulation for BigSim and be called when object is brought into memory!\n");
2777 #endif
2778         CkLocRec_local *rec=createLocal(idx,CmiFalse,CmiFalse,CmiFalse);
2779         
2780         //BIGSIM_OOC DEBUGGING
2781         //CkPrintf("Proc[%d]: Registering element %s with LDB\n", CkMyPe(), idx2str(idx));
2782
2783         //Create the new elements as we unpack the message
2784         pupElementsFor(p,rec,CkElementCreation_restore);
2785
2786         callMethod(rec,&CkMigratable::ckJustRestored);
2787 }
2788
2789
2790 /// Insert and unpack this array element from this checkpoint (e.g., from CkLocation::pup)
2791 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2792 void CkLocMgr::resume(const CkArrayIndex &idx, PUP::er &p, CmiBool create, int dummy)
2793 {
2794         CkLocRec_local *rec;
2795         CkLocRec *recGlobal;    
2796
2797         if(create){
2798                 rec = createLocal(idx,CmiFalse,CmiFalse,CmiTrue && !dummy /* home doesn't know yet */,dummy );
2799         }else{
2800                 recGlobal = elementNrec(idx);
2801                 if(recGlobal == NULL) 
2802                         CmiAbort("Local object not found");
2803                 if(recGlobal->type() != CkLocRec::local)
2804                         CmiAbort("Local object not local, :P");
2805                 rec = (CkLocRec_local *)recGlobal;
2806         }
2807         
2808     pupElementsFor(p,rec,CkElementCreation_resume,create,dummy);
2809
2810     if(!dummy){
2811         callMethod(rec,&CkMigratable::ckJustMigrated);
2812     }
2813 }
2814 #else
2815 void CkLocMgr::resume(const CkArrayIndex &idx, PUP::er &p, CmiBool notify)
2816 {
2817         CkLocRec_local *rec=createLocal(idx,CmiFalse,CmiFalse,notify /* home doesn't know yet */ );
2818
2819         //Create the new elements as we unpack the message
2820         pupElementsFor(p,rec,CkElementCreation_resume);
2821
2822         callMethod(rec,&CkMigratable::ckJustMigrated);
2823 }
2824 #endif
2825
2826 /********************* LocMgr: UTILITY ****************/
2827 void CkMagicNumber_impl::badMagicNumber(
2828         int expected,const char *file,int line,void *obj) const
2829 {
2830         CkError("FAILURE on pe %d, %s:%d> Expected %p's magic number "
2831                 "to be 0x%08x; but found 0x%08x!\n", CkMyPe(),file,line,obj,
2832                 expected, magic);
2833         CkAbort("Bad magic number detected!  This implies either\n"
2834                 "the heap or a message was corrupted!\n");
2835 }
2836 CkMagicNumber_impl::CkMagicNumber_impl(int m) :magic(m) { }
2837
2838 //Look up the object with this array index, or return NULL
2839 CkMigratable *CkLocMgr::lookup(const CkArrayIndex &idx,CkArrayID aid) {
2840         CkLocRec *rec=elementNrec(idx);
2841         if (rec==NULL) return NULL;
2842         else return rec->lookupElement(aid);
2843 }
2844 //"Last-known" location (returns a processor number)
2845 int CkLocMgr::lastKnown(const CkArrayIndex &idx) {
2846         CkLocMgr *vthis=(CkLocMgr *)this;//Cast away "const"
2847         CkLocRec *rec=vthis->elementNrec(idx);
2848         int pe=-1;
2849         if (rec!=NULL) pe=rec->lookupProcessor();
2850         if (pe==-1) return homePe(idx);
2851         else{
2852                 /*
2853                         FAULT_EVAC
2854                         if the lastKnownPE is invalid return homePE and delete this record
2855                 */
2856                 if(!CmiNodeAlive(pe)){
2857                         removeFromTable(idx);
2858                         return homePe(idx);
2859                 }
2860                 return pe;
2861         }       
2862 }
2863 /// Return true if this array element lives on another processor
2864 bool CkLocMgr::isRemote(const CkArrayIndex &idx,int *onPe) const
2865 {
2866         CkLocMgr *vthis=(CkLocMgr *)this;//Cast away "const"
2867         CkLocRec *rec=vthis->elementNrec(idx);
2868         if (rec==NULL || rec->type()!=CkLocRec::remote) 
2869                 return false; /* not definitely a remote element */
2870         else /* element is indeed remote */
2871         {
2872                 *onPe=rec->lookupProcessor();
2873                 return true;
2874         }
2875 }
2876
2877 static const char *rec2str[]={
2878     "base (INVALID)",//Base class (invalid type)
2879     "local",//Array element that lives on this Pe
2880     "remote",//Array element that lives on some other Pe
2881     "buffering",//Array element that was just created
2882     "dead"//Deleted element (for debugging)
2883 };
2884
2885 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2886 void CkLocMgr::setDuringMigration(CmiBool _duringMigration){
2887     duringMigration = _duringMigration;
2888 }
2889 #endif
2890
2891
2892 //Add given element array record at idx, replacing the existing record
2893 void CkLocMgr::insertRec(CkLocRec *rec,const CkArrayIndex &idx) {
2894         CkLocRec *old=elementNrec(idx);
2895         insertRecN(rec,idx);
2896         if (old!=NULL) {
2897                 DEBC((AA"  replaces old rec(%s) for %s\n"AB,rec2str[old->type()],idx2str(idx)));
2898                 //There was an old element at this location
2899                 if (old->type()==CkLocRec::local && rec->type()==CkLocRec::local) {
2900                     if (!CkInRestarting()) {    // ok if it is restarting
2901                         CkPrintf("ERROR! Duplicate array index: %s\n",idx2str(idx));
2902                         CkAbort("Duplicate array index used");
2903                     }
2904                 }
2905                 old->beenReplaced();
2906                 delete old;
2907         }
2908 }
2909
2910 //Add given record, when there is guarenteed to be no prior record
2911 void CkLocMgr::insertRecN(CkLocRec *rec,const CkArrayIndex &idx) {
2912         DEBC((AA"  adding new rec(%s) for %s\n"AB,rec2str[rec->type()],idx2str(idx)));
2913         CmiImmediateLock(hashImmLock);
2914         hash.put(*(CkArrayIndex *)&idx)=rec;
2915         CmiImmediateUnlock(hashImmLock);
2916 }
2917
2918 //Call this on an unrecognized array index
2919 static void abort_out_of_bounds(const CkArrayIndex &idx)
2920 {
2921   CkPrintf("ERROR! Unknown array index: %s\n",idx2str(idx));
2922   CkAbort("Array index out of bounds\n");
2923 }
2924
2925 //Look up array element in hash table.  Index out-of-bounds if not found.
2926 CkLocRec *CkLocMgr::elementRec(const CkArrayIndex &idx) {
2927 #if ! CMK_ERROR_CHECKING
2928 //Assume the element will be found
2929         return hash.getRef(*(CkArrayIndex *)&idx);
2930 #else
2931 //Include an out-of-bounds check if the element isn't found
2932         CkLocRec *rec=elementNrec(idx);
2933         if (rec==NULL) abort_out_of_bounds(idx);
2934         return rec;
2935 #endif
2936 }
2937
2938 //Look up array element in hash table.  Return NULL if not there.
2939 CkLocRec *CkLocMgr::elementNrec(const CkArrayIndex &idx) {
2940         return hash.get(*(CkArrayIndex *)&idx);
2941 }
2942
2943 struct LocalElementCounter :  public CkLocIterator
2944 {
2945     unsigned int count;
2946     LocalElementCounter() : count(0) {}
2947     void addLocation(CkLocation &loc)
2948         { ++count; }
2949 };
2950
2951 unsigned int CkLocMgr::numLocalElements()
2952 {
2953     LocalElementCounter c;
2954     iterate(c);
2955     return c.count;
2956 }
2957
2958
2959 /********************* LocMgr: LOAD BALANCE ****************/
2960
2961 #if !CMK_LBDB_ON
2962 //Empty versions of all load balancer calls
2963 void CkLocMgr::initLB(CkGroupID lbdbID_) {}
2964 void CkLocMgr::startInserting(void) {}
2965 void CkLocMgr::doneInserting(void) {}
2966 void CkLocMgr::dummyAtSync(void) {}
2967 #endif
2968
2969
2970 #if CMK_LBDB_ON
2971 void CkLocMgr::initLB(CkGroupID lbdbID_)
2972 { //Find and register with the load balancer
2973         the_lbdb = (LBDatabase *)CkLocalBranch(lbdbID_);
2974         if (the_lbdb == 0)
2975                 CkAbort("LBDatabase not yet created?\n");
2976         DEBL((AA"Connected to load balancer %p\n"AB,the_lbdb));
2977
2978         // Register myself as an object manager
2979         LDOMid myId;
2980         myId.id = thisgroup;
2981         LDCallbacks myCallbacks;
2982         myCallbacks.migrate = (LDMigrateFn)CkLocRec_local::staticMigrate;
2983         myCallbacks.setStats = NULL;
2984         myCallbacks.queryEstLoad = NULL;
2985         myLBHandle = the_lbdb->RegisterOM(myId,this,myCallbacks);
2986
2987         // Tell the lbdb that I'm registering objects
2988         the_lbdb->RegisteringObjects(myLBHandle);
2989
2990         /*Set up the dummy barrier-- the load balancer needs
2991           us to call Registering/DoneRegistering during each AtSync,
2992           and this is the only way to do so.
2993         */
2994         the_lbdb->AddLocalBarrierReceiver(
2995                 (LDBarrierFn)staticRecvAtSync,(void*)(this));
2996         dummyBarrierHandle = the_lbdb->AddLocalBarrierClient(
2997                 (LDResumeFn)staticDummyResumeFromSync,(void*)(this));
2998         dummyAtSync();
2999 }
3000 void CkLocMgr::dummyAtSync(void)
3001 {
3002         DEBL((AA"dummyAtSync called\n"AB));
3003         the_lbdb->AtLocalBarrier(dummyBarrierHandle);
3004 }
3005
3006 void CkLocMgr::staticDummyResumeFromSync(void* data)
3007 {      ((CkLocMgr*)data)->dummyResumeFromSync(); }
3008 void CkLocMgr::dummyResumeFromSync()
3009 {
3010         DEBL((AA"DummyResumeFromSync called\n"AB));
3011         the_lbdb->DoneRegisteringObjects(myLBHandle);
3012         dummyAtSync();
3013 }
3014 void CkLocMgr::staticRecvAtSync(void* data)
3015 {      ((CkLocMgr*)data)->recvAtSync(); }
3016 void CkLocMgr::recvAtSync()
3017 {
3018         DEBL((AA"recvAtSync called\n"AB));
3019         the_lbdb->RegisteringObjects(myLBHandle);
3020 }
3021
3022 void CkLocMgr::startInserting(void)
3023 {
3024         the_lbdb->RegisteringObjects(myLBHandle);
3025 }
3026 void CkLocMgr::doneInserting(void)
3027 {
3028         the_lbdb->DoneRegisteringObjects(myLBHandle);
3029 }
3030 #endif
3031
3032 #include "CkLocation.def.h"
3033
3034