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