ALFCOM-2358 Rework to stop transaction deadlock and adding first ASR unit tests.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@13234 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Mark Rogers 2009-02-13 18:35:21 +00:00
parent 4e9a4cc1c6
commit 109b51fb98
2 changed files with 598 additions and 83 deletions

View File

@ -0,0 +1,437 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing
*/
package org.alfresco.repo.deploy;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.alfresco.repo.avm.AVMServiceTestBase;
import org.alfresco.repo.avm.util.BulkLoader;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.avm.AVMException;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
import org.alfresco.service.cmr.avm.AVMNotFoundException;
import org.alfresco.service.cmr.avm.deploy.DeploymentCallback;
import org.alfresco.service.cmr.avm.deploy.DeploymentEvent;
import org.alfresco.service.cmr.avm.deploy.DeploymentReport;
import org.alfresco.service.cmr.avm.deploy.DeploymentReportCallback;
import org.alfresco.service.cmr.avm.deploy.DeploymentService;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.util.Deleter;
import org.alfresco.util.NameMatcher;
import org.springframework.context.support.FileSystemXmlApplicationContext;
/**
* End to end test of deployment to an alfresco system receiver (ASR).
* @author britt
* @author mrogers
*/
public class ASRDeploymentTest extends AVMServiceTestBase
{
DeploymentService service = null;
@Override
protected void setUp() throws Exception
{
super.setUp();
service = (DeploymentService)fContext.getBean("DeploymentService");
}
protected void tearDown() throws Exception
{
super.tearDown();
}
public void testBasic()
throws Exception
{
NameMatcher matcher = (NameMatcher)fContext.getBean("globalPathExcluder");
String destStore = "ASRDeploymentTest";
try
{
fService.purgeStore(destStore);
}
catch (AVMNotFoundException e)
{
// nothing to do - store did not exist
}
/**
* set up our test tree
*/
fService.createDirectory("main:/", "a");
fService.createDirectory("main:/a", "b");
fService.createDirectory("main:/a/b", "c");
fService.createDirectory("main:/", "d");
fService.createDirectory("main:/d", "e");
fService.createDirectory("main:/d/e", "f");
fService.createFile("main:/a/b/c", "foo").close();
String fooText="I am main:/a/b/c/foo";
ContentWriter writer = fService.getContentWriter("main:/a/b/c/foo");
writer.setEncoding("UTF-8");
writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
writer.putContent("I am main:/a/b/c/foo");
fService.createFile("main:/a/b/c", "bar").close();
writer = fService.getContentWriter("main:/a/b/c/bar");
// Force a conversion
writer.setEncoding("UTF-16");
writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
writer.putContent("I am main:/a/b/c/bar");
String buffyText = "This is test data: Buffy the Vampire Slayer is an Emmy Award-winning and Golden Globe-nominated American cult television series that aired from March 10, 1997 until May 20, 2003. The series was created in 1997 by writer-director Joss Whedon under his production tag, Mutant Enemy Productions with later co-executive producers being Jane Espenson, David Fury, and Marti Noxon. The series narrative follows Buffy Summers (played by Sarah Michelle Gellar), the latest in a line of young women chosen by fate to battle against vampires, demons, and the forces of darkness as the Slayer. Like previous Slayers, Buffy is aided by a Watcher, who guides and trains her. Unlike her predecessors, Buffy surrounds herself with a circle of loyal friends who become known as the Scooby Gang.";
fService.createFile("main:/a/b", "buffy").close();
writer = fService.getContentWriter("main:/a/b/buffy");
// Force a conversion
writer.setEncoding("UTF-16");
writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
writer.putContent(buffyText);
fService.createFile("main:/a/b", "fudge.bak").close();
DeploymentReport report = new DeploymentReport();
List<DeploymentCallback> callbacks = new ArrayList<DeploymentCallback>();
callbacks.add(new DeploymentReportCallback(report));
/**
* Do our first deployment - should deploy the basic tree defined above
* fudge.bak should be excluded due to the matcher.
*/
String destRef = destStore + ":/www/avm_webapps";
service.deployDifference(-1, "main:/", "localhost", 50500, "admin", "admin", destRef, matcher, true, false, false, callbacks);
Set<DeploymentEvent> firstDeployment = new HashSet<DeploymentEvent>();
firstDeployment.addAll(report.getEvents());
// validate the deployment report
assertTrue("first deployment no start", firstDeployment.contains(new DeploymentEvent(DeploymentEvent.Type.START, null, destRef)));
assertTrue("first deployment no finish", firstDeployment.contains(new DeploymentEvent(DeploymentEvent.Type.END, null, destRef)));
assertTrue("first deployment wrong size", firstDeployment.size() == 11);
assertTrue("Update missing: /a", firstDeployment.contains(new DeploymentEvent(DeploymentEvent.Type.COPIED, null, destRef + "/a")));
assertTrue("Update missing: /a/b", firstDeployment.contains(new DeploymentEvent(DeploymentEvent.Type.COPIED, null, destRef + "/a/b")));
assertTrue("Update missing: /a/b/c", firstDeployment.contains(new DeploymentEvent(DeploymentEvent.Type.COPIED, null, destRef + "/a/b/c")));
assertTrue("Update missing: /d/e", firstDeployment.contains(new DeploymentEvent(DeploymentEvent.Type.COPIED, null, destRef + "/d/e")));
assertTrue("Update missing: /a/b/c/foo", firstDeployment.contains(new DeploymentEvent(DeploymentEvent.Type.COPIED, null, destRef + "/a/b/c/foo")));
assertTrue("Update missing: /a/b/c/bar", firstDeployment.contains(new DeploymentEvent(DeploymentEvent.Type.COPIED, null, destRef + "/a/b/c/bar")));
assertTrue("Update missing: /a/b/buffy", firstDeployment.contains(new DeploymentEvent(DeploymentEvent.Type.COPIED, null, destRef + "/a/b/buffy")));
assertFalse("Fudge has not been excluded", firstDeployment.contains(new DeploymentEvent(DeploymentEvent.Type.COPIED, null, destRef + "/a/b/fudge.bak")));
// Check that files exist in the destination AVM Store
{
fService.getNodeProperties(-1, destRef + "/a/b/buffy");
ContentReader reader = fService.getContentReader(-1, destRef + "/a/b/buffy");
assertTrue("UTF-16 buffy text is not correct", reader.getContentString().equals(buffyText));
}
/**
* Now do the same deployment again - should just get start and end events.
*/
report = new DeploymentReport();
callbacks = new ArrayList<DeploymentCallback>();
callbacks.add(new DeploymentReportCallback(report));
service.deployDifference(-1, "main:/", "localhost", 50500, "admin", "admin", destRef, matcher, true, false, false, callbacks);
int count = 0;
for (DeploymentEvent event : report)
{
System.out.println(event);
count++;
}
assertEquals(2, count);
/**
* now remove a single file in a deployment
*/
fService.removeNode("main:/a/b/c", "bar");
report = new DeploymentReport();
callbacks = new ArrayList<DeploymentCallback>();
callbacks.add(new DeploymentReportCallback(report));
service.deployDifference(-1, "main:/", "localhost", 50500, "admin", "admin", destRef, matcher, true, false, false, callbacks);
Set<DeploymentEvent> smallUpdate = new HashSet<DeploymentEvent>();
smallUpdate.addAll(report.getEvents());
for (DeploymentEvent event : report)
{
System.out.println(event);
}
// assertEquals(3, smallUpdate.size());
assertTrue("Bar not deleted", smallUpdate.contains(new DeploymentEvent(DeploymentEvent.Type.DELETED, null, destRef + "/a/b/c/bar")));
// Check that files exist in the destination AVM Store
{
fService.getNodeProperties(-1, destRef + "/a/b/buffy");
ContentReader reader = fService.getContentReader(-1, destRef + "/a/b/buffy");
assertTrue("UTF-16 buffy text is not correct", reader.getContentString().equals(buffyText));
}
/**
* Now create a new dir and file and remove a node in a single deployment
*/
fService.createFile("main:/d", "jonathan").close();
fService.removeNode("main:/a/b");
report = new DeploymentReport();
callbacks = new ArrayList<DeploymentCallback>();
callbacks.add(new DeploymentReportCallback(report));
service.deployDifference(-1, "main:/", "localhost", 50500, "admin", "admin", destRef, matcher, true, false, false, callbacks);
count = 0;
for (DeploymentEvent event : report)
{
System.out.println(event);
count++;
}
assertEquals(4, count);
/**
* Replace a single directory with a file
*/
fService.removeNode("main:/d/e");
fService.createFile("main:/d", "e").close();
report = new DeploymentReport();
callbacks = new ArrayList<DeploymentCallback>();
callbacks.add(new DeploymentReportCallback(report));
service.deployDifference(-1, "main:/", "localhost", 50500, "admin", "admin", destRef, matcher, true, false, false, callbacks);
count = 0;
for (DeploymentEvent event : report)
{
System.out.println(event);
count++;
}
assertEquals(3, count);
// Check that files exist in the destination AVM Store
{
AVMNodeDescriptor desc = fService.lookup(-1, destRef + "/d/e");
assertTrue("e is not a file", desc.isFile());
}
/**
* Create a few files
*/
fService.removeNode("main:/d/e");
fService.createDirectory("main:/d", "e");
fService.createFile("main:/d/e", "Warren.txt").close();
fService.createFile("main:/d/e", "It's a silly name.txt").close();
report = new DeploymentReport();
callbacks = new ArrayList<DeploymentCallback>();
callbacks.add(new DeploymentReportCallback(report));
service.deployDifference(-1, "main:/", "localhost", 50500, "admin", "admin", destRef, matcher, true, false, false, callbacks);
count = 0;
for (DeploymentEvent event : report)
{
System.out.println(event);
count++;
}
assertEquals(5, count);
try
{
fService.purgeStore(destStore);
}
catch (AVMNotFoundException e)
{
// nothing to do - store did not exist
}
}
/**
* Wrong password
* Negative test
*/
public void testWrongPassword()
{
NameMatcher matcher = (NameMatcher)fContext.getBean("globalPathExcluder");
String destStore = "Junk";
String destRef = destStore + ":/www/avm_webapps";
try {
service.deployDifference(-1, "main:/", "localhost", 50500, "admin", "wronky", destRef, matcher, true, false, false, null);
fail("Wrong password should throw exception");
}
catch (AVMException de)
{
// pass
de.printStackTrace();
}
}
//
// /**
// * Now do the same deployment again - without the matcher - should deploy fudge.bak
// */
// public void testNoExclusionFilter() throws Exception
// {
// DeploymentReport report = new DeploymentReport();
// List<DeploymentCallback> callbacks = new ArrayList<DeploymentCallback>();
// callbacks.add(new DeploymentReportCallback(report));
//
// report = new DeploymentReport();
// callbacks = new ArrayList<DeploymentCallback>();
// callbacks.add(new DeploymentReportCallback(report));
//
// fService.createDirectory("main:/", "a");
// fService.createDirectory("main:/a", "b");
// fService.createFile("main:/a/b", "fudge.bak").close();
// service.deployDifferenceFS(-1, "main:/", "default", "localhost", 44100, TEST_USER, TEST_PASSWORD, TEST_TARGET, null, false, false, false, callbacks);
// Set<DeploymentEvent> smallUpdate = new HashSet<DeploymentEvent>();
// smallUpdate.addAll(report.getEvents());
//
// for (DeploymentEvent event : report)
// {
// System.out.println(event);
// }
// assertTrue("Update missing", smallUpdate.contains(new DeploymentEvent(DeploymentEvent.Type.COPIED, null, "/a/b/fudge.bak")));
// assertEquals(5, smallUpdate.size());
// }
//
// /**
// * Deploy a website, update it, then revert to the first version
// */
// public void testRevertToPreviousVersion() throws Exception
// {
// DeploymentReport report = new DeploymentReport();
// List<DeploymentCallback> callbacks = new ArrayList<DeploymentCallback>();
// callbacks.add(new DeploymentReportCallback(report));
//
// report = new DeploymentReport();
// callbacks = new ArrayList<DeploymentCallback>();
// callbacks.add(new DeploymentReportCallback(report));
//
// fService.createDirectory("main:/", "a");
// fService.createDirectory("main:/a", "b");
// fService.createFile("main:/a/b", "Zander").close();
// fService.createFile("main:/a/b", "Cordelia").close();
// fService.createFile("main:/a/b", "Buffy").close();
// service.deployDifferenceFS(-1, "main:/", "default", "localhost", 44100, TEST_USER, TEST_PASSWORD, TEST_TARGET, null, false, false, false, callbacks);
// int version = report.getEvents().get(0).getSource().getFirst();
// assertTrue("version is not set", version > 0);
//
// // Now do some updates
// report = new DeploymentReport();
// callbacks = new ArrayList<DeploymentCallback>();
// callbacks.add(new DeploymentReportCallback(report));
// fService.createFile("main:/a/b", "Master").close();
// fService.createFile("main:/a/b", "Drusilla").close();
// fService.removeNode("main:/a/b", "Zander");
// service.deployDifferenceFS(-1, "main:/", "default", "localhost", 44100, TEST_USER, TEST_PASSWORD, TEST_TARGET, null, false, false, false, callbacks);
//
// // now do the restore to previous version
// report = new DeploymentReport();
// callbacks = new ArrayList<DeploymentCallback>();
// callbacks.add(new DeploymentReportCallback(report));
// service.deployDifferenceFS(version, "main:/", "default", "localhost", 44100, TEST_USER, TEST_PASSWORD, TEST_TARGET, null, false, false, false, callbacks);
// Set<DeploymentEvent> smallUpdate = new HashSet<DeploymentEvent>();
// smallUpdate.addAll(report.getEvents());
// for (DeploymentEvent event : report)
// {
// System.out.println(event);
// }
// assertTrue("Update missing", smallUpdate.contains(new DeploymentEvent(DeploymentEvent.Type.COPIED, null, "/a/b/Zander")));
// assertTrue("Update missing", smallUpdate.contains(new DeploymentEvent(DeploymentEvent.Type.DELETED, null, "/a/b/Drusilla")));
// assertTrue("Update missing", smallUpdate.contains(new DeploymentEvent(DeploymentEvent.Type.DELETED, null, "/a/b/Master")));
// assertEquals(5, smallUpdate.size());
//
//
//
//
// }
//
// /**
// * Now load a large number of files.
// * Do a deployment - should load successfully
// *
// * Remove a node and update a file
// * Do a deployment - should only see start and end events and the two above.
// */
// public void testBulkLoad() throws Exception
// {
// DeploymentReport report = new DeploymentReport();
// List<DeploymentCallback> callbacks = new ArrayList<DeploymentCallback>();
// callbacks.add(new DeploymentReportCallback(report));
//
// BulkLoader loader = new BulkLoader();
// loader.setAvmService(fService);
// loader.recursiveLoad("source/java/org/alfresco/repo/avm", "main:/");
// report = new DeploymentReport();
// callbacks = new ArrayList<DeploymentCallback>();
// callbacks.add(new DeploymentReportCallback(report));
// service.deployDifferenceFS(-1, "main:/", "default", "localhost", 44100, TEST_USER, TEST_PASSWORD, TEST_TARGET, null, false, false, false, callbacks);
// Set<DeploymentEvent> bigUpdate = new HashSet<DeploymentEvent>();
// bigUpdate.addAll(report.getEvents());
// assertTrue("big update no start", bigUpdate.contains(new DeploymentEvent(DeploymentEvent.Type.START, null, TEST_TARGET)));
// assertTrue("big update no finish", bigUpdate.contains(new DeploymentEvent(DeploymentEvent.Type.END, null, TEST_TARGET)));
// assertTrue("big update too small", bigUpdate.size() > 100);
//
// /**
// * Now do a smaller update and check that just a few files update
// */
// fService.removeNode("main:/avm/hibernate");
// fService.getFileOutputStream("main:/avm/AVMServiceTest.java").close();
// report = new DeploymentReport();
// callbacks = new ArrayList<DeploymentCallback>();
// callbacks.add(new DeploymentReportCallback(report));
// service.deployDifferenceFS(-1, "main:/", "default", "localhost", 44100, TEST_USER, TEST_PASSWORD, TEST_TARGET, null, false, false, false, callbacks);
//
// Set<DeploymentEvent> smallUpdate = new HashSet<DeploymentEvent>();
// smallUpdate.addAll(report.getEvents());
// for (DeploymentEvent event : report)
// {
// System.out.println(event);
// }
// assertEquals(4, smallUpdate.size());
//
// assertTrue("Start missing", smallUpdate.contains(new DeploymentEvent(DeploymentEvent.Type.START, null, TEST_TARGET)));
// assertTrue("End missing", smallUpdate.contains(new DeploymentEvent(DeploymentEvent.Type.DELETED, null, "/avm/hibernate")));
// assertTrue("Update missing", smallUpdate.contains(new DeploymentEvent(DeploymentEvent.Type.UPDATED, null, "/avm/AVMServiceTest.java")));
// assertTrue("Delete Missing", smallUpdate.contains(new DeploymentEvent(DeploymentEvent.Type.END, null, TEST_TARGET)));
// }
}

