fix for migration
[charm.git] / src / ck-core / cklocation.C
index ecd3dc6936a32ef33ee3b26c51ca367c5be4010f..97602046eedd00641cb48d8f35eac00810116856 100644 (file)
 #include "ck.h"
 #include "trace.h"
 #include "TopoManager.h"
-
+#include <vector>
 #include<sstream>
 
 #if CMK_LBDB_ON
 #include "LBDatabase.h"
+#include "MetaBalancer.h"
 #if CMK_GLOBAL_LOCATION_UPDATE
 #include "BaseLB.h"
+#include "init.h"
 #endif
 #endif // CMK_LBDB_ON
 
@@ -45,6 +47,7 @@ static const char *idx2str(const CkArrayMessage *m) {
 #   define AA "LocMgr on %d: "
 #   define AB ,CkMyPe()
 #   define DEBUG(x) CkPrintf x
+#   define DEBAD(x) CkPrintf x
 #else
 #   define DEB(X) /*CkPrintf x*/
 #   define DEBI(X) /*CkPrintf x*/
@@ -56,6 +59,7 @@ static const char *idx2str(const CkArrayMessage *m) {
 #   define DEBB(x) /*CkPrintf x*/
 #   define str(x) /**/
 #   define DEBUG(x)   /**/
+#   define DEBAD(x) /*CkPrintf x*/
 #endif
 
 //whether to use block mapping in the SMP node level
@@ -89,6 +93,7 @@ LDObjid idx2LDObjid(const CkArrayIndex &idx)
 #if CMK_GLOBAL_LOCATION_UPDATE
   r.dimension = idx.dimension;
   r.nInts = idx.nInts; 
+  r.isArrayElement = 1; 
 #endif
 
   return r;
@@ -97,6 +102,10 @@ LDObjid idx2LDObjid(const CkArrayIndex &idx)
 #if CMK_GLOBAL_LOCATION_UPDATE
 void UpdateLocation(MigrateInfo& migData) {
 
+  if (migData.obj.id.isArrayElement == 0) {
+    return;
+  }
+
   CkArrayIndex idx; 
   idx.dimension = migData.obj.id.dimension; 
   idx.nInts = migData.obj.id.nInts; 
@@ -105,8 +114,9 @@ void UpdateLocation(MigrateInfo& migData) {
     idx.data()[i] = migData.obj.id.id[i];    
   }
 
-  CkLocMgr *localLocMgr = 
-    (CkLocMgr *) CkLocalBranch(migData.obj.omhandle.id.id); 
+  CkGroupID locMgrGid;
+  locMgrGid.idx = migData.obj.id.locMgrGid;
+  CkLocMgr *localLocMgr = (CkLocMgr *) CkLocalBranch(locMgrGid);
   localLocMgr->updateLocation(idx, migData.to_pe); 
 }
 #endif
@@ -1040,7 +1050,19 @@ void CkMigratable::commonInit(void) {
        thisChareType=i.chareType;
        usesAtSync=CmiFalse;
        usesAutoMeasure=CmiTrue;
+       usesChkpAtSync = CmiFalse;
        barrierRegistered=CmiFalse;
+
+  local_state = OFF;
+  prev_load = 0.0;
+  can_reset = false;
+
+#if CMK_LBDB_ON
+  if (_lb_args.metaLbOn()) {
+    atsync_iteration = myRec->getMetaBalancer()->get_iteration();
+  }
+#endif
+
        /*
        FAULT_EVAC
        */
@@ -1062,10 +1084,12 @@ void CkMigratable::pup(PUP::er &p) {
        Chare::pup(p);
        p|thisIndexMax;
        p(usesAtSync);
+  p(can_reset);
+    p(usesChkpAtSync);
        p(usesAutoMeasure);
 #if CMK_LBDB_ON 
        int readyMigrate;
-       if (p.isPacking()) readyMigrate = myRec->isReadyMigrate();
+       if (p.isPacking()||p.isCalChecking()) readyMigrate = myRec->isReadyMigrate();
        p|readyMigrate;
        if (p.isUnpacking()) myRec->ReadyMigrate(readyMigrate);
 #endif
@@ -1076,6 +1100,13 @@ void CkMigratable::pup(PUP::er &p) {
        p | asyncEvacuate;
        if(p.isUnpacking()){myRec->AsyncEvacuate(asyncEvacuate);}
        
+       if(p.isUnpacking()){
+         atsync_chkp_iter = -1;
+       }
+       if(p.isUnpacking()){
+               resetForChkp();
+       }
+
        ckFinishConstruction();
 }
 
@@ -1106,6 +1137,7 @@ CkMigratable::~CkMigratable() {
 #if CMK_LBDB_ON 
        if (barrierRegistered) {
          DEBL((AA"Removing barrier for element %s\n"AB,idx2str(thisIndexMax)));
+         //CkPrintf("Removing barrier for element %s\n",idx2str(thisIndexMax));
          if (usesAtSync)
                myRec->getLBDB()->RemoveLocalBarrierClient(ldBarrierHandle);
          else
@@ -1140,12 +1172,55 @@ double CkMigratable::getObjTime() {
        return myRec->getObjTime();
 }
 
+void CkMigratable::clearMetaLBData() {
+//  if (can_reset) {
+    local_state = OFF;
+    atsync_iteration = -1;
+    prev_load = 0.0;
+    can_reset = false;
+//  }
+}
+
+void CkMigratable::recvLBPeriod(void *data) {
+  if (atsync_iteration < 0) {
+    return;
+  }
+  int lb_period = *((int *) data);
+ DEBAD(("\t[obj %s] Received the LB Period %d current iter %d state %d on PE %d\n",
+     idx2str(thisIndexMax), lb_period, atsync_iteration, local_state, CkMyPe()));
+
+  bool is_tentative;
+  if (local_state == LOAD_BALANCE) {
+    CkAssert(lb_period == myRec->getMetaBalancer()->getPredictedLBPeriod(is_tentative));
+    return;
+  }
+
+  if (local_state == PAUSE) {
+    if (atsync_iteration < lb_period) {
+      local_state = DECIDED;
+      ResumeFromSync();
+      return;
+    }
+    local_state = LOAD_BALANCE;
+
+    can_reset = true;
+    //myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
+    return;
+  }
+  local_state = DECIDED;
+}
+
+void CkMigratable::metaLBCallLB() {
+       myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
+}
+
 void CkMigratable::ckFinishConstruction(void)
 {
 //     if ((!usesAtSync) || barrierRegistered) return;
        myRec->setMeasure(usesAutoMeasure);
        if (barrierRegistered) return;
        DEBL((AA"Registering barrier client for %s\n"AB,idx2str(thisIndexMax)));
+       //CkPrintf("Registering barrier client for %s\n",idx2str(thisIndexMax));
         if (usesAtSync)
          ldBarrierHandle = myRec->getLBDB()->AddLocalBarrierClient(
                (LDBarrierFn)staticResumeFromSync,(void*)(this));
@@ -1154,6 +1229,98 @@ void CkMigratable::ckFinishConstruction(void)
                (LDBarrierFn)staticResumeFromSync,(void*)(this));
        barrierRegistered=CmiTrue;
 }
+
+
+void CkMigratable::setChkpResumeClient(CkCallback & _cb)
+{
+        //if(CmiMyPartition()==1){
+          CkPrintf("[%d] setChkpResumeClient\n",CkMyPe());
+        //}
+       chkp_cb = _cb;
+       nextChkpIter = -1;
+       nextChkpDecided = false;
+       atsync_chkp_iter = -1;
+       local_chkp_pause = false;
+       usesChkpAtSync = CmiTrue;
+}
+
+void CkMigratable::AtChkpSync()
+{
+       if(usesChkpAtSync){
+         if(CkMyPe()==0){
+//         CkPrintf("at chkp sync\n");
+         }
+               if(CmiNumPartition()==1){
+                       chkp_cb.send();
+                       return;
+               }
+               atsync_chkp_iter++;
+               myRec->getChkpMgr()->recvIter(atsync_chkp_iter);
+               //reduction to decide the current maximum
+               if(nextChkpDecided){
+                       if(atsync_chkp_iter<nextChkpIter){
+                               chkp_cb.send();
+                       }else if(atsync_chkp_iter == nextChkpIter){
+                               resetForChkp();
+                               myRec->getChkpMgr()->reachChkpIter();
+                       }else{
+                               CkAbort("Impossible state\n");
+                       }
+               }
+               else if(myRec->getChkpMgr()->localDecided){
+                       int localIter = myRec->getChkpMgr()->localMaxIter;
+                       if(atsync_chkp_iter==localIter){
+                               local_chkp_pause = true;
+                       }
+                       else if(atsync_chkp_iter<localIter){
+                               chkp_cb.send();
+                       }
+                       else{
+                               CkAbort("local Impossible state\n");
+                       }
+               }       
+               else{
+                       chkp_cb.send();
+               }
+       }
+}
+
+void CkMigratable::resetForChkp(){
+       nextChkpDecided = false;
+       local_chkp_pause = false;
+}
+
+void CkMigratable::ResumeFromChkp(){
+       
+       if(usesChkpAtSync&&!chkp_cb.isInvalid()){
+               chkp_cb.send();
+       }
+}
+
+void CkMigratable::recvChkpIter(void * _iter){
+       if(usesChkpAtSync){
+               int iter = *(int *)_iter;
+               nextChkpIter = iter;
+               nextChkpDecided = true;
+               //if(CkMyPe()==0){
+               //  CkPrintf("receive chkp iter %d %d\n",atsync_chkp_iter, nextChkpIter);
+               //}
+               if(atsync_chkp_iter>nextChkpIter){
+                       CkAbort("impossible state in notify\n");
+               }
+               else if(atsync_chkp_iter==nextChkpIter){
+                       resetForChkp();
+                       myRec->getChkpMgr()->reachChkpIter();
+               }
+               else{
+                       if(local_chkp_pause){
+                               if(!chkp_cb.isInvalid())
+                                       chkp_cb.send(); 
+                       }
+               }
+       }
+}
+
 void CkMigratable::AtSync(int waitForMigration)
 {
        if (!usesAtSync)
@@ -1164,11 +1331,59 @@ void CkMigratable::AtSync(int waitForMigration)
        myRec->AsyncMigrate(!waitForMigration);
        if (waitForMigration) ReadyMigrate(CmiTrue);
        ckFinishConstruction();
-       DEBL((AA"Element %s going to sync\n"AB,idx2str(thisIndexMax)));
-          // model-based load balancing, ask user to provide cpu load
-        if (usesAutoMeasure == CmiFalse) UserSetLBLoad();
-       myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
+  //DEBL((AA"Element %s going to sync\n"AB,idx2str(thisIndexMax)));
+  //if(CmiMyPartition()==1)
+//     CkPrintf("Element %s going to sync\n",idx2str(thisIndexMax));
+  // model-based load balancing, ask user to provide cpu load
+  if (usesAutoMeasure == CmiFalse) UserSetLBLoad();
+
+  if (!_lb_args.metaLbOn()) {
+    myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
+    return;
+  }
+
+  // When MetaBalancer is turned on
+
+  if (atsync_iteration == -1) {
+    can_reset = false;
+    local_state = OFF;
+    prev_load = 0.0;
+  }
+
+  atsync_iteration++;
+  //CkPrintf("[pe %s] atsync_iter %d && predicted period %d state: %d\n",
+  //    idx2str(thisIndexMax), atsync_iteration,
+  //    myRec->getMetaBalancer()->getPredictedLBPeriod(), local_state);
+  double tmp = prev_load;
+  prev_load = myRec->getObjTime();
+  double current_load = prev_load - tmp;
+  if (atsync_iteration <= myRec->getMetaBalancer()->get_finished_iteration()) {
+    CkPrintf("[%d:%s] Error!! Contributing to iter %d < current iter %d\n",
+      CkMyPe(), idx2str(thisIndexMax), atsync_iteration,
+      myRec->getMetaBalancer()->get_finished_iteration());
+    CkAbort("Not contributing to the right iteration\n");
+  }
+
+  if (atsync_iteration != 0) {
+    myRec->getMetaBalancer()->AddLoad(atsync_iteration, current_load);
+  }
+
+  bool is_tentative;
+  if (atsync_iteration < myRec->getMetaBalancer()->getPredictedLBPeriod(is_tentative)) {
+    ResumeFromSync();
+  } else if (is_tentative) {
+    local_state = PAUSE;
+  } else if (local_state == DECIDED) {
+    DEBAD(("[%d:%s] Went to load balance iter %d\n", CkMyPe(), idx2str(thisIndexMax), atsync_iteration));
+    local_state = LOAD_BALANCE;
+    can_reset = true;
+    //myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
+  } else {
+    DEBAD(("[%d:%s] Went to pause state iter %d\n", CkMyPe(), idx2str(thisIndexMax), atsync_iteration));
+    local_state = PAUSE;
+  }
 }
+
 void CkMigratable::ReadyMigrate(CmiBool ready)
 {
        myRec->ReadyMigrate(ready);
@@ -1190,6 +1405,10 @@ void CkMigratable::staticResumeFromSync(void* data)
 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
     CpvAccess(_currentObj) = el;
 #endif
+
+  if (_lb_args.metaLbOn()) {
+       el->clearMetaLBData();
+       }
        el->ResumeFromSync();
 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
     el->mlogData->resumeCount++;
@@ -1301,8 +1520,14 @@ CkLocRec_local::CkLocRec_local(CkLocMgr *mgr,CmiBool fromMigration,
         enable_measure = CmiTrue;
        bounced  = CmiFalse;
        the_lbdb=mgr->getLBDB();
+       the_metalb=mgr->getMetaBalancer();
+       the_chkp = mgr->getChkpMgr();
+       LDObjid ldid = idx2LDObjid(idx);
+#if CMK_GLOBAL_LOCATION_UPDATE
+        ldid.locMgrGid = mgr->getGroupID().idx;
+#endif        
        ldHandle=the_lbdb->RegisterObj(mgr->getOMHandle(),
-               idx2LDObjid(idx),(void *)this,1);
+               ldid,(void *)this,1);
        if (fromMigration) {
                DEBL((AA"Element %s migrated in\n"AB,idx2str(idx)));
                if (!ignoreArrival)  {
@@ -1312,6 +1537,7 @@ CkLocRec_local::CkLocRec_local(CkLocMgr *mgr,CmiBool fromMigration,
                }
        }
 #endif
+       the_chkp = mgr->getChkpMgr();
        /*
                FAULT_EVAC
        */
@@ -1335,6 +1561,14 @@ void CkLocRec_local::migrateMe(int toPe) //Leaving this processor
 }
 
 #if CMK_LBDB_ON
+void CkLocRec_local::informIdealLBPeriod(int lb_ideal_period) {
+  myLocMgr->informLBPeriod(this, lb_ideal_period);
+}
+
+void CkLocRec_local::metaLBCallLB() {
+       myLocMgr->metaLBCallLB(this);
+}
+
 void CkLocRec_local::startTiming(int ignore_running) {
        if (!ignore_running) running=CmiTrue;
        DEBL((AA"Start timing for %s at %.3fs {\n"AB,idx2str(idx),CkWallTimer()));
@@ -1552,6 +1786,27 @@ CmiBool CkLocRec_local::deliver(CkArrayMessage *msg,CkDeliver_t type,int opts)
 }
 
 #if CMK_LBDB_ON
+
+void CkLocRec_local::staticMetaLBResumeWaitingChares(LDObjHandle h, int lb_ideal_period) {
+       CkLocRec_local *el=(CkLocRec_local *)LDObjUserData(h);
+       DEBL((AA"MetaBalancer wants to resume waiting chare %s\n"AB,idx2str(el->idx)));
+       el->metaLBResumeWaitingChares(lb_ideal_period);
+}
+
+void CkLocRec_local::metaLBResumeWaitingChares(int lb_ideal_period) {
+  informIdealLBPeriod(lb_ideal_period);
+}
+
+void CkLocRec_local::staticMetaLBCallLBOnChares(LDObjHandle h) {
+       CkLocRec_local *el=(CkLocRec_local *)LDObjUserData(h);
+       DEBL((AA"MetaBalancer wants to call LoadBalance on chare %s\n"AB,idx2str(el->idx)));
+       el->metaLBCallLBOnChares();
+}
+
+void CkLocRec_local::metaLBCallLBOnChares() {
+  metaLBCallLB();
+}
+
 void CkLocRec_local::staticMigrate(LDObjHandle h, int dest)
 {
        CkLocRec_local *el=(CkLocRec_local *)LDObjUserData(h);
@@ -1833,6 +2088,7 @@ inline void CkLocMgr::springCleaning(void)
     if (rec->isObsolete(nSprings,idx)) {
       //This record is obsolete-- remove it from the table
       DEBK((AA"Cleaning out old record %s\n"AB,idx2str(idx)));
+      //CkPrintf("[%d][%d]Cleaning out old record %s\n",CmiMyPartition(),CkMyPe(),idx2str(idx));
       hash.remove(*(CkArrayIndex *)&idx);
       delete rec;
       it->seek(-1);//retry this hash slot
@@ -1845,13 +2101,73 @@ void CkLocMgr::staticSpringCleaning(void *forWhom,double curWallTime) {
        DEBK((AA"Starting spring cleaning at %.2f\n"AB,CkWallTimer()));
        ((CkLocMgr *)forWhom)->springCleaning();
 }
+static const char *rec2str[]={
+    "base (INVALID)",//Base class (invalid type)
+    "local",//Array element that lives on this Pe
+    "remote",//Array element that lives on some other Pe
+    "buffering",//Array element that was just created
+    "dead"//Deleted element (for debugging)
+};
+
+//doesn't delete if there is extra pe
+void CkLocMgr::flushLocalRecs(void)
+{
+  void *objp;
+  void *keyp;
+  CkHashtableIterator *it=localHash.iterator();
+  CmiImmediateLock(hashImmLock);
+  while (NULL!=(objp=it->next(&keyp))) {
+    CkLocRec *rec=*(CkLocRec **)objp;
+    CkArrayIndex &idx=*(CkArrayIndex *)keyp;
+    //if(CmiMyPartition()==1)
+      //CkPrintf("[%d][%d] flush home object %s %p %p\n",CmiMyPartition(),CkMyPe(),idx2str(idx),rec,hash.get(*(CkArrayIndex *)&idx));
+    if (rec->type() == CkLocRec::local) {
+        callMethod((CkLocRec_local*)rec, &CkMigratable::ckDestroy);
+        it->seek(-1);//retry this hash slot
+    }
+  }
+  delete it;
+  CmiImmediateUnlock(hashImmLock);
+}
+
+void CkLocMgr::recvChkpIter(int iter)
+{
+  void *objp;
+  void *keyp;
+  CkHashtableIterator *it=localHash.iterator();
+  CmiImmediateLock(hashImmLock);
+  while (NULL!=(objp=it->next(&keyp))) {
+    CkLocRec *rec=*(CkLocRec **)objp;
+    CkArrayIndex &idx=*(CkArrayIndex *)keyp;
+    if (rec->type() == CkLocRec::local) {
+        callMethod((CkLocRec_local*)rec, &CkMigratable::recvChkpIter,&iter);
+    }
+  }
+  delete it;
+  CmiImmediateUnlock(hashImmLock);
+}
+
+void CkLocMgr::resumeFromChkp(){
+  void *objp;
+  void *keyp;
+  CkHashtableIterator *it=localHash.iterator();
+  CmiImmediateLock(hashImmLock);
+  while (NULL!=(objp=it->next(&keyp))) {
+    CkLocRec *rec=*(CkLocRec **)objp;
+    CkArrayIndex &idx=*(CkArrayIndex *)keyp;
+    if (rec->type() == CkLocRec::local) {
+        callMethod((CkLocRec_local*)rec, &CkMigratable::ResumeFromChkp);
+    }
+  }
+  delete it;
+  CmiImmediateUnlock(hashImmLock);
+}
 
 // clean all buffer'ed messages and also free local objects
 void CkLocMgr::flushAllRecs(void)
 {
   void *objp;
   void *keyp;
-    
   CkHashtableIterator *it=hash.iterator();
   CmiImmediateLock(hashImmLock);
   while (NULL!=(objp=it->next(&keyp))) {
@@ -1861,8 +2177,9 @@ void CkLocMgr::flushAllRecs(void)
       //In the case of taking core out of memory (in BigSim's emulation)
       //the meta data in the location manager are not deleted so we need
       //this condition
+      
       if(_BgOutOfCoreFlag!=1){
-        hash.remove(*(CkArrayIndex *)&idx);
+       hash.remove(*(CkArrayIndex *)&idx);
         delete rec;
         it->seek(-1);//retry this hash slot
       }
@@ -1876,6 +2193,7 @@ void CkLocMgr::flushAllRecs(void)
   CmiImmediateUnlock(hashImmLock);
 }
 
+
 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
 void CkLocMgr::callForAllRecords(CkLocFn fnPointer,CkArray *arr,void *data){
        void *objp;
@@ -1894,7 +2212,7 @@ void CkLocMgr::callForAllRecords(CkLocFn fnPointer,CkArray *arr,void *data){
 #endif
 
 /*************************** LocMgr: CREATION *****************************/
-CkLocMgr::CkLocMgr(CkGroupID mapID_,CkGroupID lbdbID_,CkArrayIndex& numInitial)
+CkLocMgr::CkLocMgr(CkGroupID mapID_,CkGroupID lbdbID_,CkGroupID metalbID_,CkArrayIndex& numInitial)
        :thisProxy(thisgroup),thislocalproxy(thisgroup,CkMyPe()),
         hash(17,0.3)
 {
@@ -1920,10 +2238,24 @@ CkLocMgr::CkLocMgr(CkGroupID mapID_,CkGroupID lbdbID_,CkArrayIndex& numInitial)
 
 //Find and register with the load balancer
        lbdbID = lbdbID_;
-       initLB(lbdbID_);
+  metalbID = metalbID_;
+       initLB(lbdbID_, metalbID_);
        hashImmLock = CmiCreateImmediateLock();
+       chkpID = ckCheckPTGroupID;
+       the_chkp = (CkMemCheckPT *)CkLocalBranch(chkpID);
 }
 
+CkLocMgr::CkLocMgr(CkGroupID mapID_,CkGroupID lbdbID_,CkArrayIndex& numInitial)
+       :thisProxy(thisgroup),thislocalproxy(thisgroup,CkMyPe()),
+        hash(17,0.3)
+{
+#if !CMK_LBDB_ON
+       CkGroupID _metalb;
+#endif
+       CkLocMgr(mapID_, lbdbID_, _metalb, numInitial);
+}
+
+
 CkLocMgr::CkLocMgr(CkMigrateMessage* m)
        :IrrGroup(m),thisProxy(thisgroup),thislocalproxy(thisgroup,CkMyPe()),hash(17,0.3)
 {
@@ -1944,6 +2276,8 @@ void CkLocMgr::pup(PUP::er &p){
        p|mapID;
        p|mapHandle;
        p|lbdbID;
+  p|metalbID;
+   p|chkpID;
        mapID = _defaultArrayMapID;
        if(p.isUnpacking()){
                thisProxy=thisgroup;
@@ -1955,20 +2289,21 @@ void CkLocMgr::pup(PUP::er &p){
                 CkArrayIndex emptyIndex;
                map->registerArray(emptyIndex,thisgroup);
                // _lbdb is the fixed global groupID
-               initLB(lbdbID);
-
-#if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))     
+               initLB(lbdbID, metalbID);
+               the_chkp = (CkMemCheckPT *)CkLocalBranch(chkpID);
+#if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_)) ||CMK_MEM_CHECKPOINT    
         int count;
         p | count;
         DEBUG(CmiPrintf("[%d] Unpacking Locmgr %d has %d home elements\n",CmiMyPe(),thisgroup.idx,count));
+#if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))    
         homeElementCount = count;
-
+#endif
         for(int i=0;i<count;i++){
             CkArrayIndex idx;
             int pe;
             idx.pup(p);
             p | pe;
-            DEBUG(CmiPrintf("[%d] idx %s is a home element exisiting on pe %d\n",CmiMyPe(),idx2str(idx),pe));
+  //          CmiPrintf("[%d] idx %s is a home element exisiting on pe %d\n",CmiMyPe(),idx2str(idx),pe);
             inform(idx,pe);
             CkLocRec *rec = elementNrec(idx);
             CmiAssert(rec!=NULL);
@@ -1986,27 +2321,43 @@ void CkLocMgr::pup(PUP::er &p){
  * indexes of local elements dont need to be packed
  * since they will be recreated later anyway
  */
-#if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))     
-        int count=0,count1=0;
+#if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))  || CMK_MEM_CHECKPOINT   
+               int count=0,count1=0;
         void *objp;
         void *keyp;
-        CkHashtableIterator *it = hash.iterator();
-      while (NULL!=(objp=it->next(&keyp))) {
-      CkLocRec *rec=*(CkLocRec **)objp;
-        CkArrayIndex &idx=*(CkArrayIndex *)keyp;
-            if(rec->type() != CkLocRec::local){
-                if(homePe(idx) == CmiMyPe()){
-                    count++;
-                }
-            }
-        }
-        p | count;
-        DEBUG(CmiPrintf("[%d] Packing Locmgr %d has %d home elements\n",CmiMyPe(),thisgroup.idx,count));
+        CkVec<int> pe_list;
+        CkVec<CkArrayIndex> idx_list;
+        //CkHashtableIterator *it = hash.iterator();
+        CkHashtableIterator *it = homeObjHash.iterator();
+      while (homeObjHash.numObjects()!=0&&NULL!=(objp=it->next(&keyp))) {
+          CkLocRec *rec=*(CkLocRec **)objp;
+          CkArrayIndex &idx=*(CkArrayIndex *)keyp;
+
+          //if(CmiMyPartition()==0&&CkMyPe()==0)
+            //CkPrintf("[%d][%d] pup home object %s rec %s\n",CmiMyPartition(),CkMyPe(),idx2str(idx),rec2str[rec->type()]);
+            //CkPrintf("[%d][%d] pup home object %s rec %p\n",CmiMyPartition(),CkMyPe(),idx2str(idx),rec);
+          if(rec!=NULL&&rec->type() != CkLocRec::local){
+              if(homePe(idx) == CmiMyPe()){
+                int pe;
+                CkArrayIndex max = idx;
+                pe = rec->lookupProcessor();
+                idx_list.push_back(max);
+                pe_list.push_back(pe);
+                  count++;
+              }
+          }
+      }
+      p | count;
 
-               // releasing iterator memory
-               delete it;
+              // releasing iterator memory
+              delete it;
 
-        it = hash.iterator();
+    for(int i=0;i<pe_list.length();i++){
+      CkArrayIndex max = idx_list[i];
+      max.pup(p);
+      p|pe_list[i];
+      }
+    /*    it = hash.iterator();
       while (NULL!=(objp=it->next(&keyp))) {
       CkLocRec *rec=*(CkLocRec **)objp;
         CkArrayIndex &idx=*(CkArrayIndex *)keyp;
@@ -2021,10 +2372,10 @@ void CkLocMgr::pup(PUP::er &p){
                 }
             }
         }
-        CmiAssert(count == count1);
+      //  CmiAssert(count == count1);
 
                // releasing iterator memory
-               delete it;
+               delete it;*/
 
 #endif
 
@@ -2133,12 +2484,12 @@ CkLocRec_local *CkLocMgr::createLocal(const CkArrayIndex &idx,
                CmiBool forMigration, CmiBool ignoreArrival,
                CmiBool notifyHome)
 {
+       //CkPrintf("Adding new record for element %s\n",idx2str(idx));
        int localIdx=nextFree();
        DEBC((AA"Adding new record for element %s at local index %d\n"AB,idx2str(idx),localIdx));
+       //CkPrintf("Adding new record for element %s at local index %d\n",idx2str(idx),localIdx);
        CkLocRec_local *rec=new CkLocRec_local(this,forMigration,ignoreArrival,idx,localIdx);
        insertRec(rec,idx); //Add to global hashtable
-
-
        if (notifyHome) informHome(idx,CkMyPe());
        return rec;
 }
@@ -2155,11 +2506,12 @@ CmiBool CkLocMgr::addElement(CkArrayID id,const CkArrayIndex &idx,
        { //This is the first we've heard of that element-- add new local record
                rec=createLocal(idx,CmiFalse,CmiFalse,CmiTrue);
 #if CMK_GLOBAL_LOCATION_UPDATE
-                DEBC((AA"Global location broadcast for new element idx %s "
-                      "assigned to %d \n"AB, idx2str(idx), CkMyPe()));
-                thisProxy.updateLocation(idx, CkMyPe());                        
+                if (homePe(idx) != CkMyPe()) {
+                  DEBC((AA"Global location broadcast for new element idx %s "
+                        "assigned to %d \n"AB, idx2str(idx), CkMyPe()));
+                  thisProxy.updateLocation(idx, CkMyPe());  
+                }
 #endif
-                
        } else 
        { //rec is *already* local-- must not be the first insertion    
                rec=((CkLocRec_local *)oldRec);
@@ -2194,7 +2546,8 @@ CmiBool CkLocMgr::addElementToRec(CkLocRec_local *rec,ManagerRec *m,
        return CmiTrue;
 }
 void CkLocMgr::updateLocation(const CkArrayIndex &idx,int nowOnPe) {
-       inform(idx,nowOnPe);
+  inform(idx,nowOnPe);
+       CProxy_CkMemCheckPT checkptMgr(ckCheckPTGroupID);
 }
 
 /*************************** LocMgr: DELETION *****************************/
@@ -2253,6 +2606,10 @@ void CkLocMgr::removeFromTable(const CkArrayIndex &idx) {
                CkAbort("CkLocMgr::removeFromTable called on invalid index!");
 #endif
         CmiImmediateLock(hashImmLock);
+       CkLocRec *old=elementNrec(idx);
+        if(old->type()==CkLocRec::local){
+          localHash.remove(*(CkArrayIndex *)&idx);
+        }
        hash.remove(*(CkArrayIndex *)&idx);
         CmiImmediateUnlock(hashImmLock);
 #if CMK_ERROR_CHECKING
@@ -2284,10 +2641,15 @@ int CkLocMgr::deliver(CkMessage *m,CkDeliver_t type,int opts) {
 //#if (!defined(_FAULT_MLOG_) && !defined(_FAULT_CAUSAL_))
 //#if !defined(_FAULT_MLOG_)
 #if CMK_LBDB_ON
+
+        LDObjid ldid = idx2LDObjid(idx);
+#if CMK_GLOBAL_LOCATION_UPDATE
+        ldid.locMgrGid = thisgroup.idx;
+#endif        
        if (type==CkDeliver_queue) {
                if (!(opts & CK_MSG_LB_NOTRACE) && the_lbdb->CollectingCommStats()) {
-               if(rec!=NULL) the_lbdb->Send(myLBHandle,idx2LDObjid(idx),UsrToEnv(msg)->getTotalsize(), rec->lookupProcessor(), 1);
-               else /*rec==NULL*/ the_lbdb->Send(myLBHandle,idx2LDObjid(idx),UsrToEnv(msg)->getTotalsize(),homePe(msg->array_index()), 1);
+               if(rec!=NULL) the_lbdb->Send(myLBHandle,ldid,UsrToEnv(msg)->getTotalsize(), rec->lookupProcessor(), 1);
+               else /*rec==NULL*/ the_lbdb->Send(myLBHandle,ldid,UsrToEnv(msg)->getTotalsize(),homePe(msg->array_index()), 1);
                }
        }
 #endif
@@ -2511,7 +2873,46 @@ void CkLocMgr::iterate(CkLocIterator &dest) {
   delete it;
 }
 
+void CkLocMgr::iterateLocal(CkLocIterator &dest) {
+  //Poke through the hash table for local ArrayRecs.
+  void *objp;
+  CkHashtableIterator *it=localHash.iterator();
+  CmiImmediateLock(hashImmLock);
 
+  while (NULL!=(objp=it->next())) {
+    CkLocRec *rec=*(CkLocRec **)objp;
+    if (rec->type()==CkLocRec::local) {
+      CkLocation loc(this,(CkLocRec_local *)rec);
+      dest.addLocation(loc);
+    }
+  }
+  CmiImmediateUnlock(hashImmLock);
+  delete it;
+}
+
+void CkLocMgr::iterateChkpSync(CkLocIterator &dest) {
+  //Poke through the hash table for local ArrayRecs.
+  void *objp;
+  CkHashtableIterator *it=localHash.iterator();
+  CmiImmediateLock(hashImmLock);
+
+  while (NULL!=(objp=it->next())) {
+    CkLocRec *rec=*(CkLocRec **)objp;
+    if (rec->type()==CkLocRec::local) {
+      CkLocation loc(this,(CkLocRec_local *)rec);
+         int localIdx=((CkLocRec_local *)rec)->getLocalIndex();
+         for (ManagerRec *m=firstManager;m!=NULL;m=m->next) {
+               CkMigratable *el=m->element(localIdx);
+       if(el->getChkpSync()==CmiTrue){
+                       dest.addLocation(loc);
+                       break;
+               }
+         }
+    }
+  }
+  CmiImmediateUnlock(hashImmLock);
+  delete it;
+}
 
 
 /************************** LocMgr: MIGRATION *************************/
@@ -2523,7 +2924,6 @@ void CkLocMgr::pupElementsFor(PUP::er &p,CkLocRec_local *rec,
     register ManagerRec *m;
     int localIdx=rec->getLocalIndex();
     CkVec<CkMigratable *> dummyElts;
-
     for (m=firstManager;m!=NULL;m=m->next) {
         int elCType;
         if (!p.isUnpacking())
@@ -2536,8 +2936,8 @@ void CkLocMgr::pupElementsFor(PUP::er &p,CkLocRec_local *rec,
         if (p.isUnpacking() && elCType!=-1) {
             CkMigratable *elt=m->mgr->allocateMigrated(elCType,rec->getIndex(),type);
             int migCtorIdx=_chareTable[elCType]->getMigCtor();
-                if(!dummy){
-                       if(create)
+                       if(!dummy){
+                               if(create)
                                if (!addElementToRec(rec,m,elt,migCtorIdx,NULL)) return;
                                }else{
                     CkMigratable_initInfo &i=CkpvAccess(mig_initInfo);
@@ -2547,7 +2947,7 @@ void CkLocMgr::pupElementsFor(PUP::er &p,CkLocRec_local *rec,
                     if (!rec->invokeEntry(elt,NULL,migCtorIdx,CmiTrue)) return ;
                 }
         }
-    }
+       }
     if(!dummy){
         for (m=firstManager;m!=NULL;m=m->next) {
             CkMigratable *elt=m->element(localIdx);
@@ -2573,7 +2973,7 @@ void CkLocMgr::pupElementsFor(PUP::er &p,CkLocRec_local *rec,
 }
 #else
 void CkLocMgr::pupElementsFor(PUP::er &p,CkLocRec_local *rec,
-               CkElementCreation_t type)
+               CkElementCreation_t type,CmiBool rebuild,CmiBool create)
 {
        p.comment("-------- Array Location --------");
        register ManagerRec *m;
@@ -2589,26 +2989,47 @@ void CkLocMgr::pupElementsFor(PUP::er &p,CkLocRec_local *rec,
                        if (elt) elCType=elt->ckGetChareType();
                        else elCType=-1; //Element hasn't been created
                }
+
                p(elCType);
                if (p.isUnpacking() && elCType!=-1) {
                        //Create the element
                        CkMigratable *elt=m->mgr->allocateMigrated(elCType,rec->getIndex(),type);
                        int migCtorIdx=_chareTable[elCType]->getMigCtor();
                        //Insert into our tables and call migration constructor
-                       if (!addElementToRec(rec,m,elt,migCtorIdx,NULL)) return;
+                       if(create)
+                               if (!addElementToRec(rec,m,elt,migCtorIdx,NULL)) return;
                }
        }
+
        //Next pup the element data
        for (m=firstManager;m!=NULL;m=m->next) {
                CkMigratable *elt=m->element(localIdx);
                if (elt!=NULL)
-                {
-                        elt->pup(p);
+               {
+                       elt->pup(p);
 #if CMK_ERROR_CHECKING
-                        if (p.isUnpacking()) elt->sanitycheck();
+                       if (p.isUnpacking()) elt->sanitycheck();
 #endif
-                }
+               }
+       }
+
+#if CMK_MEM_CHECKPOINT
+       if(rebuild){
+         ArrayElement *elt;
+         CkVec<CkMigratable *> list;
+         migratableList(rec, list);
+         CmiAssert(list.length() > 0);
+         for (int l=0; l<list.length(); l++) {
+               //    reset, may not needed now
+               // for now.
+               for (int i=0; i<CK_ARRAYLISTENER_MAXLEN; i++) {
+                       ArrayElement * elt = (ArrayElement *)list[l];
+                 contributorInfo *c=(contributorInfo *)&elt->listenerData[i];
+                 if (c) c->redNo = 0;
+               }
+         }
        }
+#endif
 }
 #endif
 
@@ -2622,6 +3043,16 @@ void CkLocMgr::callMethod(CkLocRec_local *rec,CkMigratable_voidfn_t fn)
        }
 }
 
+/// Call this member function on each element of this location:
+void CkLocMgr::callMethod(CkLocRec_local *rec,CkMigratable_voidfn_arg_t fn,     void * data)
+{
+       int localIdx=rec->getLocalIndex();
+       for (ManagerRec *m=firstManager;m!=NULL;m=m->next) {
+               CkMigratable *el=m->element(localIdx);
+               if (el) (el->* fn)(data);
+       }
+}
+
 /// return a list of migratables in this local record
 void CkLocMgr::migratableList(CkLocRec_local *rec, CkVec<CkMigratable *> &list)
 {
@@ -2719,12 +3150,10 @@ void CkLocMgr::emigrate(CkLocRec_local *rec,int toPe)
        inform(idx,toPe);
 //#if (!defined(_FAULT_MLOG_) && !defined(_FAULT_CAUSAL_))    
 //#if !defined(_FAULT_MLOG_)    
-#if !CMK_GLOBAL_LOCATION_UPDATE
        informHome(idx,toPe);
-#endif
 //#endif
 
-#if !CMK_LDB_ON && CMK_GLOBAL_LOCATION_UPDATE
+#if !CMK_LBDB_ON && CMK_GLOBAL_LOCATION_UPDATE
         DEBM((AA"Global location update. idx %s " 
               "assigned to %d \n"AB,idx2str(idx),toPe));
         thisProxy.updateLocation(idx, toPe);                        
@@ -2733,6 +3162,16 @@ void CkLocMgr::emigrate(CkLocRec_local *rec,int toPe)
        CK_MAGICNUMBER_CHECK
 }
 
+#if CMK_LBDB_ON
+void CkLocMgr::informLBPeriod(CkLocRec_local *rec, int lb_ideal_period) {
+       callMethod(rec,&CkMigratable::recvLBPeriod, (void *)&lb_ideal_period);
+}
+
+void CkLocMgr::metaLBCallLB(CkLocRec_local *rec) {
+       callMethod(rec, &CkMigratable::metaLBCallLB);
+}
+#endif
+
 /**
   Migrating array element is arriving on this processor.
 */
@@ -2853,14 +3292,25 @@ void CkLocMgr::resume(const CkArrayIndex &idx, PUP::er &p, CmiBool create, int d
     }
 }
 #else
-void CkLocMgr::resume(const CkArrayIndex &idx, PUP::er &p, CmiBool notify)
+void CkLocMgr::resume(const CkArrayIndex &idx, PUP::er &p, CmiBool notify,CmiBool rebuild,CmiBool create)
 {
-       CkLocRec_local *rec=createLocal(idx,CmiFalse,CmiFalse,notify /* home doesn't know yet */ );
-
-       //Create the new elements as we unpack the message
-       pupElementsFor(p,rec,CkElementCreation_resume);
+       CkLocRec_local *rec;
+       CkLocRec *recGlobal;    
 
-       callMethod(rec,&CkMigratable::ckJustMigrated);
+       if(create){
+               //Create the new elements as we unpack the message
+               rec=createLocal(idx,CmiFalse,CmiFalse,notify /* home doesn't know yet */ );
+       }else{
+               recGlobal = elementNrec(idx);
+               if(recGlobal == NULL) 
+                       CmiAbort("Local object not found");
+               if(recGlobal->type() != CkLocRec::local)
+                       CmiAbort("Local object not local, :P");
+               rec = (CkLocRec_local *)recGlobal;
+       }
+       pupElementsFor(p,rec,CkElementCreation_resume,rebuild,create);
+       if(!p.isChecking())
+               callMethod(rec,&CkMigratable::ckJustMigrated);
 }
 #endif
 
@@ -2915,13 +3365,6 @@ bool CkLocMgr::isRemote(const CkArrayIndex &idx,int *onPe) const
        }
 }
 
-static const char *rec2str[]={
-    "base (INVALID)",//Base class (invalid type)
-    "local",//Array element that lives on this Pe
-    "remote",//Array element that lives on some other Pe
-    "buffering",//Array element that was just created
-    "dead"//Deleted element (for debugging)
-};
 
 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
 void CkLocMgr::setDuringMigration(CmiBool _duringMigration){
@@ -2936,6 +3379,8 @@ void CkLocMgr::insertRec(CkLocRec *rec,const CkArrayIndex &idx) {
        insertRecN(rec,idx);
        if (old!=NULL) {
                DEBC((AA"  replaces old rec(%s) for %s\n"AB,rec2str[old->type()],idx2str(idx)));
+       //      if(CmiMyPartition()==1)
+        //          CkPrintf("[%d][%d]replaces old rec(%s) for %s %p new type %s\n",CmiMyPartition(),CkMyPe(),rec2str[old->type()],idx2str(idx),old,rec2str[rec->type()]);
                //There was an old element at this location
                if (old->type()==CkLocRec::local && rec->type()==CkLocRec::local) {
                    if (!CkInRestarting()) {    // ok if it is restarting
@@ -2944,6 +3389,10 @@ void CkLocMgr::insertRec(CkLocRec *rec,const CkArrayIndex &idx) {
                    }
                }
                old->beenReplaced();
+                //need to remove it from homeObjHash
+               if (old->type()!=CkLocRec::local && rec->type()==CkLocRec::local) {
+                  homeObjHash.remove(*(CkArrayIndex *)&idx);
+                }
                delete old;
        }
 }
@@ -2953,6 +3402,14 @@ void CkLocMgr::insertRecN(CkLocRec *rec,const CkArrayIndex &idx) {
        DEBC((AA"  adding new rec(%s) for %s\n"AB,rec2str[rec->type()],idx2str(idx)));
         CmiImmediateLock(hashImmLock);
        hash.put(*(CkArrayIndex *)&idx)=rec;
+        if(rec->type()==CkLocRec::local){
+          //if(CmiMyPartition()==1)
+            //CkPrintf("[%d][%d] put home object %s type %s %p \n",CmiMyPartition(),CkMyPe(),idx2str(idx),rec2str[rec->type()],rec);
+          localHash.put(*(CkArrayIndex *)&idx)=rec;
+        }
+        if(rec->type()!=CkLocRec::local&&homePe(idx)==CkMyPe()){
+          homeObjHash.put(*(CkArrayIndex *)&idx)=rec;
+        }
         CmiImmediateUnlock(hashImmLock);
 }
 
@@ -3001,7 +3458,7 @@ unsigned int CkLocMgr::numLocalElements()
 
 #if !CMK_LBDB_ON
 //Empty versions of all load balancer calls
-void CkLocMgr::initLB(CkGroupID lbdbID_) {}
+void CkLocMgr::initLB(CkGroupID lbdbID_, CkGroupID metalbID_) {}
 void CkLocMgr::startInserting(void) {}
 void CkLocMgr::doneInserting(void) {}
 void CkLocMgr::dummyAtSync(void) {}
@@ -3009,12 +3466,15 @@ void CkLocMgr::dummyAtSync(void) {}
 
 
 #if CMK_LBDB_ON
-void CkLocMgr::initLB(CkGroupID lbdbID_)
+void CkLocMgr::initLB(CkGroupID lbdbID_, CkGroupID metalbID_)
 { //Find and register with the load balancer
        the_lbdb = (LBDatabase *)CkLocalBranch(lbdbID_);
        if (the_lbdb == 0)
                CkAbort("LBDatabase not yet created?\n");
        DEBL((AA"Connected to load balancer %p\n"AB,the_lbdb));
+       the_metalb = (MetaBalancer *)CkLocalBranch(metalbID_);
+       if (the_metalb == 0)
+               CkAbort("MetaBalancer not yet created?\n");
 
        // Register myself as an object manager
        LDOMid myId;
@@ -3023,6 +3483,10 @@ void CkLocMgr::initLB(CkGroupID lbdbID_)
        myCallbacks.migrate = (LDMigrateFn)CkLocRec_local::staticMigrate;
        myCallbacks.setStats = NULL;
        myCallbacks.queryEstLoad = NULL;
+  myCallbacks.metaLBResumeWaitingChares =
+      (LDMetaLBResumeWaitingCharesFn)CkLocRec_local::staticMetaLBResumeWaitingChares;
+  myCallbacks.metaLBCallLBOnChares =
+      (LDMetaLBCallLBOnCharesFn)CkLocRec_local::staticMetaLBCallLBOnChares;
        myLBHandle = the_lbdb->RegisterOM(myId,this,myCallbacks);
 
        // Tell the lbdb that I'm registering objects