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