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