fix for migration
[charm.git] / src / ck-core / cklocation.C
index 472e87a19fc9bfd4642431e1ce8071e1aa6bffc0..97602046eedd00641cb48d8f35eac00810116856 100644 (file)
@@ -13,7 +13,7 @@
 #include "ck.h"
 #include "trace.h"
 #include "TopoManager.h"
-
+#include <vector>
 #include<sstream>
 
 #if CMK_LBDB_ON
@@ -1050,14 +1050,18 @@ 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
@@ -1081,10 +1085,11 @@ void CkMigratable::pup(PUP::er &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
@@ -1095,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();
 }
 
@@ -1125,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
@@ -1191,18 +1204,23 @@ void CkMigratable::recvLBPeriod(void *data) {
     local_state = LOAD_BALANCE;
 
     can_reset = true;
-    myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
+    //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));
@@ -1212,6 +1230,97 @@ void CkMigratable::ckFinishConstruction(void)
        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)
@@ -1222,7 +1331,9 @@ void CkMigratable::AtSync(int waitForMigration)
        myRec->AsyncMigrate(!waitForMigration);
        if (waitForMigration) ReadyMigrate(CmiTrue);
        ckFinishConstruction();
-  DEBL((AA"Element %s going to sync\n"AB,idx2str(thisIndexMax)));
+  //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();
 
@@ -1240,9 +1351,9 @@ void CkMigratable::AtSync(int waitForMigration)
   }
 
   atsync_iteration++;
-  // CkPrintf("[pe %s] atsync_iter %d && predicted period %d state: %d\n",
-  //     idx2str(thisIndexMax), atsync_iteration,
-  //     myRec->getMetaBalancer()->getPredictedLBPeriod(), local_state);
+  //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;
@@ -1266,7 +1377,7 @@ void CkMigratable::AtSync(int waitForMigration)
     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);
+    //myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
   } else {
     DEBAD(("[%d:%s] Went to pause state iter %d\n", CkMyPe(), idx2str(thisIndexMax), atsync_iteration));
     local_state = PAUSE;
@@ -1294,7 +1405,10 @@ void CkMigratable::staticResumeFromSync(void* data)
 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
     CpvAccess(_currentObj) = el;
 #endif
-  el->clearMetaLBData();
+
+  if (_lb_args.metaLbOn()) {
+       el->clearMetaLBData();
+       }
        el->ResumeFromSync();
 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
     el->mlogData->resumeCount++;
@@ -1406,10 +1520,9 @@ CkLocRec_local::CkLocRec_local(CkLocMgr *mgr,CmiBool fromMigration,
         enable_measure = CmiTrue;
        bounced  = CmiFalse;
        the_lbdb=mgr->getLBDB();
-  if (_lb_args.metaLbOn()) {
-    the_metalb=mgr->getMetaBalancer();
-  }
-        LDObjid ldid = idx2LDObjid(idx);
+       the_metalb=mgr->getMetaBalancer();
+       the_chkp = mgr->getChkpMgr();
+       LDObjid ldid = idx2LDObjid(idx);
 #if CMK_GLOBAL_LOCATION_UPDATE
         ldid.locMgrGid = mgr->getGroupID().idx;
 #endif        
@@ -1424,6 +1537,7 @@ CkLocRec_local::CkLocRec_local(CkLocMgr *mgr,CmiBool fromMigration,
                }
        }
 #endif
+       the_chkp = mgr->getChkpMgr();
        /*
                FAULT_EVAC
        */
@@ -1446,11 +1560,15 @@ void CkLocRec_local::migrateMe(int toPe) //Leaving this processor
        myLocMgr->emigrate(this,toPe);
 }
 
+#if CMK_LBDB_ON
 void CkLocRec_local::informIdealLBPeriod(int lb_ideal_period) {
   myLocMgr->informLBPeriod(this, lb_ideal_period);
 }
 
