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