You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by up...@apache.org on 2016/02/12 02:37:46 UTC

[2/2] incubator-geode git commit: GEODE-657: Add an abort flag to the FinishBackupMessage

GEODE-657: Add an abort flag to the FinishBackupMessage

If the prepare phase of a backup fails, it can leave the backup in a
prepared state on several nodes. The FinishBackupMessage should always
be sent to cleanup the backup. Adding an abort flag to
FinishBackupMessage and always sending that message regardless of
failures during the prepare.


Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/3adb0b8e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/3adb0b8e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/3adb0b8e

Branch: refs/heads/develop
Commit: 3adb0b8e17436af555e1acbe2bf729bf72365305
Parents: 2b2e619
Author: Dan Smith <up...@apache.org>
Authored: Wed Feb 10 14:05:44 2016 -0800
Committer: Dan Smith <up...@apache.org>
Committed: Thu Feb 11 17:20:03 2016 -0800

----------------------------------------------------------------------
 .../admin/internal/BackupDataStoreHelper.java   |   2 +-
 .../admin/internal/FinishBackupRequest.java     |  14 ++-
 .../internal/locks/DLockService.java            |  18 +++-
 .../internal/admin/remote/AdminResponse.java    |   2 +-
 .../internal/cache/GemFireCacheImpl.java        |   2 +-
 .../cache/persistence/BackupManager.java        |  10 +-
 .../internal/beans/DistributedSystemBridge.java |   5 +-
 .../internal/beans/MemberMBeanBridge.java       |  14 ++-
 .../gemfire/internal/cache/BackupDUnitTest.java |  57 ++++++++++
 .../gemfire/internal/cache/BackupJUnitTest.java |   8 +-
 .../beans/DistributedSystemBridgeJUnitTest.java | 106 +++++++++++++++++++
 .../com/gemstone/gemfire/test/fake/Fakes.java   |  99 +++++++++++++++++
 .../sanctionedDataSerializables.txt             |   4 +-
 13 files changed, 314 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3adb0b8e/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/BackupDataStoreHelper.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/BackupDataStoreHelper.java b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/BackupDataStoreHelper.java
