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