-#if CMK_LBDB_ON
+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()));
@@ -1671,7 +1789,7 @@ CmiBool CkLocRec_local::deliver(CkArrayMessage *msg,CkDeliver_t type,int opts)
 
 void CkLocRec_local::staticMetaLBResumeWaitingChares(LDObjHandle h, int lb_ideal_period) {
        CkLocRec_local *el=(CkLocRec_local *)LDObjUserData(h);
-       DEBL((AA"Load balancer wants to migrate %s to %d\n"AB,idx2str(el->idx),dest));
+       DEBL((AA"MetaBalancer wants to resume waiting chare %s\n"AB,idx2str(el->idx)));
        el->metaLBResumeWaitingChares(lb_ideal_period);
 }
 
@@ -1679,6 +1797,16 @@ 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);
@@ -1960,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
@@ -1972,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))) {
@@ -1988,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
       }
@@ -2003,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;
@@ -2050,6 +2241,8 @@ CkLocMgr::CkLocMgr(CkGroupID mapID_,CkGroupID lbdbID_,CkGroupID metalbID_,CkArra
   metalbID = metalbID_;
        initLB(lbdbID_, metalbID_);
        hashImmLock = CmiCreateImmediateLock();
+       chkpID = ckCheckPTGroupID;
+       the_chkp = (CkMemCheckPT *)CkLocalBranch(chkpID);
 }
 
 CkLocMgr::CkLocMgr(CkGroupID mapID_,CkGroupID lbdbID_,CkArrayIndex& numInitial)
@@ -2084,6 +2277,7 @@ void CkLocMgr::pup(PUP::er &p){
        p|mapHandle;
        p|lbdbID;
   p|metalbID;
+   p|chkpID;
        mapID = _defaultArrayMapID;
        if(p.isUnpacking()){
                thisProxy=thisgroup;
@@ -2096,19 +2290,20 @@ void CkLocMgr::pup(PUP::er &p){
                map->registerArray(emptyIndex,thisgroup);
                // _lbdb is the fixed global groupID
                initLB(lbdbID, metalbID);
-
-#if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))     
+               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);
@@ -2126,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;
@@ -2161,10 +2372,10 @@ void CkLocMgr::pup(PUP::er &p){
                 }
             }
         }
-        CmiAssert(count == count1);
+      //  CmiAssert(count == count1);
 
                // releasing iterator memory
-               delete it;
+               delete it;*/
 
 #endif
 
@@ -2273,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;
 }
@@ -2301,7 +2512,6 @@ CmiBool CkLocMgr::addElement(CkArrayID id,const CkArrayIndex &idx,
                   thisProxy.updateLocation(idx, CkMyPe());  
                 }
 #endif
-                
        } else 
        { //rec is *already* local-- must not be the first insertion    
                rec=((CkLocRec_local *)oldRec);
@@ -2336,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 *****************************/
@@ -2395,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
@@ -2658,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 *************************/
@@ -2670,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())
@@ -2683,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);
@@ -2694,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);
@@ -2720,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;
@@ -2736,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
 
@@ -2888,10 +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.
 */
@@ -3012,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
 
@@ -3074,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){
@@ -3095,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
@@ -3103,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;
        }
 }
@@ -3112,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);
 }
 
@@ -3174,11 +3472,9 @@ void CkLocMgr::initLB(CkGroupID lbdbID_, CkGroupID metalbID_)
        if (the_lbdb == 0)
                CkAbort("LBDatabase not yet created?\n");
        DEBL((AA"Connected to load balancer %p\n"AB,the_lbdb));
-  if (_lb_args.metaLbOn()) {
-    the_metalb = (MetaBalancer *)CkLocalBranch(metalbID_);
-    if (the_metalb == 0)
-      CkAbort("MetaBalancer not yet created?\n");
-  }
+       the_metalb = (MetaBalancer *)CkLocalBranch(metalbID_);
+       if (the_metalb == 0)
+               CkAbort("MetaBalancer not yet created?\n");
 
        // Register myself as an object manager
        LDOMid myId;
@@ -3189,6 +3485,8 @@ void CkLocMgr::initLB(CkGroupID lbdbID_, CkGroupID metalbID_)
        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