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