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