index 26a70a8..d628718 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/BackupDataStoreHelper.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/BackupDataStoreHelper.java
@@ -12,7 +12,7 @@ import com.gemstone.gemfire.internal.Assert;
 
 public class BackupDataStoreHelper {
 
-  private static String LOCK_SERVICE_NAME = BackupDataStoreHelper.class.getSimpleName();
+  public static String LOCK_SERVICE_NAME = BackupDataStoreHelper.class.getSimpleName();
 
   private static String LOCK_NAME = LOCK_SERVICE_NAME + "_token";
   

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3adb0b8e/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/FinishBackupRequest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/FinishBackupRequest.java b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/FinishBackupRequest.java
index 3833587..58577d6 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/FinishBackupRequest.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/FinishBackupRequest.java
@@ -58,18 +58,20 @@ public class FinishBackupRequest  extends CliLegacyMessage {
   
   private File targetDir;
   private File baselineDir;
+  private boolean abort;
   
   public FinishBackupRequest() {
     super();
   }
 
-  public FinishBackupRequest(File targetDir,File baselineDir) {
+  public FinishBackupRequest(File targetDir,File baselineDir, boolean abort) {
     this.targetDir = targetDir;
     this.baselineDir = baselineDir;
+    this.abort = abort;
   }
   
-  public static Map<DistributedMember, Set<PersistentID>> send(DM dm, Set recipients, File targetDir, File baselineDir) {
-    FinishBackupRequest request = new FinishBackupRequest(targetDir,baselineDir);
+  public static Map<DistributedMember, Set<PersistentID>> send(DM dm, Set recipients, File targetDir, File baselineDir, boolean abort) {
+    FinishBackupRequest request = new FinishBackupRequest(targetDir,baselineDir, abort);
     request.setRecipients(recipients);
 
     FinishBackupReplyProcessor replyProcessor = new FinishBackupReplyProcessor(dm, recipients);
@@ -94,11 +96,11 @@ public class FinishBackupRequest  extends CliLegacyMessage {
   protected AdminResponse createResponse(DistributionManager dm) {
     GemFireCacheImpl cache = GemFireCacheImpl.getInstance();
     HashSet<PersistentID> persistentIds;
-    if(cache == null) {
+    if(cache == null || cache.getBackupManager() == null) {
       persistentIds = new HashSet<PersistentID>();
     } else {
       try {
-        persistentIds = cache.getBackupManager().finishBackup(targetDir, baselineDir);
+        persistentIds = cache.getBackupManager().finishBackup(targetDir, baselineDir, abort);
       } catch (IOException e) {
         logger.error(LocalizedMessage.create(LocalizedStrings.CliLegacyMessage_ERROR, this.getClass()), e);
         return AdminFailureResponse.create(dm, getSender(), e);
@@ -117,6 +119,7 @@ public class FinishBackupRequest  extends CliLegacyMessage {
     super.fromData(in);
     targetDir = DataSerializer.readFile(in);
     baselineDir = DataSerializer.readFile(in);
+    abort = DataSerializer.readBoolean(in);
   }
 
   @Override
@@ -124,6 +127,7 @@ public class FinishBackupRequest  extends CliLegacyMessage {
     super.toData(out);
     DataSerializer.writeFile(targetDir, out);
     DataSerializer.writeFile(baselineDir, out);
+    DataSerializer.writeBoolean(abort, out);
   }
 
   private static class FinishBackupReplyProcessor extends AdminMultipleReplyProcessor {

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3adb0b8e/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/locks/DLockService.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/locks/DLockService.java b/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/locks/DLockService.java
index ca3840e..626d85e 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/locks/DLockService.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/distributed/internal/locks/DLockService.java
@@ -2998,7 +2998,7 @@ public class DLockService extends DistributedLockService {
         ds.getCancelCriterion().checkCancelInProgress(null);
         
         // make sure thread group is ready...
-        readyThreadGroup();
+        readyThreadGroup(ds);
         
         if (services.get(serviceName) != null) {
           throw new IllegalArgumentException(LocalizedStrings.DLockService_SERVICE_NAMED_0_ALREADY_CREATED.toLocalizedString(serviceName));
@@ -3203,6 +3203,18 @@ public class DLockService extends DistributedLockService {
   protected static synchronized DistributedLockStats getDistributedLockStats() {
     return stats;
   }
+  
+  public static void addLockServiceForTests(String name, DLockService service) {
+    synchronized (services) {
+      services.put(name, service);
+    }
+  }
+  
+  public static void removeLockServiceForTests(String name) {
+    synchronized (services) {
+      services.remove(name);
+    }
+  }
 
   protected static void removeLockService(DLockService service) {
     service.removeAllTokens();
@@ -3253,10 +3265,8 @@ public class DLockService extends DistributedLockService {
   //   Internal
   // -------------------------------------------------------------------------
   
-  protected static synchronized void readyThreadGroup() {
+  protected static synchronized void readyThreadGroup(InternalDistributedSystem ds) {
     if (threadGroup == null) {
-      InternalDistributedSystem ds = 
-          InternalDistributedSystem.getAnyInstance();
       Assert.assertTrue(ds != null, 
           "Cannot find any instance of InternalDistributedSystem");
       String threadGroupName = LocalizedStrings.DLockService_DISTRIBUTED_LOCKING_THREADS.toLocalizedString();

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3adb0b8e/gemfire-core/src/main/java/com/gemstone/gemfire/internal/admin/remote/AdminResponse.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/admin/remote/AdminResponse.java b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/admin/remote/AdminResponse.java
index 14a201c..692deed 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/admin/remote/AdminResponse.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/admin/remote/AdminResponse.java
@@ -42,7 +42,7 @@ public abstract class AdminResponse extends HighPriorityDistributionMessage
     return this.msgId;
   }
 
-  void setMsgId(int msgId) {
+  public void setMsgId(int msgId) {
     this.msgId = msgId;
   }
   

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3adb0b8e/gemfire-core/src/main/java/com/gemstone/gemfire/internal/cache/GemFireCacheImpl.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/cache/GemFireCacheImpl.java b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/cache/GemFireCacheImpl.java
index 256e293..201acc0 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/cache/GemFireCacheImpl.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/cache/GemFireCacheImpl.java
@@ -2729,7 +2729,7 @@ public class GemFireCacheImpl implements InternalCache, ClientCache, HasCachePer
 
   }
 
-  public final InternalDistributedSystem getDistributedSystem() {
+  public InternalDistributedSystem getDistributedSystem() {
     return this.system;
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3adb0b8e/gemfire-core/src/main/java/com/gemstone/gemfire/internal/cache/persistence/BackupManager.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/cache/persistence/BackupManager.java b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/cache/persistence/BackupManager.java
index 1a5c765..c764007 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/cache/persistence/BackupManager.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/cache/persistence/BackupManager.java
@@ -166,8 +166,12 @@ public class BackupManager implements MembershipListener {
     return baselineDir;
   }
   
-  public HashSet<PersistentID> finishBackup(File targetDir, File baselineDir) throws IOException {
+  public HashSet<PersistentID> finishBackup(File targetDir, File baselineDir, boolean abort) throws IOException {
     try {
+      if(abort) {
+        return new HashSet<PersistentID>();
+      }
+      
       File backupDir = getBackupDir(targetDir);
       
       // Make sure our baseline is okay for this member
@@ -225,6 +229,10 @@ public class BackupManager implements MembershipListener {
     }
   }
   
+  public void abort() {
+    cleanup();
+  }
+  
   private void backupConfigFiles(RestoreScript restoreScript, File backupDir) throws IOException {
     File configBackupDir = new File(backupDir, CONFIG);
     FileUtil.mkdirs(configBackupDir);

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3adb0b8e/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/beans/DistributedSystemBridge.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/beans/DistributedSystemBridge.java b/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/beans/DistributedSystemBridge.java
index 9427831..d95de82 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/beans/DistributedSystemBridge.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/beans/DistributedSystemBridge.java
@@ -265,7 +265,7 @@ public class DistributedSystemBridge {
     this.dm = system.getDistributionManager();
     this.alertLevel = ManagementConstants.DEFAULT_ALERT_LEVEL;
     this.thisMemberName = MBeanJMXAdapter
-    .getMemberMBeanName(InternalDistributedSystem.getConnectedInstance().getDistributedMember());
+    .getMemberMBeanName(system.getDistributedMember());
 
     this.distributedSystemId = this.system.getConfig().getDistributedSystemId();
 
@@ -588,9 +588,6 @@ public class DistributedSystemBridge {
       diskBackupStatus.setBackedUpDiskStores(backedUpDiskStores);
       diskBackupStatus.setOfflineDiskStores(setOfMissingDiskStr);
       return diskBackupStatus;
-
-    } catch (Exception e) {
-      throw new Exception(e.getLocalizedMessage());
     } finally {
       BackupDataStoreHelper.releaseLock(dm);
     }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3adb0b8e/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/beans/MemberMBeanBridge.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/beans/MemberMBeanBridge.java b/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/beans/MemberMBeanBridge.java
index dc54c6d..61e328d 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/beans/MemberMBeanBridge.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/management/internal/beans/MemberMBeanBridge.java
@@ -1155,10 +1155,16 @@ public class MemberMBeanBridge {
       try {
         BackupManager manager = cache.startBackup(cache.getDistributedSystem()
             .getDistributedMember());
-        Set<PersistentID> existingDataStores = manager.prepareBackup();
-
-        Set<PersistentID> successfulDataStores = manager
-          .finishBackup(targetDir, null/* TODO rishi */);
+        boolean abort = true;
+        Set<PersistentID> existingDataStores;
+        Set<PersistentID> successfulDataStores;
+        try {
+          existingDataStores = manager.prepareBackup();
+          abort = false;
+        } finally {
+          successfulDataStores = manager
+              .finishBackup(targetDir, null/* TODO rishi */, abort);
+        }
         diskBackUpResult = new DiskBackupResult[existingDataStores.size()];
         int j = 0;
 

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3adb0b8e/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/BackupDUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/BackupDUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/BackupDUnitTest.java
index a91fb8e..3ad768e 100755
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/BackupDUnitTest.java
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/BackupDUnitTest.java
@@ -31,7 +31,10 @@ import java.util.TreeSet;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 
+import com.gemstone.gemfire.GemFireIOException;
 import com.gemstone.gemfire.admin.BackupStatus;
+import com.gemstone.gemfire.admin.internal.FinishBackupRequest;
+import com.gemstone.gemfire.admin.internal.PrepareBackupRequest;
 import com.gemstone.gemfire.cache.Cache;
 import com.gemstone.gemfire.cache.DataPolicy;
 import com.gemstone.gemfire.cache.DiskStore;
@@ -49,11 +52,13 @@ import com.gemstone.gemfire.distributed.internal.DistributionMessage;
 import com.gemstone.gemfire.distributed.internal.DistributionMessageObserver;
 import com.gemstone.gemfire.distributed.internal.ReplyMessage;
 import com.gemstone.gemfire.internal.FileUtil;
+import com.gemstone.gemfire.internal.admin.remote.AdminFailureResponse;
 import com.gemstone.gemfire.internal.cache.partitioned.PersistentPartitionedRegionTestBase;
 import com.gemstone.gemfire.test.dunit.Assert;
 import com.gemstone.gemfire.test.dunit.AsyncInvocation;
 import com.gemstone.gemfire.test.dunit.DUnitEnv;
 import com.gemstone.gemfire.test.dunit.Host;
+import com.gemstone.gemfire.test.dunit.IgnoredException;
 import com.gemstone.gemfire.test.dunit.Invoke;
 import com.gemstone.gemfire.test.dunit.LogWriterUtils;
 import com.gemstone.gemfire.test.dunit.SerializableCallable;
@@ -353,6 +358,58 @@ public class BackupDUnitTest extends PersistentPartitionedRegionTestBase {
     
     backupWhileBucketIsMoved(observer);
   }
+  
+  public void testBackupStatusCleanedUpAfterFailureOnOneMember() throws Throwable {
+    IgnoredException.addIgnoredException("Uncaught exception");
+    IgnoredException.addIgnoredException("Stop processing");
+    Host host = Host.getHost(0);
+    final VM vm0 = host.getVM(0);
+    VM vm1 = host.getVM(1);
+    final VM vm2 = host.getVM(2);
+
+    //Create an observer that will fail a backup
+    //When this member receives a prepare
+    DistributionMessageObserver observer = new SerializableDistributionMessageObserver() {
+      @Override
+      public void beforeProcessMessage(DistributionManager dm,
+          DistributionMessage message) {
+        if(message instanceof PrepareBackupRequest) {
+          DistributionMessageObserver.setInstance(null);
+          IOException exception = new IOException("Backup in progess");
+          AdminFailureResponse response = AdminFailureResponse.create(dm, message.getSender(), exception);
+          response.setMsgId(((PrepareBackupRequest) message).getMsgId());
+          dm.putOutgoing(response);
+          throw new RuntimeException("Stop processing");
+        }
+      }
+    };
+    
+    vm0.invoke(() -> {
+      disconnectFromDS();
+      DistributionMessageObserver.setInstance(observer);
+    });
+    
+    createPersistentRegion(vm0);
+    createPersistentRegion(vm1);
+    
+    createData(vm0, 0, 5, "A", "region1");
+    createData(vm0, 0, 5, "B", "region2");
+    
+    try {
+      backup(vm2);
+      fail("Backup should have failed with in progress exception");
+    } catch(Exception expected) {
+      //that's ok, hte backup should have failed
+    }
+    
+    //A second backup should succeed because the observer
+    //has been cleared and the backup state should be cleared.
+    BackupStatus status = backup(vm2);
+    assertEquals(2, status.getBackedUpDiskStores().size());
+    assertEquals(Collections.emptySet(), status.getOfflineDiskStores());
+
+    
+  }
    
   /**
    * Test for bug 42420. Invoke a backup

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3adb0b8e/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/BackupJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/BackupJUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/BackupJUnitTest.java
index 616e4d5..31f5947 100644
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/BackupJUnitTest.java
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/BackupJUnitTest.java
@@ -199,7 +199,7 @@ public class BackupJUnitTest {
     
     BackupManager backup = cache.startBackup(cache.getDistributedSystem().getDistributedMember());
     backup.prepareBackup();
-    backup.finishBackup(backupDir,null);
+    backup.finishBackup(backupDir, null, false);
     
     //Put another key to make sure we restore
     //from a backup that doesn't contain this key
@@ -247,7 +247,7 @@ public class BackupJUnitTest {
 
     BackupManager backup = cache.startBackup(cache.getDistributedSystem().getDistributedMember());
     backup.prepareBackup();
-    backup.finishBackup(backupDir,null);
+    backup.finishBackup(backupDir, null, false);
     assertEquals("No backup files should have been created", Collections.emptyList(), Arrays.asList(backupDir.list()));
   }
   
@@ -261,7 +261,7 @@ public class BackupJUnitTest {
 
     BackupManager backup = cache.startBackup(cache.getDistributedSystem().getDistributedMember());
     backup.prepareBackup();
-    backup.finishBackup(backupDir,null);
+    backup.finishBackup(backupDir, null, false);
     
     
     assertEquals("No backup files should have been created", Collections.emptyList(), Arrays.asList(backupDir.list()));
@@ -318,7 +318,7 @@ public class BackupJUnitTest {
 
     BackupManager backup = cache.startBackup(cache.getDistributedSystem().getDistributedMember());
     backup.prepareBackup();
-    backup.finishBackup(backupDir,null);
+    backup.finishBackup(backupDir, null, false);
     File cacheXmlBackup = FileUtil.find(backupDir, ".*config.cache.xml");
     assertTrue(cacheXmlBackup.exists());
     byte[] expectedBytes = getBytes(CACHE_XML_FILE);

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3adb0b8e/gemfire-core/src/test/java/com/gemstone/gemfire/management/internal/beans/DistributedSystemBridgeJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/management/internal/beans/DistributedSystemBridgeJUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/management/internal/beans/DistributedSystemBridgeJUnitTest.java
new file mode 100644
index 0000000..84b39d4
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/management/internal/beans/DistributedSystemBridgeJUnitTest.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gemstone.gemfire.management.internal.beans;
+
+import static org.junit.Assert.*;
+import static org.mockito.Matchers.*;
+import static org.mockito.Mockito.*;
+
+import java.io.IOException;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.mockito.InOrder;
+
+import com.gemstone.gemfire.admin.internal.BackupDataStoreHelper;
+import com.gemstone.gemfire.admin.internal.FinishBackupRequest;
+import com.gemstone.gemfire.admin.internal.PrepareBackupRequest;
+import com.gemstone.gemfire.distributed.internal.DM;
+import com.gemstone.gemfire.distributed.internal.locks.DLockService;
+import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
+import com.gemstone.gemfire.internal.cache.persistence.BackupManager;
+import com.gemstone.gemfire.internal.cache.persistence.PersistentMemberManager;
+import com.gemstone.gemfire.test.fake.Fakes;
+import com.gemstone.gemfire.test.junit.categories.UnitTest;
+
+@Category(UnitTest.class)
+public class DistributedSystemBridgeJUnitTest {
+  
+  private GemFireCacheImpl cache;
+  private BackupManager backupManager;
+
+  @Before
+  public void createCache() throws IOException {
+    cache = Fakes.cache();
+    PersistentMemberManager memberManager = mock(PersistentMemberManager.class);
+    backupManager = mock(BackupManager.class);
+    when(cache.startBackup(any())).thenReturn(backupManager);
+    when(cache.getPersistentMemberManager()).thenReturn(memberManager);
+    when(cache.getBackupManager()).thenReturn(backupManager);
+    
+    DLockService dlock = mock(DLockService.class);
+    when(dlock.lock(any(), anyLong(), anyLong())).thenReturn(true);
+    
+    DLockService.addLockServiceForTests(BackupDataStoreHelper.LOCK_SERVICE_NAME, dlock);
+    GemFireCacheImpl.setInstanceForTests(cache);
+  }
+  
+  @After
+  public void clearCache() {
+    GemFireCacheImpl.setInstanceForTests(null);
+    DLockService.removeLockServiceForTests(BackupDataStoreHelper.LOCK_SERVICE_NAME);
+  }
+  
+  @Test
+  public void testSucessfulBackup() throws Exception {
+    DM dm = cache.getDistributionManager();
+    
+    DistributedSystemBridge bridge = new DistributedSystemBridge(null);
+    bridge.backupAllMembers("/tmp", null);
+    
+    InOrder inOrder = inOrder(dm, backupManager);
+    inOrder.verify(dm).putOutgoing(isA(PrepareBackupRequest.class));
+    inOrder.verify(backupManager).prepareBackup();
+    inOrder.verify(dm).putOutgoing(isA(FinishBackupRequest.class));
+    inOrder.verify(backupManager).finishBackup(any(), any(), eq(false));
+  }
+
+  @Test
+  public void testPrepareErrorAbortsBackup() throws Exception {
+    DM dm = cache.getDistributionManager();
+    PersistentMemberManager memberManager = mock(PersistentMemberManager.class);
+    BackupManager backupManager = mock(BackupManager.class);
+    when(cache.startBackup(any())).thenReturn(backupManager);
+    when(cache.getPersistentMemberManager()).thenReturn(memberManager);
+    when(cache.getBackupManager()).thenReturn(backupManager);
+    when(dm.putOutgoing(isA(PrepareBackupRequest.class))).thenThrow(new RuntimeException("Fail the prepare"));
+    
+    
+    DistributedSystemBridge bridge = new DistributedSystemBridge(null);
+    try {
+      bridge.backupAllMembers("/tmp", null);
+      fail("Should have failed with an exception");
+    } catch(RuntimeException expected) {
+      
+    }
+    
+    verify(dm).putOutgoing(isA(FinishBackupRequest.class));
+    verify(backupManager).finishBackup(any(), any(), eq(true));
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3adb0b8e/gemfire-core/src/test/java/com/gemstone/gemfire/test/fake/Fakes.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/fake/Fakes.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/fake/Fakes.java
new file mode 100644
index 0000000..ffb4896
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/fake/Fakes.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gemstone.gemfire.test.fake;
+
+import static org.mockito.Mockito.*;
+
+import java.net.UnknownHostException;
+
+import org.junit.Assert;
+
+import com.gemstone.gemfire.CancelCriterion;
+import com.gemstone.gemfire.distributed.internal.DistributionConfig;
+import com.gemstone.gemfire.distributed.internal.DistributionManager;
+import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
+import com.gemstone.gemfire.distributed.internal.membership.InternalDistributedMember;
+import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
+
+/**
+ * Factory methods for fake objects for use in test.
+ * 
+ * These fakes are essentially mock objects with some limited
+ * functionality. For example the fake cache can return a fake
+ * distributed system.
+ * 
+ * All of the fakes returned by this class are Mockito.mocks, so
+ * they can be modified by using Mockito stubbing, ie
+ * 
+ * <pre>
+ * cache = Fakes.cache();
+ * Mockito.when(cache.getName()).thenReturn(...)
+ * <pre>
+ * 
+ * Please help extend this class by adding other commonly
+ * used objects to this collection of fakes.
+ */
+public class Fakes {
+  
+  /**
+   * A fake cache, which contains a fake distributed
+   * system, distribution manager, etc.
+   */
+  public static GemFireCacheImpl cache() {
+    GemFireCacheImpl cache = mock(GemFireCacheImpl.class);
+    InternalDistributedSystem system = mock(InternalDistributedSystem.class);
+    DistributionConfig config = mock(DistributionConfig.class);
+    DistributionManager distributionManager = mock(DistributionManager.class);
+    CancelCriterion systemCancelCriterion = mock(CancelCriterion.class);
+    
+    InternalDistributedMember member;
+    try {
+      member = new InternalDistributedMember("localhost", 5555);
+    } catch (UnknownHostException e) {
+      throw new RuntimeException(e);
+    }
+    
+    
+    when(cache.getDistributedSystem()).thenReturn(system);
+    when(cache.getMyId()).thenReturn(member);
+    when(cache.getDistributionManager()).thenReturn(distributionManager);
+    when(cache.getCancelCriterion()).thenReturn(systemCancelCriterion);
+    
+    when(system.getDistributedMember()).thenReturn(member);
+    when(system.getConfig()).thenReturn(config);
+    when(system.getDistributionManager()).thenReturn(distributionManager);
+    when(system.getCancelCriterion()).thenReturn(systemCancelCriterion);
+    
+    when(distributionManager.getId()).thenReturn(member);
+    when(distributionManager.getConfig()).thenReturn(config);
+    when(distributionManager.getSystem()).thenReturn(system);
+    when(distributionManager.getCancelCriterion()).thenReturn(systemCancelCriterion);
+    
+    return cache;
+  }
+
+  /**
+   * A fake distributed system, which contains a fake distribution manager.
+   */
+  public static InternalDistributedSystem distributedSystem() {
+    return cache().getDistributedSystem();
+  }
+
+  private Fakes() {
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3adb0b8e/gemfire-core/src/test/resources/com/gemstone/gemfire/codeAnalysis/sanctionedDataSerializables.txt
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/resources/com/gemstone/gemfire/codeAnalysis/sanctionedDataSerializables.txt b/gemfire-core/src/test/resources/com/gemstone/gemfire/codeAnalysis/sanctionedDataSerializables.txt
index 3b4bd02..472d821 100644
--- a/gemfire-core/src/test/resources/com/gemstone/gemfire/codeAnalysis/sanctionedDataSerializables.txt
+++ b/gemfire-core/src/test/resources/com/gemstone/gemfire/codeAnalysis/sanctionedDataSerializables.txt
@@ -3,8 +3,8 @@ fromData,62,2a2bb80023b500082a2bb900240100b5000b2a2bb80025b500052ab40005b9002601
 toData,30,2ab400082bb800202b2ab4000bb9002102002ab40005c000032bb80022b1
 
 com/gemstone/gemfire/admin/internal/FinishBackupRequest,2
-fromData,22,2a2bb700282a2bb80029b500022a2bb80029b50003b1
-toData,22,2a2bb7002a2ab400022bb8002b2ab400032bb8002bb1
+fromData,33,2a2bb700292a2bb8002ab500022a2bb8002ab500032a2bb8002bb6002cb50004b1
+toData,33,2a2bb7002d2ab400022bb8002e2ab400032bb8002e2ab40004b8002f2bb80030b1
 
 com/gemstone/gemfire/admin/internal/FinishBackupResponse,2
 fromData,14,2a2bb700042a2bb80005b50003b1