From 109b51fb98482943596b915743f9bfc16ee127be Mon Sep 17 00:00:00 2001 From: Mark Rogers Date: Fri, 13 Feb 2009 18:35:21 +0000 Subject: [PATCH] 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 --- .../repo/deploy/ASRDeploymentTest.java | 437 ++++++++++++++++++ .../repo/deploy/DeploymentServiceImpl.java | 244 ++++++---- 2 files changed, 598 insertions(+), 83 deletions(-) create mode 100644 source/java/org/alfresco/repo/deploy/ASRDeploymentTest.java diff --git a/source/java/org/alfresco/repo/deploy/ASRDeploymentTest.java b/source/java/org/alfresco/repo/deploy/ASRDeploymentTest.java new file mode 100644 index 0000000000..e0d96560c3 --- /dev/null +++ b/source/java/org/alfresco/repo/deploy/ASRDeploymentTest.java @@ -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 callbacks = new ArrayList(); + 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 firstDeployment = new HashSet(); + 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(); + 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(); + callbacks.add(new DeploymentReportCallback(report)); + service.deployDifference(-1, "main:/", "localhost", 50500, "admin", "admin", destRef, matcher, true, false, false, callbacks); + Set smallUpdate = new HashSet(); + 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(); + 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(); + 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(); + 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 callbacks = new ArrayList(); +// callbacks.add(new DeploymentReportCallback(report)); +// +// report = new DeploymentReport(); +// callbacks = new ArrayList(); +// 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 smallUpdate = new HashSet(); +// 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 callbacks = new ArrayList(); +// callbacks.add(new DeploymentReportCallback(report)); +// +// report = new DeploymentReport(); +// callbacks = new ArrayList(); +// 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(); +// 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(); +// callbacks.add(new DeploymentReportCallback(report)); +// service.deployDifferenceFS(version, "main:/", "default", "localhost", 44100, TEST_USER, TEST_PASSWORD, TEST_TARGET, null, false, false, false, callbacks); +// Set smallUpdate = new HashSet(); +// 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 callbacks = new ArrayList(); +// 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(); +// callbacks.add(new DeploymentReportCallback(report)); +// service.deployDifferenceFS(-1, "main:/", "default", "localhost", 44100, TEST_USER, TEST_PASSWORD, TEST_TARGET, null, false, false, false, callbacks); +// Set bigUpdate = new HashSet(); +// 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(); +// callbacks.add(new DeploymentReportCallback(report)); +// service.deployDifferenceFS(-1, "main:/", "default", "localhost", 44100, TEST_USER, TEST_PASSWORD, TEST_TARGET, null, false, false, false, callbacks); +// +// Set smallUpdate = new HashSet(); +// 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))); +// } + +} diff --git a/source/java/org/alfresco/repo/deploy/DeploymentServiceImpl.java b/source/java/org/alfresco/repo/deploy/DeploymentServiceImpl.java index cfa9fdceb7..f78136d507 100644 --- a/source/java/org/alfresco/repo/deploy/DeploymentServiceImpl.java +++ b/source/java/org/alfresco/repo/deploy/DeploymentServiceImpl.java @@ -150,11 +150,18 @@ public class DeploymentServiceImpl implements DeploymentService * (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) */ - public void deployDifference(int version, String srcPath, String hostName, - int port, String userName, String password, - String dstPath, NameMatcher matcher, boolean createDst, - boolean dontDelete, boolean dontDo, - List callbacks) + public void deployDifference(int version, + String srcPath, + String hostName, + int port, + String userName, + String password, + String dstPath, + final NameMatcher matcher, + boolean createDst, + final boolean dontDelete, + final boolean dontDo, + final List callbacks) { DeploymentDestination dest = getLock(hostName, port); synchronized (dest) @@ -165,11 +172,28 @@ public class DeploymentServiceImpl implements DeploymentService } 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) { - 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 localSnapshot = new RetryingTransactionCallback() + { + 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); } { @@ -178,9 +202,55 @@ public class DeploymentServiceImpl implements DeploymentService dstPath); 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 readRoot = new RetryingTransactionCallback() + { + 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. - AVMNodeDescriptor srcRoot = fAVMService.lookup(version, srcPath); + // AVMNodeDescriptor srcRoot = fAVMService.lookup(version, srcPath); + if (srcRoot == null) { throw new AVMNotFoundException("Directory Not Found: " + srcPath); @@ -189,97 +259,92 @@ public class DeploymentServiceImpl implements DeploymentService { 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. - AVMNodeDescriptor dstRoot = remote.lookup(-1, dstPath); - if (dstRoot == null) + if (createdRoot) { - // If it doesn't exist, do a copyDirectory to create it. - DeploymentEvent event = - new DeploymentEvent(DeploymentEvent.Type.COPIED, - new Pair(version, srcPath), - dstPath); - if (fgLogger.isDebugEnabled()) - { - fgLogger.debug(event); - } - processEvent(event, callbacks); + /** + * This is the first deployment + */ if (dontDo) { + fgLogger.debug("dont do specified returning"); return; } - copyDirectory(version, srcRoot, dstParent, remote, matcher); + + /** + * Copy the new directory + */ + fgLogger.debug("start copying to remote"); + final AVMNodeDescriptor dstParentNode = dstRoot; + RetryingTransactionCallback copyContents = new RetryingTransactionCallback() + { + 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."); if (callbacks != null) { - event = new DeploymentEvent(DeploymentEvent.Type.END, + DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.END, new Pair(version, srcPath), dstPath); - if (fgLogger.isDebugEnabled()) - { - fgLogger.debug(event); - } processEvent(event, callbacks); } return; } + + /** + * The destination directory exists - check is actually a directory + */ if (!dstRoot.isDirectory()) { throw new AVMWrongTypeException("Not a Directory: " + dstPath); } - // The corresponding directory exists so recursively deploy. + try { - deployDirectoryPush(version, srcRoot, dstRoot, remote, matcher, dontDelete, dontDo, callbacks); - remote.createSnapshot(storePath[0], "Deployment", "Post Deployment Snapshot."); - if (callbacks != null) + /** + * Recursivly copy + */ + fgLogger.debug("both src and dest exist, recursivly deploy"); + final AVMNodeDescriptor dstParentNode = dstRoot; + RetryingTransactionCallback copyContentsRecursivly = new RetryingTransactionCallback() { + 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, new Pair(version, srcPath), dstPath); processEvent(event, callbacks); - - } return; } catch (AVMException e) { - if (callbacks != null) - { - DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.FAILED, - new Pair(version, srcPath), - dstPath, e.getMessage()); - for (DeploymentCallback callback : callbacks) - { - callback.eventOccurred(event); - } - } + fgLogger.debug("error during remote copy and snapshot"); try { if (snapshot != -1) { + fgLogger.debug("Attempting to roll back "); AVMSyncService syncService = getSyncService(hostName, port); List diffs = syncService.compare(snapshot, dstPath, -1, dstPath, null); syncService.update(diffs, null, false, false, true, true, "Aborted Deployment", "Aborted Deployment"); @@ -294,21 +359,20 @@ public class DeploymentServiceImpl implements DeploymentService } catch (Exception e) { - if (callbacks != null) - { - DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.FAILED, + DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.FAILED, new Pair(version, srcPath), dstPath, e.getMessage()); - processEvent(event, callbacks); - } - throw new AVMException("Deployment to " + hostName + " failed.", e); + processEvent(event, callbacks); + + throw new AVMException("Deployment to " + hostName + " failed." + e.toString(), e); } finally { + fgLogger.debug("ASR Finally block, Releasing ASR deployment ticket"); fTicketHolder.setTicket(null); } } - } + } /** * Deploy all the children of corresponding directories. (ASR version) @@ -410,7 +474,7 @@ public class DeploymentServiceImpl implements DeploymentService { return; } - copyDirectory(version, src, dstParent, remote, matcher); + copyDirectory(version, src, dstParent, remote, matcher, callbacks); return; } Pair source = @@ -451,8 +515,10 @@ public class DeploymentServiceImpl implements DeploymentService { return; } + // MER WHY IS THIS HERE ? + fgLogger.debug("Remove and recopy node :" + dstParent.getPath() + '/' + src.getName()); remote.removeNode(dstParent.getPath(), src.getName()); - copyDirectory(version, src, dstParent, remote, matcher); + copyDirectory(version, src, dstParent, remote, matcher, callbacks); return; } // Source is a file. @@ -469,10 +535,6 @@ public class DeploymentServiceImpl implements DeploymentService DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.UPDATED, source, destination); - if (fgLogger.isDebugEnabled()) - { - fgLogger.debug(event); - } processEvent(event, callbacks); if (dontDo) { @@ -511,7 +573,7 @@ public class DeploymentServiceImpl implements DeploymentService * @param remote */ private void copyDirectory(int version, AVMNodeDescriptor src, AVMNodeDescriptor parent, - AVMRemote remote, NameMatcher matcher) + AVMRemote remote, NameMatcher matcher, Listcallbacks) { // Create the destination directory. remote.createDirectory(parent.getPath(), src.getName()); @@ -524,17 +586,33 @@ public class DeploymentServiceImpl implements DeploymentService { if (!excluded(matcher, child.getPath(), null)) { + + // If it's a file, copy it over and move on. if (child.isFile()) - { + { + DeploymentEvent event = + new DeploymentEvent(DeploymentEvent.Type.COPIED, + new Pair(version, src.getPath() + '/' + child.getName()), + newParent.getPath() + '/' + child.getName()); + processEvent(event, callbacks); + InputStream in = fAVMService.getFileInputStream(child); OutputStream out = remote.createFile(newParent.getPath(), child.getName()); copyStream(in, out); copyMetadata(version, child, remote.lookup(-1, newParent.getPath() + '/' + child.getName()), remote); - continue; } - // Otherwise copy the child directory recursively. - copyDirectory(version, child, newParent, remote, matcher); + else + { + // is a directory + DeploymentEvent event = + new DeploymentEvent(DeploymentEvent.Type.COPIED, + new Pair(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); + } } } }