From 1362d02f8e275238690513b6920e167aa7edadfb Mon Sep 17 00:00:00 2001 From: Jan Vonka Date: Tue, 27 Oct 2009 11:13:25 +0000 Subject: [PATCH] Fix intermittent HEAD test failure (AVMCrawler -> NPE) git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@17175 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../org/alfresco/repo/avm/AVMCrawlTestP.java | 416 +++++++++--------- .../org/alfresco/repo/avm/AVMCrawler.java | 37 +- .../repo/avm/ibatis/ChildEntryDAOIbatis.java | 17 +- 3 files changed, 250 insertions(+), 220 deletions(-) diff --git a/source/java/org/alfresco/repo/avm/AVMCrawlTestP.java b/source/java/org/alfresco/repo/avm/AVMCrawlTestP.java index 43af609834..9a87ba29b8 100644 --- a/source/java/org/alfresco/repo/avm/AVMCrawlTestP.java +++ b/source/java/org/alfresco/repo/avm/AVMCrawlTestP.java @@ -1,203 +1,213 @@ -/* - * Copyright (C) 2005-2008 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.avm; - -import java.util.ArrayList; -import java.util.List; - -import net.sf.acegisecurity.Authentication; - -import org.alfresco.repo.avm.util.BulkLoader; -import org.alfresco.repo.security.authentication.AuthenticationUtil; - - -/** - * Another performance test that runs simultaneous crawlers that - * do operations with locality of reference. - * @author britt - */ -public class AVMCrawlTestP extends AVMServiceTestBase -{ - public void testCrawlA() - { - testCrawl(1, - "source/java/org/alfresco/repo/avm/actions", // relative from .../repository - 1, - 30000); // 30 secs - } - - public void testCrawlB() - { - testCrawl(2, - "source/java/org/alfresco/repo/avm", // relative from .../repository - 2, - 30000); // 30 secs - } - - /* - public void xtestCrawlZ() - { - testCrawl(8, - "source", // relative from .../repository - 2, - 28800000); // 8 hours - } - */ - - /** - * Do the crawl test - * - * @param n Number of threads - * @param fsPath The path in the filesystem to load (tree of stuff) from - * @param m How many multiples of content to start with - * @param runTime Min run time (in msecs) - */ - private void testCrawl(int n, String fsPath, int m, long runTime) - { - try - { - Authentication authentication = AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.SYSTEM_USER_NAME); - try - { - if (m < 1) - { - fail("Must have at least one 1 copy of content"); - } - - BulkLoader loader = new BulkLoader(); - loader.setAvmService(fService); - for (int i = 0; i < m; i++) - { - fService.createStore("d" + i); - loader.recursiveLoad(fsPath, "d" + i + ":/"); - fService.createSnapshot("d" + i, null, null); - } - long startTime = System.currentTimeMillis(); - List crawlers = new ArrayList(); - List threads = new ArrayList(); - for (int i = 0; i < n; i++) - { - crawlers.add(new AVMCrawler(fService, authentication)); - threads.add(new Thread(crawlers.get(i))); - threads.get(i).start(); - } - while (true) - { - try - { - Thread.sleep(5000); - // Check that none of the crawlers has errored out. - for (AVMCrawler crawler : crawlers) - { - if (crawler.getError()) - { - for (AVMCrawler craw : crawlers) - { - craw.setDone(); - } - for (Thread thread : threads) - { - try - { - thread.join(); - } - catch (InterruptedException ie) - { - // Do nothing. - } - } - //fail(); - System.err.println("Crawler error"); - } - } - } - catch (InterruptedException ie) - { - // Do nothing. - } - long now = System.currentTimeMillis(); - if (now - startTime > runTime) - { - break; - } - } - for (AVMCrawler crawler : crawlers) - { - crawler.setDone(); - } - for (Thread thread : threads) - { - try - { - thread.join(); - } - catch (InterruptedException ie) - { - // Do nothing. - } - } - long ops = 0L; - int errorCnt = 0; - for (AVMCrawler crawler : crawlers) - { - ops += crawler.getOpCount(); - errorCnt += (crawler.getError() ? 1 : 0); - } - - long time = System.currentTimeMillis() - startTime; - System.out.println("Ops/Sec: " + (ops * 1000L / time)); - - if (errorCnt > 0) - { - StringBuffer errorStack = new StringBuffer(); - errorStack.append("Crawler errors: ").append(errorCnt).append(" out of ").append(crawlers.size()).append(" are in error state"); - - for (AVMCrawler crawler : crawlers) - { - if (crawler.getError()) - { - errorStack.append("\n\n").append(crawler.getErrorStackTrace()); - } - } - - fail(errorStack.toString()); - } - } - finally - { - for (int i = 0; i < m; i++) - { - if (fService.getStore("d" + i) != null) - { - fService.purgeStore("d" + i); - } - } - } - } - finally - { - AuthenticationUtil.clearCurrentSecurityContext(); - } - } -} +/* + * Copyright (C) 2005-2009 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.avm; + +import java.util.ArrayList; +import java.util.List; + +import net.sf.acegisecurity.Authentication; + +import org.alfresco.repo.avm.util.BulkLoader; +import org.alfresco.repo.security.authentication.AuthenticationUtil; + + +/** + * Another performance test that runs simultaneous crawlers that + * do operations with locality of reference. + * @author britt + */ +public class AVMCrawlTestP extends AVMServiceTestBase +{ + public void testCrawlA() + { + testCrawl(1, + "source/java/org/alfresco/repo/avm/actions", // relative from .../repository + 1, + 30000); // 30 secs + } + + public void testCrawlB() + { + testCrawl(2, + "source/java/org/alfresco/repo/avm", // relative from .../repository + 2, + 30000); // 30 secs + } + + /* + public void xtestCrawlC() + { + testCrawl(10, + "source/java/org/alfresco/repo/avm", // relative from .../repository + 2, + 60000); // 1 min + } + */ + + /* + public void xtestCrawlZ() + { + testCrawl(8, + "source", // relative from .../repository + 2, + 28800000); // 8 hours + } + */ + + /** + * Do the crawl test + * + * @param n Number of threads + * @param fsPath The path in the filesystem to load (tree of stuff) from + * @param m How many multiples of content to start with + * @param runTime Min run time (in msecs) + */ + private void testCrawl(int n, String fsPath, int m, long runTime) + { + try + { + Authentication authentication = AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.SYSTEM_USER_NAME); + try + { + if (m < 1) + { + fail("Must have at least one 1 copy of content"); + } + + BulkLoader loader = new BulkLoader(); + loader.setAvmService(fService); + for (int i = 0; i < m; i++) + { + fService.createStore("d" + i); + loader.recursiveLoad(fsPath, "d" + i + ":/"); + fService.createSnapshot("d" + i, null, null); + } + long startTime = System.currentTimeMillis(); + List crawlers = new ArrayList(); + List threads = new ArrayList(); + for (int i = 0; i < n; i++) + { + crawlers.add(new AVMCrawler(fService, authentication)); + threads.add(new Thread(crawlers.get(i))); + threads.get(i).start(); + } + while (true) + { + try + { + Thread.sleep(5000); + // Check that none of the crawlers has errored out. + for (AVMCrawler crawler : crawlers) + { + if (crawler.getError()) + { + for (AVMCrawler craw : crawlers) + { + craw.setDone(); + } + for (Thread thread : threads) + { + try + { + thread.join(); + } + catch (InterruptedException ie) + { + // Do nothing. + } + } + //fail(); + System.err.println("Crawler error"); + } + } + } + catch (InterruptedException ie) + { + // Do nothing. + } + long now = System.currentTimeMillis(); + if (now - startTime > runTime) + { + break; + } + } + for (AVMCrawler crawler : crawlers) + { + crawler.setDone(); + } + for (Thread thread : threads) + { + try + { + thread.join(); + } + catch (InterruptedException ie) + { + // Do nothing. + } + } + long ops = 0L; + int errorCnt = 0; + for (AVMCrawler crawler : crawlers) + { + ops += crawler.getOpCount(); + errorCnt += (crawler.getError() ? 1 : 0); + } + + long time = System.currentTimeMillis() - startTime; + System.out.println("Ops/Sec: " + (ops * 1000L / time)); + + if (errorCnt > 0) + { + StringBuffer errorStack = new StringBuffer(); + errorStack.append("Crawler errors: ").append(errorCnt).append(" out of ").append(crawlers.size()).append(" are in error state"); + + for (AVMCrawler crawler : crawlers) + { + if (crawler.getError()) + { + errorStack.append("\n\n").append(crawler.getErrorStackTrace()); + } + } + + fail(errorStack.toString()); + } + } + finally + { + for (int i = 0; i < m; i++) + { + if (fService.getStore("d" + i) != null) + { + fService.purgeStore("d" + i); + } + } + } + } + finally + { + AuthenticationUtil.clearCurrentSecurityContext(); + } + } +} diff --git a/source/java/org/alfresco/repo/avm/AVMCrawler.java b/source/java/org/alfresco/repo/avm/AVMCrawler.java index 360e573e60..3e6db781ba 100644 --- a/source/java/org/alfresco/repo/avm/AVMCrawler.java +++ b/source/java/org/alfresco/repo/avm/AVMCrawler.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2008 Alfresco Software Limited. + * Copyright (C) 2005-2009 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 @@ -39,9 +39,12 @@ import net.sf.acegisecurity.Authentication; import org.alfresco.repo.security.authentication.AuthenticationUtil; 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.AVMService; import org.alfresco.service.cmr.avm.AVMStoreDescriptor; import org.alfresco.service.cmr.repository.ContentIOException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; /** @@ -50,6 +53,8 @@ import org.alfresco.service.cmr.repository.ContentIOException; */ class AVMCrawler implements Runnable { + private static Log logger = LogFactory.getLog(AVMCrawler.class); + /** * The AVMService to use. */ @@ -158,7 +163,7 @@ class AVMCrawler implements Runnable if (reps.size() == 0) { - System.out.println("No AVM stores"); + logger.warn("No AVM stores"); return; } @@ -177,7 +182,7 @@ class AVMCrawler implements Runnable if (dirs.size() == 0) { - System.out.println("No dirs in root: "+repDesc.getName() + ":/"); + logger.warn("No dirs in root: "+repDesc.getName() + ":/"); } else { @@ -205,20 +210,25 @@ class AVMCrawler implements Runnable { for (int i = 0; i < 6; i++) { + String path = files.get(fRandom.nextInt(files.size())).getPath(); + logger.info("Reading: " + path); BufferedReader reader = new BufferedReader (new InputStreamReader - (fService.getFileInputStream(-1, files.get(fRandom.nextInt(files.size())).getPath()))); + (fService.getFileInputStream(-1, path))); fOpCount++; String line = reader.readLine(); - System.out.println(line); + if (logger.isDebugEnabled()) + { + logger.debug(line); + } reader.close(); } // Modify some files. for (int i = 0; i < 2; i++) { String path = files.get(fRandom.nextInt(files.size())).getPath(); - System.out.println("Modifying: " + path); + logger.info("Modifying: " + path); PrintStream out = new PrintStream(fService.getFileOutputStream(path)); out.println("I am " + path); out.close(); @@ -235,7 +245,7 @@ class AVMCrawler implements Runnable { break; } - System.out.println("Creating File: " + name); + logger.info("Creating File: " + name); fService.createFile(dir.getPath(), name, new ByteArrayInputStream(("I am " + name).getBytes())); fOpCount++; @@ -249,7 +259,7 @@ class AVMCrawler implements Runnable { break; } - System.out.println("Creating Directory: " + name); + logger.info("Creating Directory: " + name); fService.createDirectory(dir.getPath(), name); fOpCount++; } @@ -260,7 +270,7 @@ class AVMCrawler implements Runnable { List names = new ArrayList(listing.keySet()); String name = names.get(fRandom.nextInt(names.size())); - System.out.println("Removing: " + name); + logger.info("Removing: " + name); fService.removeNode(dir.getPath(), name); fOpCount++; @@ -280,13 +290,18 @@ class AVMCrawler implements Runnable if (fRandom.nextInt(16) == 0) { - System.out.println("Snapshotting: " + repDesc.getName()); + logger.info("Snapshotting: " + repDesc.getName()); fService.createSnapshot(repDesc.getName(), null, null); fOpCount++; } } catch (Exception e) { + if (e instanceof AVMNotFoundException) + { + logger.info(e.getMessage()); + return; + } e.printStackTrace(System.err); if (e instanceof AVMException) { @@ -320,5 +335,3 @@ class AVMCrawler implements Runnable return fOpCount; } } - - diff --git a/source/java/org/alfresco/repo/avm/ibatis/ChildEntryDAOIbatis.java b/source/java/org/alfresco/repo/avm/ibatis/ChildEntryDAOIbatis.java index d68064746c..01274e2017 100644 --- a/source/java/org/alfresco/repo/avm/ibatis/ChildEntryDAOIbatis.java +++ b/source/java/org/alfresco/repo/avm/ibatis/ChildEntryDAOIbatis.java @@ -34,6 +34,7 @@ import org.alfresco.repo.avm.ChildEntryImpl; import org.alfresco.repo.avm.ChildKey; import org.alfresco.repo.avm.DirectoryNode; import org.alfresco.repo.domain.avm.AVMChildEntryEntity; +import org.springframework.dao.ConcurrencyFailureException; /** * iBATIS DAO wrapper for ChildEntry @@ -147,9 +148,12 @@ class ChildEntryDAOIbatis implements ChildEntryDAO AVMNode childNode = AVMDAOs.Instance().fAVMNodeDAO.getByID(childEntryEntity.getChildId()); + if (childNode == null) + { + throw new ConcurrencyFailureException("Child node (" + childEntryEntity.getParentNodeId() + ", " + childEntryEntity.getChildId() + ") no longer exists"); + } + ChildEntry ce = new ChildEntryImpl(new ChildKey(parentNode, childEntryEntity.getName()), childNode); - ce.setKey(new ChildKey(parentNode, childEntryEntity.getName())); - ce.setChild(childNode); return ce; } @@ -160,11 +164,14 @@ class ChildEntryDAOIbatis implements ChildEntryDAO return null; } - DirectoryNode parentNode = (DirectoryNode)AVMDAOs.Instance().fAVMNodeDAO.getByID(childEntryEntity.getParentNodeId()); + DirectoryNode parentNode = (DirectoryNode)AVMDAOs.Instance().fAVMNodeDAO.getByID(childEntryEntity.getParentNodeId()); + + if (parentNode == null) + { + throw new ConcurrencyFailureException("Parent node (" + childEntryEntity.getParentNodeId() + ", " + childEntryEntity.getChildId() + ") no longer exists"); + } ChildEntry ce = new ChildEntryImpl(new ChildKey(parentNode, childEntryEntity.getName()), childNode); - ce.setKey(new ChildKey(parentNode, childEntryEntity.getName())); - ce.setChild(childNode); return ce; } }