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