Merge branch 'newManual' 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 #if CMK_GLOBAL_LOCATION_UPDATE
2127                 DEBC((AA"Global location broadcast for new element idx %s "
2128                       "assigned to %d \n"AB, idx2str(idx), CkMyPe()));
2129                 thisProxy.updateLocation(idx, CkMyPe());                        
2130 #endif
2131                 
2132         } else 
2133         { //rec is *already* local-- must not be the first insertion    
2134                 rec=((CkLocRec_local *)oldRec);
2135                 rec->addedElement();
2136         }
2137         if (!addElementToRec(rec,managers.find(id),elt,ctorIdx,ctorMsg)) return CmiFalse;
2138         elt->ckFinishConstruction();
2139         return CmiTrue;
2140 }
2141
2142 //As above, but shared with the migration code
2143 CmiBool CkLocMgr::addElementToRec(CkLocRec_local *rec,ManagerRec *m,
2144                 CkMigratable *elt,int ctorIdx,void *ctorMsg)
2145 {//Insert the new element into its manager's local list
2146         int localIdx=rec->getLocalIndex();
2147         if (m->elts.get(localIdx)!=NULL) CkAbort("Cannot insert array element twice!");
2148         m->elts.put(elt,localIdx); //Local element table
2149
2150 //Call the element's constructor
2151         DEBC((AA"Constructing element %s of array\n"AB,idx2str(rec->getIndex())));
2152         CkMigratable_initInfo &i=CkpvAccess(mig_initInfo);
2153         i.locRec=rec;
2154         i.chareType=_entryTable[ctorIdx]->chareIdx;
2155         if (!rec->invokeEntry(elt,ctorMsg,ctorIdx,CmiTrue)) return CmiFalse;
2156
2157 #if CMK_OUT_OF_CORE
2158         /* Register new element with out-of-core */
2159         PUP::sizer p_getSize; elt->pup(p_getSize);
2160         elt->prefetchObjID=CooRegisterObject(&CkArrayElementPrefetcher,p_getSize.size(),elt);
2161 #endif
2162         
2163         return CmiTrue;
2164 }
2165 void CkLocMgr::updateLocation(const CkArrayIndex &idx,int nowOnPe) {
2166         inform(idx,nowOnPe);
2167 }
2168
2169 /*************************** LocMgr: DELETION *****************************/
2170 /// This index will no longer be used-- delete the associated elements
2171 void CkLocMgr::reclaim(const CkArrayIndex &idx,int localIdx) {
2172         CK_MAGICNUMBER_CHECK
2173         DEBC((AA"Destroying element %s (local %d)\n"AB,idx2str(idx),localIdx));
2174         //Delete, and mark as empty, each array element
2175         for (ManagerRec *m=firstManager;m!=NULL;m=m->next) {
2176                 delete m->elts.get(localIdx);
2177                 m->elts.empty(localIdx);
2178         }
2179         
2180         removeFromTable(idx);
2181         
2182         //Link local index into free list
2183         freeList[localIdx]=firstFree;
2184         firstFree=localIdx;
2185         
2186                 
2187         if (!duringMigration) 
2188         { //This is a local element dying a natural death
2189             #if CMK_BIGSIM_CHARM
2190                 //After migration, reclaimRemote will be called through 
2191                 //the CkRemoveArrayElement in the pupping routines for those 
2192                 //objects that are not on the home processors. However,
2193                 //those remote records should not be deleted since the corresponding
2194                 //objects are not actually deleted but on disk. If deleted, msgs
2195                 //that seeking where is the object will be accumulated (a circular
2196                 //msg chain) and causes the program no progress
2197                 if(_BgOutOfCoreFlag==1) return; 
2198             #endif
2199                 int home=homePe(idx);
2200                 if (home!=CkMyPe())
2201 #if CMK_MEM_CHECKPOINT
2202                 if (!CkInRestarting()) // all array elements are removed anyway
2203 #endif
2204                         thisProxy[home].reclaimRemote(idx,CkMyPe());
2205         /*      //Install a zombie to keep the living from re-using this index.
2206                 insertRecN(new CkLocRec_dead(this),idx); */
2207         }
2208 }
2209
2210 void CkLocMgr::reclaimRemote(const CkArrayIndex &idx,int deletedOnPe) {
2211         DEBC((AA"Our element %s died on PE %d\n"AB,idx2str(idx),deletedOnPe));
2212         CkLocRec *rec=elementNrec(idx);
2213         if (rec==NULL) return; //We never knew him
2214         if (rec->type()==CkLocRec::local) return; //He's already been reborn
2215         removeFromTable(idx);
2216         delete rec;
2217 }
2218 void CkLocMgr::removeFromTable(const CkArrayIndex &idx) {
2219 #if CMK_ERROR_CHECKING
2220         //Make sure it's actually in the table before we delete it
2221         if (NULL==elementNrec(idx))
2222                 CkAbort("CkLocMgr::removeFromTable called on invalid index!");
2223 #endif
2224         CmiImmediateLock(hashImmLock);
2225         hash.remove(*(CkArrayIndex *)&idx);
2226         CmiImmediateUnlock(hashImmLock);
2227 #if CMK_ERROR_CHECKING
2228         //Make sure it's really gone
2229         if (NULL!=elementNrec(idx))
2230                 CkAbort("CkLocMgr::removeFromTable called, but element still there!");
2231 #endif
2232 }
2233
2234 /************************** LocMgr: MESSAGING *************************/
2235 /// Deliver message to this element, going via the scheduler if local
2236 /// @return 0 if object local, 1 if not
2237 int CkLocMgr::deliver(CkMessage *m,CkDeliver_t type,int opts) {
2238         DEBS((AA"deliver \n"AB));
2239         CK_MAGICNUMBER_CHECK
2240         CkArrayMessage *msg=(CkArrayMessage *)m;
2241
2242
2243         const CkArrayIndex &idx=msg->array_index();
2244         DEBS((AA"deliver %s\n"AB,idx2str(idx)));
2245         if (type==CkDeliver_queue)
2246                 _TRACE_CREATION_DETAILED(UsrToEnv(m),msg->array_ep());
2247         CkLocRec *rec=elementNrec(idx);
2248         if(rec != NULL){
2249                 DEBS((AA"deliver %s of type %d \n"AB,idx2str(idx),rec->type()));
2250         }else{
2251                 DEBS((AA"deliver %s rec is null\n"AB,idx2str(idx)));
2252         }
2253 //#if (!defined(_FAULT_MLOG_) && !defined(_FAULT_CAUSAL_))
2254 //#if !defined(_FAULT_MLOG_)
2255 #if CMK_LBDB_ON
2256         if (type==CkDeliver_queue) {
2257                 if (!(opts & CK_MSG_LB_NOTRACE) && the_lbdb->CollectingCommStats()) {
2258                 if(rec!=NULL) the_lbdb->Send(myLBHandle,idx2LDObjid(idx),UsrToEnv(msg)->getTotalsize(), rec->lookupProcessor(), 1);
2259                 else /*rec==NULL*/ the_lbdb->Send(myLBHandle,idx2LDObjid(idx),UsrToEnv(msg)->getTotalsize(),homePe(msg->array_index()), 1);
2260                 }
2261         }
2262 #endif
2263 //#endif
2264 #if CMK_GRID_QUEUE_AVAILABLE
2265         int gridSrcPE;
2266         int gridSrcCluster;
2267         int gridDestPE;
2268         int gridDestCluster;
2269         CkMigratable *obj;
2270         ArrayElement *obj2;
2271         CkGroupID gid;
2272         int *data;
2273
2274         obj = (CkMigratable *) CpvAccess(CkGridObject);   // CkGridObject is a pointer to the sending object (retained earlier)
2275         if (obj != NULL) {
2276           obj2 = dynamic_cast<ArrayElement *> (obj);
2277           if (obj2 > 0) {
2278             // Get the sending object's array gid and indexes.
2279             // These are guaranteed to exist due to the succeeding dynamic cast above.
2280             gid = obj2->ckGetArrayID ();
2281             data = obj2->thisIndexMax.data ();
2282
2283             // Get the source PE and destination PE.
2284             gridSrcPE = CkMyPe ();
2285             if (rec != NULL) {
2286               gridDestPE = rec->lookupProcessor ();
2287             } else {
2288               gridDestPE = homePe (msg->array_index ());
2289             }
2290
2291             // Get the source cluster and destination cluster.
2292             gridSrcCluster = CmiGetCluster (gridSrcPE);
2293             gridDestCluster = CmiGetCluster (gridDestPE);
2294
2295             // If the Grid queue interval is greater than zero, it means that the more complicated
2296             // technique for registering border objects that exceed a specified threshold of
2297             // cross-cluster messages within a specified interval (and deregistering border objects
2298             // that do not meet this threshold) is used.  Otherwise a much simpler technique is used
2299             // where a border object is registered immediately upon sending a single cross-cluster
2300             // message (and deregistered when load balancing takes place).
2301             if (obj2->grid_queue_interval > 0) {
2302               // Increment the sending object's count of all messages.
2303               obj2->msg_count += 1;
2304
2305               // If the source cluster and destination cluster differ, this is a Grid message.
2306               // (Increment the count of all Grid messages.)
2307               if (gridSrcCluster != gridDestCluster) {
2308                 obj2->msg_count_grid += 1;
2309               }
2310
2311               // If the number of messages exceeds the interval, check to see if the object has
2312               // sent enough cross-cluster messages to qualify as a border object.
2313               if (obj2->msg_count >= obj2->grid_queue_interval) {
2314                 if (obj2->msg_count_grid >= obj2->grid_queue_threshold) {
2315                   // The object is a border object; if it is not already registered, register it.
2316                   if (!obj2->border_flag) {
2317                     CmiGridQueueRegister (gid.idx, obj2->thisIndexMax.nInts, data[0], data[1], data[2]);
2318                   }
2319                   obj2->border_flag = 1;
2320                 } else {
2321                   // The object is not a border object; if it is registered, deregister it.
2322                   if (obj2->border_flag) {
2323                     CmiGridQueueDeregister (gid.idx, obj2->thisIndexMax.nInts, data[0], data[1], data[2]);
2324                   }
2325                   obj2->border_flag = 0;
2326                 }
2327                 // Reset the counts.
2328                 obj2->msg_count = 0;
2329                 obj2->msg_count_grid = 0;
2330               }
2331             } else {
2332               if (gridSrcCluster != gridDestCluster) {
2333                 CmiGridQueueRegister (gid.idx, obj2->thisIndexMax.nInts, data[0], data[1], data[2]);
2334               }
2335             }
2336           }
2337
2338           // Reset the CkGridObject pointer.
2339           CpvAccess(CkGridObject) = NULL;
2340         }
2341 #endif
2342         /**FAULT_EVAC*/
2343         if (rec!=NULL){
2344                 CmiBool result = rec->deliver(msg,type,opts);
2345                 // if result is CmiFalse, than rec is not valid anymore, as the object
2346                 // the message was just delivered to has died or migrated out.
2347                 // Therefore rec->type() cannot be invoked!
2348                 if (result==CmiTrue && rec->type()==CkLocRec::local) return 0;
2349                 else return 1;
2350                 /*if(!result){
2351                         //DEBS((AA"deliver %s failed type %d \n"AB,idx2str(idx),rec->type()));
2352                         DEBS((AA"deliver %s failed \n"AB,idx2str(idx)));
2353                         if(rec->type() == CkLocRec::remote){
2354                                 if (opts & CK_MSG_KEEP)
2355                                         msg = (CkArrayMessage *)CkCopyMsg((void **)&msg);
2356                                 deliverUnknown(msg,type);
2357                         }
2358                 }*/
2359         }else /* rec==NULL*/ {
2360                 if (opts & CK_MSG_KEEP)
2361                         msg = (CkArrayMessage *)CkCopyMsg((void **)&msg);
2362                 deliverUnknown(msg,type,opts);
2363                 return 1;
2364         }
2365
2366 }
2367
2368 /// This index is not hashed-- somehow figure out what to do.
2369 CmiBool CkLocMgr::deliverUnknown(CkArrayMessage *msg,CkDeliver_t type,int opts)
2370 {
2371         CK_MAGICNUMBER_CHECK
2372         const CkArrayIndex &idx=msg->array_index();
2373         int onPe=homePe(idx);
2374         if (onPe!=CkMyPe()) 
2375         {// Forward the message to its home processor
2376                 DEBM((AA"Forwarding message for unknown %s to home %d \n"AB,idx2str(idx),onPe));
2377                 msg->array_hops()++;
2378                 CkArrayManagerDeliver(onPe,msg,opts);
2379                 return CmiTrue;
2380         }
2381         else
2382         { // We *are* the home processor:
2383         //Check if the element's array manager has been registered yet:
2384           CkArrMgr *mgr=managers.find(UsrToEnv((void *)msg)->getsetArrayMgr())->mgr;
2385           if (!mgr) { //No manager yet-- postpone the message (stupidly)
2386             if (CkInRestarting()) {
2387               // during restarting, this message should be ignored
2388               delete msg;
2389             }
2390             else {
2391               CkArrayManagerDeliver(CkMyPe(),msg); 
2392             }
2393           }
2394           else { // Has a manager-- must buffer the message
2395             DEBC((AA"Adding buffer for unknown element %s\n"AB,idx2str(idx)));
2396             CkLocRec *rec=new CkLocRec_buffering(this);
2397             insertRecN(rec,idx);
2398             rec->deliver(msg,type);
2399           
2400             if (msg->array_ifNotThere()!=CkArray_IfNotThere_buffer) 
2401             { //Demand-create the element:
2402               return demandCreateElement(msg,-1,type);
2403             }
2404           }
2405           return CmiTrue;
2406         }
2407 }
2408
2409 CmiBool CkLocMgr::demandCreateElement(CkArrayMessage *msg,int onPe,CkDeliver_t type)
2410 {
2411         CK_MAGICNUMBER_CHECK
2412         const CkArrayIndex &idx=msg->array_index();
2413         int chareType=_entryTable[msg->array_ep()]->chareIdx;
2414         int ctor=_chareTable[chareType]->getDefaultCtor();
2415         if (ctor==-1) CkAbort("Can't create array element to handle message--\n"
2416                               "The element has no default constructor in the .ci file!\n");
2417         if (onPe==-1) 
2418         { //Decide where element needs to live
2419                 if (msg->array_ifNotThere()==CkArray_IfNotThere_createhere) 
2420                         onPe=UsrToEnv(msg)->getsetArraySrcPe();
2421                 else //Createhome
2422                         onPe=homePe(idx);
2423         }
2424         
2425         //Find the manager and build the element
2426         DEBC((AA"Demand-creating element %s on pe %d\n"AB,idx2str(idx),onPe));
2427         CkArrMgr *mgr=managers.find(UsrToEnv((void *)msg)->getsetArrayMgr())->mgr;
2428         if (!mgr) CkAbort("Tried to demand-create for nonexistent arrMgr");
2429         return mgr->demandCreateElement(idx,onPe,ctor,type);
2430 }
2431
2432 //This message took several hops to reach us-- fix it
2433 void CkLocMgr::multiHop(CkArrayMessage *msg)
2434 {
2435         CK_MAGICNUMBER_CHECK
2436         int srcPe=msg->array_getSrcPe();
2437         if (srcPe==CkMyPe())
2438                 DEB((AA"Odd routing: local element %s is %d hops away!\n"AB,idx2str(msg),msg->array_hops()));
2439         else
2440         {//Send a routing message letting original sender know new element location
2441                 DEBS((AA"Sending update back to %d for element\n"AB,srcPe,idx2str(msg)));
2442                 thisProxy[srcPe].updateLocation(msg->array_index(),CkMyPe());
2443         }
2444 }
2445
2446 /************************** LocMgr: ITERATOR *************************/
2447 CkLocation::CkLocation(CkLocMgr *mgr_, CkLocRec_local *rec_)
2448         :mgr(mgr_), rec(rec_) {}
2449         
2450 const CkArrayIndex &CkLocation::getIndex(void) const {
2451         return rec->getIndex();
2452 }
2453
2454 void CkLocation::destroyAll() {
2455         mgr->callMethod(rec, &CkMigratable::ckDestroy);
2456 }
2457
2458 void CkLocation::pup(PUP::er &p) {
2459         mgr->pupElementsFor(p,rec,CkElementCreation_migrate);
2460 }
2461
2462 CkLocIterator::~CkLocIterator() {}
2463
2464 /// Iterate over our local elements:
2465 void CkLocMgr::iterate(CkLocIterator &dest) {
2466   //Poke through the hash table for local ArrayRecs.
2467   void *objp;
2468   CkHashtableIterator *it=hash.iterator();
2469   CmiImmediateLock(hashImmLock);
2470
2471   while (NULL!=(objp=it->next())) {
2472     CkLocRec *rec=*(CkLocRec **)objp;
2473     if (rec->type()==CkLocRec::local) {
2474       CkLocation loc(this,(CkLocRec_local *)rec);
2475       dest.addLocation(loc);
2476     }
2477   }
2478   CmiImmediateUnlock(hashImmLock);
2479   delete it;
2480 }
2481
2482
2483
2484
2485 /************************** LocMgr: MIGRATION *************************/
2486 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2487 void CkLocMgr::pupElementsFor(PUP::er &p,CkLocRec_local *rec,
2488         CkElementCreation_t type, CmiBool create, int dummy)
2489 {
2490     p.comment("-------- Array Location --------");
2491     register ManagerRec *m;
2492     int localIdx=rec->getLocalIndex();
2493     CkVec<CkMigratable *> dummyElts;
2494
2495     for (m=firstManager;m!=NULL;m=m->next) {
2496         int elCType;
2497         if (!p.isUnpacking())
2498         { //Need to find the element's existing type
2499             CkMigratable *elt=m->element(localIdx);
2500             if (elt) elCType=elt->ckGetChareType();
2501             else elCType=-1; //Element hasn't been created
2502         }
2503         p(elCType);
2504         if (p.isUnpacking() && elCType!=-1) {
2505             CkMigratable *elt=m->mgr->allocateMigrated(elCType,rec->getIndex(),type);
2506             int migCtorIdx=_chareTable[elCType]->getMigCtor();
2507                 if(!dummy){
2508                         if(create)
2509                                 if (!addElementToRec(rec,m,elt,migCtorIdx,NULL)) return;
2510                                 }else{
2511                     CkMigratable_initInfo &i=CkpvAccess(mig_initInfo);
2512                     i.locRec=rec;
2513                     i.chareType=_entryTable[migCtorIdx]->chareIdx;
2514                     dummyElts.push_back(elt);
2515                     if (!rec->invokeEntry(elt,NULL,migCtorIdx,CmiTrue)) return ;
2516                 }
2517         }
2518     }
2519     if(!dummy){
2520         for (m=firstManager;m!=NULL;m=m->next) {
2521             CkMigratable *elt=m->element(localIdx);
2522             if (elt!=NULL)
2523                 {
2524                        elt->pup(p);
2525                 }
2526         }
2527     }else{
2528             for(int i=0;i<dummyElts.size();i++){
2529                 CkMigratable *elt = dummyElts[i];
2530                 if (elt!=NULL){
2531             elt->pup(p);
2532                         }
2533                 delete elt;
2534             }
2535                         for (ManagerRec *m=firstManager;m!=NULL;m=m->next) {
2536                 m->elts.empty(localIdx);
2537             }
2538         freeList[localIdx]=firstFree;
2539         firstFree=localIdx;
2540     }
2541 }
2542 #else
2543 void CkLocMgr::pupElementsFor(PUP::er &p,CkLocRec_local *rec,
2544                 CkElementCreation_t type)
2545 {
2546         p.comment("-------- Array Location --------");
2547         register ManagerRec *m;
2548         int localIdx=rec->getLocalIndex();
2549
2550         //First pup the element types
2551         // (A separate loop so ckLocal works even in element pup routines)
2552         for (m=firstManager;m!=NULL;m=m->next) {
2553                 int elCType;
2554                 if (!p.isUnpacking())
2555                 { //Need to find the element's existing type
2556                         CkMigratable *elt=m->element(localIdx);
2557                         if (elt) elCType=elt->ckGetChareType();
2558                         else elCType=-1; //Element hasn't been created
2559                 }
2560                 p(elCType);
2561                 if (p.isUnpacking() && elCType!=-1) {
2562                         //Create the element
2563                         CkMigratable *elt=m->mgr->allocateMigrated(elCType,rec->getIndex(),type);
2564                         int migCtorIdx=_chareTable[elCType]->getMigCtor();
2565                         //Insert into our tables and call migration constructor
2566                         if (!addElementToRec(rec,m,elt,migCtorIdx,NULL)) return;
2567                 }
2568         }
2569         //Next pup the element data
2570         for (m=firstManager;m!=NULL;m=m->next) {
2571                 CkMigratable *elt=m->element(localIdx);
2572                 if (elt!=NULL)
2573                 {
2574                         elt->pup(p);
2575 #if CMK_ERROR_CHECKING
2576                         if (p.isUnpacking()) elt->sanitycheck();
2577 #endif
2578                 }
2579         }
2580 }
2581 #endif
2582
2583 /// Call this member function on each element of this location:
2584 void CkLocMgr::callMethod(CkLocRec_local *rec,CkMigratable_voidfn_t fn)
2585 {
2586         int localIdx=rec->getLocalIndex();
2587         for (ManagerRec *m=firstManager;m!=NULL;m=m->next) {
2588                 CkMigratable *el=m->element(localIdx);
2589                 if (el) (el->* fn)();
2590         }
2591 }
2592
2593 /// return a list of migratables in this local record
2594 void CkLocMgr::migratableList(CkLocRec_local *rec, CkVec<CkMigratable *> &list)
2595 {
2596         register ManagerRec *m;
2597         int localIdx=rec->getLocalIndex();
2598
2599         for (m=firstManager;m!=NULL;m=m->next) {
2600                 CkMigratable *elt=m->element(localIdx);
2601                 if (elt) list.push_back(elt);
2602         }
2603 }
2604
2605 /// Migrate this local element away to another processor.
2606 void CkLocMgr::emigrate(CkLocRec_local *rec,int toPe)
2607 {
2608         CK_MAGICNUMBER_CHECK
2609         if (toPe==CkMyPe()) return; //You're already there!
2610         /*
2611                 FAULT_EVAC
2612                 if the toProcessor is already marked as invalid, dont emigrate
2613                 Shouldn't happen but might
2614         */
2615         if(!CmiNodeAlive(toPe)){
2616                 return;
2617         }
2618         CkArrayIndex idx=rec->getIndex();
2619
2620 #if CMK_OUT_OF_CORE
2621         int localIdx=rec->getLocalIndex();
2622         /* Load in any elements that are out-of-core */
2623         for (ManagerRec *m=firstManager;m!=NULL;m=m->next) {
2624                 CkMigratable *el=m->element(localIdx);
2625                 if (el) if (!el->isInCore) CooBringIn(el->prefetchObjID);
2626         }
2627 #endif
2628
2629         //Let all the elements know we're leaving
2630         callMethod(rec,&CkMigratable::ckAboutToMigrate);
2631         /*EVAC*/
2632
2633 //First pass: find size of migration message
2634         int bufSize;
2635         {
2636                 PUP::sizer p;
2637                 p(nManagers);
2638                 pupElementsFor(p,rec,CkElementCreation_migrate);
2639                 bufSize=p.size(); 
2640         }
2641
2642 //Allocate and pack into message
2643         int doubleSize=bufSize/sizeof(double)+1;
2644         CkArrayElementMigrateMessage *msg = 
2645                 new (doubleSize, 0) CkArrayElementMigrateMessage;
2646         msg->idx=idx;
2647         msg->length=bufSize;
2648 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_)) 
2649     msg->gid = ckGetGroupID();
2650 #endif
2651 #if CMK_LBDB_ON
2652         msg->ignoreArrival = rec->isAsyncMigrate()?1:0;
2653 #endif
2654         /*
2655                 FAULT_EVAC
2656         */
2657         msg->bounced = rec->isBounced();
2658         {
2659                 PUP::toMem p(msg->packData); 
2660                 p.becomeDeleting(); 
2661                 p(nManagers);
2662                 pupElementsFor(p,rec,CkElementCreation_migrate);
2663                 if (p.size()!=bufSize) {
2664                         CkError("ERROR! Array element claimed it was %d bytes to a "
2665                                 "sizing PUP::er, but copied %d bytes into the packing PUP::er!\n",
2666                                 bufSize,p.size());
2667                         CkAbort("Array element's pup routine has a direction mismatch.\n");
2668                 }
2669         }
2670
2671         DEBM((AA"Migrated index size %s to %d \n"AB,idx2str(idx),toPe));        
2672
2673 //#if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2674 //#if defined(_FAULT_MLOG_)
2675 //    sendMlogLocation(toPe,UsrToEnv(msg));
2676 //#else
2677         //Send off message and delete old copy
2678         thisProxy[toPe].immigrate(msg);
2679 //#endif
2680
2681         duringMigration=CmiTrue;
2682         delete rec; //Removes elements, hashtable entries, local index
2683         
2684         
2685         duringMigration=CmiFalse;
2686         //The element now lives on another processor-- tell ourselves and its home
2687         inform(idx,toPe);
2688 //#if (!defined(_FAULT_MLOG_) && !defined(_FAULT_CAUSAL_))    
2689 //#if !defined(_FAULT_MLOG_)    
2690         informHome(idx,toPe);
2691 //#endif
2692
2693 #if CMK_GLOBAL_LOCATION_UPDATE
2694         DEBM((AA"Global location update. idx %s " 
2695               "assigned to %d \n"AB,idx2str(idx),toPe));
2696         thisProxy.updateLocation(idx, toPe);                        
2697 #endif
2698
2699         CK_MAGICNUMBER_CHECK
2700 }
2701
2702 /**
2703   Migrating array element is arriving on this processor.
2704 */
2705 void CkLocMgr::immigrate(CkArrayElementMigrateMessage *msg)
2706 {
2707         const CkArrayIndex &idx=msg->idx;
2708                 
2709         PUP::fromMem p(msg->packData); 
2710         
2711         int nMsgMan;
2712         p(nMsgMan);
2713         if (nMsgMan<nManagers)
2714                 CkAbort("Array element arrived from location with fewer managers!\n");
2715         if (nMsgMan>nManagers) {
2716                 //Some array managers haven't registered yet-- throw it back
2717                 DEBM((AA"Busy-waiting for array registration on migrating %s\n"AB,idx2str(idx)));
2718                 thisProxy[CkMyPe()].immigrate(msg);
2719                 return;
2720         }
2721
2722         //Create a record for this element
2723 //#if (!defined(_FAULT_MLOG_) && !defined(_FAULT_CAUSAL_))    
2724 //#if !defined(_FAULT_MLOG_)     
2725         CkLocRec_local *rec=createLocal(idx,CmiTrue,msg->ignoreArrival,CmiFalse /* home told on departure */ );
2726 //#else
2727 //    CkLocRec_local *rec=createLocal(idx,CmiTrue,CmiTrue,CmiFalse /* home told on departure */ );
2728 //#endif
2729         
2730         //Create the new elements as we unpack the message
2731         pupElementsFor(p,rec,CkElementCreation_migrate);
2732         if (p.size()!=msg->length) {
2733                 CkError("ERROR! Array element claimed it was %d bytes to a"
2734                         "packing PUP::er, but %d bytes in the unpacking PUP::er!\n",
2735                         msg->length,p.size());
2736                 CkError("(I have %d managers; he claims %d managers)\n",
2737                         nManagers,nMsgMan);
2738                 
2739                 CkAbort("Array element's pup routine has a direction mismatch.\n");
2740         }
2741         /*
2742                 FAULT_EVAC
2743                         if this element came in as a result of being bounced off some other process,
2744                         then it needs to be resumed. It is assumed that it was bounced because load 
2745                         balancing caused it to move into a processor which later crashed
2746         */
2747         if(msg->bounced){
2748                 callMethod(rec,&CkMigratable::ResumeFromSync);
2749         }
2750         
2751         //Let all the elements know we've arrived
2752         callMethod(rec,&CkMigratable::ckJustMigrated);
2753         /*FAULT_EVAC
2754                 If this processor has started evacuating array elements on it 
2755                 dont let new immigrants in. If they arrive send them to what
2756                 would be their correct homePE.
2757                 Leave a record here mentioning the processor where it got sent
2758         */
2759         
2760         if(CkpvAccess(startedEvac)){
2761                 int newhomePE = getNextPE(idx);
2762                 DEBM((AA"Migrated into failed processor index size %s resent to %d \n"AB,idx2str(idx),newhomePE));      
2763                 CkLocMgr *mgr = rec->getLocMgr();
2764                 int targetPE=getNextPE(idx);
2765                 //set this flag so that load balancer is not informed when
2766                 //this element migrates
2767                 rec->AsyncMigrate(CmiTrue);
2768                 rec->Bounced(CmiTrue);
2769                 mgr->emigrate(rec,targetPE);
2770                 
2771         }
2772
2773         delete msg;
2774 }
2775
2776 void CkLocMgr::restore(const CkArrayIndex &idx, PUP::er &p)
2777 {
2778         //This is in broughtIntoMem during out-of-core emulation in BigSim,
2779         //informHome should not be called since such information is already
2780         //immediately updated real migration
2781 #if CMK_ERROR_CHECKING
2782         if(_BgOutOfCoreFlag!=2)
2783             CmiAbort("CkLocMgr::restore should only be used in out-of-core emulation for BigSim and be called when object is brought into memory!\n");
2784 #endif
2785         CkLocRec_local *rec=createLocal(idx,CmiFalse,CmiFalse,CmiFalse);
2786         
2787         //BIGSIM_OOC DEBUGGING
2788         //CkPrintf("Proc[%d]: Registering element %s with LDB\n", CkMyPe(), idx2str(idx));
2789
2790         //Create the new elements as we unpack the message
2791         pupElementsFor(p,rec,CkElementCreation_restore);
2792
2793         callMethod(rec,&CkMigratable::ckJustRestored);
2794 }
2795
2796
2797 /// Insert and unpack this array element from this checkpoint (e.g., from CkLocation::pup)
2798 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2799 void CkLocMgr::resume(const CkArrayIndex &idx, PUP::er &p, CmiBool create, int dummy)
2800 {
2801         CkLocRec_local *rec;
2802         CkLocRec *recGlobal;    
2803
2804         if(create){
2805                 rec = createLocal(idx,CmiFalse,CmiFalse,CmiTrue && !dummy /* home doesn't know yet */,dummy );
2806         }else{
2807                 recGlobal = elementNrec(idx);
2808                 if(recGlobal == NULL) 
2809                         CmiAbort("Local object not found");
2810                 if(recGlobal->type() != CkLocRec::local)
2811                         CmiAbort("Local object not local, :P");
2812                 rec = (CkLocRec_local *)recGlobal;
2813         }
2814         
2815     pupElementsFor(p,rec,CkElementCreation_resume,create,dummy);
2816
2817     if(!dummy){
2818         callMethod(rec,&CkMigratable::ckJustMigrated);
2819     }
2820 }
2821 #else
2822 void CkLocMgr::resume(const CkArrayIndex &idx, PUP::er &p, CmiBool notify)
2823 {
2824         CkLocRec_local *rec=createLocal(idx,CmiFalse,CmiFalse,notify /* home doesn't know yet */ );
2825
2826         //Create the new elements as we unpack the message
2827         pupElementsFor(p,rec,CkElementCreation_resume);
2828
2829         callMethod(rec,&CkMigratable::ckJustMigrated);
2830 }
2831 #endif
2832
2833 /********************* LocMgr: UTILITY ****************/
2834 void CkMagicNumber_impl::badMagicNumber(
2835         int expected,const char *file,int line,void *obj) const
2836 {
2837         CkError("FAILURE on pe %d, %s:%d> Expected %p's magic number "
2838                 "to be 0x%08x; but found 0x%08x!\n", CkMyPe(),file,line,obj,
2839                 expected, magic);
2840         CkAbort("Bad magic number detected!  This implies either\n"
2841                 "the heap or a message was corrupted!\n");
2842 }
2843 CkMagicNumber_impl::CkMagicNumber_impl(int m) :magic(m) { }
2844
2845 //Look up the object with this array index, or return NULL
2846 CkMigratable *CkLocMgr::lookup(const CkArrayIndex &idx,CkArrayID aid) {
2847         CkLocRec *rec=elementNrec(idx);
2848         if (rec==NULL) return NULL;
2849         else return rec->lookupElement(aid);
2850 }
2851 //"Last-known" location (returns a processor number)
2852 int CkLocMgr::lastKnown(const CkArrayIndex &idx) {
2853         CkLocMgr *vthis=(CkLocMgr *)this;//Cast away "const"
2854         CkLocRec *rec=vthis->elementNrec(idx);
2855         int pe=-1;
2856         if (rec!=NULL) pe=rec->lookupProcessor();
2857         if (pe==-1) return homePe(idx);
2858         else{
2859                 /*
2860                         FAULT_EVAC
2861                         if the lastKnownPE is invalid return homePE and delete this record
2862                 */
2863                 if(!CmiNodeAlive(pe)){
2864                         removeFromTable(idx);
2865                         return homePe(idx);
2866                 }
2867                 return pe;
2868         }       
2869 }
2870 /// Return true if this array element lives on another processor
2871 bool CkLocMgr::isRemote(const CkArrayIndex &idx,int *onPe) const
2872 {
2873         CkLocMgr *vthis=(CkLocMgr *)this;//Cast away "const"
2874         CkLocRec *rec=vthis->elementNrec(idx);
2875         if (rec==NULL || rec->type()!=CkLocRec::remote) 
2876                 return false; /* not definitely a remote element */
2877         else /* element is indeed remote */
2878         {
2879                 *onPe=rec->lookupProcessor();
2880                 return true;
2881         }
2882 }
2883
2884 static const char *rec2str[]={
2885     "base (INVALID)",//Base class (invalid type)
2886     "local",//Array element that lives on this Pe
2887     "remote",//Array element that lives on some other Pe
2888     "buffering",//Array element that was just created
2889     "dead"//Deleted element (for debugging)
2890 };
2891
2892 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2893 void CkLocMgr::setDuringMigration(CmiBool _duringMigration){
2894     duringMigration = _duringMigration;
2895 }
2896 #endif
2897
2898
2899 //Add given element array record at idx, replacing the existing record
2900 void CkLocMgr::insertRec(CkLocRec *rec,const CkArrayIndex &idx) {
2901         CkLocRec *old=elementNrec(idx);
2902         insertRecN(rec,idx);
2903         if (old!=NULL) {
2904                 DEBC((AA"  replaces old rec(%s) for %s\n"AB,rec2str[old->type()],idx2str(idx)));
2905                 //There was an old element at this location
2906                 if (old->type()==CkLocRec::local && rec->type()==CkLocRec::local) {
2907                     if (!CkInRestarting()) {    // ok if it is restarting
2908                         CkPrintf("ERROR! Duplicate array index: %s\n",idx2str(idx));
2909                         CkAbort("Duplicate array index used");
2910                     }
2911                 }
2912                 old->beenReplaced();
2913                 delete old;
2914         }
2915 }
2916
2917 //Add given record, when there is guarenteed to be no prior record
2918 void CkLocMgr::insertRecN(CkLocRec *rec,const CkArrayIndex &idx) {
2919         DEBC((AA"  adding new rec(%s) for %s\n"AB,rec2str[rec->type()],idx2str(idx)));
2920         CmiImmediateLock(hashImmLock);
2921         hash.put(*(CkArrayIndex *)&idx)=rec;
2922         CmiImmediateUnlock(hashImmLock);
2923 }
2924
2925 //Call this on an unrecognized array index
2926 static void abort_out_of_bounds(const CkArrayIndex &idx)
2927 {
2928   CkPrintf("ERROR! Unknown array index: %s\n",idx2str(idx));
2929   CkAbort("Array index out of bounds\n");
2930 }
2931
2932 //Look up array element in hash table.  Index out-of-bounds if not found.
2933 CkLocRec *CkLocMgr::elementRec(const CkArrayIndex &idx) {
2934 #if ! CMK_ERROR_CHECKING
2935 //Assume the element will be found
2936         return hash.getRef(*(CkArrayIndex *)&idx);
2937 #else
2938 //Include an out-of-bounds check if the element isn't found
2939         CkLocRec *rec=elementNrec(idx);
2940         if (rec==NULL) abort_out_of_bounds(idx);
2941         return rec;
2942 #endif
2943 }
2944
2945 //Look up array element in hash table.  Return NULL if not there.
2946 CkLocRec *CkLocMgr::elementNrec(const CkArrayIndex &idx) {
2947         return hash.get(*(CkArrayIndex *)&idx);
2948 }
2949
2950 struct LocalElementCounter :  public CkLocIterator
2951 {
2952     unsigned int count;
2953     LocalElementCounter() : count(0) {}
2954     void addLocation(CkLocation &loc)
2955         { ++count; }
2956 };
2957
2958 unsigned int CkLocMgr::numLocalElements()
2959 {
2960     LocalElementCounter c;
2961     iterate(c);
2962     return c.count;
2963 }
2964
2965
2966 /********************* LocMgr: LOAD BALANCE ****************/
2967
2968 #if !CMK_LBDB_ON
2969 //Empty versions of all load balancer calls
2970 void CkLocMgr::initLB(CkGroupID lbdbID_) {}
2971 void CkLocMgr::startInserting(void) {}
2972 void CkLocMgr::doneInserting(void) {}
2973 void CkLocMgr::dummyAtSync(void) {}
2974 #endif
2975
2976
2977 #if CMK_LBDB_ON
2978 void CkLocMgr::initLB(CkGroupID lbdbID_)
2979 { //Find and register with the load balancer
2980         the_lbdb = (LBDatabase *)CkLocalBranch(lbdbID_);
2981         if (the_lbdb == 0)
2982                 CkAbort("LBDatabase not yet created?\n");
2983         DEBL((AA"Connected to load balancer %p\n"AB,the_lbdb));
2984
2985         // Register myself as an object manager
2986         LDOMid myId;
2987         myId.id = thisgroup;
2988         LDCallbacks myCallbacks;
2989         myCallbacks.migrate = (LDMigrateFn)CkLocRec_local::staticMigrate;
2990         myCallbacks.setStats = NULL;
2991         myCallbacks.queryEstLoad = NULL;
2992         myLBHandle = the_lbdb->RegisterOM(myId,this,myCallbacks);
2993
2994         // Tell the lbdb that I'm registering objects
2995         the_lbdb->RegisteringObjects(myLBHandle);
2996
2997         /*Set up the dummy barrier-- the load balancer needs
2998           us to call Registering/DoneRegistering during each AtSync,
2999           and this is the only way to do so.
3000         */
3001         the_lbdb->AddLocalBarrierReceiver(
3002                 (LDBarrierFn)staticRecvAtSync,(void*)(this));
3003         dummyBarrierHandle = the_lbdb->AddLocalBarrierClient(
3004                 (LDResumeFn)staticDummyResumeFromSync,(void*)(this));
3005         dummyAtSync();
3006 }
3007 void CkLocMgr::dummyAtSync(void)
3008 {
3009         DEBL((AA"dummyAtSync called\n"AB));
3010         the_lbdb->AtLocalBarrier(dummyBarrierHandle);
3011 }
3012
3013 void CkLocMgr::staticDummyResumeFromSync(void* data)
3014 {      ((CkLocMgr*)data)->dummyResumeFromSync(); }
3015 void CkLocMgr::dummyResumeFromSync()
3016 {
3017         DEBL((AA"DummyResumeFromSync called\n"AB));
3018         the_lbdb->DoneRegisteringObjects(myLBHandle);
3019         dummyAtSync();
3020 }
3021 void CkLocMgr::staticRecvAtSync(void* data)
3022 {      ((CkLocMgr*)data)->recvAtSync(); }
3023 void CkLocMgr::recvAtSync()
3024 {
3025         DEBL((AA"recvAtSync called\n"AB));
3026         the_lbdb->RegisteringObjects(myLBHandle);
3027 }
3028
3029 void CkLocMgr::startInserting(void)
3030 {
3031         the_lbdb->RegisteringObjects(myLBHandle);
3032 }
3033 void CkLocMgr::doneInserting(void)
3034 {
3035         the_lbdb->DoneRegisteringObjects(myLBHandle);
3036 }
3037 #endif
3038
3039 #include "CkLocation.def.h"
3040
3041