recover from soft failure
[charm.git] / src / ck-core / cklocation.h
1 /*
2 Location manager: keeps track of an indexed set of migratable
3 objects.  Used by the array manager to locate array elements,
4 interact with the load balancer, and perform migrations.
5
6 Does not handle reductions (see ckreduction.h), broadcasts,
7 array proxies, or the details of element creation (see ckarray.h).
8 */
9 #ifndef __CKLOCATION_H
10 #define __CKLOCATION_H
11
12 /*********************** Array Messages ************************/
13 class CkArrayMessage : public CkMessage {
14 public:
15   //These routines are implementation utilities
16   CkArrayIndex &array_index(void);
17   unsigned short &array_ep(void);
18   unsigned short &array_ep_bcast(void);
19   unsigned char &array_hops(void);
20   unsigned int array_getSrcPe(void);
21   unsigned int array_ifNotThere(void);
22   void array_setIfNotThere(unsigned int);
23   
24   //This allows us to delete bare CkArrayMessages
25   void operator delete(void *p){CkFreeMsg(p);}
26 };
27
28 /* Utility */
29 //#if CMK_LBDB_ON
30 #include "LBDatabase.h"
31 #include "MetaBalancer.h"
32 class LBDatabase;
33 //#endif
34
35 //Forward declarations
36 class CkArray;
37 class ArrayElement;
38 //What to do if an entry method is invoked on
39 // an array element that does not (yet) exist:
40 typedef enum {
41         CkArray_IfNotThere_buffer=0, //Wait for it to be created
42         CkArray_IfNotThere_createhere=1, //Make it on sending Pe
43         CkArray_IfNotThere_createhome=2 //Make it on (a) home Pe
44 } CkArray_IfNotThere;
45
46 /// How to do a message delivery:
47 typedef enum {
48         CkDeliver_queue=0, //Deliver via the scheduler's queue
49         CkDeliver_inline=1  //Deliver via a regular call
50 } CkDeliver_t;
51
52 #include "CkLocation.decl.h"
53
54 /************************** Array Messages ****************************/
55 /**
56  *  This is the message type used to actually send a migrating array element.
57  */
58
59 class CkArrayElementMigrateMessage : public CMessage_CkArrayElementMigrateMessage {
60 public:
61         CkArrayIndex idx; // Array index that is migrating
62         int ignoreArrival;   // if to inform LB of arrival
63         int length;//Size in bytes of the packed data
64 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
65         CkGroupID gid; //gid of location manager
66 #endif
67         CmiBool bounced;
68         double* packData;
69 };
70
71 /******************* Map object ******************/
72
73 extern CkGroupID _defaultArrayMapID;
74 extern CkGroupID _fastArrayMapID;
75 class CkLocMgr;
76 class CkArrMgr;
77
78 /**
79 \addtogroup CkArray
80 */
81 /*@{*/
82
83 /** The "map" is used by the array manager to map an array index to 
84  * a home processor number.
85  */
86 class CkArrayMap : public IrrGroup // : public CkGroupReadyCallback
87 {
88 public:
89   CkArrayMap(void);
90   CkArrayMap(CkMigrateMessage *m): IrrGroup(m) {}
91   virtual ~CkArrayMap();
92   virtual int registerArray(CkArrayIndex& numElements,CkArrayID aid);
93   virtual void populateInitial(int arrayHdl,CkArrayIndex& numElements,void *ctorMsg,CkArrMgr *mgr);
94   virtual int procNum(int arrayHdl,const CkArrayIndex &element) =0;
95   virtual int homePe(int arrayHdl,const CkArrayIndex &element)
96              { return procNum(arrayHdl, element); }
97 //  virtual void pup(PUP::er &p) { CkGroupReadyCallback::pup(p); }
98 };
99 /*@}*/
100
101 /**
102 \addtogroup CkArrayImpl
103 \brief Migratable Chare Arrays: Implementation classes.
104 */
105 /*@{*/
106 static inline CkGroupID CkCreatePropMap(void)
107 {
108   return CProxy_PropMap::ckNew();
109 }
110
111 extern void _propMapInit(void);
112 extern void _CkMigratable_initInfoInit(void);
113
114
115 /*************************** CkLocRec ******************************/
116 class CkArray;//Array manager
117 class CkLocMgr;//Location manager
118 class CkMigratable;//Migratable object
119
120 /**
121  * A CkLocRec is our local representation of an array element.
122  * The location manager's main hashtable maps array indices to
123  * CkLocRec *'s.
124  */
125 class CkLocRec {
126 protected:
127   CkLocMgr *myLocMgr;
128   //int lastAccess;//Age when last accessed. Removed since unused and colliding with a inheriting class, Filippo
129   //Called when we discover we are obsolete before we delete ourselves
130   virtual void weAreObsolete(const CkArrayIndex &idx);
131 public:
132   CkLocRec(CkLocMgr *mgr) :myLocMgr(mgr) { }
133   virtual ~CkLocRec();
134   inline CkLocMgr *getLocMgr(void) const {return myLocMgr;}
135
136   /// Return the type of this ArrayRec:
137   typedef enum {
138     base=0,//Base class (invalid type)
139     local,//Array element that lives on this Pe
140     remote,//Array element that lives on some other Pe
141     buffering,//Array element that was just created
142     dead//Deleted element (for debugging)
143   } RecType;
144   virtual RecType type(void)=0;
145   
146   /// Accept a message for this element
147   virtual CmiBool deliver(CkArrayMessage *m,CkDeliver_t type,int opts=0)=0;
148   
149   /// This is called when this ArrayRec is about to be replaced.
150   /// It is only used to deliver buffered element messages.
151   virtual void beenReplaced(void);
152   
153   /// Return if this rec is now obsolete
154   virtual CmiBool isObsolete(int nSprings,const CkArrayIndex &idx)=0; 
155
156   /// Return the represented array element; or NULL if there is none
157   virtual CkMigratable *lookupElement(CkArrayID aid);
158
159   /// Return the last known processor; or -1 if none
160   virtual int lookupProcessor(void);
161 };
162
163 /**
164  * Represents a local array element.
165  */
166 class CkLocRec_local : public CkLocRec {
167   CkArrayIndex idx;/// Element's array index
168   int localIdx; /// Local index (into array manager's element lists)
169   CmiBool running; /// True when inside a startTiming/stopTiming pair
170   CmiBool *deletedMarker; /// Set this if we're deleted during processing
171   CkQ<CkArrayMessage *> halfCreated; /// Stores messages for nonexistent siblings of existing elements
172 public:
173   //Creation and Destruction:
174   CkLocRec_local(CkLocMgr *mgr,CmiBool fromMigration,CmiBool ignoreArrival,
175         const CkArrayIndex &idx_,int localIdx_);
176   void migrateMe(int toPe); //Leave this processor
177   void informIdealLBPeriod(int lb_ideal_period);
178   void metaLBCallLB();
179   void destroy(void); //User called destructor
180   virtual ~CkLocRec_local();
181
182   /// A new element has been added to this index
183   void addedElement(void);
184
185   /**
186    *  Accept a message for this element.
187    *  Returns false if the element died during the receive.
188    */
189   virtual CmiBool deliver(CkArrayMessage *m,CkDeliver_t type,int opts=0);
190
191   /** Invoke the given entry method on this element.
192    *   Returns false if the element died during the receive.
193    *   If doFree is true, the message is freed after send;
194    *    if false, the message can be reused.
195    */
196   CmiBool invokeEntry(CkMigratable *obj,void *msg,int idx,CmiBool doFree);
197
198   virtual RecType type(void);
199   virtual CmiBool isObsolete(int nSprings,const CkArrayIndex &idx);
200
201 #if CMK_LBDB_ON  //For load balancing:
202   /// Control the load balancer:
203   void startTiming(int ignore_running=0);
204   void stopTiming(int ignore_running=0);
205   void setObjTime(double cputime);
206   double getObjTime();
207 #else
208   inline void startTiming(int ignore_running=0) {  }
209   inline void stopTiming(int ignore_running=0) { }
210 #endif
211   inline int getLocalIndex(void) const {return localIdx;}
212   inline const CkArrayIndex &getIndex(void) const {return idx;}
213   virtual CkMigratable *lookupElement(CkArrayID aid);
214   virtual int lookupProcessor(void);
215
216 #if CMK_LBDB_ON
217 public:
218   inline LBDatabase *getLBDB(void) const {return the_lbdb;}
219   inline MetaBalancer *getMetaBalancer(void) const {return the_metalb;}
220   inline LDObjHandle getLdHandle() const{return ldHandle;}
221   static void staticMigrate(LDObjHandle h, int dest);
222   static void staticMetaLBResumeWaitingChares(LDObjHandle h, int lb_ideal_period);
223   static void staticMetaLBCallLBOnChares(LDObjHandle h);
224   void metaLBResumeWaitingChares(int lb_ideal_period);
225   void metaLBCallLBOnChares();
226   void recvMigrate(int dest);
227   void setMigratable(int migratable);   /// set migratable
228   void AsyncMigrate(CmiBool use);
229   CmiBool isAsyncMigrate()   { return asyncMigrate; }
230   void ReadyMigrate(CmiBool ready) { readyMigrate = ready; } ///called from user
231   int  isReadyMigrate() { return readyMigrate; }
232   CmiBool checkBufferedMigration();     // check and execute pending migration
233   int   MigrateToPe();
234 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
235         void Migrated();
236 #endif
237   inline void setMeasure(CmiBool status) { enable_measure = status; }
238 private:
239   LBDatabase *the_lbdb;
240   MetaBalancer *the_metalb;
241   LDObjHandle ldHandle;
242   CmiBool  asyncMigrate;  /// if readyMove is inited
243   CmiBool  readyMigrate;    /// status whether it is ready to migrate
244   CmiBool  enable_measure;
245   int  nextPe;              /// next migration dest processor
246 #else
247   void AsyncMigrate(CmiBool use){};
248 #endif
249 /**FAULT_EVAC*/
250 private:
251         CmiBool asyncEvacuate; //can the element be evacuated anytime, false for tcharm 
252         CmiBool bounced; //did this element try to immigrate into a processor which was evacuating
253                                                                                         // and was bounced away to some other processor. This is assumed to happen
254                                                                                         //only if this object was migrated by a load balancer, but the processor
255                                                                                         // started crashing soon after
256 public: 
257         CmiBool isAsyncEvacuate(){return asyncEvacuate;}
258         void AsyncEvacuate(CmiBool set){asyncEvacuate = set;}
259         CmiBool isBounced(){return bounced;}
260         void Bounced(CmiBool set){bounced = set;}
261 };
262 class CkLocRec_remote;
263
264 /*********************** CkMigratable ******************************/
265 /** This is the superclass of all migratable parallel objects.
266  *  Currently, that's just array elements.
267  */
268 #if CMK_OUT_OF_CORE
269 #  include "conv-ooc.h"
270 extern CooPrefetchManager CkArrayElementPrefetcher;
271 // If this flag is set, this creation/deletion is just 
272 //   a "fake" constructor/destructor call for prefetching.
273 CkpvExtern(int,CkSaveRestorePrefetch);
274 #endif
275
276 class CkMigratable : public Chare {
277 protected:
278   CkLocRec_local *myRec;
279 private:
280   int thisChareType;//My chare type
281   void commonInit(void);
282   CmiBool asyncEvacuate;
283   int atsync_iteration;
284
285   enum state {
286     OFF,
287     ON,
288     PAUSE,
289     DECIDED,
290     LOAD_BALANCE
291   } local_state;
292   double  prev_load;
293   bool can_reset;
294
295 public:
296   CkArrayIndex thisIndexMax;
297
298   CkMigratable(void);
299   CkMigratable(CkMigrateMessage *m);
300   virtual ~CkMigratable();
301   virtual void pup(PUP::er &p);
302   virtual void CkAddThreadListeners(CthThread tid, void *msg);
303
304   virtual int ckGetChareType(void) const;// {return thisChareType;}
305   const CkArrayIndex &ckGetArrayIndex(void) const {return myRec->getIndex();}
306
307 #if CMK_LBDB_ON  //For load balancing:
308   //Suspend load balancer measurements (e.g., before CthSuspend)
309   inline void ckStopTiming(void) {myRec->stopTiming();}
310   //Begin load balancer measurements again (e.g., after CthSuspend)
311   inline void ckStartTiming(void) {myRec->startTiming();}
312   inline LBDatabase *getLBDB(void) const {return myRec->getLBDB();}
313   inline MetaBalancer *getMetaBalancer(void) const {return myRec->getMetaBalancer();}
314 #else
315   inline void ckStopTiming(void) { }
316   inline void ckStartTiming(void) { }
317 #endif
318
319   /// for inline call
320   LDObjHandle timingBeforeCall(int *objstopped);
321   void timingAfterCall(LDObjHandle objHandle,int *objstopped);
322
323   //Initiate a migration to the given processor
324   inline void ckMigrate(int toPe) {myRec->migrateMe(toPe);}
325   
326   /// Called by the system just before and after migration to another processor:  
327   virtual void ckAboutToMigrate(void); /*default is empty*/
328   virtual void ckJustMigrated(void); /*default is empty*/
329
330   void recvLBPeriod(void *data);
331   void metaLBCallLB();
332   void clearMetaLBData(void);
333
334   //used for out-of-core emulation
335   virtual void ckJustRestored(void); /*default is empty*/
336
337   /// Delete this object
338   virtual void ckDestroy(void);
339
340   /// Execute the given entry method.  Returns false if the element 
341   /// deleted itself or migrated away during execution.
342   inline CmiBool ckInvokeEntry(int epIdx,void *msg,CmiBool doFree) 
343           {return myRec->invokeEntry(this,msg,epIdx,doFree);}
344
345 protected:
346   /// A more verbose form of abort
347   virtual void CkAbort(const char *str) const;
348
349   CmiBool usesAtSync;//You must set this in the constructor to use AtSync().
350   CmiBool usesAutoMeasure; //You must set this to use auto lb instrumentation.
351   CmiBool barrierRegistered;//True iff barrier handle below is set
352
353 public:
354   virtual void ResumeFromSync(void);
355   virtual void UserSetLBLoad(void);  /// user define this when setLBLoad is true
356   void setObjTime(double cputime);
357   double getObjTime();
358
359 #if CMK_LBDB_ON  //For load balancing:
360   void AtSync(int waitForMigration=1);
361   int MigrateToPe()  { return myRec->MigrateToPe(); }
362
363 private: //Load balancer state:
364   LDBarrierClient ldBarrierHandle;//Transient (not migrated)  
365   LDBarrierReceiver ldBarrierRecvHandle;//Transient (not migrated)  
366   static void staticResumeFromSync(void* data);
367 public:
368   void ReadyMigrate(CmiBool ready);
369   void ckFinishConstruction(void);
370   void setMigratable(int migratable);
371 #else
372   void AtSync(int waitForMigration=1) { ResumeFromSync();}
373   void setMigratable(int migratable)  { }
374 public:
375   void ckFinishConstruction(void) { }
376 #endif
377
378 #if CMK_OUT_OF_CORE
379 private:
380   friend class CkLocMgr;
381   friend int CkArrayPrefetch_msg2ObjId(void *msg);
382   friend void CkArrayPrefetch_writeToSwap(FILE *swapfile,void *objptr);
383   friend void CkArrayPrefetch_readFromSwap(FILE *swapfile,void *objptr);
384   int prefetchObjID; //From CooRegisterObject
385   CmiBool isInCore; //If true, the object is present in memory
386 #endif
387
388   // FAULT_EVAC
389   void AsyncEvacuate(CmiBool set){myRec->AsyncEvacuate(set);asyncEvacuate = set;};
390 public:
391   CmiBool isAsyncEvacuate(){return asyncEvacuate;};
392 };
393
394 /** 
395  * Stores a list of array elements.  These lists are 
396  * kept by the array managers. 
397  */
398 class CkMigratableList {
399         CkVec< CkZeroPtr<CkMigratable> > el;
400  public:
401         CkMigratableList();
402         ~CkMigratableList();
403         
404         void setSize(int s);
405         inline int length(void) const {return el.length();}
406
407         /// Add an element at the given location
408         void put(CkMigratable *v,int atIdx);
409
410         /// Return the element at the given location
411         inline CkMigratable *get(int localIdx) {return el[localIdx];}
412
413         /**
414          * Return the next non-empty element starting from the given index,
415          * or NULL if there is none.  Updates from to point past the returned index.
416         */
417         CkMigratable *next(int &from) {
418                 while (from<length()) {
419                         CkMigratable *ret=el[from];
420                         from++;
421                         if (ret!=NULL) return ret;
422                 }
423                 return NULL;
424         }
425
426         /// Remove the element at the given location
427         inline void empty(int localIdx) {el[localIdx]=NULL;}
428 };
429
430 /**
431  *A typed version of the above.
432  */
433 template <class T>
434 class CkMigratableListT : public CkMigratableList {
435         typedef CkMigratableList super;
436 public:
437         inline void put(T *v,int atIdx) {super::put((CkMigratable *)v,atIdx);}
438         inline T *get(int localIdx) {return (T *)super::get(localIdx);}
439         inline T *next(int &from) {return (T *)super::next(from);}
440 };
441
442
443 /********************** CkLocMgr ********************/
444 /// A tiny class for detecting heap corruption
445 class CkMagicNumber_impl {
446  protected:
447         int magic;
448         void badMagicNumber(int expected,const char *file,int line,void *obj) const;
449         CkMagicNumber_impl(int m);
450 };
451 template<class T>
452 class CkMagicNumber : public CkMagicNumber_impl {
453         enum {good=sizeof(T)^0x7EDC0000};
454  public:
455         CkMagicNumber(void) :CkMagicNumber_impl(good) {}
456         inline void check(const char *file,int line,void *obj) const {
457                 if (magic!=good) badMagicNumber(good,file,line,obj);
458         }
459 #if CMK_ERROR_CHECKING
460 #   define CK_MAGICNUMBER_CHECK magic.check(__FILE__,__LINE__,this);
461 #else
462 #   define CK_MAGICNUMBER_CHECK /*empty, for speed*/
463 #endif
464 };
465
466 /**
467  * The "data" class passed to a CkLocIterator, which refers to a bound
468  * glob of array elements.
469  * This is a transient class-- do not attempt to store it or send 
470  * it across processors.
471  */
472
473         
474 class CkLocation {
475         CkLocMgr *mgr;
476         CkLocRec_local *rec;
477 public:
478         CkLocation(CkLocMgr *mgr_, CkLocRec_local *rec_);
479         
480         /// Find our location manager
481         inline CkLocMgr *getManager(void) const {return mgr;}
482         
483         /// Find the local record that refers to this element
484         inline CkLocRec_local *getLocalRecord(void) const {return rec;}
485         
486         /// Look up and return the array index of this location.
487         const CkArrayIndex &getIndex(void) const;
488         
489         void destroyAll();
490
491         /// Pup all the array elements at this location.
492         void pup(PUP::er &p);
493 };
494
495 /**
496  * This interface describes the destination for an iterator over
497  * the locations in an array.
498  */
499 class CkLocIterator {
500 public:
501         virtual ~CkLocIterator();
502         
503         /// This location is part of the calling location manager.
504         virtual void addLocation(CkLocation &loc) =0;
505 };
506
507 enum CkElementCreation_t {
508   CkElementCreation_migrate=2, // Create object for normal migration arrival
509   CkElementCreation_resume=3,  // Create object after checkpoint
510   CkElementCreation_restore=4  // Create object after checkpoint, skip listeners
511 };
512 /// Abstract superclass of all array manager objects 
513 class CkArrMgr {
514 public:
515         virtual ~CkArrMgr() {}
516         /// Insert this initial element on this processor
517         virtual void insertInitial(const CkArrayIndex &idx,void *ctorMsg, int local=1)=0;
518         
519         /// Done with initial insertions
520         virtual void doneInserting(void)=0;
521         
522         /// Create an uninitialized element after migration
523         ///  The element's constructor will be called immediately after.
524         virtual CkMigratable *allocateMigrated(int elChareType,
525                 const CkArrayIndex &idx,CkElementCreation_t type) =0;
526
527         /// Demand-create an element at this index on this processor
528         ///  Returns true if the element was successfully added;
529         ///  false if the element migrated away or deleted itself.
530         virtual CmiBool demandCreateElement(const CkArrayIndex &idx,
531                 int onPe,int ctor,CkDeliver_t type) =0;
532 };
533
534
535 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
536 typedef void (*CkLocFn)(CkArray *,void *,CkLocRec *,CkArrayIndex *);
537 #endif
538
539
540 /**
541  * A group which manages the location of an indexed set of
542  * migratable objects.  Knows about insertions, deletions,
543  * home processors, migration, and message forwarding.
544  */
545 class CkLocMgr : public IrrGroup {
546         CkMagicNumber<CkMigratable> magic; //To detect heap corruption
547 public:
548         CkLocMgr(CkGroupID map,CkGroupID _lbdb,CkGroupID _metalb,CkArrayIndex& numInitial);
549         CkLocMgr(CkGroupID map,CkGroupID _lbdb,CkArrayIndex& numInitial);
550         CkLocMgr(CkMigrateMessage *m);
551         inline CmiBool isLocMgr(void) { return CmiTrue; }
552         CkGroupID &getGroupID(void) {return thisgroup;}
553         inline CProxy_CkLocMgr &getProxy(void)
554                 {return thisProxy;}
555         inline CProxyElement_CkLocMgr &getLocalProxy(void)
556                 {return thislocalproxy;}
557
558 //Interface used by array manager and proxies
559         /// Add a new local array manager to our list.  Array managers
560         ///  must be registered in the same order on all processors.
561         /// Returns a list which will contain that array's local elements
562         CkMigratableList *addManager(CkArrayID aid,CkArrMgr *mgr);
563
564         /// Populate this array with initial elements
565         void populateInitial(CkArrayIndex& numElements,void *initMsg,CkArrMgr *mgr)
566                 {map->populateInitial(mapHandle,numElements,initMsg,mgr);}
567
568         /// Add a new local array element, calling element's constructor
569         ///  Returns true if the element was successfully added;
570         ///  false if the element migrated away or deleted itself.
571         CmiBool addElement(CkArrayID aid,const CkArrayIndex &idx,
572                 CkMigratable *elt,int ctorIdx,void *ctorMsg);
573
574         ///Deliver message to this element:
575         inline void deliverViaQueue(CkMessage *m) {deliver(m,CkDeliver_queue);}
576         inline void deliverInline(CkMessage *m) {deliver(m,CkDeliver_inline);}
577         int deliver(CkMessage *m, CkDeliver_t type, int opts=0);
578
579         ///Done inserting elements for now
580         void doneInserting(void);
581         void startInserting(void);
582
583         // How many elements of each associated array are local to this PE?
584         // If this returns n, and there are k associated arrays, that
585         // means k*n elements are living here
586         unsigned int numLocalElements();
587
588 //Advisories:
589         ///This index now lives on the given processor-- update local records
590         void inform(const CkArrayIndex &idx,int nowOnPe);
591
592         ///This index now lives on the given processor-- tell the home processor
593         void informHome(const CkArrayIndex &idx,int nowOnPe);
594
595         ///This message took several hops to reach us-- fix it
596         void multiHop(CkArrayMessage *m);
597
598 //Interface used by CkLocRec_local
599         //Look up the object with this local index
600         inline CkMigratable *lookupLocal(int localIdx,CkArrayID arrayID) {
601 #if CMK_ERROR_CHECKING
602                 if (managers.find(arrayID)->mgr==NULL)
603                         CkAbort("CkLocMgr::lookupLocal called for unknown array!\n");
604 #endif
605                 return managers.find(arrayID)->elts.get(localIdx);
606         }
607
608         //Migrate us to another processor
609         void emigrate(CkLocRec_local *rec,int toPe);
610   void informLBPeriod(CkLocRec_local *rec, int lb_ideal_period);
611   void metaLBCallLB(CkLocRec_local *rec);
612
613 #if CMK_LBDB_ON
614         LBDatabase *getLBDB(void) const { return the_lbdb; }
615   MetaBalancer *getMetaBalancer(void) const { return the_metalb;}
616         const LDOMHandle &getOMHandle(void) const { return myLBHandle; }
617 #endif
618
619         //This index will no longer be used-- delete the associated elements
620         void reclaim(const CkArrayIndex &idx,int localIdx);
621
622         int getSpringCount(void) const { return nSprings; }
623
624         CmiBool demandCreateElement(CkArrayMessage *msg,int onPe,CkDeliver_t type);
625
626 //Interface used by external users:
627         /// Home mapping
628         inline int homePe(const CkArrayIndex &idx) const
629                 {return map->homePe(mapHandle,idx);}
630         inline int procNum(const CkArrayIndex &idx) const
631                 {return map->procNum(mapHandle,idx);}
632         inline CmiBool isHome(const CkArrayIndex &idx) const
633                 {return (CmiBool)(homePe(idx)==CkMyPe());}
634
635         /// Look up the object with this array index, or return NULL
636         CkMigratable *lookup(const CkArrayIndex &idx,CkArrayID aid);
637
638         /// Return the "last-known" location (returns a processor number)
639         int lastKnown(const CkArrayIndex &idx);
640
641         /// Return true if this array element lives on another processor
642         bool isRemote(const CkArrayIndex &idx,int *onPe) const;
643
644 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
645         //mark the duringMigration variable .. used for parallel restart
646         void setDuringMigration(CmiBool _duringMigration);
647 #endif
648
649         /// Pass each of our locations (each separate array index) to this destination.
650         void iterate(CkLocIterator &dest);
651
652         /// Insert and unpack this array element from this checkpoint (e.g., from CkLocation::pup), skip listeners
653         void restore(const CkArrayIndex &idx, PUP::er &p);
654         /// Insert and unpack this array element from this checkpoint (e.g., from CkLocation::pup)
655 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
656         void resume(const CkArrayIndex &idx, PUP::er &p, CmiBool create, int dummy=0);
657 #else
658         void resume(const CkArrayIndex &idx, PUP::er &p, CmiBool notify=CmiTrue,CmiBool rebuild=CmiFalse,CmiBool create = CmiTrue);
659 #endif
660
661 //Communication:
662         void immigrate(CkArrayElementMigrateMessage *msg);
663         void updateLocation(const CkArrayIndex &idx,int nowOnPe);
664         void reclaimRemote(const CkArrayIndex &idx,int deletedOnPe);
665         void dummyAtSync(void);
666
667         /// return a list of migratables in this local record
668         void migratableList(CkLocRec_local *rec, CkVec<CkMigratable *> &list);
669
670         void flushAllRecs(void);
671         void flushLocalRecs(void);
672         void pup(PUP::er &p);
673         
674         //Look up array element in hash table.  Index out-of-bounds if not found.
675         CkLocRec *elementRec(const CkArrayIndex &idx);
676         //Look up array element in hash table.  Return NULL if not there.
677         CkLocRec *elementNrec(const CkArrayIndex &idx);
678
679
680 private:
681 //Internal interface:
682         //Add given element array record at idx, replacing the existing record
683         void insertRec(CkLocRec *rec,const CkArrayIndex &idx);
684         //Add given record, when there is guarenteed to be no prior record
685         void insertRecN(CkLocRec *rec,const CkArrayIndex &idx);
686         //Insert a remote record at the given index
687         CkLocRec_remote *insertRemote(const CkArrayIndex &idx,int nowOnPe);
688
689         //Remove this entry from the table (does not delete record)
690         void removeFromTable(const CkArrayIndex &idx);
691
692         friend class CkLocation; //so it can call pupElementsFor
693         friend class ArrayElement;
694         friend class MemElementPacker;
695 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
696         void pupElementsFor(PUP::er &p,CkLocRec_local *rec,
697         CkElementCreation_t type, CmiBool create=CmiTrue, int dummy=0);
698 #else
699         void pupElementsFor(PUP::er &p,CkLocRec_local *rec,
700         CkElementCreation_t type,CmiBool rebuild = CmiFalse, CmiBool create=CmiTrue);
701 #endif
702         /// Call this member function on each element of this location:
703         typedef void (CkMigratable::* CkMigratable_voidfn_t)(void);
704
705         typedef void (CkMigratable::* CkMigratable_voidfn_arg_t)(void*);
706         void callMethod(CkLocRec_local *rec,CkMigratable_voidfn_arg_t fn, void*);
707
708         CmiBool deliverUnknown(CkArrayMessage *msg,CkDeliver_t type,int opts);
709
710         /// Create a new local record at this array index.
711 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
712 CkLocRec_local *createLocal(const CkArrayIndex &idx,
713         CmiBool forMigration, CmiBool ignoreArrival,
714         CmiBool notifyHome,int dummy=0);
715 #else
716         CkLocRec_local *createLocal(const CkArrayIndex &idx, 
717                 CmiBool forMigration, CmiBool ignoreArrival,
718                 CmiBool notifyHome);
719 #endif
720
721 public:
722         void callMethod(CkLocRec_local *rec,CkMigratable_voidfn_t fn);
723
724 //Data Members:
725         //Map array ID to manager and elements
726         class ManagerRec {
727         public:
728                 ManagerRec *next; //next non-null array manager
729                 CkArrMgr *mgr;
730                 CkMigratableList elts;
731                 ManagerRec() {
732                         next=NULL;
733                         mgr=NULL;
734                 }
735                 void init(void) { next=NULL; mgr=NULL; }
736                 CkMigratable *element(int localIdx) {
737                         return elts.get(localIdx);
738                 }
739         };
740         GroupIdxArray<ManagerRec *> managers;
741         int nManagers;
742         ManagerRec *firstManager; //First non-null array manager
743
744         CmiBool addElementToRec(CkLocRec_local *rec,ManagerRec *m,
745                 CkMigratable *elt,int ctorIdx,void *ctorMsg);
746
747         //For keeping track of free local indices
748         CkVec<int> freeList;//Linked list of free local indices
749         int firstFree;//First free local index
750         int localLen;//Last allocated local index plus one
751         int nextFree(void);
752
753         CProxy_CkLocMgr thisProxy;
754         CProxyElement_CkLocMgr thislocalproxy;
755         /// The core of the location manager: map array index to element representative
756         CkHashtableT<CkArrayIndex,CkLocRec *> hash;
757         CmiImmediateLockType hashImmLock;
758
759         /// This flag is set while we delete an old copy of a migrator
760         CmiBool duringMigration;
761
762         //Occasionally clear out stale remote pointers
763         static void staticSpringCleaning(void *mgr,double curWallTime);
764         void springCleaning(void);
765         int nSprings;
766
767         //Map object
768         CkGroupID mapID;
769         int mapHandle;
770         CkArrayMap *map;
771
772         CkGroupID lbdbID;
773         CkGroupID metalbID;
774 #if CMK_LBDB_ON
775         LBDatabase *the_lbdb;
776   MetaBalancer *the_metalb;
777         LDBarrierClient dummyBarrierHandle;
778         static void staticDummyResumeFromSync(void* data);
779         void dummyResumeFromSync(void);
780         static void staticRecvAtSync(void* data);
781         void recvAtSync(void);
782         LDOMHandle myLBHandle;
783 #endif
784         void initLB(CkGroupID lbdbID, CkGroupID metalbID);
785
786 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
787 public:
788         void callForAllRecords(CkLocFn,CkArray *,void *);
789         int homeElementCount;
790 #endif
791
792 };
793
794
795
796
797
798 /// check the command line arguments to determine if we can use ConfigurableRRMap
799 bool haveConfigurableRRMap();
800
801
802
803
804 /*@}*/
805
806 #endif /*def(thisHeader)*/