increasing the time after which to check for no objs
[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   if (_lb_args.metaLbOn()) {
1059     atsync_iteration = myRec->getMetaBalancer()->get_iteration();
1060   }
1061
1062         /*
1063         FAULT_EVAC
1064         */
1065         AsyncEvacuate(CmiTrue);
1066 }
1067
1068 CkMigratable::CkMigratable(void) {
1069         DEBC((AA"In CkMigratable constructor\n"AB));
1070         commonInit();
1071 }
1072 CkMigratable::CkMigratable(CkMigrateMessage *m): Chare(m) {
1073         commonInit();
1074 }
1075
1076 int CkMigratable::ckGetChareType(void) const {return thisChareType;}
1077
1078 void CkMigratable::pup(PUP::er &p) {
1079         DEBM((AA"In CkMigratable::pup %s\n"AB,idx2str(thisIndexMax)));
1080         Chare::pup(p);
1081         p|thisIndexMax;
1082         p(usesAtSync);
1083   p(can_reset);
1084         p(usesAutoMeasure);
1085 #if CMK_LBDB_ON 
1086         int readyMigrate;
1087         if (p.isPacking()) readyMigrate = myRec->isReadyMigrate();
1088         p|readyMigrate;
1089         if (p.isUnpacking()) myRec->ReadyMigrate(readyMigrate);
1090 #endif
1091         if(p.isUnpacking()) barrierRegistered=CmiFalse;
1092         /*
1093                 FAULT_EVAC
1094         */
1095         p | asyncEvacuate;
1096         if(p.isUnpacking()){myRec->AsyncEvacuate(asyncEvacuate);}
1097         
1098         ckFinishConstruction();
1099 }
1100
1101 void CkMigratable::ckDestroy(void) {
1102         DEBC((AA"In CkMigratable::ckDestroy %s\n"AB,idx2str(thisIndexMax)));
1103         myRec->destroy();
1104 }
1105
1106 void CkMigratable::ckAboutToMigrate(void) { }
1107 void CkMigratable::ckJustMigrated(void) { }
1108 void CkMigratable::ckJustRestored(void) { }
1109
1110 CkMigratable::~CkMigratable() {
1111         DEBC((AA"In CkMigratable::~CkMigratable %s\n"AB,idx2str(thisIndexMax)));
1112 #if CMK_OUT_OF_CORE
1113         isInCore=CmiFalse;
1114         if (CkpvAccess(CkSaveRestorePrefetch)) 
1115                 return; /* Just saving to disk--don't deregister anything. */
1116         /* We're really leaving or dying-- unregister from the ooc system*/
1117         if (prefetchObjID!=-1) {
1118                 CooDeregisterObject(prefetchObjID);
1119                 prefetchObjID=-1;
1120         }
1121 #endif
1122         /*Might want to tell myRec about our doom here--
1123         it's difficult to avoid some kind of circular-delete, though.
1124         */
1125 #if CMK_LBDB_ON 
1126         if (barrierRegistered) {
1127           DEBL((AA"Removing barrier for element %s\n"AB,idx2str(thisIndexMax)));
1128           if (usesAtSync)
1129                 myRec->getLBDB()->RemoveLocalBarrierClient(ldBarrierHandle);
1130           else
1131                 myRec->getLBDB()->RemoveLocalBarrierReceiver(ldBarrierRecvHandle);
1132         }
1133 #endif
1134         //To detect use-after-delete
1135         thisIndexMax.nInts=-12345;
1136         thisIndexMax.dimension=-12345;
1137 }
1138
1139 void CkMigratable::CkAbort(const char *why) const {
1140         CkError("CkMigratable '%s' aborting:\n",_chareTable[thisChareType]->name);
1141         ::CkAbort(why);
1142 }
1143
1144 void CkMigratable::ResumeFromSync(void)
1145 {
1146 //      CkAbort("::ResumeFromSync() not defined for this array element!\n");
1147 }
1148
1149 void CkMigratable::UserSetLBLoad() {
1150         CkAbort("::UserSetLBLoad() not defined for this array element!\n");
1151 }
1152
1153 #if CMK_LBDB_ON  //For load balancing:
1154 // user can call this helper function to set obj load (for model-based lb)
1155 void CkMigratable::setObjTime(double cputime) {
1156         myRec->setObjTime(cputime);
1157 }
1158 double CkMigratable::getObjTime() {
1159         return myRec->getObjTime();
1160 }
1161
1162 void CkMigratable::clearMetaLBData() {
1163 //  if (can_reset) {
1164     local_state = OFF;
1165     atsync_iteration = -1;
1166     prev_load = 0.0;
1167     can_reset = false;
1168 //  }
1169 }
1170
1171 void CkMigratable::recvLBPeriod(void *data) {
1172   if (atsync_iteration < 0) {
1173     return;
1174   }
1175   int lb_period = *((int *) data);
1176  DEBAD(("\t[obj %s] Received the LB Period %d current iter %d state %d on PE %d\n",
1177      idx2str(thisIndexMax), lb_period, atsync_iteration, local_state, CkMyPe()));
1178
1179   bool is_tentative;
1180   if (local_state == LOAD_BALANCE) {
1181     CkAssert(lb_period == myRec->getMetaBalancer()->getPredictedLBPeriod(is_tentative));
1182     return;
1183   }
1184
1185   if (local_state == PAUSE) {
1186     if (atsync_iteration < lb_period) {
1187       local_state = DECIDED;
1188       ResumeFromSync();
1189       return;
1190     }
1191     local_state = LOAD_BALANCE;
1192
1193     can_reset = true;
1194     myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
1195     return;
1196   }
1197   local_state = DECIDED;
1198 }
1199
1200 void CkMigratable::ckFinishConstruction(void)
1201 {
1202 //      if ((!usesAtSync) || barrierRegistered) return;
1203         myRec->setMeasure(usesAutoMeasure);
1204         if (barrierRegistered) return;
1205         DEBL((AA"Registering barrier client for %s\n"AB,idx2str(thisIndexMax)));
1206         if (usesAtSync)
1207           ldBarrierHandle = myRec->getLBDB()->AddLocalBarrierClient(
1208                 (LDBarrierFn)staticResumeFromSync,(void*)(this));
1209         else
1210           ldBarrierRecvHandle = myRec->getLBDB()->AddLocalBarrierReceiver(
1211                 (LDBarrierFn)staticResumeFromSync,(void*)(this));
1212         barrierRegistered=CmiTrue;
1213 }
1214
1215 void CkMigratable::AtSync(int waitForMigration)
1216 {
1217         if (!usesAtSync)
1218                 CkAbort("You must set usesAtSync=CmiTrue in your array element constructor to use AtSync!\n");
1219 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1220         mlogData->toResumeOrNot=1;
1221 #endif
1222         myRec->AsyncMigrate(!waitForMigration);
1223         if (waitForMigration) ReadyMigrate(CmiTrue);
1224         ckFinishConstruction();
1225   DEBL((AA"Element %s going to sync\n"AB,idx2str(thisIndexMax)));
1226   // model-based load balancing, ask user to provide cpu load
1227   if (usesAutoMeasure == CmiFalse) UserSetLBLoad();
1228   
1229   if (!_lb_args.metaLbOn()) {
1230     myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
1231     return;
1232   }
1233
1234   // When MetaBalancer is turned on
1235
1236   if (atsync_iteration == -1) {
1237     can_reset = false;
1238     local_state = OFF;
1239     prev_load = 0.0;
1240   }
1241
1242   atsync_iteration++;
1243   // CkPrintf("[pe %s] atsync_iter %d && predicted period %d state: %d\n",
1244   //     idx2str(thisIndexMax), atsync_iteration,
1245   //     myRec->getMetaBalancer()->getPredictedLBPeriod(), local_state);
1246   double tmp = prev_load;
1247   prev_load = myRec->getObjTime();
1248   double current_load = prev_load - tmp;
1249   if (atsync_iteration <= myRec->getMetaBalancer()->get_finished_iteration()) {
1250     CkPrintf("[%d:%s] Error!! Contributing to iter %d < current iter %d\n",
1251       CkMyPe(), idx2str(thisIndexMax), atsync_iteration,
1252       myRec->getMetaBalancer()->get_finished_iteration());
1253     CkAbort("Not contributing to the right iteration\n");
1254   }
1255
1256   if (atsync_iteration != 0) {
1257     myRec->getMetaBalancer()->AddLoad(atsync_iteration, current_load);
1258   }
1259
1260   bool is_tentative;
1261   if (atsync_iteration < myRec->getMetaBalancer()->getPredictedLBPeriod(is_tentative)) {
1262     ResumeFromSync();
1263   } else if (is_tentative) {
1264     local_state = PAUSE;
1265   } else if (local_state == DECIDED) {
1266     DEBAD(("[%d:%s] Went to load balance iter %d\n", CkMyPe(), idx2str(thisIndexMax), atsync_iteration));
1267     local_state = LOAD_BALANCE;
1268     can_reset = true;
1269     myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
1270   } else {
1271     DEBAD(("[%d:%s] Went to pause state iter %d\n", CkMyPe(), idx2str(thisIndexMax), atsync_iteration));
1272     local_state = PAUSE;
1273   }
1274 }
1275
1276 void CkMigratable::ReadyMigrate(CmiBool ready)
1277 {
1278         myRec->ReadyMigrate(ready);
1279 }
1280
1281 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1282     extern int globalResumeCount;
1283 #endif
1284
1285 void CkMigratable::staticResumeFromSync(void* data)
1286 {
1287         CkMigratable *el=(CkMigratable *)data;
1288 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1289     if(el->mlogData->toResumeOrNot ==0 || el->mlogData->resumeCount >= globalResumeCount){
1290         return;
1291     }
1292 #endif
1293         DEBL((AA"Element %s resuming from sync\n"AB,idx2str(el->thisIndexMax)));
1294 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1295     CpvAccess(_currentObj) = el;
1296 #endif
1297   el->clearMetaLBData();
1298         el->ResumeFromSync();
1299 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1300     el->mlogData->resumeCount++;
1301 #endif
1302 }
1303 void CkMigratable::setMigratable(int migratable) 
1304 {
1305         myRec->setMigratable(migratable);
1306 }
1307
1308 struct CkArrayThreadListener {
1309         struct CthThreadListener base;
1310         CkMigratable *mig;
1311 };
1312
1313 extern "C"
1314 void CkArrayThreadListener_suspend(struct CthThreadListener *l)
1315 {
1316         CkArrayThreadListener *a=(CkArrayThreadListener *)l;
1317         a->mig->ckStopTiming();
1318 }
1319
1320 extern "C"
1321 void CkArrayThreadListener_resume(struct CthThreadListener *l)
1322 {
1323         CkArrayThreadListener *a=(CkArrayThreadListener *)l;
1324         a->mig->ckStartTiming();
1325 }
1326
1327 extern "C"
1328 void CkArrayThreadListener_free(struct CthThreadListener *l)
1329 {
1330         CkArrayThreadListener *a=(CkArrayThreadListener *)l;
1331         delete a;
1332 }
1333
1334 void CkMigratable::CkAddThreadListeners(CthThread tid, void *msg)
1335 {
1336         Chare::CkAddThreadListeners(tid, msg);   // for trace
1337         CthSetThreadID(tid, thisIndexMax.data()[0], thisIndexMax.data()[1], 
1338                        thisIndexMax.data()[2]);
1339         CkArrayThreadListener *a=new CkArrayThreadListener;
1340         a->base.suspend=CkArrayThreadListener_suspend;
1341         a->base.resume=CkArrayThreadListener_resume;
1342         a->base.free=CkArrayThreadListener_free;
1343         a->mig=this;
1344         CthAddListener(tid,(struct CthThreadListener *)a);
1345 }
1346 #else
1347 void CkMigratable::setObjTime(double cputime) {}
1348 double CkMigratable::getObjTime() {return 0.0;}
1349
1350 /* no load balancer: need dummy implementations to prevent link error */
1351 void CkMigratable::CkAddThreadListeners(CthThread tid, void *msg)
1352 {
1353 }
1354 #endif
1355
1356
1357 /*CkMigratableList*/
1358 CkMigratableList::CkMigratableList() {}
1359 CkMigratableList::~CkMigratableList() {}
1360
1361 void CkMigratableList::setSize(int s) {
1362         el.resize(s);
1363 }
1364
1365 void CkMigratableList::put(CkMigratable *v,int atIdx) {
1366 #if CMK_ERROR_CHECKING
1367         if (atIdx>=length())
1368                 CkAbort("Internal array manager error (CkMigrableList::put index out of bounds)");
1369 #endif
1370         el[atIdx]=v;
1371 }
1372
1373
1374 /************************** Location Records: *********************************/
1375
1376 //---------------- Base type:
1377 void CkLocRec::weAreObsolete(const CkArrayIndex &idx) {}
1378 CkLocRec::~CkLocRec() { }
1379 void CkLocRec::beenReplaced(void)
1380     {/*Default: ignore replacement*/}
1381
1382 //Return the represented array element; or NULL if there is none
1383 CkMigratable *CkLocRec::lookupElement(CkArrayID aid) {return NULL;}
1384
1385 //Return the last known processor; or -1 if none
1386 int CkLocRec::lookupProcessor(void) {return -1;}
1387
1388
1389 /*----------------- Local:
1390 Matches up the array index with the local index, an
1391 interfaces with the load balancer on behalf of the
1392 represented array elements.
1393 */
1394 CkLocRec_local::CkLocRec_local(CkLocMgr *mgr,CmiBool fromMigration,
1395   CmiBool ignoreArrival, const CkArrayIndex &idx_,int localIdx_)
1396         :CkLocRec(mgr),idx(idx_),localIdx(localIdx_),
1397          running(CmiFalse),deletedMarker(NULL)
1398 {
1399 #if CMK_LBDB_ON
1400         DEBL((AA"Registering element %s with load balancer\n"AB,idx2str(idx)));
1401         //BIGSIM_OOC DEBUGGING
1402         //CkPrintf("LocMgr on %d: Registering element %s with load balancer\n", CkMyPe(), idx2str(idx));
1403         nextPe = -1;
1404         asyncMigrate = CmiFalse;
1405         readyMigrate = CmiTrue;
1406         enable_measure = CmiTrue;
1407         bounced  = CmiFalse;
1408         the_lbdb=mgr->getLBDB();
1409   if (_lb_args.metaLbOn()) {
1410     the_metalb=mgr->getMetaBalancer();
1411   }
1412         LDObjid ldid = idx2LDObjid(idx);
1413 #if CMK_GLOBAL_LOCATION_UPDATE
1414         ldid.locMgrGid = mgr->getGroupID().idx;
1415 #endif        
1416         ldHandle=the_lbdb->RegisterObj(mgr->getOMHandle(),
1417                 ldid,(void *)this,1);
1418         if (fromMigration) {
1419                 DEBL((AA"Element %s migrated in\n"AB,idx2str(idx)));
1420                 if (!ignoreArrival)  {
1421                         the_lbdb->Migrated(ldHandle, CmiTrue);
1422                   // load balancer should ignore this objects movement
1423                 //  AsyncMigrate(CmiTrue);
1424                 }
1425         }
1426 #endif
1427         /*
1428                 FAULT_EVAC
1429         */
1430         asyncEvacuate = CmiTrue;
1431 }
1432 CkLocRec_local::~CkLocRec_local()
1433 {
1434         if (deletedMarker!=NULL) *deletedMarker=CmiTrue;
1435         myLocMgr->reclaim(idx,localIdx);
1436 #if CMK_LBDB_ON
1437         stopTiming();
1438         DEBL((AA"Unregistering element %s from load balancer\n"AB,idx2str(idx)));
1439         the_lbdb->UnregisterObj(ldHandle);
1440 #endif
1441 }
1442 void CkLocRec_local::migrateMe(int toPe) //Leaving this processor
1443 {
1444         //This will pack us up, send us off, and delete us
1445 //      printf("[%d] migrating migrateMe to %d \n",CkMyPe(),toPe);
1446         myLocMgr->emigrate(this,toPe);
1447 }
1448
1449 void CkLocRec_local::informIdealLBPeriod(int lb_ideal_period) {
1450   myLocMgr->informLBPeriod(this, lb_ideal_period);
1451 }
1452
1453 #if CMK_LBDB_ON
1454 void CkLocRec_local::startTiming(int ignore_running) {
1455         if (!ignore_running) running=CmiTrue;
1456         DEBL((AA"Start timing for %s at %.3fs {\n"AB,idx2str(idx),CkWallTimer()));
1457         if (enable_measure) the_lbdb->ObjectStart(ldHandle);
1458 }
1459 void CkLocRec_local::stopTiming(int ignore_running) {
1460         DEBL((AA"} Stop timing for %s at %.3fs\n"AB,idx2str(idx),CkWallTimer()));
1461         if ((ignore_running || running) && enable_measure) the_lbdb->ObjectStop(ldHandle);
1462         if (!ignore_running) running=CmiFalse;
1463 }
1464 void CkLocRec_local::setObjTime(double cputime) {
1465         the_lbdb->EstObjLoad(ldHandle, cputime);
1466 }
1467 double CkLocRec_local::getObjTime() {
1468         LBRealType walltime, cputime;
1469         the_lbdb->GetObjLoad(ldHandle, walltime, cputime);
1470         return walltime;
1471 }
1472 #endif
1473
1474 void CkLocRec_local::destroy(void) //User called destructor
1475 {
1476         //Our destructor does all the needed work
1477         delete this;
1478 }
1479 //Return the represented array element; or NULL if there is none
1480 CkMigratable *CkLocRec_local::lookupElement(CkArrayID aid) {
1481         return myLocMgr->lookupLocal(localIdx,aid);
1482 }
1483
1484 //Return the last known processor; or -1 if none
1485 int CkLocRec_local::lookupProcessor(void) {
1486         return CkMyPe();
1487 }
1488
1489 CkLocRec::RecType CkLocRec_local::type(void)
1490 {
1491         return local;
1492 }
1493
1494 void CkLocRec_local::addedElement(void) 
1495 {
1496         //Push everything in the half-created queue into the system--
1497         // anything not ready yet will be put back in.
1498         while (!halfCreated.isEmpty()) 
1499                 CkArrayManagerDeliver(CkMyPe(),halfCreated.deq());
1500 }
1501
1502 CmiBool CkLocRec_local::isObsolete(int nSprings,const CkArrayIndex &idx_)
1503
1504         int len=halfCreated.length();
1505         if (len!=0) {
1506                 /* This is suspicious-- the halfCreated queue should be extremely
1507                  transient.  It's possible we just looked at the wrong time, though;
1508                  so this is only a warning. 
1509                 */
1510                 CkPrintf("CkLoc WARNING> %d messages still around for uncreated element %s!\n",
1511                          len,idx2str(idx));
1512         }
1513         //A local element never expires
1514         return CmiFalse;
1515 }
1516
1517 /**********Added for cosmology (inline function handling without parameter marshalling)***********/
1518
1519 LDObjHandle CkMigratable::timingBeforeCall(int* objstopped){
1520
1521         LDObjHandle objHandle;
1522 #if CMK_LBDB_ON
1523         if (getLBDB()->RunningObject(&objHandle)) {
1524                 *objstopped = 1;
1525                 getLBDB()->ObjectStop(objHandle);
1526         }
1527         myRec->startTiming(1);
1528 #endif
1529
1530   //DEBS((AA"   Invoking entry %d on element %s\n"AB,epIdx,idx2str(idx)));
1531         //CmiBool isDeleted=CmiFalse; //Enables us to detect deletion during processing
1532         //deletedMarker=&isDeleted;
1533 /*#ifndef CMK_OPTIMIZE
1534         if (msg) {  Tracing: 
1535                 envelope *env=UsrToEnv(msg);
1536         //      CkPrintf("ckLocation.C beginExecuteDetailed %d %d \n",env->getEvent(),env->getsetArraySrcPe());
1537                 if (_entryTable[epIdx]->traceEnabled)
1538                         _TRACE_BEGIN_EXECUTE_DETAILED(env->getEvent(),
1539                                  ForChareMsg,epIdx,env->getsetArraySrcPe(), env->getTotalsize(), idx.getProjectionID(((CkGroupID)env->getsetArrayMgr())).idx);
1540         }
1541 #endif*/
1542
1543   return objHandle;
1544 }
1545
1546 void CkMigratable::timingAfterCall(LDObjHandle objHandle,int *objstopped){
1547   
1548 /*#ifndef CMK_OPTIMIZE
1549         if (msg) {  Tracing: 
1550                 if (_entryTable[epIdx]->traceEnabled)
1551                         _TRACE_END_EXECUTE();
1552         }
1553 #endif*/
1554 //#if CMK_LBDB_ON
1555 //        if (!isDeleted) checkBufferedMigration();   // check if should migrate
1556 //#endif
1557 //      if (isDeleted) return CmiFalse;//We were deleted
1558 //      deletedMarker=NULL;
1559 //      return CmiTrue;
1560         myRec->stopTiming(1);
1561 #if CMK_LBDB_ON
1562         if (*objstopped) {
1563                  getLBDB()->ObjectStart(objHandle);
1564         }
1565 #endif
1566
1567  return;
1568 }
1569 /****************************************************************************/
1570
1571
1572 CmiBool CkLocRec_local::invokeEntry(CkMigratable *obj,void *msg,
1573         int epIdx,CmiBool doFree) 
1574 {
1575
1576         DEBS((AA"   Invoking entry %d on element %s\n"AB,epIdx,idx2str(idx)));
1577         CmiBool isDeleted=CmiFalse; //Enables us to detect deletion during processing
1578         deletedMarker=&isDeleted;
1579         startTiming();
1580
1581
1582 #if CMK_TRACE_ENABLED
1583         if (msg) { /* Tracing: */
1584                 envelope *env=UsrToEnv(msg);
1585         //      CkPrintf("ckLocation.C beginExecuteDetailed %d %d \n",env->getEvent(),env->getsetArraySrcPe());
1586                 if (_entryTable[epIdx]->traceEnabled)
1587                         _TRACE_BEGIN_EXECUTE_DETAILED(env->getEvent(),
1588                                  ForChareMsg,epIdx,env->getsetArraySrcPe(), env->getTotalsize(), idx.getProjectionID((((CkGroupID)env->getsetArrayMgr())).idx));
1589         }
1590 #endif
1591
1592         if (doFree) 
1593            CkDeliverMessageFree(epIdx,msg,obj);
1594         else /* !doFree */
1595            CkDeliverMessageReadonly(epIdx,msg,obj);
1596
1597
1598 #if CMK_TRACE_ENABLED
1599         if (msg) { /* Tracing: */
1600                 if (_entryTable[epIdx]->traceEnabled)
1601                         _TRACE_END_EXECUTE();
1602         }
1603 #endif
1604 #if CMK_LBDB_ON
1605         if (!isDeleted) checkBufferedMigration();   // check if should migrate
1606 #endif
1607         if (isDeleted) return CmiFalse;//We were deleted
1608         deletedMarker=NULL;
1609         stopTiming();
1610         return CmiTrue;
1611 }
1612
1613 CmiBool CkLocRec_local::deliver(CkArrayMessage *msg,CkDeliver_t type,int opts)
1614 {
1615
1616         if (type==CkDeliver_queue) { /*Send via the message queue */
1617                 if (opts & CK_MSG_KEEP)
1618                         msg = (CkArrayMessage *)CkCopyMsg((void **)&msg);
1619                 CkArrayManagerDeliver(CkMyPe(),msg,opts);
1620                 return CmiTrue;
1621         }
1622         else
1623         {
1624                 CkMigratable *obj=myLocMgr->lookupLocal(localIdx,
1625                         UsrToEnv(msg)->getsetArrayMgr());
1626                 if (obj==NULL) {//That sibling of this object isn't created yet!
1627                         if (opts & CK_MSG_KEEP)
1628                                 msg = (CkArrayMessage *)CkCopyMsg((void **)&msg);
1629                         if (msg->array_ifNotThere()!=CkArray_IfNotThere_buffer) {
1630                                 return myLocMgr->demandCreateElement(msg,CkMyPe(),type);
1631                         }
1632                         else {
1633                                 DEBS((AA"   BUFFERING message for nonexistent element %s!\n"AB,idx2str(this->idx)));
1634                                 halfCreated.enq(msg);
1635                                 return CmiTrue;
1636                         }
1637                 }
1638                         
1639                 if (msg->array_hops()>1)
1640                         myLocMgr->multiHop(msg);
1641                 CmiBool doFree = (CmiBool)!(opts & CK_MSG_KEEP);
1642 #if CMK_LBDB_ON
1643                 // if there is a running obj being measured, stop it temporarily
1644                 LDObjHandle objHandle;
1645                 int objstopped = 0;
1646                 if (the_lbdb->RunningObject(&objHandle)) {
1647                         objstopped = 1;
1648                         the_lbdb->ObjectStop(objHandle);
1649                 }
1650 #endif
1651 #if CMK_GRID_QUEUE_AVAILABLE
1652                 // retain a pointer to the sending object (needed later)
1653                 CpvAccess(CkGridObject) = obj;
1654 #endif
1655
1656         CmiBool status = invokeEntry(obj,(void *)msg,msg->array_ep(),doFree);
1657         
1658 #if CMK_GRID_QUEUE_AVAILABLE
1659                 CpvAccess(CkGridObject) = NULL;
1660 #endif
1661 #if CMK_LBDB_ON
1662                 if (objstopped) the_lbdb->ObjectStart(objHandle);
1663 #endif
1664                 return status;
1665         }
1666
1667
1668 }
1669
1670 #if CMK_LBDB_ON
1671
1672 void CkLocRec_local::staticMetaLBResumeWaitingChares(LDObjHandle h, int lb_ideal_period) {
1673         CkLocRec_local *el=(CkLocRec_local *)LDObjUserData(h);
1674         DEBL((AA"Load balancer wants to migrate %s to %d\n"AB,idx2str(el->idx),dest));
1675         el->metaLBResumeWaitingChares(lb_ideal_period);
1676 }
1677
1678 void CkLocRec_local::metaLBResumeWaitingChares(int lb_ideal_period) {
1679   informIdealLBPeriod(lb_ideal_period);
1680 }
1681
1682 void CkLocRec_local::staticMigrate(LDObjHandle h, int dest)
1683 {
1684         CkLocRec_local *el=(CkLocRec_local *)LDObjUserData(h);
1685         DEBL((AA"Load balancer wants to migrate %s to %d\n"AB,idx2str(el->idx),dest));
1686         el->recvMigrate(dest);
1687 }
1688
1689 void CkLocRec_local::recvMigrate(int toPe)
1690 {
1691         // we are in the mode of delaying actual migration
1692         // till readyMigrate()
1693         if (readyMigrate) { migrateMe(toPe); }
1694         else nextPe = toPe;
1695 }
1696
1697 void CkLocRec_local::AsyncMigrate(CmiBool use)  
1698 {
1699         asyncMigrate = use; 
1700         the_lbdb->UseAsyncMigrate(ldHandle, use);
1701 }
1702
1703 CmiBool CkLocRec_local::checkBufferedMigration()
1704 {
1705         // we don't migrate in user's code when calling ReadyMigrate(true)
1706         // we postphone the action to here until we exit from the user code.
1707         if (readyMigrate && nextPe != -1) {
1708             int toPe = nextPe;
1709             nextPe = -1;
1710             // don't migrate inside the object call
1711             migrateMe(toPe);
1712             // don't do anything
1713             return CmiTrue;
1714         }
1715         return CmiFalse;
1716 }
1717
1718 int CkLocRec_local::MigrateToPe()
1719 {
1720         int pe = nextPe;
1721         nextPe = -1;
1722         return pe;
1723 }
1724
1725 void CkLocRec_local::setMigratable(int migratable)
1726 {
1727         if (migratable)
1728           the_lbdb->Migratable(ldHandle);
1729         else
1730           the_lbdb->NonMigratable(ldHandle);
1731 }
1732 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1733 void CkLocRec_local::Migrated(){
1734     the_lbdb->Migrated(ldHandle, CmiTrue);
1735 }
1736 #endif
1737 #endif
1738
1739 /**
1740  * Represents a deleted array element (and prevents re-use).
1741  * These are a debugging aid, usable only by uncommenting a line in
1742  * the element destruction code.
1743  */
1744 class CkLocRec_dead:public CkLocRec {
1745 public:
1746         CkLocRec_dead(CkLocMgr *Narr):CkLocRec(Narr) {}
1747   
1748         virtual RecType type(void) {return dead;}
1749   
1750         virtual CmiBool deliver(CkArrayMessage *msg,CkDeliver_t type,int opts=0) {
1751                 CkPrintf("Dead array element is %s.\n",idx2str(msg->array_index()));
1752                 CkAbort("Send to dead array element!\n");
1753                 return CmiFalse;
1754         }
1755         virtual void beenReplaced(void) 
1756                 {CkAbort("Can't re-use dead array element!\n");}
1757   
1758         //Return if this element is now obsolete (it isn't)
1759         virtual CmiBool isObsolete(int nSprings,const CkArrayIndex &idx) {return CmiFalse;}     
1760 };
1761
1762 /**
1763  * This is the abstract superclass of arrayRecs that keep track of their age,
1764  * and eventually expire. Its kids are remote and buffering.
1765  */
1766 class CkLocRec_aging:public CkLocRec {
1767 private:
1768         int lastAccess;//Age when last accessed
1769 protected:
1770         //Update our access time
1771         inline void access(void) {
1772                 lastAccess=myLocMgr->getSpringCount();
1773         }
1774         //Return if we are "stale"-- we were last accessed a while ago
1775         CmiBool isStale(void) {
1776                 if (myLocMgr->getSpringCount()-lastAccess>3) return CmiTrue;
1777                 else return CmiFalse;
1778         }
1779 public:
1780         CkLocRec_aging(CkLocMgr *Narr):CkLocRec(Narr) {
1781                 lastAccess=myLocMgr->getSpringCount();
1782         }
1783         //Return if this element is now obsolete
1784         virtual CmiBool isObsolete(int nSprings,const CkArrayIndex &idx)=0;
1785         //virtual void pup(PUP::er &p) { CkLocRec::pup(p); p(lastAccess); }
1786 };
1787
1788
1789 /**
1790  * Represents a remote array element.  This is just a PE number.
1791  */
1792 class CkLocRec_remote:public CkLocRec_aging {
1793 private:
1794         int onPe;//The last known Pe for this element
1795 public:
1796         CkLocRec_remote(CkLocMgr *Narr,int NonPe)
1797                 :CkLocRec_aging(Narr)
1798                 {
1799                         onPe=NonPe;
1800 #if CMK_ERROR_CHECKING
1801                         if (onPe==CkMyPe())
1802                                 CkAbort("ERROR!  'remote' array element on this Pe!\n");
1803 #endif
1804                 }
1805         //Return the last known processor for this element
1806         int lookupProcessor(void) {
1807                 return onPe;
1808         }  
1809         virtual RecType type(void) {return remote;}
1810   
1811         //Send a message for this element.
1812         virtual CmiBool deliver(CkArrayMessage *msg,CkDeliver_t type,int opts=0) {
1813                 /*FAULT_EVAC*/
1814                 int destPE = onPe;
1815                 if((!CmiNodeAlive(onPe) && onPe != allowMessagesOnly)){
1816 //                      printf("Delivery failed because process %d is invalid\n",onPe);
1817                         /*
1818                                 Send it to its home processor instead
1819                         */
1820                         const CkArrayIndex &idx=msg->array_index();
1821                         destPE = getNextPE(idx);
1822                 }
1823                 access();//Update our modification date
1824                 msg->array_hops()++;
1825                 DEBS((AA"   Forwarding message for element %s to %d (REMOTE)\n"AB,
1826                       idx2str(msg->array_index()),destPE));
1827                 if (opts & CK_MSG_KEEP)
1828                         msg = (CkArrayMessage *)CkCopyMsg((void **)&msg);
1829                 CkArrayManagerDeliver(destPE,msg,opts);
1830                 return CmiTrue;
1831         }
1832         //Return if this element is now obsolete
1833         virtual CmiBool isObsolete(int nSprings,const CkArrayIndex &idx) {
1834                 if (myLocMgr->isHome(idx)) 
1835                         //Home elements never become obsolete
1836                         // if they did, we couldn't deliver messages to that element.
1837                         return CmiFalse;
1838                 else if (isStale())
1839                         return CmiTrue;//We haven't been used in a long time
1840                 else
1841                         return CmiFalse;//We're fairly recent
1842         }
1843         //virtual void pup(PUP::er &p) { CkLocRec_aging::pup(p); p(onPe); }
1844 };
1845
1846
1847 /**
1848  * Buffers messages until record is replaced in the hash table, 
1849  * then delivers all messages to the replacing record.  This is 
1850  * used when a message arrives for a local element that has not
1851  * yet been created, buffering messages until the new element finally
1852  * checks in.
1853  *
1854  * It's silly to send a message to an element you won't ever create,
1855  * so this kind of record causes an abort "Stale array manager message!"
1856  * if it's left undelivered too long.
1857  */
1858 class CkLocRec_buffering:public CkLocRec_aging {
1859 private:
1860         CkQ<CkArrayMessage *> buffer;//Buffered messages.
1861 public:
1862         CkLocRec_buffering(CkLocMgr *Narr):CkLocRec_aging(Narr) {}
1863         virtual ~CkLocRec_buffering() {
1864                 if (0!=buffer.length()) {
1865                         CkPrintf("[%d] Warning: Messages abandoned in array manager buffer!\n", CkMyPe());
1866                         CkArrayMessage *m;
1867                         while (NULL!=(m=buffer.deq()))  {
1868                                 delete m;
1869                         }
1870                 }
1871         }
1872   
1873         virtual RecType type(void) {return buffering;}
1874   
1875         //Buffer a message for this element.
1876         virtual CmiBool deliver(CkArrayMessage *msg,CkDeliver_t type,int opts=0) {
1877                 DEBS((AA" Queued message for %s\n"AB,idx2str(msg->array_index())));
1878                 if (opts & CK_MSG_KEEP)
1879                         msg = (CkArrayMessage *)CkCopyMsg((void **)&msg);
1880                 buffer.enq(msg);
1881 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1882                 envelope *env = UsrToEnv(msg);
1883                 env->sender = CpvAccess(_currentObj)->mlogData->objID;
1884 #endif
1885                 return CmiTrue;
1886         }
1887  
1888         //This is called when this ArrayRec is about to be replaced.
1889         // We dump all our buffered messages off on the next guy,
1890         // who should know what to do with them.
1891         virtual void beenReplaced(void) {
1892                 DEBS((AA" Delivering queued messages:\n"AB));
1893                 CkArrayMessage *m;
1894                 while (NULL!=(m=buffer.deq())) {
1895 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))         
1896                 DEBUG(CmiPrintf("[%d] buffered message being sent\n",CmiMyPe()));
1897                 envelope *env = UsrToEnv(m);
1898                 Chare *oldObj = CpvAccess(_currentObj);
1899                 CpvAccess(_currentObj) =(Chare *) env->sender.getObject();
1900                 env->sender.type = TypeInvalid;
1901 #endif
1902                 DEBS((AA"Sending buffered message to %s\n"AB,idx2str(m->array_index())));
1903                 myLocMgr->deliverViaQueue(m);
1904 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))         
1905                 CpvAccess(_currentObj) = oldObj;
1906 #endif
1907                 }
1908         }
1909   
1910         //Return if this element is now obsolete
1911         virtual CmiBool isObsolete(int nSprings,const CkArrayIndex &idx) {
1912                 if (isStale() && buffer.length()>0) {
1913                         /*This indicates something is seriously wrong--
1914                           buffers should be short-lived.*/
1915                         CkPrintf("[%d] WARNING: %d stale array message(s) found!\n",CkMyPe(),buffer.length());
1916                         CkArrayMessage *msg=buffer[0];
1917                         CkPrintf("Addressed to: ");
1918                         CkPrintEntryMethod(msg->array_ep());
1919                         CkPrintf(" index %s\n",idx2str(idx));
1920                         if (myLocMgr->isHome(idx)) 
1921                                 CkPrintf("is this an out-of-bounds array index, or was it never created?\n");
1922                         else //Idx is a remote-home index
1923                                 CkPrintf("why weren't they forwarded?\n");
1924                         
1925                         // CkAbort("Stale array manager message(s)!\n");
1926                 }
1927                 return CmiFalse;
1928         }
1929   
1930 /*  virtual void pup(PUP::er &p) {
1931     CkLocRec_aging::pup(p);
1932     CkArray::pupArrayMsgQ(buffer, p);
1933     }*/
1934 };
1935
1936 /*********************** Spring Cleaning *****************/
1937 /**
1938  * Used to periodically flush out unused remote element pointers.
1939  *
1940  * Cleaning often will free up memory quickly, but slow things
1941  * down because the cleaning takes time and some not-recently-referenced
1942  * remote element pointers might be valid and used some time in 
1943  * the future.
1944  *
1945  * Also used to determine if buffered messages have become stale.
1946  */
1947 inline void CkLocMgr::springCleaning(void)
1948 {
1949   nSprings++;
1950
1951   //Poke through the hash table for old ArrayRecs.
1952   void *objp;
1953   void *keyp;
1954   
1955   CkHashtableIterator *it=hash.iterator();
1956   CmiImmediateLock(hashImmLock);
1957   while (NULL!=(objp=it->next(&keyp))) {
1958     CkLocRec *rec=*(CkLocRec **)objp;
1959     CkArrayIndex &idx=*(CkArrayIndex *)keyp;
1960     if (rec->isObsolete(nSprings,idx)) {
1961       //This record is obsolete-- remove it from the table
1962       DEBK((AA"Cleaning out old record %s\n"AB,idx2str(idx)));
1963       hash.remove(*(CkArrayIndex *)&idx);
1964       delete rec;
1965       it->seek(-1);//retry this hash slot
1966     }
1967   }
1968   CmiImmediateUnlock(hashImmLock);
1969   delete it;
1970 }
1971 void CkLocMgr::staticSpringCleaning(void *forWhom,double curWallTime) {
1972         DEBK((AA"Starting spring cleaning at %.2f\n"AB,CkWallTimer()));
1973         ((CkLocMgr *)forWhom)->springCleaning();
1974 }
1975
1976 // clean all buffer'ed messages and also free local objects
1977 void CkLocMgr::flushAllRecs(void)
1978 {
1979   void *objp;
1980   void *keyp;
1981     
1982   CkHashtableIterator *it=hash.iterator();
1983   CmiImmediateLock(hashImmLock);
1984   while (NULL!=(objp=it->next(&keyp))) {
1985     CkLocRec *rec=*(CkLocRec **)objp;
1986     CkArrayIndex &idx=*(CkArrayIndex *)keyp;
1987     if (rec->type() != CkLocRec::local) {
1988       //In the case of taking core out of memory (in BigSim's emulation)
1989       //the meta data in the location manager are not deleted so we need
1990       //this condition
1991       if(_BgOutOfCoreFlag!=1){
1992         hash.remove(*(CkArrayIndex *)&idx);
1993         delete rec;
1994         it->seek(-1);//retry this hash slot
1995       }
1996     }
1997     else {
1998         callMethod((CkLocRec_local*)rec, &CkMigratable::ckDestroy);
1999         it->seek(-1);//retry this hash slot
2000     }
2001   }
2002   delete it;
2003   CmiImmediateUnlock(hashImmLock);
2004 }
2005
2006 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2007 void CkLocMgr::callForAllRecords(CkLocFn fnPointer,CkArray *arr,void *data){
2008         void *objp;
2009         void *keyp;
2010
2011         CkHashtableIterator *it = hash.iterator();
2012         while (NULL!=(objp=it->next(&keyp))) {
2013                 CkLocRec *rec=*(CkLocRec **)objp;
2014                 CkArrayIndex &idx=*(CkArrayIndex *)keyp;
2015                 fnPointer(arr,data,rec,&idx);
2016         }
2017
2018         // releasing iterator memory
2019         delete it;
2020 }
2021 #endif
2022
2023 /*************************** LocMgr: CREATION *****************************/
2024 CkLocMgr::CkLocMgr(CkGroupID mapID_,CkGroupID lbdbID_,CkGroupID metalbID_,CkArrayIndex& numInitial)
2025         :thisProxy(thisgroup),thislocalproxy(thisgroup,CkMyPe()),
2026          hash(17,0.3)
2027 {
2028         DEBC((AA"Creating new location manager %d\n"AB,thisgroup));
2029 // moved to _CkMigratable_initInfoInit()
2030 //      CkpvInitialize(CkMigratable_initInfo,mig_initInfo);
2031
2032         managers.init();
2033         nManagers=0;
2034         firstManager=NULL;
2035         firstFree=localLen=0;
2036         duringMigration=CmiFalse;
2037         nSprings=0;
2038 #if !CMK_GLOBAL_LOCATION_UPDATE
2039         CcdCallOnConditionKeepOnPE(CcdPERIODIC_1minute,staticSpringCleaning,(void *)this, CkMyPe());
2040 #endif
2041
2042 //Register with the map object
2043         mapID=mapID_;
2044         map=(CkArrayMap *)CkLocalBranch(mapID);
2045         if (map==NULL) CkAbort("ERROR!  Local branch of array map is NULL!");
2046         mapHandle=map->registerArray(numInitial,thisgroup);
2047
2048 //Find and register with the load balancer
2049         lbdbID = lbdbID_;
2050   metalbID = metalbID_;
2051         initLB(lbdbID_, metalbID_);
2052         hashImmLock = CmiCreateImmediateLock();
2053 }
2054
2055 CkLocMgr::CkLocMgr(CkGroupID mapID_,CkGroupID lbdbID_,CkArrayIndex& numInitial)
2056         :thisProxy(thisgroup),thislocalproxy(thisgroup,CkMyPe()),
2057          hash(17,0.3)
2058 {
2059 #if !CMK_LBDB_ON
2060         CkGroupID _metalb;
2061 #endif
2062         CkLocMgr(mapID_, lbdbID_, _metalb, numInitial);
2063 }
2064
2065
2066 CkLocMgr::CkLocMgr(CkMigrateMessage* m)
2067         :IrrGroup(m),thisProxy(thisgroup),thislocalproxy(thisgroup,CkMyPe()),hash(17,0.3)
2068 {
2069         managers.init();
2070         nManagers=0;
2071         firstManager=NULL;
2072         firstFree=localLen=0;
2073         duringMigration=CmiFalse;
2074         nSprings=0;
2075 #if !CMK_GLOBAL_LOCATION_UPDATE
2076         CcdCallOnConditionKeepOnPE(CcdPERIODIC_1minute,staticSpringCleaning,(void *)this, CkMyPe());
2077 #endif
2078         hashImmLock = CmiCreateImmediateLock();
2079 }
2080
2081 void CkLocMgr::pup(PUP::er &p){
2082         IrrGroup::pup(p);
2083         p|mapID;
2084         p|mapHandle;
2085         p|lbdbID;
2086   p|metalbID;
2087         mapID = _defaultArrayMapID;
2088         if(p.isUnpacking()){
2089                 thisProxy=thisgroup;
2090                 CProxyElement_CkLocMgr newlocalproxy(thisgroup,CkMyPe());
2091                 thislocalproxy=newlocalproxy;
2092                 //Register with the map object
2093                 map=(CkArrayMap *)CkLocalBranch(mapID);
2094                 if (map==NULL) CkAbort("ERROR!  Local branch of array map is NULL!");
2095                 CkArrayIndex emptyIndex;
2096                 map->registerArray(emptyIndex,thisgroup);
2097                 // _lbdb is the fixed global groupID
2098                 initLB(lbdbID, metalbID);
2099
2100 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))     
2101         int count;
2102         p | count;
2103         DEBUG(CmiPrintf("[%d] Unpacking Locmgr %d has %d home elements\n",CmiMyPe(),thisgroup.idx,count));
2104         homeElementCount = count;
2105
2106         for(int i=0;i<count;i++){
2107             CkArrayIndex idx;
2108             int pe;
2109             idx.pup(p);
2110             p | pe;
2111             DEBUG(CmiPrintf("[%d] idx %s is a home element exisiting on pe %d\n",CmiMyPe(),idx2str(idx),pe));
2112             inform(idx,pe);
2113             CkLocRec *rec = elementNrec(idx);
2114             CmiAssert(rec!=NULL);
2115             CmiAssert(lastKnown(idx) == pe);
2116         }
2117 #endif
2118                 // delay doneInserting when it is unpacking during restart.
2119                 // to prevent load balancing kicking in
2120                 if (!CkInRestarting()) 
2121                         doneInserting();
2122         }else{
2123  /**
2124  * pack the indexes of elements which have their homes on this processor
2125  * but dont exist on it.. needed for broadcast after a restart
2126  * indexes of local elements dont need to be packed
2127  * since they will be recreated later anyway
2128  */
2129 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))     
2130         int count=0,count1=0;
2131         void *objp;
2132         void *keyp;
2133         CkHashtableIterator *it = hash.iterator();
2134       while (NULL!=(objp=it->next(&keyp))) {
2135       CkLocRec *rec=*(CkLocRec **)objp;
2136         CkArrayIndex &idx=*(CkArrayIndex *)keyp;
2137             if(rec->type() != CkLocRec::local){
2138                 if(homePe(idx) == CmiMyPe()){
2139                     count++;
2140                 }
2141             }
2142         }
2143         p | count;
2144         DEBUG(CmiPrintf("[%d] Packing Locmgr %d has %d home elements\n",CmiMyPe(),thisgroup.idx,count));
2145
2146                 // releasing iterator memory
2147                 delete it;
2148
2149         it = hash.iterator();
2150       while (NULL!=(objp=it->next(&keyp))) {
2151       CkLocRec *rec=*(CkLocRec **)objp;
2152         CkArrayIndex &idx=*(CkArrayIndex *)keyp;
2153             CkArrayIndex max = idx;
2154             if(rec->type() != CkLocRec::local){
2155                 if(homePe(idx) == CmiMyPe()){
2156                     int pe;
2157                     max.pup(p);
2158                     pe = rec->lookupProcessor();
2159                     p | pe;
2160                     count1++;
2161                 }
2162             }
2163         }
2164         CmiAssert(count == count1);
2165
2166                 // releasing iterator memory
2167                 delete it;
2168
2169 #endif
2170
2171         }
2172 }
2173
2174 void _CkLocMgrInit(void) {
2175   /* Don't trace our deliver method--it does its own tracing */
2176   CkDisableTracing(CkIndex_CkLocMgr::deliverInline(0));
2177 }
2178
2179 /// Add a new local array manager to our list.
2180 /// Returns a new CkMigratableList for the manager to store his
2181 /// elements in.
2182 CkMigratableList *CkLocMgr::addManager(CkArrayID id,CkArrMgr *mgr)
2183 {
2184         CK_MAGICNUMBER_CHECK
2185         DEBC((AA"Adding new array manager\n"AB));
2186         //Link new manager into list
2187         ManagerRec *n=new ManagerRec;
2188         managers.find(id)=n;
2189         n->next=firstManager;
2190         n->mgr=mgr;
2191         n->elts.setSize(localLen);
2192         nManagers++;
2193         firstManager=n;
2194         return &n->elts;
2195 }
2196
2197 /// Return the next unused local element index.
2198 int CkLocMgr::nextFree(void) {
2199         if (firstFree>=localLen)
2200         {//Need more space in the local index arrays-- enlarge them
2201                 int oldLen=localLen;
2202                 localLen=localLen*2+8;
2203                 DEBC((AA"Growing the local list from %d to %d...\n"AB,oldLen,localLen));
2204                 for (ManagerRec *m=firstManager;m!=NULL;m=m->next)
2205                         m->elts.setSize(localLen);
2206                 //Update the free list
2207                 freeList.resize(localLen);
2208                 for (int i=oldLen;i<localLen;i++)
2209                         freeList[i]=i+1;
2210         }
2211         int localIdx=firstFree;
2212         if (localIdx==-1) CkAbort("CkLocMgr free list corrupted!");
2213         firstFree=freeList[localIdx];
2214         freeList[localIdx]=-1; //Mark as used
2215         return localIdx;
2216 }
2217
2218 CkLocRec_remote *CkLocMgr::insertRemote(const CkArrayIndex &idx,int nowOnPe)
2219 {
2220         DEBS((AA"Remote element %s lives on %d\n"AB,idx2str(idx),nowOnPe));
2221         CkLocRec_remote *rem=new CkLocRec_remote(this,nowOnPe);
2222         insertRec(rem,idx);
2223         return rem;
2224 }
2225
2226 //This element now lives on the given Pe
2227 void CkLocMgr::inform(const CkArrayIndex &idx,int nowOnPe)
2228 {
2229         if (nowOnPe==CkMyPe())
2230                 return; //Never insert a "remote" record pointing here
2231         CkLocRec *rec=elementNrec(idx);
2232         if (rec!=NULL && rec->type()==CkLocRec::local){
2233 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2234         CmiPrintf("[%d]WARNING!!! Element %d:%s is local but is being told it exists on %d\n",CkMyPe(),idx.dimension,idx2str(idx), nowOnPe);
2235 #endif
2236                 return; //Never replace a local element's record!
2237         }
2238         insertRemote(idx,nowOnPe);
2239 }
2240
2241 //Tell this element's home processor it now lives "there"
2242 void CkLocMgr::informHome(const CkArrayIndex &idx,int nowOnPe)
2243 {
2244         int home=homePe(idx);
2245         if (home!=CkMyPe() && home!=nowOnPe) {
2246                 //Let this element's home Pe know it lives here now
2247                 DEBC((AA"  Telling %s's home %d that it lives on %d.\n"AB,idx2str(idx),home,nowOnPe));
2248 //#if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2249 //#if defined(_FAULT_MLOG_)
2250 //        informLocationHome(thisgroup,idx,home,CkMyPe());
2251 //#else
2252                 thisProxy[home].updateLocation(idx,nowOnPe);
2253 //#endif
2254         }
2255 }
2256
2257 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2258 CkLocRec_local *CkLocMgr::createLocal(const CkArrayIndex &idx,
2259         CmiBool forMigration, CmiBool ignoreArrival,
2260         CmiBool notifyHome,int dummy)
2261 {
2262     int localIdx=nextFree();
2263     DEBC((AA"Adding new record for element %s at local index %d\n"AB,idx2str(idx),localIdx));
2264     CkLocRec_local *rec=new CkLocRec_local(this,forMigration,ignoreArrival,idx,localIdx);
2265     if(!dummy){
2266         insertRec(rec,idx); //Add to global hashtable
2267     }   
2268     if (notifyHome) informHome(idx,CkMyPe());
2269     return rec; 
2270 }
2271 #else
2272 CkLocRec_local *CkLocMgr::createLocal(const CkArrayIndex &idx, 
2273                 CmiBool forMigration, CmiBool ignoreArrival,
2274                 CmiBool notifyHome)
2275 {
2276         int localIdx=nextFree();
2277         DEBC((AA"Adding new record for element %s at local index %d\n"AB,idx2str(idx),localIdx));
2278         CkLocRec_local *rec=new CkLocRec_local(this,forMigration,ignoreArrival,idx,localIdx);
2279         insertRec(rec,idx); //Add to global hashtable
2280
2281
2282         if (notifyHome) informHome(idx,CkMyPe());
2283         return rec;
2284 }
2285 #endif
2286
2287 //Add a new local array element, calling element's constructor
2288 CmiBool CkLocMgr::addElement(CkArrayID id,const CkArrayIndex &idx,
2289                 CkMigratable *elt,int ctorIdx,void *ctorMsg)
2290 {
2291         CK_MAGICNUMBER_CHECK
2292         CkLocRec *oldRec=elementNrec(idx);
2293         CkLocRec_local *rec;
2294         if (oldRec==NULL||oldRec->type()!=CkLocRec::local) 
2295         { //This is the first we've heard of that element-- add new local record
2296                 rec=createLocal(idx,CmiFalse,CmiFalse,CmiTrue);
2297 #if CMK_GLOBAL_LOCATION_UPDATE
2298                 if (homePe(idx) != CkMyPe()) {
2299                   DEBC((AA"Global location broadcast for new element idx %s "
2300                         "assigned to %d \n"AB, idx2str(idx), CkMyPe()));
2301                   thisProxy.updateLocation(idx, CkMyPe());  
2302                 }
2303 #endif
2304                 
2305         } else 
2306         { //rec is *already* local-- must not be the first insertion    
2307                 rec=((CkLocRec_local *)oldRec);
2308                 rec->addedElement();
2309         }
2310         if (!addElementToRec(rec,managers.find(id),elt,ctorIdx,ctorMsg)) return CmiFalse;
2311         elt->ckFinishConstruction();
2312         return CmiTrue;
2313 }
2314
2315 //As above, but shared with the migration code
2316 CmiBool CkLocMgr::addElementToRec(CkLocRec_local *rec,ManagerRec *m,
2317                 CkMigratable *elt,int ctorIdx,void *ctorMsg)
2318 {//Insert the new element into its manager's local list
2319         int localIdx=rec->getLocalIndex();
2320         if (m->elts.get(localIdx)!=NULL) CkAbort("Cannot insert array element twice!");
2321         m->elts.put(elt,localIdx); //Local element table
2322
2323 //Call the element's constructor
2324         DEBC((AA"Constructing element %s of array\n"AB,idx2str(rec->getIndex())));
2325         CkMigratable_initInfo &i=CkpvAccess(mig_initInfo);
2326         i.locRec=rec;
2327         i.chareType=_entryTable[ctorIdx]->chareIdx;
2328         if (!rec->invokeEntry(elt,ctorMsg,ctorIdx,CmiTrue)) return CmiFalse;
2329
2330 #if CMK_OUT_OF_CORE
2331         /* Register new element with out-of-core */
2332         PUP::sizer p_getSize; elt->pup(p_getSize);
2333         elt->prefetchObjID=CooRegisterObject(&CkArrayElementPrefetcher,p_getSize.size(),elt);
2334 #endif
2335         
2336         return CmiTrue;
2337 }
2338 void CkLocMgr::updateLocation(const CkArrayIndex &idx,int nowOnPe) {
2339         inform(idx,nowOnPe);
2340 }
2341
2342 /*************************** LocMgr: DELETION *****************************/
2343 /// This index will no longer be used-- delete the associated elements
2344 void CkLocMgr::reclaim(const CkArrayIndex &idx,int localIdx) {
2345         CK_MAGICNUMBER_CHECK
2346         DEBC((AA"Destroying element %s (local %d)\n"AB,idx2str(idx),localIdx));
2347         //Delete, and mark as empty, each array element
2348         for (ManagerRec *m=firstManager;m!=NULL;m=m->next) {
2349                 delete m->elts.get(localIdx);
2350                 m->elts.empty(localIdx);
2351         }
2352         
2353         removeFromTable(idx);
2354         
2355         //Link local index into free list
2356         freeList[localIdx]=firstFree;
2357         firstFree=localIdx;
2358         
2359                 
2360         if (!duringMigration) 
2361         { //This is a local element dying a natural death
2362             #if CMK_BIGSIM_CHARM
2363                 //After migration, reclaimRemote will be called through 
2364                 //the CkRemoveArrayElement in the pupping routines for those 
2365                 //objects that are not on the home processors. However,
2366                 //those remote records should not be deleted since the corresponding
2367                 //objects are not actually deleted but on disk. If deleted, msgs
2368                 //that seeking where is the object will be accumulated (a circular
2369                 //msg chain) and causes the program no progress
2370                 if(_BgOutOfCoreFlag==1) return; 
2371             #endif
2372                 int home=homePe(idx);
2373                 if (home!=CkMyPe())
2374 #if CMK_MEM_CHECKPOINT
2375                 if (!CkInRestarting()) // all array elements are removed anyway
2376 #endif
2377                         thisProxy[home].reclaimRemote(idx,CkMyPe());
2378         /*      //Install a zombie to keep the living from re-using this index.
2379                 insertRecN(new CkLocRec_dead(this),idx); */
2380         }
2381 }
2382
2383 void CkLocMgr::reclaimRemote(const CkArrayIndex &idx,int deletedOnPe) {
2384         DEBC((AA"Our element %s died on PE %d\n"AB,idx2str(idx),deletedOnPe));
2385         CkLocRec *rec=elementNrec(idx);
2386         if (rec==NULL) return; //We never knew him
2387         if (rec->type()==CkLocRec::local) return; //He's already been reborn
2388         removeFromTable(idx);
2389         delete rec;
2390 }
2391 void CkLocMgr::removeFromTable(const CkArrayIndex &idx) {
2392 #if CMK_ERROR_CHECKING
2393         //Make sure it's actually in the table before we delete it
2394         if (NULL==elementNrec(idx))
2395                 CkAbort("CkLocMgr::removeFromTable called on invalid index!");
2396 #endif
2397         CmiImmediateLock(hashImmLock);
2398         hash.remove(*(CkArrayIndex *)&idx);
2399         CmiImmediateUnlock(hashImmLock);
2400 #if CMK_ERROR_CHECKING
2401         //Make sure it's really gone
2402         if (NULL!=elementNrec(idx))
2403                 CkAbort("CkLocMgr::removeFromTable called, but element still there!");
2404 #endif
2405 }
2406
2407 /************************** LocMgr: MESSAGING *************************/
2408 /// Deliver message to this element, going via the scheduler if local
2409 /// @return 0 if object local, 1 if not
2410 int CkLocMgr::deliver(CkMessage *m,CkDeliver_t type,int opts) {
2411         DEBS((AA"deliver \n"AB));
2412         CK_MAGICNUMBER_CHECK
2413         CkArrayMessage *msg=(CkArrayMessage *)m;
2414
2415
2416         const CkArrayIndex &idx=msg->array_index();
2417         DEBS((AA"deliver %s\n"AB,idx2str(idx)));
2418         if (type==CkDeliver_queue)
2419                 _TRACE_CREATION_DETAILED(UsrToEnv(m),msg->array_ep());
2420         CkLocRec *rec=elementNrec(idx);
2421         if(rec != NULL){
2422                 DEBS((AA"deliver %s of type %d \n"AB,idx2str(idx),rec->type()));
2423         }else{
2424                 DEBS((AA"deliver %s rec is null\n"AB,idx2str(idx)));
2425         }
2426 //#if (!defined(_FAULT_MLOG_) && !defined(_FAULT_CAUSAL_))
2427 //#if !defined(_FAULT_MLOG_)
2428 #if CMK_LBDB_ON
2429
2430         LDObjid ldid = idx2LDObjid(idx);
2431 #if CMK_GLOBAL_LOCATION_UPDATE
2432         ldid.locMgrGid = thisgroup.idx;
2433 #endif        
2434         if (type==CkDeliver_queue) {
2435                 if (!(opts & CK_MSG_LB_NOTRACE) && the_lbdb->CollectingCommStats()) {
2436                 if(rec!=NULL) the_lbdb->Send(myLBHandle,ldid,UsrToEnv(msg)->getTotalsize(), rec->lookupProcessor(), 1);
2437                 else /*rec==NULL*/ the_lbdb->Send(myLBHandle,ldid,UsrToEnv(msg)->getTotalsize(),homePe(msg->array_index()), 1);
2438                 }
2439         }
2440 #endif
2441 //#endif
2442 #if CMK_GRID_QUEUE_AVAILABLE
2443         int gridSrcPE;
2444         int gridSrcCluster;
2445         int gridDestPE;
2446         int gridDestCluster;
2447         CkMigratable *obj;
2448         ArrayElement *obj2;
2449         CkGroupID gid;
2450         int *data;
2451
2452         obj = (CkMigratable *) CpvAccess(CkGridObject);   // CkGridObject is a pointer to the sending object (retained earlier)
2453         if (obj != NULL) {
2454           obj2 = dynamic_cast<ArrayElement *> (obj);
2455           if (obj2 > 0) {
2456             // Get the sending object's array gid and indexes.
2457             // These are guaranteed to exist due to the succeeding dynamic cast above.
2458             gid = obj2->ckGetArrayID ();
2459             data = obj2->thisIndexMax.data ();
2460
2461             // Get the source PE and destination PE.
2462             gridSrcPE = CkMyPe ();
2463             if (rec != NULL) {
2464               gridDestPE = rec->lookupProcessor ();
2465             } else {
2466               gridDestPE = homePe (msg->array_index ());
2467             }
2468
2469             // Get the source cluster and destination cluster.
2470             gridSrcCluster = CmiGetCluster (gridSrcPE);
2471             gridDestCluster = CmiGetCluster (gridDestPE);
2472
2473             // If the Grid queue interval is greater than zero, it means that the more complicated
2474             // technique for registering border objects that exceed a specified threshold of
2475             // cross-cluster messages within a specified interval (and deregistering border objects
2476             // that do not meet this threshold) is used.  Otherwise a much simpler technique is used
2477             // where a border object is registered immediately upon sending a single cross-cluster
2478             // message (and deregistered when load balancing takes place).
2479             if (obj2->grid_queue_interval > 0) {
2480               // Increment the sending object's count of all messages.
2481               obj2->msg_count += 1;
2482
2483               // If the source cluster and destination cluster differ, this is a Grid message.
2484               // (Increment the count of all Grid messages.)
2485               if (gridSrcCluster != gridDestCluster) {
2486                 obj2->msg_count_grid += 1;
2487               }
2488
2489               // If the number of messages exceeds the interval, check to see if the object has
2490               // sent enough cross-cluster messages to qualify as a border object.
2491               if (obj2->msg_count >= obj2->grid_queue_interval) {
2492                 if (obj2->msg_count_grid >= obj2->grid_queue_threshold) {
2493                   // The object is a border object; if it is not already registered, register it.
2494                   if (!obj2->border_flag) {
2495                     CmiGridQueueRegister (gid.idx, obj2->thisIndexMax.nInts, data[0], data[1], data[2]);
2496                   }
2497                   obj2->border_flag = 1;
2498                 } else {
2499                   // The object is not a border object; if it is registered, deregister it.
2500                   if (obj2->border_flag) {
2501                     CmiGridQueueDeregister (gid.idx, obj2->thisIndexMax.nInts, data[0], data[1], data[2]);
2502                   }
2503                   obj2->border_flag = 0;
2504                 }
2505                 // Reset the counts.
2506                 obj2->msg_count = 0;
2507                 obj2->msg_count_grid = 0;
2508               }
2509             } else {
2510               if (gridSrcCluster != gridDestCluster) {
2511                 CmiGridQueueRegister (gid.idx, obj2->thisIndexMax.nInts, data[0], data[1], data[2]);
2512               }
2513             }
2514           }
2515
2516           // Reset the CkGridObject pointer.
2517           CpvAccess(CkGridObject) = NULL;
2518         }
2519 #endif
2520         /**FAULT_EVAC*/
2521         if (rec!=NULL){
2522                 CmiBool result = rec->deliver(msg,type,opts);
2523                 // if result is CmiFalse, than rec is not valid anymore, as the object
2524                 // the message was just delivered to has died or migrated out.
2525                 // Therefore rec->type() cannot be invoked!
2526                 if (result==CmiTrue && rec->type()==CkLocRec::local) return 0;
2527                 else return 1;
2528                 /*if(!result){
2529                         //DEBS((AA"deliver %s failed type %d \n"AB,idx2str(idx),rec->type()));
2530                         DEBS((AA"deliver %s failed \n"AB,idx2str(idx)));
2531                         if(rec->type() == CkLocRec::remote){
2532                                 if (opts & CK_MSG_KEEP)
2533                                         msg = (CkArrayMessage *)CkCopyMsg((void **)&msg);
2534                                 deliverUnknown(msg,type);
2535                         }
2536                 }*/
2537         }else /* rec==NULL*/ {
2538                 if (opts & CK_MSG_KEEP)
2539                         msg = (CkArrayMessage *)CkCopyMsg((void **)&msg);
2540                 deliverUnknown(msg,type,opts);
2541                 return 1;
2542         }
2543
2544 }
2545
2546 /// This index is not hashed-- somehow figure out what to do.
2547 CmiBool CkLocMgr::deliverUnknown(CkArrayMessage *msg,CkDeliver_t type,int opts)
2548 {
2549         CK_MAGICNUMBER_CHECK
2550         const CkArrayIndex &idx=msg->array_index();
2551         int onPe=homePe(idx);
2552         if (onPe!=CkMyPe()) 
2553         {// Forward the message to its home processor
2554                 DEBM((AA"Forwarding message for unknown %s to home %d \n"AB,idx2str(idx),onPe));
2555                 msg->array_hops()++;
2556                 CkArrayManagerDeliver(onPe,msg,opts);
2557                 return CmiTrue;
2558         }
2559         else
2560         { // We *are* the home processor:
2561         //Check if the element's array manager has been registered yet:
2562           CkArrMgr *mgr=managers.find(UsrToEnv((void *)msg)->getsetArrayMgr())->mgr;
2563           if (!mgr) { //No manager yet-- postpone the message (stupidly)
2564             if (CkInRestarting()) {
2565               // during restarting, this message should be ignored
2566               delete msg;
2567             }
2568             else {
2569               CkArrayManagerDeliver(CkMyPe(),msg); 
2570             }
2571           }
2572           else { // Has a manager-- must buffer the message
2573             DEBC((AA"Adding buffer for unknown element %s\n"AB,idx2str(idx)));
2574             CkLocRec *rec=new CkLocRec_buffering(this);
2575             insertRecN(rec,idx);
2576             rec->deliver(msg,type);
2577           
2578             if (msg->array_ifNotThere()!=CkArray_IfNotThere_buffer) 
2579             { //Demand-create the element:
2580               return demandCreateElement(msg,-1,type);
2581             }
2582           }
2583           return CmiTrue;
2584         }
2585 }
2586
2587 CmiBool CkLocMgr::demandCreateElement(CkArrayMessage *msg,int onPe,CkDeliver_t type)
2588 {
2589         CK_MAGICNUMBER_CHECK
2590         const CkArrayIndex &idx=msg->array_index();
2591         int chareType=_entryTable[msg->array_ep()]->chareIdx;
2592         int ctor=_chareTable[chareType]->getDefaultCtor();
2593         if (ctor==-1) CkAbort("Can't create array element to handle message--\n"
2594                               "The element has no default constructor in the .ci file!\n");
2595         if (onPe==-1) 
2596         { //Decide where element needs to live
2597                 if (msg->array_ifNotThere()==CkArray_IfNotThere_createhere) 
2598                         onPe=UsrToEnv(msg)->getsetArraySrcPe();
2599                 else //Createhome
2600                         onPe=homePe(idx);
2601         }
2602         
2603         //Find the manager and build the element
2604         DEBC((AA"Demand-creating element %s on pe %d\n"AB,idx2str(idx),onPe));
2605         CkArrMgr *mgr=managers.find(UsrToEnv((void *)msg)->getsetArrayMgr())->mgr;
2606         if (!mgr) CkAbort("Tried to demand-create for nonexistent arrMgr");
2607         return mgr->demandCreateElement(idx,onPe,ctor,type);
2608 }
2609
2610 //This message took several hops to reach us-- fix it
2611 void CkLocMgr::multiHop(CkArrayMessage *msg)
2612 {
2613
2614         CK_MAGICNUMBER_CHECK
2615         int srcPe=msg->array_getSrcPe();
2616         if (srcPe==CkMyPe())
2617                 DEB((AA"Odd routing: local element %s is %d hops away!\n"AB,idx2str(msg),msg->array_hops()));
2618         else
2619         {//Send a routing message letting original sender know new element location
2620                 DEBS((AA"Sending update back to %d for element\n"AB,srcPe,idx2str(msg)));
2621                 thisProxy[srcPe].updateLocation(msg->array_index(),CkMyPe());
2622         }
2623 }
2624
2625 /************************** LocMgr: ITERATOR *************************/
2626 CkLocation::CkLocation(CkLocMgr *mgr_, CkLocRec_local *rec_)
2627         :mgr(mgr_), rec(rec_) {}
2628         
2629 const CkArrayIndex &CkLocation::getIndex(void) const {
2630         return rec->getIndex();
2631 }
2632
2633 void CkLocation::destroyAll() {
2634         mgr->callMethod(rec, &CkMigratable::ckDestroy);
2635 }
2636
2637 void CkLocation::pup(PUP::er &p) {
2638         mgr->pupElementsFor(p,rec,CkElementCreation_migrate);
2639 }
2640
2641 CkLocIterator::~CkLocIterator() {}
2642
2643 /// Iterate over our local elements:
2644 void CkLocMgr::iterate(CkLocIterator &dest) {
2645   //Poke through the hash table for local ArrayRecs.
2646   void *objp;
2647   CkHashtableIterator *it=hash.iterator();
2648   CmiImmediateLock(hashImmLock);
2649
2650   while (NULL!=(objp=it->next())) {
2651     CkLocRec *rec=*(CkLocRec **)objp;
2652     if (rec->type()==CkLocRec::local) {
2653       CkLocation loc(this,(CkLocRec_local *)rec);
2654       dest.addLocation(loc);
2655     }
2656   }
2657   CmiImmediateUnlock(hashImmLock);
2658   delete it;
2659 }
2660
2661
2662
2663
2664 /************************** LocMgr: MIGRATION *************************/
2665 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2666 void CkLocMgr::pupElementsFor(PUP::er &p,CkLocRec_local *rec,
2667         CkElementCreation_t type, CmiBool create, int dummy)
2668 {
2669     p.comment("-------- Array Location --------");
2670     register ManagerRec *m;
2671     int localIdx=rec->getLocalIndex();
2672     CkVec<CkMigratable *> dummyElts;
2673
2674     for (m=firstManager;m!=NULL;m=m->next) {
2675         int elCType;
2676         if (!p.isUnpacking())
2677         { //Need to find the element's existing type
2678             CkMigratable *elt=m->element(localIdx);
2679             if (elt) elCType=elt->ckGetChareType();
2680             else elCType=-1; //Element hasn't been created
2681         }
2682         p(elCType);
2683         if (p.isUnpacking() && elCType!=-1) {
2684             CkMigratable *elt=m->mgr->allocateMigrated(elCType,rec->getIndex(),type);
2685             int migCtorIdx=_chareTable[elCType]->getMigCtor();
2686                 if(!dummy){
2687                         if(create)
2688                                 if (!addElementToRec(rec,m,elt,migCtorIdx,NULL)) return;
2689                                 }else{
2690                     CkMigratable_initInfo &i=CkpvAccess(mig_initInfo);
2691                     i.locRec=rec;
2692                     i.chareType=_entryTable[migCtorIdx]->chareIdx;
2693                     dummyElts.push_back(elt);
2694                     if (!rec->invokeEntry(elt,NULL,migCtorIdx,CmiTrue)) return ;
2695                 }
2696         }
2697     }
2698     if(!dummy){
2699         for (m=firstManager;m!=NULL;m=m->next) {
2700             CkMigratable *elt=m->element(localIdx);
2701             if (elt!=NULL)
2702                 {
2703                        elt->pup(p);
2704                 }
2705         }
2706     }else{
2707             for(int i=0;i<dummyElts.size();i++){
2708                 CkMigratable *elt = dummyElts[i];
2709                 if (elt!=NULL){
2710             elt->pup(p);
2711                         }
2712                 delete elt;
2713             }
2714                         for (ManagerRec *m=firstManager;m!=NULL;m=m->next) {
2715                 m->elts.empty(localIdx);
2716             }
2717         freeList[localIdx]=firstFree;
2718         firstFree=localIdx;
2719     }
2720 }
2721 #else
2722 void CkLocMgr::pupElementsFor(PUP::er &p,CkLocRec_local *rec,
2723                 CkElementCreation_t type)
2724 {
2725         p.comment("-------- Array Location --------");
2726         register ManagerRec *m;
2727         int localIdx=rec->getLocalIndex();
2728
2729         //First pup the element types
2730         // (A separate loop so ckLocal works even in element pup routines)
2731         for (m=firstManager;m!=NULL;m=m->next) {
2732                 int elCType;
2733                 if (!p.isUnpacking())
2734                 { //Need to find the element's existing type
2735                         CkMigratable *elt=m->element(localIdx);
2736                         if (elt) elCType=elt->ckGetChareType();
2737                         else elCType=-1; //Element hasn't been created
2738                 }
2739                 p(elCType);
2740                 if (p.isUnpacking() && elCType!=-1) {
2741                         //Create the element
2742                         CkMigratable *elt=m->mgr->allocateMigrated(elCType,rec->getIndex(),type);
2743                         int migCtorIdx=_chareTable[elCType]->getMigCtor();
2744                         //Insert into our tables and call migration constructor
2745                         if (!addElementToRec(rec,m,elt,migCtorIdx,NULL)) return;
2746                 }
2747         }
2748         //Next pup the element data
2749         for (m=firstManager;m!=NULL;m=m->next) {
2750                 CkMigratable *elt=m->element(localIdx);
2751                 if (elt!=NULL)
2752                 {
2753                         elt->pup(p);
2754 #if CMK_ERROR_CHECKING
2755                         if (p.isUnpacking()) elt->sanitycheck();
2756 #endif
2757                 }
2758         }
2759 }
2760 #endif
2761
2762 /// Call this member function on each element of this location:
2763 void CkLocMgr::callMethod(CkLocRec_local *rec,CkMigratable_voidfn_t fn)
2764 {
2765         int localIdx=rec->getLocalIndex();
2766         for (ManagerRec *m=firstManager;m!=NULL;m=m->next) {
2767                 CkMigratable *el=m->element(localIdx);
2768                 if (el) (el->* fn)();
2769         }
2770 }
2771
2772 /// Call this member function on each element of this location:
2773 void CkLocMgr::callMethod(CkLocRec_local *rec,CkMigratable_voidfn_arg_t fn,     void * data)
2774 {
2775         int localIdx=rec->getLocalIndex();
2776         for (ManagerRec *m=firstManager;m!=NULL;m=m->next) {
2777                 CkMigratable *el=m->element(localIdx);
2778                 if (el) (el->* fn)(data);
2779         }
2780 }
2781
2782 /// return a list of migratables in this local record
2783 void CkLocMgr::migratableList(CkLocRec_local *rec, CkVec<CkMigratable *> &list)
2784 {
2785         register ManagerRec *m;
2786         int localIdx=rec->getLocalIndex();
2787
2788         for (m=firstManager;m!=NULL;m=m->next) {
2789                 CkMigratable *elt=m->element(localIdx);
2790                 if (elt) list.push_back(elt);
2791         }
2792 }
2793
2794 /// Migrate this local element away to another processor.
2795 void CkLocMgr::emigrate(CkLocRec_local *rec,int toPe)
2796 {
2797         CK_MAGICNUMBER_CHECK
2798         if (toPe==CkMyPe()) return; //You're already there!
2799         /*
2800                 FAULT_EVAC
2801                 if the toProcessor is already marked as invalid, dont emigrate
2802                 Shouldn't happen but might
2803         */
2804         if(!CmiNodeAlive(toPe)){
2805                 return;
2806         }
2807         CkArrayIndex idx=rec->getIndex();
2808
2809 #if CMK_OUT_OF_CORE
2810         int localIdx=rec->getLocalIndex();
2811         /* Load in any elements that are out-of-core */
2812         for (ManagerRec *m=firstManager;m!=NULL;m=m->next) {
2813                 CkMigratable *el=m->element(localIdx);
2814                 if (el) if (!el->isInCore) CooBringIn(el->prefetchObjID);
2815         }
2816 #endif
2817
2818         //Let all the elements know we're leaving
2819         callMethod(rec,&CkMigratable::ckAboutToMigrate);
2820         /*EVAC*/
2821
2822 //First pass: find size of migration message
2823         int bufSize;
2824         {
2825                 PUP::sizer p;
2826                 p(nManagers);
2827                 pupElementsFor(p,rec,CkElementCreation_migrate);
2828                 bufSize=p.size(); 
2829         }
2830
2831 //Allocate and pack into message
2832         int doubleSize=bufSize/sizeof(double)+1;
2833         CkArrayElementMigrateMessage *msg = 
2834                 new (doubleSize, 0) CkArrayElementMigrateMessage;
2835         msg->idx=idx;
2836         msg->length=bufSize;
2837 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_)) 
2838     msg->gid = ckGetGroupID();
2839 #endif
2840 #if CMK_LBDB_ON
2841         msg->ignoreArrival = rec->isAsyncMigrate()?1:0;
2842 #endif
2843         /*
2844                 FAULT_EVAC
2845         */
2846         msg->bounced = rec->isBounced();
2847         {
2848                 PUP::toMem p(msg->packData); 
2849                 p.becomeDeleting(); 
2850                 p(nManagers);
2851                 pupElementsFor(p,rec,CkElementCreation_migrate);
2852                 if (p.size()!=bufSize) {
2853                         CkError("ERROR! Array element claimed it was %d bytes to a "
2854                                 "sizing PUP::er, but copied %d bytes into the packing PUP::er!\n",
2855                                 bufSize,p.size());
2856                         CkAbort("Array element's pup routine has a direction mismatch.\n");
2857                 }
2858         }
2859
2860         DEBM((AA"Migrated index size %s to %d \n"AB,idx2str(idx),toPe));        
2861
2862 //#if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2863 //#if defined(_FAULT_MLOG_)
2864 //    sendMlogLocation(toPe,UsrToEnv(msg));
2865 //#else
2866         //Send off message and delete old copy
2867         thisProxy[toPe].immigrate(msg);
2868 //#endif
2869
2870         duringMigration=CmiTrue;
2871         delete rec; //Removes elements, hashtable entries, local index
2872         
2873         
2874         duringMigration=CmiFalse;
2875         //The element now lives on another processor-- tell ourselves and its home
2876         inform(idx,toPe);
2877 //#if (!defined(_FAULT_MLOG_) && !defined(_FAULT_CAUSAL_))    
2878 //#if !defined(_FAULT_MLOG_)    
2879         informHome(idx,toPe);
2880 //#endif
2881
2882 #if !CMK_LBDB_ON && CMK_GLOBAL_LOCATION_UPDATE
2883         DEBM((AA"Global location update. idx %s " 
2884               "assigned to %d \n"AB,idx2str(idx),toPe));
2885         thisProxy.updateLocation(idx, toPe);                        
2886 #endif
2887
2888         CK_MAGICNUMBER_CHECK
2889 }
2890
2891 void CkLocMgr::informLBPeriod(CkLocRec_local *rec, int lb_ideal_period) {
2892         callMethod(rec,&CkMigratable::recvLBPeriod, (void *)&lb_ideal_period);
2893 }
2894
2895 /**
2896   Migrating array element is arriving on this processor.
2897 */
2898 void CkLocMgr::immigrate(CkArrayElementMigrateMessage *msg)
2899 {
2900         const CkArrayIndex &idx=msg->idx;
2901                 
2902         PUP::fromMem p(msg->packData); 
2903         
2904         int nMsgMan;
2905         p(nMsgMan);
2906         if (nMsgMan<nManagers)
2907                 CkAbort("Array element arrived from location with fewer managers!\n");
2908         if (nMsgMan>nManagers) {
2909                 //Some array managers haven't registered yet-- throw it back
2910                 DEBM((AA"Busy-waiting for array registration on migrating %s\n"AB,idx2str(idx)));
2911                 thisProxy[CkMyPe()].immigrate(msg);
2912                 return;
2913         }
2914
2915         //Create a record for this element
2916 //#if (!defined(_FAULT_MLOG_) && !defined(_FAULT_CAUSAL_))    
2917 //#if !defined(_FAULT_MLOG_)     
2918         CkLocRec_local *rec=createLocal(idx,CmiTrue,msg->ignoreArrival,CmiFalse /* home told on departure */ );
2919 //#else
2920 //    CkLocRec_local *rec=createLocal(idx,CmiTrue,CmiTrue,CmiFalse /* home told on departure */ );
2921 //#endif
2922         
2923         //Create the new elements as we unpack the message
2924         pupElementsFor(p,rec,CkElementCreation_migrate);
2925         if (p.size()!=msg->length) {
2926                 CkError("ERROR! Array element claimed it was %d bytes to a"
2927                         "packing PUP::er, but %d bytes in the unpacking PUP::er!\n",
2928                         msg->length,p.size());
2929                 CkError("(I have %d managers; he claims %d managers)\n",
2930                         nManagers,nMsgMan);
2931                 
2932                 CkAbort("Array element's pup routine has a direction mismatch.\n");
2933         }
2934         /*
2935                 FAULT_EVAC
2936                         if this element came in as a result of being bounced off some other process,
2937                         then it needs to be resumed. It is assumed that it was bounced because load 
2938                         balancing caused it to move into a processor which later crashed
2939         */
2940         if(msg->bounced){
2941                 callMethod(rec,&CkMigratable::ResumeFromSync);
2942         }
2943         
2944         //Let all the elements know we've arrived
2945         callMethod(rec,&CkMigratable::ckJustMigrated);
2946         /*FAULT_EVAC
2947                 If this processor has started evacuating array elements on it 
2948                 dont let new immigrants in. If they arrive send them to what
2949                 would be their correct homePE.
2950                 Leave a record here mentioning the processor where it got sent
2951         */
2952         
2953         if(CkpvAccess(startedEvac)){
2954                 int newhomePE = getNextPE(idx);
2955                 DEBM((AA"Migrated into failed processor index size %s resent to %d \n"AB,idx2str(idx),newhomePE));      
2956                 CkLocMgr *mgr = rec->getLocMgr();
2957                 int targetPE=getNextPE(idx);
2958                 //set this flag so that load balancer is not informed when
2959                 //this element migrates
2960                 rec->AsyncMigrate(CmiTrue);
2961                 rec->Bounced(CmiTrue);
2962                 mgr->emigrate(rec,targetPE);
2963                 
2964         }
2965
2966         delete msg;
2967 }
2968
2969 void CkLocMgr::restore(const CkArrayIndex &idx, PUP::er &p)
2970 {
2971         //This is in broughtIntoMem during out-of-core emulation in BigSim,
2972         //informHome should not be called since such information is already
2973         //immediately updated real migration
2974 #if CMK_ERROR_CHECKING
2975         if(_BgOutOfCoreFlag!=2)
2976             CmiAbort("CkLocMgr::restore should only be used in out-of-core emulation for BigSim and be called when object is brought into memory!\n");
2977 #endif
2978         CkLocRec_local *rec=createLocal(idx,CmiFalse,CmiFalse,CmiFalse);
2979         
2980         //BIGSIM_OOC DEBUGGING
2981         //CkPrintf("Proc[%d]: Registering element %s with LDB\n", CkMyPe(), idx2str(idx));
2982
2983         //Create the new elements as we unpack the message
2984         pupElementsFor(p,rec,CkElementCreation_restore);
2985
2986         callMethod(rec,&CkMigratable::ckJustRestored);
2987 }
2988
2989
2990 /// Insert and unpack this array element from this checkpoint (e.g., from CkLocation::pup)
2991 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2992 void CkLocMgr::resume(const CkArrayIndex &idx, PUP::er &p, CmiBool create, int dummy)
2993 {
2994         CkLocRec_local *rec;
2995         CkLocRec *recGlobal;    
2996
2997         if(create){
2998                 rec = createLocal(idx,CmiFalse,CmiFalse,CmiTrue && !dummy /* home doesn't know yet */,dummy );
2999         }else{
3000                 recGlobal = elementNrec(idx);
3001                 if(recGlobal == NULL) 
3002                         CmiAbort("Local object not found");
3003                 if(recGlobal->type() != CkLocRec::local)
3004                         CmiAbort("Local object not local, :P");
3005                 rec = (CkLocRec_local *)recGlobal;
3006         }
3007         
3008     pupElementsFor(p,rec,CkElementCreation_resume,create,dummy);
3009
3010     if(!dummy){
3011         callMethod(rec,&CkMigratable::ckJustMigrated);
3012     }
3013 }
3014 #else
3015 void CkLocMgr::resume(const CkArrayIndex &idx, PUP::er &p, CmiBool notify)
3016 {
3017         CkLocRec_local *rec=createLocal(idx,CmiFalse,CmiFalse,notify /* home doesn't know yet */ );
3018
3019         //Create the new elements as we unpack the message
3020         pupElementsFor(p,rec,CkElementCreation_resume);
3021
3022         callMethod(rec,&CkMigratable::ckJustMigrated);
3023 }
3024 #endif
3025
3026 /********************* LocMgr: UTILITY ****************/
3027 void CkMagicNumber_impl::badMagicNumber(
3028         int expected,const char *file,int line,void *obj) const
3029 {
3030         CkError("FAILURE on pe %d, %s:%d> Expected %p's magic number "
3031                 "to be 0x%08x; but found 0x%08x!\n", CkMyPe(),file,line,obj,
3032                 expected, magic);
3033         CkAbort("Bad magic number detected!  This implies either\n"
3034                 "the heap or a message was corrupted!\n");
3035 }
3036 CkMagicNumber_impl::CkMagicNumber_impl(int m) :magic(m) { }
3037
3038 //Look up the object with this array index, or return NULL
3039 CkMigratable *CkLocMgr::lookup(const CkArrayIndex &idx,CkArrayID aid) {
3040         CkLocRec *rec=elementNrec(idx);
3041         if (rec==NULL) return NULL;
3042         else return rec->lookupElement(aid);
3043 }
3044 //"Last-known" location (returns a processor number)
3045 int CkLocMgr::lastKnown(const CkArrayIndex &idx) {
3046         CkLocMgr *vthis=(CkLocMgr *)this;//Cast away "const"
3047         CkLocRec *rec=vthis->elementNrec(idx);
3048         int pe=-1;
3049         if (rec!=NULL) pe=rec->lookupProcessor();
3050         if (pe==-1) return homePe(idx);
3051         else{
3052                 /*
3053                         FAULT_EVAC
3054                         if the lastKnownPE is invalid return homePE and delete this record
3055                 */
3056                 if(!CmiNodeAlive(pe)){
3057                         removeFromTable(idx);
3058                         return homePe(idx);
3059                 }
3060                 return pe;
3061         }       
3062 }
3063 /// Return true if this array element lives on another processor
3064 bool CkLocMgr::isRemote(const CkArrayIndex &idx,int *onPe) const
3065 {
3066         CkLocMgr *vthis=(CkLocMgr *)this;//Cast away "const"
3067         CkLocRec *rec=vthis->elementNrec(idx);
3068         if (rec==NULL || rec->type()!=CkLocRec::remote) 
3069                 return false; /* not definitely a remote element */
3070         else /* element is indeed remote */
3071         {
3072                 *onPe=rec->lookupProcessor();
3073                 return true;
3074         }
3075 }
3076
3077 static const char *rec2str[]={
3078     "base (INVALID)",//Base class (invalid type)
3079     "local",//Array element that lives on this Pe
3080     "remote",//Array element that lives on some other Pe
3081     "buffering",//Array element that was just created
3082     "dead"//Deleted element (for debugging)
3083 };
3084
3085 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
3086 void CkLocMgr::setDuringMigration(CmiBool _duringMigration){
3087     duringMigration = _duringMigration;
3088 }
3089 #endif
3090
3091
3092 //Add given element array record at idx, replacing the existing record
3093 void CkLocMgr::insertRec(CkLocRec *rec,const CkArrayIndex &idx) {
3094         CkLocRec *old=elementNrec(idx);
3095         insertRecN(rec,idx);
3096         if (old!=NULL) {
3097                 DEBC((AA"  replaces old rec(%s) for %s\n"AB,rec2str[old->type()],idx2str(idx)));
3098                 //There was an old element at this location
3099                 if (old->type()==CkLocRec::local && rec->type()==CkLocRec::local) {
3100                     if (!CkInRestarting()) {    // ok if it is restarting
3101                         CkPrintf("ERROR! Duplicate array index: %s\n",idx2str(idx));
3102                         CkAbort("Duplicate array index used");
3103                     }
3104                 }
3105                 old->beenReplaced();
3106                 delete old;
3107         }
3108 }
3109
3110 //Add given record, when there is guarenteed to be no prior record
3111 void CkLocMgr::insertRecN(CkLocRec *rec,const CkArrayIndex &idx) {
3112         DEBC((AA"  adding new rec(%s) for %s\n"AB,rec2str[rec->type()],idx2str(idx)));
3113         CmiImmediateLock(hashImmLock);
3114         hash.put(*(CkArrayIndex *)&idx)=rec;
3115         CmiImmediateUnlock(hashImmLock);
3116 }
3117
3118 //Call this on an unrecognized array index
3119 static void abort_out_of_bounds(const CkArrayIndex &idx)
3120 {
3121   CkPrintf("ERROR! Unknown array index: %s\n",idx2str(idx));
3122   CkAbort("Array index out of bounds\n");
3123 }
3124
3125 //Look up array element in hash table.  Index out-of-bounds if not found.
3126 CkLocRec *CkLocMgr::elementRec(const CkArrayIndex &idx) {
3127 #if ! CMK_ERROR_CHECKING
3128 //Assume the element will be found
3129         return hash.getRef(*(CkArrayIndex *)&idx);
3130 #else
3131 //Include an out-of-bounds check if the element isn't found
3132         CkLocRec *rec=elementNrec(idx);
3133         if (rec==NULL) abort_out_of_bounds(idx);
3134         return rec;
3135 #endif
3136 }
3137
3138 //Look up array element in hash table.  Return NULL if not there.
3139 CkLocRec *CkLocMgr::elementNrec(const CkArrayIndex &idx) {
3140         return hash.get(*(CkArrayIndex *)&idx);
3141 }
3142
3143 struct LocalElementCounter :  public CkLocIterator
3144 {
3145     unsigned int count;
3146     LocalElementCounter() : count(0) {}
3147     void addLocation(CkLocation &loc)
3148         { ++count; }
3149 };
3150
3151 unsigned int CkLocMgr::numLocalElements()
3152 {
3153     LocalElementCounter c;
3154     iterate(c);
3155     return c.count;
3156 }
3157
3158
3159 /********************* LocMgr: LOAD BALANCE ****************/
3160
3161 #if !CMK_LBDB_ON
3162 //Empty versions of all load balancer calls
3163 void CkLocMgr::initLB(CkGroupID lbdbID_, CkGroupID metalbID_) {}
3164 void CkLocMgr::startInserting(void) {}
3165 void CkLocMgr::doneInserting(void) {}
3166 void CkLocMgr::dummyAtSync(void) {}
3167 #endif
3168
3169
3170 #if CMK_LBDB_ON
3171 void CkLocMgr::initLB(CkGroupID lbdbID_, CkGroupID metalbID_)
3172 { //Find and register with the load balancer
3173         the_lbdb = (LBDatabase *)CkLocalBranch(lbdbID_);
3174         if (the_lbdb == 0)
3175                 CkAbort("LBDatabase not yet created?\n");
3176         DEBL((AA"Connected to load balancer %p\n"AB,the_lbdb));
3177   if (_lb_args.metaLbOn()) {
3178     the_metalb = (MetaBalancer *)CkLocalBranch(metalbID_);
3179     if (the_metalb == 0)
3180       CkAbort("MetaBalancer not yet created?\n");
3181   }
3182
3183         // Register myself as an object manager
3184         LDOMid myId;
3185         myId.id = thisgroup;
3186         LDCallbacks myCallbacks;
3187         myCallbacks.migrate = (LDMigrateFn)CkLocRec_local::staticMigrate;
3188         myCallbacks.setStats = NULL;
3189         myCallbacks.queryEstLoad = NULL;
3190   myCallbacks.metaLBResumeWaitingChares =
3191       (LDMetaLBResumeWaitingCharesFn)CkLocRec_local::staticMetaLBResumeWaitingChares;
3192         myLBHandle = the_lbdb->RegisterOM(myId,this,myCallbacks);
3193
3194         // Tell the lbdb that I'm registering objects
3195         the_lbdb->RegisteringObjects(myLBHandle);
3196
3197         /*Set up the dummy barrier-- the load balancer needs
3198           us to call Registering/DoneRegistering during each AtSync,
3199           and this is the only way to do so.
3200         */
3201         the_lbdb->AddLocalBarrierReceiver(
3202                 (LDBarrierFn)staticRecvAtSync,(void*)(this));
3203         dummyBarrierHandle = the_lbdb->AddLocalBarrierClient(
3204                 (LDResumeFn)staticDummyResumeFromSync,(void*)(this));
3205         dummyAtSync();
3206 }
3207 void CkLocMgr::dummyAtSync(void)
3208 {
3209         DEBL((AA"dummyAtSync called\n"AB));
3210         the_lbdb->AtLocalBarrier(dummyBarrierHandle);
3211 }
3212
3213 void CkLocMgr::staticDummyResumeFromSync(void* data)
3214 {      ((CkLocMgr*)data)->dummyResumeFromSync(); }
3215 void CkLocMgr::dummyResumeFromSync()
3216 {
3217         DEBL((AA"DummyResumeFromSync called\n"AB));
3218         the_lbdb->DoneRegisteringObjects(myLBHandle);
3219         dummyAtSync();
3220 }
3221 void CkLocMgr::staticRecvAtSync(void* data)
3222 {      ((CkLocMgr*)data)->recvAtSync(); }
3223 void CkLocMgr::recvAtSync()
3224 {
3225         DEBL((AA"recvAtSync called\n"AB));
3226         the_lbdb->RegisteringObjects(myLBHandle);
3227 }
3228
3229 void CkLocMgr::startInserting(void)
3230 {
3231         the_lbdb->RegisteringObjects(myLBHandle);
3232 }
3233 void CkLocMgr::doneInserting(void)
3234 {
3235         the_lbdb->DoneRegisteringObjects(myLBHandle);
3236 }
3237 #endif
3238
3239 #include "CkLocation.def.h"
3240
3241