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