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