View File

@ -150,11 +150,18 @@ public class DeploymentServiceImpl implements DeploymentService
* (non-Javadoc) * (non-Javadoc)
* @see org.alfresco.service.cmr.avm.deploy.DeploymentService#deployDifference(int, java.lang.String, java.lang.String, int, java.lang.String, java.lang.String, java.lang.String, boolean, boolean) * @see org.alfresco.service.cmr.avm.deploy.DeploymentService#deployDifference(int, java.lang.String, java.lang.String, int, java.lang.String, java.lang.String, java.lang.String, boolean, boolean)
*/ */
public void deployDifference(int version, String srcPath, String hostName, public void deployDifference(int version,
int port, String userName, String password, String srcPath,
String dstPath, NameMatcher matcher, boolean createDst, String hostName,
boolean dontDelete, boolean dontDo, int port,
List<DeploymentCallback> callbacks) String userName,
String password,
String dstPath,
final NameMatcher matcher,
boolean createDst,
final boolean dontDelete,
final boolean dontDo,
final List<DeploymentCallback> callbacks)
{ {
DeploymentDestination dest = getLock(hostName, port); DeploymentDestination dest = getLock(hostName, port);
synchronized (dest) synchronized (dest)
@ -165,11 +172,28 @@ public class DeploymentServiceImpl implements DeploymentService
} }
try try
{ {
AVMRemote remote = getRemote(hostName, port, userName, password); RetryingTransactionHelper trn = trxService.getRetryingTransactionHelper();
fgLogger.debug("Connecting to remote AVM at " + hostName + ":" +port);
final AVMRemote remote = getRemote(hostName, port, userName, password);
if (version < 0) if (version < 0)
{ {
String storeName = srcPath.substring(0, srcPath.indexOf(":")); /**
version = fAVMService.createSnapshot(storeName, null, null).get(storeName); * If version is -1, Create a local snapshot to deploy
*/
fgLogger.debug("creating snapshot of local version");
final String storeName = srcPath.substring(0, srcPath.indexOf(":"));
RetryingTransactionCallback<Integer> localSnapshot = new RetryingTransactionCallback<Integer>()
{
public Integer execute() throws Throwable
{
int newVersion = fAVMService.createSnapshot(storeName, null, null).get(storeName);
return new Integer(newVersion);
}
};
version = trn.doInTransaction(localSnapshot, false, true).intValue();
fgLogger.debug("snapshot local created " + storeName + ", " + version);
} }
{ {
@ -179,8 +203,54 @@ public class DeploymentServiceImpl implements DeploymentService
processEvent(event, callbacks); processEvent(event, callbacks);
} }
/*
* Create a snapshot on the destination server.
*/
boolean createdRoot = false;
String [] storePath = dstPath.split(":");
int snapshot = -1;
// Get the root of the deployment on the destination server.
AVMNodeDescriptor dstRoot = remote.lookup(-1, dstPath);
if (!dontDo)
{
// Get the root of the deployment on the destination server.
if (dstRoot == null)
{
if (createDst)
{
fgLogger.debug("Create destination parent folder:" + dstPath);
createDestination(remote, dstPath);
dstRoot = remote.lookup(-1, dstPath);
createdRoot = true;
}
else
{
throw new AVMNotFoundException("Node Not Found: " + dstRoot);
}
}
fgLogger.debug("create snapshot on remote");
snapshot = remote.createSnapshot(storePath[0], "PreDeploy", "Pre Deployment Snapshot").get(storePath[0]);
fgLogger.debug("snapshot created on remote");
}
final int srcVersion = version;
final String srcFinalPath = srcPath;
RetryingTransactionCallback<AVMNodeDescriptor> readRoot = new RetryingTransactionCallback<AVMNodeDescriptor>()
{
public AVMNodeDescriptor execute() throws Throwable
{
return fAVMService.lookup(srcVersion, srcFinalPath);
}
};
final AVMNodeDescriptor srcRoot = trn.doInTransaction(readRoot, true, true);
// Get the root of the deployment from this server. // Get the root of the deployment from this server.
AVMNodeDescriptor srcRoot = fAVMService.lookup(version, srcPath); // AVMNodeDescriptor srcRoot = fAVMService.lookup(version, srcPath);
if (srcRoot == null) if (srcRoot == null)
{ {
throw new AVMNotFoundException("Directory Not Found: " + srcPath); throw new AVMNotFoundException("Directory Not Found: " + srcPath);
@ -189,97 +259,92 @@ public class DeploymentServiceImpl implements DeploymentService
{ {
throw new AVMWrongTypeException("Not a directory: " + srcPath); throw new AVMWrongTypeException("Not a directory: " + srcPath);
} }
// Create a snapshot on the destination store.
String [] storePath = dstPath.split(":");
int snapshot = -1;
AVMNodeDescriptor dstParent = null;
if (!dontDo)
{
String[] parentBase = AVMNodeConverter.SplitBase(dstPath);
dstParent = remote.lookup(-1, parentBase[0]);
if (dstParent == null)
{
if (createDst)
{
createDestination(remote, parentBase[0]);
dstParent = remote.lookup(-1, parentBase[0]);
}
else
{
throw new AVMNotFoundException("Node Not Found: " + parentBase[0]);
}
}
snapshot = remote.createSnapshot(storePath[0], "PreDeploy", "Pre Deployment Snapshot").get(storePath[0]);
}
// Get the root of the deployment on the destination server. // Get the root of the deployment on the destination server.
AVMNodeDescriptor dstRoot = remote.lookup(-1, dstPath); if (createdRoot)
if (dstRoot == null)
{ {
// If it doesn't exist, do a copyDirectory to create it. /**
DeploymentEvent event = * This is the first deployment
new DeploymentEvent(DeploymentEvent.Type.COPIED, */
new Pair<Integer, String>(version, srcPath),
dstPath);
if (fgLogger.isDebugEnabled())
{
fgLogger.debug(event);
}
processEvent(event, callbacks);
if (dontDo) if (dontDo)
{ {
fgLogger.debug("dont do specified returning");
return; return;
} }
copyDirectory(version, srcRoot, dstParent, remote, matcher);
/**
* Copy the new directory
*/
fgLogger.debug("start copying to remote");
final AVMNodeDescriptor dstParentNode = dstRoot;
RetryingTransactionCallback<Integer> copyContents = new RetryingTransactionCallback<Integer>()
{
public Integer execute() throws Throwable
{
copyDirectory(srcVersion, srcRoot, dstParentNode, remote, matcher, callbacks);
return new Integer(0);
}
};
trn.setMaxRetries(1);
version = trn.doInTransaction(copyContents, false, true).intValue();
fgLogger.debug("finished copying, snapshot remote");
remote.createSnapshot(storePath[0], "Deployment", "Post Deployment Snapshot."); remote.createSnapshot(storePath[0], "Deployment", "Post Deployment Snapshot.");
if (callbacks != null) if (callbacks != null)
{ {
event = new DeploymentEvent(DeploymentEvent.Type.END, DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.END,
new Pair<Integer, String>(version, srcPath), new Pair<Integer, String>(version, srcPath),
dstPath); dstPath);
if (fgLogger.isDebugEnabled())
{
fgLogger.debug(event);
}
processEvent(event, callbacks); processEvent(event, callbacks);
} }
return; return;
} }
/**
* The destination directory exists - check is actually a directory
*/
if (!dstRoot.isDirectory()) if (!dstRoot.isDirectory())
{ {
throw new AVMWrongTypeException("Not a Directory: " + dstPath); throw new AVMWrongTypeException("Not a Directory: " + dstPath);
} }
// The corresponding directory exists so recursively deploy.
try try
{ {
deployDirectoryPush(version, srcRoot, dstRoot, remote, matcher, dontDelete, dontDo, callbacks); /**
remote.createSnapshot(storePath[0], "Deployment", "Post Deployment Snapshot."); * Recursivly copy
if (callbacks != null) */
fgLogger.debug("both src and dest exist, recursivly deploy");
final AVMNodeDescriptor dstParentNode = dstRoot;
RetryingTransactionCallback<Integer> copyContentsRecursivly = new RetryingTransactionCallback<Integer>()
{ {
public Integer execute() throws Throwable
{
deployDirectoryPush(srcVersion, srcRoot, dstParentNode, remote, matcher, dontDelete, dontDo, callbacks);
return new Integer(0);
}
};
trn.setMaxRetries(1);
trn.doInTransaction(copyContentsRecursivly, false, true);
fgLogger.debug("finished copying, snapshot remote");
remote.createSnapshot(storePath[0], "Deployment", "Post Deployment Snapshot.");
DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.END, DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.END,
new Pair<Integer, String>(version, srcPath), new Pair<Integer, String>(version, srcPath),
dstPath); dstPath);
processEvent(event, callbacks); processEvent(event, callbacks);
}
return; return;
} }
catch (AVMException e) catch (AVMException e)
{ {
if (callbacks != null) fgLogger.debug("error during remote copy and snapshot");
{
DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.FAILED,
new Pair<Integer, String>(version, srcPath),
dstPath, e.getMessage());
for (DeploymentCallback callback : callbacks)
{
callback.eventOccurred(event);
}
}
try try
{ {
if (snapshot != -1) if (snapshot != -1)
{ {
fgLogger.debug("Attempting to roll back ");
AVMSyncService syncService = getSyncService(hostName, port); AVMSyncService syncService = getSyncService(hostName, port);
List<AVMDifference> diffs = syncService.compare(snapshot, dstPath, -1, dstPath, null); List<AVMDifference> diffs = syncService.compare(snapshot, dstPath, -1, dstPath, null);
syncService.update(diffs, null, false, false, true, true, "Aborted Deployment", "Aborted Deployment"); syncService.update(diffs, null, false, false, true, true, "Aborted Deployment", "Aborted Deployment");
@ -294,17 +359,16 @@ public class DeploymentServiceImpl implements DeploymentService
} }
catch (Exception e) catch (Exception e)
{ {
if (callbacks != null) DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.FAILED,
{
DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.FAILED,
new Pair<Integer, String>(version, srcPath), new Pair<Integer, String>(version, srcPath),
dstPath, e.getMessage()); dstPath, e.getMessage());
processEvent(event, callbacks); processEvent(event, callbacks);
}
throw new AVMException("Deployment to " + hostName + " failed.", e); throw new AVMException("Deployment to " + hostName + " failed." + e.toString(), e);
} }
finally finally
{ {
fgLogger.debug("ASR Finally block, Releasing ASR deployment ticket");
fTicketHolder.setTicket(null); fTicketHolder.setTicket(null);
} }
} }
@ -410,7 +474,7 @@ public class DeploymentServiceImpl implements DeploymentService
{ {
return; return;
} }
copyDirectory(version, src, dstParent, remote, matcher); copyDirectory(version, src, dstParent, remote, matcher, callbacks);
return; return;
} }
Pair<Integer, String> source = Pair<Integer, String> source =
@ -451,8 +515,10 @@ public class DeploymentServiceImpl implements DeploymentService
{ {
return; return;
} }
// MER WHY IS THIS HERE ?
fgLogger.debug("Remove and recopy node :" + dstParent.getPath() + '/' + src.getName());
remote.removeNode(dstParent.getPath(), src.getName()); remote.removeNode(dstParent.getPath(), src.getName());
copyDirectory(version, src, dstParent, remote, matcher); copyDirectory(version, src, dstParent, remote, matcher, callbacks);
return; return;
} }
// Source is a file. // Source is a file.
@ -469,10 +535,6 @@ public class DeploymentServiceImpl implements DeploymentService
DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.UPDATED, DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.UPDATED,
source, source,
destination); destination);
if (fgLogger.isDebugEnabled())
{
fgLogger.debug(event);
}
processEvent(event, callbacks); processEvent(event, callbacks);
if (dontDo) if (dontDo)
{ {
@ -511,7 +573,7 @@ public class DeploymentServiceImpl implements DeploymentService
* @param remote * @param remote
*/ */
private void copyDirectory(int version, AVMNodeDescriptor src, AVMNodeDescriptor parent, private void copyDirectory(int version, AVMNodeDescriptor src, AVMNodeDescriptor parent,
AVMRemote remote, NameMatcher matcher) AVMRemote remote, NameMatcher matcher, List<DeploymentCallback>callbacks)
{ {
// Create the destination directory. // Create the destination directory.
remote.createDirectory(parent.getPath(), src.getName()); remote.createDirectory(parent.getPath(), src.getName());
@ -524,17 +586,33 @@ public class DeploymentServiceImpl implements DeploymentService
{ {
if (!excluded(matcher, child.getPath(), null)) if (!excluded(matcher, child.getPath(), null))
{ {
// If it's a file, copy it over and move on. // If it's a file, copy it over and move on.
if (child.isFile()) if (child.isFile())
{ {
DeploymentEvent event =
new DeploymentEvent(DeploymentEvent.Type.COPIED,
new Pair<Integer, String>(version, src.getPath() + '/' + child.getName()),
newParent.getPath() + '/' + child.getName());
processEvent(event, callbacks);
InputStream in = fAVMService.getFileInputStream(child); InputStream in = fAVMService.getFileInputStream(child);
OutputStream out = remote.createFile(newParent.getPath(), child.getName()); OutputStream out = remote.createFile(newParent.getPath(), child.getName());
copyStream(in, out); copyStream(in, out);
copyMetadata(version, child, remote.lookup(-1, newParent.getPath() + '/' + child.getName()), remote); copyMetadata(version, child, remote.lookup(-1, newParent.getPath() + '/' + child.getName()), remote);
continue;
} }
// Otherwise copy the child directory recursively. else
copyDirectory(version, child, newParent, remote, matcher); {
// is a directory
DeploymentEvent event =
new DeploymentEvent(DeploymentEvent.Type.COPIED,
new Pair<Integer, String>(version, src.getPath() + '/' + child.getName() ),
newParent.getPath() + '/' + child.getName());
processEvent(event, callbacks);
// Otherwise copy the child directory recursively.
copyDirectory(version, child, newParent, remote, matcher, callbacks);
}
} }
} }
} }