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