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