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