106bc93f37a500d20fd5e73e0414d0aca550cc29
[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   inline CkMemCheckPT *getChkpMgr(void) const {return the_chkp;} 
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   CkMemCheckPT * the_chkp;
242   LDObjHandle ldHandle;
243   CmiBool  asyncMigrate;  /// if readyMove is inited
244   CmiBool  readyMigrate;    /// status whether it is ready to migrate
245   CmiBool  enable_measure;
246   int  nextPe;              /// next migration dest processor
247 #else
248   void AsyncMigrate(CmiBool use){};
249 #endif
250 /**FAULT_EVAC*/
251 private:
252         CmiBool asyncEvacuate; //can the element be evacuated anytime, false for tcharm 
253         CmiBool bounced; //did this element try to immigrate into a processor which was evacuating
254                                                                                         // and was bounced away to some other processor. This is assumed to happen
255                                                                                         //only if this object was migrated by a load balancer, but the processor
256                                                                                         // started crashing soon after
257 public: 
258         CmiBool isAsyncEvacuate(){return asyncEvacuate;}
259         void AsyncEvacuate(CmiBool set){asyncEvacuate = set;}
260         CmiBool isBounced(){return bounced;}
261         void Bounced(CmiBool set){bounced = set;}
262 };
263 class CkLocRec_remote;
264
265 /*********************** CkMigratable ******************************/
266 /** This is the superclass of all migratable parallel objects.
267  *  Currently, that's just array elements.
268  */
269 #if CMK_OUT_OF_CORE
270 #  include "conv-ooc.h"
271 extern CooPrefetchManager CkArrayElementPrefetcher;
272 // If this flag is set, this creation/deletion is just 
273 //   a "fake" constructor/destructor call for prefetching.
274 CkpvExtern(int,CkSaveRestorePrefetch);
275 #endif
276
277 class CkMigratable : public Chare {
278 protected:
279   CkLocRec_local *myRec;
280 private:
281   int thisChareType;//My chare type
282   void commonInit(void);
283   CmiBool asyncEvacuate;
284   int atsync_iteration;
285   int atsync_chkp_iter;
286   int nextChkpIter; 
287   CkCallback chkp_cb;
288
289   enum state {
290     OFF,
291     ON,
292     PAUSE,
293     DECIDED,
294     LOAD_BALANCE
295   } local_state;
296   
297   bool local_chkp_pause;
298   bool nextChkpDecided;
299   double  prev_load;
300   bool can_reset;
301
302 public:
303   CkArrayIndex thisIndexMax;
304
305   CkMigratable(void);
306   CkMigratable(CkMigrateMessage *m);
307   virtual ~CkMigratable();
308   virtual void pup(PUP::er &p);
309   virtual void CkAddThreadListeners(CthThread tid, void *msg);
310
311   virtual int ckGetChareType(void) const;// {return thisChareType;}
312   const CkArrayIndex &ckGetArrayIndex(void) const {return myRec->getIndex();}
313
314 #if CMK_LBDB_ON  //For load balancing:
315   //Suspend load balancer measurements (e.g., before CthSuspend)
316   inline void ckStopTiming(void) {myRec->stopTiming();}
317   //Begin load balancer measurements again (e.g., after CthSuspend)
318   inline void ckStartTiming(void) {myRec->startTiming();}
319   inline LBDatabase *getLBDB(void) const {return myRec->getLBDB();}
320   inline MetaBalancer *getMetaBalancer(void) const {return myRec->getMetaBalancer();}
321 #else
322   inline void ckStopTiming(void) { }
323   inline void ckStartTiming(void) { }
324 #endif
325
326   /// for inline call
327   LDObjHandle timingBeforeCall(int *objstopped);
328   void timingAfterCall(LDObjHandle objHandle,int *objstopped);
329
330   //Initiate a migration to the given processor
331   inline void ckMigrate(int toPe) {myRec->migrateMe(toPe);}
332   
333   /// Called by the system just before and after migration to another processor:  
334   virtual void ckAboutToMigrate(void); /*default is empty*/
335   virtual void ckJustMigrated(void); /*default is empty*/
336
337   void recvLBPeriod(void *data);
338   void metaLBCallLB();
339   void clearMetaLBData(void);
340
341   //used for out-of-core emulation
342   virtual void ckJustRestored(void); /*default is empty*/
343
344   /// Delete this object
345   virtual void ckDestroy(void);
346
347   /// Execute the given entry method.  Returns false if the element 
348   /// deleted itself or migrated away during execution.
349   inline CmiBool ckInvokeEntry(int epIdx,void *msg,CmiBool doFree) 
350           {return myRec->invokeEntry(this,msg,epIdx,doFree);}
351
352 protected:
353   /// A more verbose form of abort
354   virtual void CkAbort(const char *str) const;
355
356   CmiBool usesAtSync;//You must set this in the constructor to use AtSync().
357   CmiBool usesAutoMeasure; //You must set this to use auto lb instrumentation.
358   CmiBool barrierRegistered;//True iff barrier handle below is set
359   CmiBool usesChkpAtSync;
360 public:
361   virtual void ResumeFromSync(void);
362   virtual void UserSetLBLoad(void);  /// user define this when setLBLoad is true
363   void setObjTime(double cputime);
364   double getObjTime();
365   CmiBool getChkpSync(){return usesChkpAtSync;}
366 #if CMK_LBDB_ON  //For load balancing:
367   
368   void AtSync(int waitForMigration=1);
369   int MigrateToPe()  { return myRec->MigrateToPe(); }
370
371 private: //Load balancer state:
372   LDBarrierClient ldBarrierHandle;//Transient (not migrated)  
373   LDBarrierReceiver ldBarrierRecvHandle;//Transient (not migrated)  
374   static void staticResumeFromSync(void* data);
375 public:
376   void ReadyMigrate(CmiBool ready);
377   void ckFinishConstruction(void);
378   void setMigratable(int migratable);
379 #else
380   void AtSync(int waitForMigration=1) { ResumeFromSync();}
381   void setMigratable(int migratable)  { }
382 public:
383   void ckFinishConstruction(void) { }
384 #endif
385
386   void AtChkpSync();
387   void resetForChkp();
388   void recvChkpIter(void * _iter);
389   void ResumeFromChkp();
390
391   void setChkpResumeClient(CkCallback &cb);
392 #if CMK_OUT_OF_CORE
393 private:
394   friend class CkLocMgr;
395   friend int CkArrayPrefetch_msg2ObjId(void *msg);
396   friend void CkArrayPrefetch_writeToSwap(FILE *swapfile,void *objptr);
397   friend void CkArrayPrefetch_readFromSwap(FILE *swapfile,void *objptr);
398   int prefetchObjID; //From CooRegisterObject
399   CmiBool isInCore; //If true, the object is present in memory
400 #endif
401
402   // FAULT_EVAC
403   void AsyncEvacuate(CmiBool set){myRec->AsyncEvacuate(set);asyncEvacuate = set;};
404 public:
405   CmiBool isAsyncEvacuate(){return asyncEvacuate;};
406 };
407
408 /** 
409  * Stores a list of array elements.  These lists are 
410  * kept by the array managers. 
411  */
412 class CkMigratableList {
413         CkVec< CkZeroPtr<CkMigratable> > el;
414  public:
415         CkMigratableList();
416         ~CkMigratableList();
417         
418         void setSize(int s);
419         inline int length(void) const {return el.length();}
420
421         /// Add an element at the given location
422         void put(CkMigratable *v,int atIdx);
423
424         /// Return the element at the given location
425         inline CkMigratable *get(int localIdx) {return el[localIdx];}
426
427         /**
428          * Return the next non-empty element starting from the given index,
429          * or NULL if there is none.  Updates from to point past the returned index.
430         */
431         CkMigratable *next(int &from) {
432                 while (from<length()) {
433                         CkMigratable *ret=el[from];
434                         from++;
435                         if (ret!=NULL) return ret;
436                 }
437                 return NULL;
438         }
439
440         /// Remove the element at the given location
441         inline void empty(int localIdx) {el[localIdx]=NULL;}
442 };
443
444 /**
445  *A typed version of the above.
446  */
447 template <class T>
448 class CkMigratableListT : public CkMigratableList {
449         typedef CkMigratableList super;
450 public:
451         inline void put(T *v,int atIdx) {super::put((CkMigratable *)v,atIdx);}
452         inline T *get(int localIdx) {return (T *)super::get(localIdx);}
453         inline T *next(int &from) {return (T *)super::next(from);}
454 };
455
456
457 /********************** CkLocMgr ********************/
458 /// A tiny class for detecting heap corruption
459 class CkMagicNumber_impl {
460  protected:
461         int magic;
462         void badMagicNumber(int expected,const char *file,int line,void *obj) const;
463         CkMagicNumber_impl(int m);
464 };
465 template<class T>
466 class CkMagicNumber : public CkMagicNumber_impl {
467         enum {good=sizeof(T)^0x7EDC0000};
468  public:
469         CkMagicNumber(void) :CkMagicNumber_impl(good) {}
470         inline void check(const char *file,int line,void *obj) const {
471                 if (magic!=good) badMagicNumber(good,file,line,obj);
472         }
473 #if CMK_ERROR_CHECKING
474 #   define CK_MAGICNUMBER_CHECK magic.check(__FILE__,__LINE__,this);
475 #else
476 #   define CK_MAGICNUMBER_CHECK /*empty, for speed*/
477 #endif
478 };
479
480 /**
481  * The "data" class passed to a CkLocIterator, which refers to a bound
482  * glob of array elements.
483  * This is a transient class-- do not attempt to store it or send 
484  * it across processors.
485  */
486
487         
488 class CkLocation {
489         CkLocMgr *mgr;
490         CkLocRec_local *rec;
491 public:
492         CkLocation(CkLocMgr *mgr_, CkLocRec_local *rec_);
493         CkLocation(){}
494         
495         /// Find our location manager
496         inline CkLocMgr *getManager(void) const {return mgr;}
497         
498         /// Find the local record that refers to this element
499         inline CkLocRec_local *getLocalRecord(void) const {return rec;}
500         
501         /// Look up and return the array index of this location.
502         const CkArrayIndex &getIndex(void) const;
503         
504         void destroyAll();
505
506         /// Pup all the array elements at this location.
507         void pup(PUP::er &p);
508 };
509
510 /**
511  * This interface describes the destination for an iterator over
512  * the locations in an array.
513  */
514 class CkLocIterator {
515 public:
516         virtual ~CkLocIterator();
517         
518         /// This location is part of the calling location manager.
519         virtual void addLocation(CkLocation &loc) =0;
520 };
521
522 enum CkElementCreation_t {
523   CkElementCreation_migrate=2, // Create object for normal migration arrival
524   CkElementCreation_resume=3,  // Create object after checkpoint
525   CkElementCreation_restore=4  // Create object after checkpoint, skip listeners
526 };
527 /// Abstract superclass of all array manager objects 
528 class CkArrMgr {
529 public:
530         virtual ~CkArrMgr() {}
531         /// Insert this initial element on this processor
532         virtual void insertInitial(const CkArrayIndex &idx,void *ctorMsg, int local=1)=0;
533         
534         /// Done with initial insertions
535         virtual void doneInserting(void)=0;
536         
537         /// Create an uninitialized element after migration
538         ///  The element's constructor will be called immediately after.
539         virtual CkMigratable *allocateMigrated(int elChareType,
540                 const CkArrayIndex &idx,CkElementCreation_t type) =0;
541
542         /// Demand-create an element at this index on this processor
543         ///  Returns true if the element was successfully added;
544         ///  false if the element migrated away or deleted itself.
545         virtual CmiBool demandCreateElement(const CkArrayIndex &idx,
546                 int onPe,int ctor,CkDeliver_t type) =0;
547 };
548
549
550 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
551 typedef void (*CkLocFn)(CkArray *,void *,CkLocRec *,CkArrayIndex *);
552 #endif
553
554
555 /**
556  * A group which manages the location of an indexed set of
557  * migratable objects.  Knows about insertions, deletions,
558  * home processors, migration, and message forwarding.
559  */
560 class CkLocMgr : public IrrGroup {
561         CkMagicNumber<CkMigratable> magic; //To detect heap corruption
562 public:
563         CkLocMgr(CkGroupID map,CkGroupID _lbdb,CkGroupID _metalb,CkArrayIndex& numInitial);
564         CkLocMgr(CkGroupID map,CkGroupID _lbdb,CkArrayIndex& numInitial);
565         CkLocMgr(CkMigrateMessage *m);
566         inline CmiBool isLocMgr(void) { return CmiTrue; }
567         CkGroupID &getGroupID(void) {return thisgroup;}
568         inline CProxy_CkLocMgr &getProxy(void)
569                 {return thisProxy;}
570         inline CProxyElement_CkLocMgr &getLocalProxy(void)
571                 {return thislocalproxy;}
572
573 //Interface used by array manager and proxies
574         /// Add a new local array manager to our list.  Array managers
575         ///  must be registered in the same order on all processors.
576         /// Returns a list which will contain that array's local elements
577         CkMigratableList *addManager(CkArrayID aid,CkArrMgr *mgr);
578
579         /// Populate this array with initial elements
580         void populateInitial(CkArrayIndex& numElements,void *initMsg,CkArrMgr *mgr)
581                 {map->populateInitial(mapHandle,numElements,initMsg,mgr);}
582
583         /// Add a new local array element, calling element's constructor
584         ///  Returns true if the element was successfully added;
585         ///  false if the element migrated away or deleted itself.
586         CmiBool addElement(CkArrayID aid,const CkArrayIndex &idx,
587                 CkMigratable *elt,int ctorIdx,void *ctorMsg);
588
589         ///Deliver message to this element:
590         inline void deliverViaQueue(CkMessage *m) {deliver(m,CkDeliver_queue);}
591         inline void deliverInline(CkMessage *m) {deliver(m,CkDeliver_inline);}
592         int deliver(CkMessage *m, CkDeliver_t type, int opts=0);
593
594         ///Done inserting elements for now
595         void doneInserting(void);
596         void startInserting(void);
597
598         // How many elements of each associated array are local to this PE?
599         // If this returns n, and there are k associated arrays, that
600         // means k*n elements are living here
601         unsigned int numLocalElements();
602
603 //Advisories:
604         ///This index now lives on the given processor-- update local records
605         void inform(const CkArrayIndex &idx,int nowOnPe);
606
607         ///This index now lives on the given processor-- tell the home processor
608         void informHome(const CkArrayIndex &idx,int nowOnPe);
609
610         ///This message took several hops to reach us-- fix it
611         void multiHop(CkArrayMessage *m);
612
613 //Interface used by CkLocRec_local
614         //Look up the object with this local index
615         inline CkMigratable *lookupLocal(int localIdx,CkArrayID arrayID) {
616 #if CMK_ERROR_CHECKING
617                 if (managers.find(arrayID)->mgr==NULL)
618                         CkAbort("CkLocMgr::lookupLocal called for unknown array!\n");
619 #endif
620                 return managers.find(arrayID)->elts.get(localIdx);
621         }
622
623         //Migrate us to another processor
624         void emigrate(CkLocRec_local *rec,int toPe);
625   void informLBPeriod(CkLocRec_local *rec, int lb_ideal_period);
626   void metaLBCallLB(CkLocRec_local *rec);
627   CkMemCheckPT * getChkpMgr(void) const{return the_chkp;}
628 #if CMK_LBDB_ON
629         LBDatabase *getLBDB(void) const { return the_lbdb; }
630   MetaBalancer *getMetaBalancer(void) const { return the_metalb;}
631         const LDOMHandle &getOMHandle(void) const { return myLBHandle; }
632 #endif
633
634         //This index will no longer be used-- delete the associated elements
635         void reclaim(const CkArrayIndex &idx,int localIdx);
636
637         int getSpringCount(void) const { return nSprings; }
638
639         CmiBool demandCreateElement(CkArrayMessage *msg,int onPe,CkDeliver_t type);
640
641 //Interface used by external users:
642         /// Home mapping
643         inline int homePe(const CkArrayIndex &idx) const
644                 {return map->homePe(mapHandle,idx);}
645         inline int procNum(const CkArrayIndex &idx) const
646                 {return map->procNum(mapHandle,idx);}
647         inline CmiBool isHome(const CkArrayIndex &idx) const
648                 {return (CmiBool)(homePe(idx)==CkMyPe());}
649
650         /// Look up the object with this array index, or return NULL
651         CkMigratable *lookup(const CkArrayIndex &idx,CkArrayID aid);
652
653         /// Return the "last-known" location (returns a processor number)
654         int lastKnown(const CkArrayIndex &idx);
655
656         /// Return true if this array element lives on another processor
657         bool isRemote(const CkArrayIndex &idx,int *onPe) const;
658
659 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
660         //mark the duringMigration variable .. used for parallel restart
661         void setDuringMigration(CmiBool _duringMigration);
662 #endif
663
664         /// Pass each of our locations (each separate array index) to this destination.
665         void iterate(CkLocIterator &dest);
666         
667         void iterateChkpSync(CkLocIterator &dest);
668
669         /// Insert and unpack this array element from this checkpoint (e.g., from CkLocation::pup), skip listeners
670         void restore(const CkArrayIndex &idx, PUP::er &p);
671         /// Insert and unpack this array element from this checkpoint (e.g., from CkLocation::pup)
672 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
673         void resume(const CkArrayIndex &idx, PUP::er &p, CmiBool create, int dummy=0);
674 #else
675         void resume(const CkArrayIndex &idx, PUP::er &p, CmiBool notify=CmiTrue,CmiBool rebuild=CmiFalse,CmiBool create = CmiTrue);
676 #endif
677
678 //Communication:
679         void immigrate(CkArrayElementMigrateMessage *msg);
680         void updateLocation(const CkArrayIndex &idx,int nowOnPe);
681         void reclaimRemote(const CkArrayIndex &idx,int deletedOnPe);
682         void dummyAtSync(void);
683
684         /// return a list of migratables in this local record
685         void migratableList(CkLocRec_local *rec, CkVec<CkMigratable *> &list);
686
687         void flushAllRecs(void);
688         void flushLocalRecs(void);
689         void recvChkpIter(int iter);
690         void resumeFromChkp();
691         void pup(PUP::er &p);
692         
693         //Look up array element in hash table.  Index out-of-bounds if not found.
694         CkLocRec *elementRec(const CkArrayIndex &idx);
695         //Look up array element in hash table.  Return NULL if not there.
696         CkLocRec *elementNrec(const CkArrayIndex &idx);
697
698
699 private:
700 //Internal interface:
701         //Add given element array record at idx, replacing the existing record
702         void insertRec(CkLocRec *rec,const CkArrayIndex &idx);
703         //Add given record, when there is guarenteed to be no prior record
704         void insertRecN(CkLocRec *rec,const CkArrayIndex &idx);
705         //Insert a remote record at the given index
706         CkLocRec_remote *insertRemote(const CkArrayIndex &idx,int nowOnPe);
707
708         //Remove this entry from the table (does not delete record)
709         void removeFromTable(const CkArrayIndex &idx);
710
711         friend class CkLocation; //so it can call pupElementsFor
712         friend class ArrayElement;
713         friend class MemElementPacker;
714 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
715         void pupElementsFor(PUP::er &p,CkLocRec_local *rec,
716         CkElementCreation_t type, CmiBool create=CmiTrue, int dummy=0);
717 #else
718         void pupElementsFor(PUP::er &p,CkLocRec_local *rec,
719         CkElementCreation_t type,CmiBool rebuild = CmiFalse, CmiBool create=CmiTrue);
720 #endif
721         /// Call this member function on each element of this location:
722         typedef void (CkMigratable::* CkMigratable_voidfn_t)(void);
723
724         typedef void (CkMigratable::* CkMigratable_voidfn_arg_t)(void*);
725         void callMethod(CkLocRec_local *rec,CkMigratable_voidfn_arg_t fn, void*);
726
727         CmiBool deliverUnknown(CkArrayMessage *msg,CkDeliver_t type,int opts);
728
729         /// Create a new local record at this array index.
730 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
731 CkLocRec_local *createLocal(const CkArrayIndex &idx,
732         CmiBool forMigration, CmiBool ignoreArrival,
733         CmiBool notifyHome,int dummy=0);
734 #else
735         CkLocRec_local *createLocal(const CkArrayIndex &idx, 
736                 CmiBool forMigration, CmiBool ignoreArrival,
737                 CmiBool notifyHome);
738 #endif
739
740 public:
741         void callMethod(CkLocRec_local *rec,CkMigratable_voidfn_t fn);
742
743 //Data Members:
744         //Map array ID to manager and elements
745         class ManagerRec {
746         public:
747                 ManagerRec *next; //next non-null array manager
748                 CkArrMgr *mgr;
749                 CkMigratableList elts;
750                 ManagerRec() {
751                         next=NULL;
752                         mgr=NULL;
753                 }
754                 void init(void) { next=NULL; mgr=NULL; }
755                 CkMigratable *element(int localIdx) {
756                         return elts.get(localIdx);
757                 }
758         };
759         GroupIdxArray<ManagerRec *> managers;
760         int nManagers;
761         ManagerRec *firstManager; //First non-null array manager
762
763         CmiBool addElementToRec(CkLocRec_local *rec,ManagerRec *m,
764                 CkMigratable *elt,int ctorIdx,void *ctorMsg);
765
766         //For keeping track of free local indices
767         CkVec<int> freeList;//Linked list of free local indices
768         int firstFree;//First free local index
769         int localLen;//Last allocated local index plus one
770         int nextFree(void);
771
772         CProxy_CkLocMgr thisProxy;
773         CProxyElement_CkLocMgr thislocalproxy;
774         /// The core of the location manager: map array index to element representative
775         CkHashtableT<CkArrayIndex,CkLocRec *> hash;
776         CmiImmediateLockType hashImmLock;
777
778         /// This flag is set while we delete an old copy of a migrator
779         CmiBool duringMigration;
780
781         //Occasionally clear out stale remote pointers
782         static void staticSpringCleaning(void *mgr,double curWallTime);
783         void springCleaning(void);
784         int nSprings;
785
786         //Map object
787         CkGroupID mapID;
788         int mapHandle;
789         CkArrayMap *map;
790
791         CkGroupID lbdbID;
792         CkGroupID metalbID;
793         CkGroupID chkpID;
794
795         CkMemCheckPT * the_chkp;
796 #if CMK_LBDB_ON
797         LBDatabase *the_lbdb;
798   MetaBalancer *the_metalb;
799         LDBarrierClient dummyBarrierHandle;
800         static void staticDummyResumeFromSync(void* data);
801         void dummyResumeFromSync(void);
802         static void staticRecvAtSync(void* data);
803         void recvAtSync(void);
804         LDOMHandle myLBHandle;
805 #endif
806         void initLB(CkGroupID lbdbID, CkGroupID metalbID);
807
808 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
809 public:
810         void callForAllRecords(CkLocFn,CkArray *,void *);
811         int homeElementCount;
812 #endif
813
814 };
815
816
817
818
819
820 /// check the command line arguments to determine if we can use ConfigurableRRMap
821 bool haveConfigurableRRMap();
822
823
824
825
826 /*@}*/
827
828 #endif /*def(thisHeader)*/