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