From c012545bfa68f701cefc7db667402a64fdbdbcfd Mon Sep 17 00:00:00 2001 From: Britt Park Date: Thu, 7 Dec 2006 01:02:40 +0000 Subject: [PATCH] Callback mechanism for notifying CIFS when Stores are created or purged, and when versions are created or purged. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@4541 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/avm-services-context.xml | 20 +++ .../org/alfresco/repo/avm/AVMRepository.java | 76 +++++++--- .../alfresco/repo/avm/AVMServiceTestBase.java | 40 +++++ .../repo/avm/CreateStoreCallback.java | 18 +++ .../repo/avm/CreateStoreTxnListener.java | 89 +++++++++++ .../repo/avm/CreateVersionCallback.java | 18 +++ .../repo/avm/CreateVersionTxnListener.java | 91 +++++++++++ .../org/alfresco/repo/avm/OrphanReaper.java | 1 - .../alfresco/repo/avm/PurgeStoreCallback.java | 17 +++ .../repo/avm/PurgeStoreTxnListener.java | 89 +++++++++++ .../java/org/alfresco/repo/avm/PurgeTest.java | 141 ------------------ .../org/alfresco/repo/avm/PurgeTestP.java | 141 ++++++++++++++++++ .../repo/avm/PurgeVersionCallback.java | 18 +++ .../repo/avm/PurgeVersionTxnListener.java | 91 +++++++++++ 14 files changed, 687 insertions(+), 163 deletions(-) create mode 100644 source/java/org/alfresco/repo/avm/CreateStoreCallback.java create mode 100644 source/java/org/alfresco/repo/avm/CreateStoreTxnListener.java create mode 100644 source/java/org/alfresco/repo/avm/CreateVersionCallback.java create mode 100644 source/java/org/alfresco/repo/avm/CreateVersionTxnListener.java create mode 100644 source/java/org/alfresco/repo/avm/PurgeStoreCallback.java create mode 100644 source/java/org/alfresco/repo/avm/PurgeStoreTxnListener.java delete mode 100644 source/java/org/alfresco/repo/avm/PurgeTest.java create mode 100644 source/java/org/alfresco/repo/avm/PurgeTestP.java create mode 100644 source/java/org/alfresco/repo/avm/PurgeVersionCallback.java create mode 100644 source/java/org/alfresco/repo/avm/PurgeVersionTxnListener.java diff --git a/config/alfresco/avm-services-context.xml b/config/alfresco/avm-services-context.xml index ec6f032d1a..99ac4cdce0 100644 --- a/config/alfresco/avm-services-context.xml +++ b/config/alfresco/avm-services-context.xml @@ -165,6 +165,14 @@ + + + + + + + + @@ -178,6 +186,18 @@ + + + + + + + + + + + + diff --git a/source/java/org/alfresco/repo/avm/AVMRepository.java b/source/java/org/alfresco/repo/avm/AVMRepository.java index 453f7caaa3..40c4872e76 100644 --- a/source/java/org/alfresco/repo/avm/AVMRepository.java +++ b/source/java/org/alfresco/repo/avm/AVMRepository.java @@ -30,6 +30,7 @@ import java.util.SortedMap; import org.alfresco.repo.content.ContentStore; import org.alfresco.repo.domain.DbAccessControlList; import org.alfresco.repo.domain.PropertyValue; +import org.alfresco.repo.transaction.AlfrescoTransactionSupport; import org.alfresco.service.cmr.avm.AVMBadArgumentException; import org.alfresco.service.cmr.avm.AVMCycleException; import org.alfresco.service.cmr.avm.AVMException; @@ -86,6 +87,28 @@ public class AVMRepository */ private LookupCache fLookupCache; + // A bunch of TransactionListeners that do work for this. + + /** + * One for create store. + */ + private CreateStoreTxnListener fCreateStoreTxnListener; + + /** + * One for purge store. + */ + private PurgeStoreTxnListener fPurgeStoreTxnListener; + + /** + * One for create version. + */ + private CreateVersionTxnListener fCreateVersionTxnListener; + + /** + * One for purge version. + */ + private PurgeVersionTxnListener fPurgeVersionTxnListener; + /** * Create a new one. */ @@ -130,6 +153,26 @@ public class AVMRepository fLookupCache = cache; } + public void setCreateStoreTxnListener(CreateStoreTxnListener listener) + { + fCreateStoreTxnListener = listener; + } + + public void setPurgeStoreTxnListener(PurgeStoreTxnListener listener) + { + fPurgeStoreTxnListener = listener; + } + + public void setCreateVersionTxnListener(CreateVersionTxnListener listener) + { + fCreateVersionTxnListener = listener; + } + + public void setPurgeVersionTxnListener(PurgeVersionTxnListener listener) + { + fPurgeVersionTxnListener = listener; + } + /** * Create a file. * @param path The path to the containing directory. @@ -311,6 +354,7 @@ public class AVMRepository */ public void createAVMStore(String name) { + AlfrescoTransactionSupport.bindListener(fCreateStoreTxnListener); if (getAVMStoreByName(name) != null) { throw new AVMExistsException("AVMStore exists: " + name); @@ -320,6 +364,7 @@ public class AVMRepository AVMStore rep = new AVMStoreImpl(this, name); // Special handling for AVMStore creation. rep.getRoot().setStoreNew(null); + fCreateStoreTxnListener.storeCreated(name); } /** @@ -672,27 +717,6 @@ public class AVMRepository } } - /** - * Snapshot the given repositories. - * @param repositories The list of AVMStore name to snapshot. - * @return A List of version ids for each newly snapshotted AVMStore. - */ - public List createSnapshot(List repositories) - { - List result = new ArrayList(); - for (String repName : repositories) - { - AVMStore store = getAVMStoreByName(repName); - if (store == null) - { - throw new AVMNotFoundException("Store not found."); - } - fLookupCache.onSnapshot(repName); - result.add(store.createSnapshot(null, null)); - } - return result; - } - /** * Create a snapshot of a single AVMStore. * @param store The name of the repository. @@ -702,6 +726,7 @@ public class AVMRepository */ public int createSnapshot(String storeName, String tag, String description) { + AlfrescoTransactionSupport.bindListener(fCreateVersionTxnListener); AVMStore store = getAVMStoreByName(storeName); if (store == null) { @@ -709,6 +734,7 @@ public class AVMRepository } fLookupCache.onSnapshot(storeName); int result = store.createSnapshot(tag, description); + fCreateVersionTxnListener.versionCreated(storeName, result); return result; } @@ -745,6 +771,7 @@ public class AVMRepository @SuppressWarnings("unchecked") public void purgeAVMStore(String name) { + AlfrescoTransactionSupport.bindListener(fPurgeStoreTxnListener); AVMStore store = getAVMStoreByName(name); if (store == null) { @@ -769,6 +796,7 @@ public class AVMRepository AVMDAOs.Instance().fAVMStorePropertyDAO.delete(store); AVMDAOs.Instance().fAVMStoreDAO.delete(store); AVMDAOs.Instance().fAVMStoreDAO.invalidateCache(); + fPurgeStoreTxnListener.storePurged(name); } /** @@ -778,6 +806,7 @@ public class AVMRepository */ public void purgeVersion(String name, int version) { + AlfrescoTransactionSupport.bindListener(fPurgeVersionTxnListener); AVMStore store = getAVMStoreByName(name); if (store == null) { @@ -785,6 +814,7 @@ public class AVMRepository } fLookupCache.onDelete(name); store.purgeVersion(version); + fPurgeVersionTxnListener.versionPurged(name, version); } /** @@ -2279,6 +2309,8 @@ public class AVMRepository */ public void renameStore(String sourceName, String destName) { + AlfrescoTransactionSupport.bindListener(fPurgeStoreTxnListener); + AlfrescoTransactionSupport.bindListener(fCreateStoreTxnListener); AVMStore store = getAVMStoreByName(sourceName); if (store == null) { @@ -2295,5 +2327,7 @@ public class AVMRepository store.setName(destName); fLookupCache.onDelete(sourceName); AVMDAOs.Instance().fAVMStoreDAO.invalidateCache(); + fPurgeStoreTxnListener.storePurged(sourceName); + fCreateStoreTxnListener.storeCreated(destName); } } diff --git a/source/java/org/alfresco/repo/avm/AVMServiceTestBase.java b/source/java/org/alfresco/repo/avm/AVMServiceTestBase.java index 9ee5ba0cd3..ef8054ea13 100644 --- a/source/java/org/alfresco/repo/avm/AVMServiceTestBase.java +++ b/source/java/org/alfresco/repo/avm/AVMServiceTestBase.java @@ -75,6 +75,46 @@ public class AVMServiceTestBase extends TestCase fService = (AVMService)fContext.getBean("AVMService"); fReaper = (OrphanReaper)fContext.getBean("orphanReaper"); fSyncService = (AVMSyncService)fContext.getBean("AVMSyncService"); + CreateStoreTxnListener cstl = (CreateStoreTxnListener)fContext.getBean("createStoreTxnListener"); + cstl.addCallback( + new CreateStoreCallback() + { + public void storeCreated(String name) + { + System.err.println("Store created: " + name); + } + } + ); + PurgeStoreTxnListener pstl = (PurgeStoreTxnListener)fContext.getBean("purgeStoreTxnListener"); + pstl.addCallback( + new PurgeStoreCallback() + { + public void storePurged(String name) + { + System.err.println("Store purged: " + name); + } + } + ); + CreateVersionTxnListener cvtl = (CreateVersionTxnListener)fContext.getBean("createVersionTxnListener"); + cvtl.addCallback( + new CreateVersionCallback() + { + public void versionCreated(String name, int versionID) + { + System.err.println("Version created: " + name + " " + versionID); + } + } + ); + PurgeVersionTxnListener pvtl = (PurgeVersionTxnListener)fContext.getBean("purgeVersionTxnListener"); + pvtl.addCallback( + new PurgeVersionCallback() + { + public void versionPurged(String name, int versionID) + { + System.err.println("Version purged: " + name + " " + versionID); + } + } + ); } fService.createAVMStore("main"); fStartTime = System.currentTimeMillis(); diff --git a/source/java/org/alfresco/repo/avm/CreateStoreCallback.java b/source/java/org/alfresco/repo/avm/CreateStoreCallback.java new file mode 100644 index 0000000000..872210e6b5 --- /dev/null +++ b/source/java/org/alfresco/repo/avm/CreateStoreCallback.java @@ -0,0 +1,18 @@ +/** + * + */ +package org.alfresco.repo.avm; + +/** + * Interface for listeners to new store events. + * @author britt + */ +public interface CreateStoreCallback +{ + /** + * A new store has been created. + * @param storeName The name of the new store. + */ + public void storeCreated(String storeName); +} + diff --git a/source/java/org/alfresco/repo/avm/CreateStoreTxnListener.java b/source/java/org/alfresco/repo/avm/CreateStoreTxnListener.java new file mode 100644 index 0000000000..a11d060fdb --- /dev/null +++ b/source/java/org/alfresco/repo/avm/CreateStoreTxnListener.java @@ -0,0 +1,89 @@ +/** + * + */ +package org.alfresco.repo.avm; + +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.repo.transaction.TransactionListenerAdapter; + +/** + * Transaction listener for firing create store events. + * @author britt + */ +public class CreateStoreTxnListener extends TransactionListenerAdapter +{ + /** + * Storage for stores created in a transaction. + */ + private ThreadLocal> fCreatedStores; + + /** + * Callbacks to invoke on commit. + */ + private List fCallbacks; + + /** + * Default constructor. + */ + public CreateStoreTxnListener() + { + fCreatedStores = new ThreadLocal>(); + fCallbacks = new ArrayList(); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.transaction.TransactionListenerAdapter#afterCommit() + */ + @Override + public void afterCommit() + { + List created = fCreatedStores.get(); + for (String name : created) + { + synchronized (this) + { + for (CreateStoreCallback cb : fCallbacks) + { + cb.storeCreated(name); + } + } + } + fCreatedStores.set(null); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.transaction.TransactionListenerAdapter#afterRollback() + */ + @Override + public void afterRollback() + { + fCreatedStores.set(null); + } + + /** + * During the transaction somebody is responsible for + * calling this. + * @param storeName The name of the store that has been created. + */ + public void storeCreated(String storeName) + { + List created = fCreatedStores.get(); + if (created == null) + { + created = new ArrayList(); + fCreatedStores.set(created); + } + created.add(storeName); + } + + /** + * Register a callback. + * @param cb The callback. + */ + public synchronized void addCallback(CreateStoreCallback cb) + { + fCallbacks.add(cb); + } +} diff --git a/source/java/org/alfresco/repo/avm/CreateVersionCallback.java b/source/java/org/alfresco/repo/avm/CreateVersionCallback.java new file mode 100644 index 0000000000..388637dc29 --- /dev/null +++ b/source/java/org/alfresco/repo/avm/CreateVersionCallback.java @@ -0,0 +1,18 @@ +/** + * + */ +package org.alfresco.repo.avm; + +/** + * Callback interface for those interested in new version creation. + * @author britt + */ +public interface CreateVersionCallback +{ + /** + * A version of a store has been purged. + * @param storeName The name of the store in which a new version has been created. + * @param versionID The version id of the new version. + */ + public void versionCreated(String storeName, int versionID); +} diff --git a/source/java/org/alfresco/repo/avm/CreateVersionTxnListener.java b/source/java/org/alfresco/repo/avm/CreateVersionTxnListener.java new file mode 100644 index 0000000000..9841d78e77 --- /dev/null +++ b/source/java/org/alfresco/repo/avm/CreateVersionTxnListener.java @@ -0,0 +1,91 @@ +/** + * + */ +package org.alfresco.repo.avm; + +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.repo.transaction.TransactionListenerAdapter; +import org.alfresco.util.Pair; + +/** + * Transaction listener that fires create version events. + * @author britt + */ +public class CreateVersionTxnListener extends TransactionListenerAdapter +{ + /** + * Storage for versions created in a transaction. + */ + private ThreadLocal>> fCreatedVersions; + + /** + * Callbacks to invoke on commit. + */ + private List fCallbacks; + + /** + * Default constructor. + */ + public CreateVersionTxnListener() + { + fCreatedVersions = new ThreadLocal>>(); + fCallbacks = new ArrayList(); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.transaction.TransactionListenerAdapter#afterCommit() + */ + @Override + public void afterCommit() + { + List> created = fCreatedVersions.get(); + for (Pair version : created) + { + synchronized (this) + { + for (CreateVersionCallback cb : fCallbacks) + { + cb.versionCreated(version.getFirst(), version.getSecond()); + } + } + } + fCreatedVersions.set(null); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.transaction.TransactionListenerAdapter#afterRollback() + */ + @Override + public void afterRollback() + { + fCreatedVersions.set(null); + } + + /** + * During the transaction somebody is responsible for + * calling this. + * @param storeName The name of the store that just created a new version + * @param versionID The id of the new version. + */ + public void versionCreated(String storeName, int versionID) + { + List> created = fCreatedVersions.get(); + if (created == null) + { + created = new ArrayList>(); + fCreatedVersions.set(created); + } + created.add(new Pair(storeName, versionID)); + } + + /** + * Register a callback. + * @param cb The callback. + */ + public synchronized void addCallback(CreateVersionCallback cb) + { + fCallbacks.add(cb); + } +} diff --git a/source/java/org/alfresco/repo/avm/OrphanReaper.java b/source/java/org/alfresco/repo/avm/OrphanReaper.java index ee7cf96b9b..221ef0a228 100644 --- a/source/java/org/alfresco/repo/avm/OrphanReaper.java +++ b/source/java/org/alfresco/repo/avm/OrphanReaper.java @@ -20,7 +20,6 @@ package org.alfresco.repo.avm; import java.util.LinkedList; import java.util.List; -import org.alfresco.repo.avm.util.RawServices; import org.alfresco.repo.domain.DbAccessControlList; import org.alfresco.repo.transaction.TransactionUtil; import org.alfresco.service.transaction.TransactionService; diff --git a/source/java/org/alfresco/repo/avm/PurgeStoreCallback.java b/source/java/org/alfresco/repo/avm/PurgeStoreCallback.java new file mode 100644 index 0000000000..fac487ef4c --- /dev/null +++ b/source/java/org/alfresco/repo/avm/PurgeStoreCallback.java @@ -0,0 +1,17 @@ +/** + * + */ +package org.alfresco.repo.avm; + +/** + * Callback interface for those interested in store purges. + * @author britt + */ +public interface PurgeStoreCallback +{ + /** + * A store has been purged. + * @param storeName The name of the purged store. + */ + public void storePurged(String storeName); +} diff --git a/source/java/org/alfresco/repo/avm/PurgeStoreTxnListener.java b/source/java/org/alfresco/repo/avm/PurgeStoreTxnListener.java new file mode 100644 index 0000000000..1a657e2ffe --- /dev/null +++ b/source/java/org/alfresco/repo/avm/PurgeStoreTxnListener.java @@ -0,0 +1,89 @@ +/** + * + */ +package org.alfresco.repo.avm; + +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.repo.transaction.TransactionListenerAdapter; + +/** + * Transaction listener for firing purge store events. + * @author britt + */ +public class PurgeStoreTxnListener extends TransactionListenerAdapter +{ + /** + * Storage for stores purged in a transaction. + */ + private ThreadLocal> fPurgedStores; + + /** + * Callbacks to invoke on commit. + */ + private List fCallbacks; + + /** + * Default constructor. + */ + public PurgeStoreTxnListener() + { + fPurgedStores = new ThreadLocal>(); + fCallbacks = new ArrayList(); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.transaction.TransactionListenerAdapter#afterCommit() + */ + @Override + public void afterCommit() + { + List created = fPurgedStores.get(); + for (String name : created) + { + synchronized (this) + { + for (PurgeStoreCallback cb : fCallbacks) + { + cb.storePurged(name); + } + } + } + fPurgedStores.set(null); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.transaction.TransactionListenerAdapter#afterRollback() + */ + @Override + public void afterRollback() + { + fPurgedStores.set(null); + } + + /** + * During the transaction somebody is responsible for + * calling this. + * @param storeName The name of the store that has been purged. + */ + public void storePurged(String storeName) + { + List purged = fPurgedStores.get(); + if (purged == null) + { + purged = new ArrayList(); + fPurgedStores.set(purged); + } + purged.add(storeName); + } + + /** + * Register a callback. + * @param cb The callback. + */ + public synchronized void addCallback(PurgeStoreCallback cb) + { + fCallbacks.add(cb); + } +} diff --git a/source/java/org/alfresco/repo/avm/PurgeTest.java b/source/java/org/alfresco/repo/avm/PurgeTest.java deleted file mode 100644 index 9d607eafd7..0000000000 --- a/source/java/org/alfresco/repo/avm/PurgeTest.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2006 Alfresco, Inc. - * - * Licensed under the Mozilla Public License version 1.1 - * with a permitted attribution clause. You may obtain a - * copy of the License at - * - * http://www.alfresco.org/legal/license.txt - * - * 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 org.alfresco.repo.avm; - -import org.alfresco.repo.avm.util.BulkLoader; - -/** - * Test the purge thread. - * @author britt - */ -public class PurgeTest extends AVMServiceTestBase -{ - /** - * Test purging a version. - */ - public void testPurgeVersion() - { -// try -// { -// setupBasicTree(); -// BulkLoader loader = new BulkLoader(); -// loader.setAvmService(fService); -// long start = System.currentTimeMillis(); -// loader.recursiveLoad("source/web", "main:/"); -// System.err.println("Load time: " + (System.currentTimeMillis() - start) + "ms"); -// fService.createSnapshot("main", null, null); -// System.err.println("Load time + snapshot: " + (System.currentTimeMillis() - start) + "ms"); -// fService.purgeVersion(2, "main"); -// fReaper.activate(); -// while (fReaper.isActive()) -// { -// try -// { -// Thread.sleep(2000); -// } -// catch (InterruptedException e) -// { -// // Do nothing. -// } -// } -// } -// catch (Exception e) -// { -// e.printStackTrace(System.err); -// fail(); -// } - } - - /** - * Test purging a version that's not the latest. - */ - public void testPurgeOlderVersion() - { -// try -// { -// setupBasicTree(); -// BulkLoader loader = new BulkLoader(); -// loader.setAvmService(fService); -// long start = System.currentTimeMillis(); -// loader.recursiveLoad("source", "main:/"); -// System.err.println("Load time: " + (System.currentTimeMillis() - start) + "ms"); -// fService.createSnapshot("main", null, null); -// System.err.println("Load time + snapshot: " + (System.currentTimeMillis() - start) + "ms"); -// fService.removeNode("main:/source/java/org/alfresco", "repo"); -// fService.createSnapshot("main", null, null); -// fService.purgeVersion(2, "main"); -// fReaper.activate(); -// while (fReaper.isActive()) -// { -// try -// { -// Thread.sleep(2000); -// } -// catch (InterruptedException e) -// { -// // Do nothing. -// } -// } -// } -// catch (Exception e) -// { -// e.printStackTrace(System.err); -// fail(); -// } - } - - /** - * Test purging an entire store. - */ - public void testPurgeStore() - { -// try -// { -// setupBasicTree(); -// BulkLoader loader = new BulkLoader(); -// loader.setAvmService(fService); -// long start = System.currentTimeMillis(); -// loader.recursiveLoad("source", "main:/"); -// System.err.println("Load time: " + (System.currentTimeMillis() - start) + "ms"); -// fService.createSnapshot("main", null, null); -// System.err.println("Load time + snapshot: " + (System.currentTimeMillis() - start) + "ms"); -// fService.createLayeredDirectory("main:/source", "main:/", "layer"); -// fService.removeNode("main:/layer/java/org/alfresco", "repo"); -// fService.createFile("main:/layer/java/org/alfresco", "goofy").close(); -// fService.createSnapshot("main", null, null); -// fService.purgeAVMStore("main"); -// fReaper.activate(); -// while (fReaper.isActive()) -// { -// try -// { -// Thread.sleep(2000); -// } -// catch (InterruptedException e) -// { -// // Do nothing. -// } -// } -// } -// catch (Exception e) -// { -// e.printStackTrace(System.err); -// fail(); -// } - } -} diff --git a/source/java/org/alfresco/repo/avm/PurgeTestP.java b/source/java/org/alfresco/repo/avm/PurgeTestP.java new file mode 100644 index 0000000000..eefecb1357 --- /dev/null +++ b/source/java/org/alfresco/repo/avm/PurgeTestP.java @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2006 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * 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 org.alfresco.repo.avm; + +import org.alfresco.repo.avm.util.BulkLoader; + +/** + * Test the purge thread. + * @author britt + */ +public class PurgeTestP extends AVMServiceTestBase +{ + /** + * Test purging a version. + */ + public void testPurgeVersion() + { + try + { + setupBasicTree(); + BulkLoader loader = new BulkLoader(); + loader.setAvmService(fService); + long start = System.currentTimeMillis(); + loader.recursiveLoad("source/web", "main:/"); + System.err.println("Load time: " + (System.currentTimeMillis() - start) + "ms"); + fService.createSnapshot("main", null, null); + System.err.println("Load time + snapshot: " + (System.currentTimeMillis() - start) + "ms"); + fService.purgeVersion(2, "main"); + fReaper.activate(); + while (fReaper.isActive()) + { + try + { + Thread.sleep(2000); + } + catch (InterruptedException e) + { + // Do nothing. + } + } + } + catch (Exception e) + { + e.printStackTrace(System.err); + fail(); + } + } + + /** + * Test purging a version that's not the latest. + */ + public void testPurgeOlderVersion() + { + try + { + setupBasicTree(); + BulkLoader loader = new BulkLoader(); + loader.setAvmService(fService); + long start = System.currentTimeMillis(); + loader.recursiveLoad("source", "main:/"); + System.err.println("Load time: " + (System.currentTimeMillis() - start) + "ms"); + fService.createSnapshot("main", null, null); + System.err.println("Load time + snapshot: " + (System.currentTimeMillis() - start) + "ms"); + fService.removeNode("main:/source/java/org/alfresco", "repo"); + fService.createSnapshot("main", null, null); + fService.purgeVersion(2, "main"); + fReaper.activate(); + while (fReaper.isActive()) + { + try + { + Thread.sleep(2000); + } + catch (InterruptedException e) + { + // Do nothing. + } + } + } + catch (Exception e) + { + e.printStackTrace(System.err); + fail(); + } + } + + /** + * Test purging an entire store. + */ + public void testPurgeStore() + { + try + { + setupBasicTree(); + BulkLoader loader = new BulkLoader(); + loader.setAvmService(fService); + long start = System.currentTimeMillis(); + loader.recursiveLoad("source", "main:/"); + System.err.println("Load time: " + (System.currentTimeMillis() - start) + "ms"); + fService.createSnapshot("main", null, null); + System.err.println("Load time + snapshot: " + (System.currentTimeMillis() - start) + "ms"); + fService.createLayeredDirectory("main:/source", "main:/", "layer"); + fService.removeNode("main:/layer/java/org/alfresco", "repo"); + fService.createFile("main:/layer/java/org/alfresco", "goofy").close(); + fService.createSnapshot("main", null, null); + fService.purgeAVMStore("main"); + fReaper.activate(); + while (fReaper.isActive()) + { + try + { + Thread.sleep(2000); + } + catch (InterruptedException e) + { + // Do nothing. + } + } + } + catch (Exception e) + { + e.printStackTrace(System.err); + fail(); + } + } +} diff --git a/source/java/org/alfresco/repo/avm/PurgeVersionCallback.java b/source/java/org/alfresco/repo/avm/PurgeVersionCallback.java new file mode 100644 index 0000000000..bda8a81800 --- /dev/null +++ b/source/java/org/alfresco/repo/avm/PurgeVersionCallback.java @@ -0,0 +1,18 @@ +/** + * + */ +package org.alfresco.repo.avm; + +/** + * A Callback interface for those interested in versions being purged. + * @author britt + */ +public interface PurgeVersionCallback +{ + /** + * A version was purged from a store. + * @param storeName The name of the store from which a version was purged. + * @param versionID The id of the purged version. + */ + public void versionPurged(String storeName, int versionID); +} diff --git a/source/java/org/alfresco/repo/avm/PurgeVersionTxnListener.java b/source/java/org/alfresco/repo/avm/PurgeVersionTxnListener.java new file mode 100644 index 0000000000..2bf2c30db0 --- /dev/null +++ b/source/java/org/alfresco/repo/avm/PurgeVersionTxnListener.java @@ -0,0 +1,91 @@ +/** + * + */ +package org.alfresco.repo.avm; + +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.repo.transaction.TransactionListenerAdapter; +import org.alfresco.util.Pair; + +/** + * Transaction listener that fires purge version events. + * @author britt + */ +public class PurgeVersionTxnListener extends TransactionListenerAdapter +{ + /** + * Storage for versions purged in a transaction. + */ + private ThreadLocal>> fPurgedVersions; + + /** + * Callbacks to invoke on commit. + */ + private List fCallbacks; + + /** + * Default constructor. + */ + public PurgeVersionTxnListener() + { + fPurgedVersions = new ThreadLocal>>(); + fCallbacks = new ArrayList(); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.transaction.TransactionListenerAdapter#afterCommit() + */ + @Override + public void afterCommit() + { + List> created = fPurgedVersions.get(); + for (Pair version : created) + { + synchronized (this) + { + for (PurgeVersionCallback cb : fCallbacks) + { + cb.versionPurged(version.getFirst(), version.getSecond()); + } + } + } + fPurgedVersions.set(null); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.transaction.TransactionListenerAdapter#afterRollback() + */ + @Override + public void afterRollback() + { + fPurgedVersions.set(null); + } + + /** + * During the transaction somebody is responsible for + * calling this. + * @param storeName The name of the store that just created a new version + * @param versionID The id of the new version. + */ + public void versionPurged(String storeName, int versionID) + { + List> purged = fPurgedVersions.get(); + if (purged == null) + { + purged = new ArrayList>(); + fPurgedVersions.set(purged); + } + purged.add(new Pair(storeName, versionID)); + } + + /** + * Register a callback. + * @param cb The callback. + */ + public synchronized void addCallback(PurgeVersionCallback cb) + { + fCallbacks.add(cb); + } +}