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