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