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