Merged V4.1-BUG-FIX to HEAD

40690: Removed 'repository-bm' project, which is no longer distributed, referenced or supported
    - Part of ALF-14420: Remove benchmarking tool (alfresco-bm.jar) from installer and Alfresco war installation file
    - Also: ALF-15588
   40692: Removed 'repository-bm' project, which is no longer distributed, referenced or supported
    - Part of ALF-14420: Remove benchmarking tool (alfresco-bm.jar) from installer and Alfresco war installation file
   40695: Fixed ALF-14420: Remove benchmarking tool (alfresco-bm.jar) from installer and Alfresco war installation file
    - Removed all related code as well
   40700: Remove XAM Connector.  Now built as a standalone project
   40707: ALF-14399 Share Calendar changes dates when "All Day" is selected. Event comparator now checks if date strings contain a time zone, previously was failing because we strip time zones from all day events.
   40708: Complete - task : ALF-14399 Share Calendar changes dates when "All Day" is selected. Added the time zone in which the recurrence rule was parsed to the recurrence rule string.
   40711: Merged V3.4-BUG-FIX to V4.1-BUG-FIX
      40700: (RECORD ONLY) Remove XAM Connector.  Now built as a standalone project
      40701: (RECORD ONLY) Remove Kofax.  Now built as a standalone integration.
      40703: (RECORD ONLY) Revert Kofax removal.
      40704: (RECORD ONLY) Revert XAM Connector removal for V3.4.
      40709: (RECORD ONLY) ALF-14752 - Collapse Links part at the WCM details page lead to error
      40710: ALF-15592: Merged PATCHES/V3.4.8 to V3.4-BUG-FIX
         40543: ALF-15507: Orphan content URLs when you overwrite a file with identical content in CIFS
         - Removed diffing behaviour that was leaking content URLs

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@40712 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Dave Ward
2012-08-22 09:27:02 +00:00
parent 4d5dbe31ed
commit b28d894e2a
18 changed files with 9 additions and 3662 deletions

View File

@@ -1,324 +0,0 @@
/*
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.model.filefolder.loader;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicBoolean;
import java.net.URL;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.cache.EhCacheAdapter;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Cache;
/**
* A description of what the remote loader should do.
*
* @author Derek Hulley
*/
public abstract class AbstractLoaderThread extends Thread
{
protected final LoaderSession session;
protected final String loaderName;
protected final long testPeriod;
protected final long testTotal;
protected final long testLoadDepth;
protected final boolean verbose;
private AtomicBoolean mustStop;
private Random random;
// Statistics
private int statCount;
private double statTotalMs;
private static EhCacheAdapter<String, NodeRef> pathCache;
static
{
System.setProperty(CacheManager.ENABLE_SHUTDOWN_HOOK_PROPERTY, "TRUE");
URL url = LoaderUploadThread.class.getResource("/org/alfresco/repo/model/filefolder/loader/loader-ehcache.xml");
CacheManager cacheManager = CacheManager.create(url);
Cache cache = cacheManager.getCache("org.alfresco.LoaderUploadThread.PathCache");
pathCache = new EhCacheAdapter<String, NodeRef>();
pathCache.setCache(cache);
}
public AbstractLoaderThread(
LoaderSession session,
String loaderName,
long testPeriod,
long testTotal,
long testLoadDepth,
boolean verbose)
{
super(LoaderSession.THREAD_GROUP, "LoaderThread-" + loaderName);
this.session = session;
this.loaderName = loaderName;
this.testPeriod = testPeriod;
this.testTotal = testTotal < 1 ? Integer.MAX_VALUE : testTotal;
this.testLoadDepth = testLoadDepth;
this.verbose = verbose;
this.mustStop = new AtomicBoolean(false);
this.random = new Random();
this.statCount = 0;
this.statTotalMs = 0.0D;
// Check the load depth
if (this.testLoadDepth < 1 || this.testLoadDepth > this.session.getFolderProfiles().length)
{
throw new AlfrescoRuntimeException("The load depth must be [1," + this.session.getFolderProfiles().length);
}
}
/**
* Notify the running thread to exit at the first available opportunity.
*/
public void setStop()
{
mustStop.set(true);
}
@Override
public void run()
{
int testCount = 0;
while (!mustStop.get())
{
try
{
// Choose a server
int serverCount = session.getRemoteServers().size();
int serverIndex = random.nextInt(serverCount);
LoaderServerProxy serverProxy = session.getRemoteServers().get(serverIndex);
// Choose a working root node
int nodeCount = session.getWorkingRootNodeRefs().size();
int nodeIndex = random.nextInt(nodeCount);
NodeRef workingRootNodeRef = session.getWorkingRootNodeRefs().get(nodeIndex);
this.doBefore(serverProxy, workingRootNodeRef);
long startTime = System.nanoTime();
String msg = doLoading(serverProxy, workingRootNodeRef);
long endTime = System.nanoTime();
// Record stats
updateStats(startTime, endTime);
// Dump the specifics of the load
logVerbose(startTime, endTime, msg);
// Have we done this enough?
testCount++;
if (testCount > testTotal)
{
break;
}
// Do we wait or continue immediately
long duration = endTime - startTime;
long mustWait = testPeriod - (long)(duration / 1000.0 / 1000.0);
if (mustWait >= 5)
{
synchronized(this)
{
this.wait(mustWait);
}
}
this.doAfter(serverProxy, workingRootNodeRef);
}
catch (Throwable e)
{
session.logError("Loading error on '" + loaderName + "': " + e.getMessage(), e);
}
}
}
private synchronized void updateStats(long startTime, long endTime)
{
statCount++;
// Calculate the delta in milliseconds
double delta = ((double)(endTime - startTime) / 1000.0 / 1000.0);
// Now recalculate the average
statTotalMs += delta;
}
/**
* <pre>
* NAME+36\tCOUNT \tTIME \tAVERAGE TIME \tPER SECOND \tDESCRIPTION
* </pre>
*/
private void logVerbose(long startTime, long endTime, String msg)
{
double delta = ((double)(endTime - startTime) / 1000.0 / 1000.0 / 1000.0);
double statTotalSec = statTotalMs / 1000.0;
double statPerSec = statCount / statTotalSec;
double statAveSec = statTotalSec / statCount;
// Summarize the results
StringBuilder sb = new StringBuilder();
sb
.append(String.format("%40s", loaderName)).append("\t")
.append(String.format("%15.0f", (float)statCount)).append("\t")
.append(String.format("%15.3f", delta)).append("\t")
.append(String.format("%15.3f", statPerSec)).append("\t")
.append(String.format("%15.3f", statAveSec)).append("\t")
.append(msg);
session.logVerbose(sb.toString(), verbose);
}
/**
* <pre>
* NAME+36\tCOUNT \tTOTAL TIME \tAVERAGE TIME \tPER SECOND \tDESCRIPTION
* </pre>
*
* @return Returns the summary of the results
*/
public String getSummary()
{
double statTotalSec = statTotalMs / 1000.0;
double statPerSec = statCount / statTotalSec;
double statAveSec = statTotalSec / statCount;
// Summarize the results
StringBuilder sb = new StringBuilder();
sb
.append(String.format("%40s", loaderName)).append("\t")
.append(String.format("%15.0f", (float)statCount)).append("\t")
.append(String.format("%15.3f", statTotalSec)).append("\t")
.append(String.format("%15.3f", statAveSec)).append("\t")
.append(String.format("%15.3f", statPerSec)).append("\t")
.append("");
return sb.toString();
}
/**
* @param serverProxy the server to load
* @param workingRootNodeRef the root of the hierarchy to use
* @return a brief description of the loading
* @throws Exception any exception will be handled
*/
protected abstract String doLoading(
LoaderServerProxy serverProxy,
NodeRef workingRootNodeRef) throws Exception;
protected List<String> chooseFolderPath()
{
int[] folderProfiles = session.getFolderProfiles();
// We work through these until we get the required depth.
// The root node is ignored as it acts as the search root
List<String> path = new ArrayList<String>((int)testLoadDepth);
for (int i = 1; i < testLoadDepth; i++)
{
int folderProfile = folderProfiles[i];
int randomFolderId = random.nextInt(folderProfile);
String name = String.format("folder-%05d", randomFolderId);
path.add(name);
}
return path;
}
protected File getFile() throws Exception
{
File[] files = session.getSourceFiles();
File file = files[random.nextInt(files.length)];
if (!file.exists() || file.isDirectory())
{
throw new LoaderClientException("Cannot find loading file: " + file);
}
return file;
}
/**
* Creates or find the folders based on caching.
*/
protected NodeRef makeFolders(
String ticket,
LoaderServerProxy serverProxy,
NodeRef workingRootNodeRef,
List<String> folderPath) throws Exception
{
// Iterate down the path, checking the cache and populating it as necessary
NodeRef currentParentNodeRef = workingRootNodeRef;
String currentKey = workingRootNodeRef.toString();
for (String aFolderPath : folderPath)
{
currentKey += ("/" + aFolderPath);
// Is this there?
NodeRef nodeRef = pathCache.get(currentKey);
if (nodeRef != null)
{
// Found it
currentParentNodeRef = nodeRef;
// Step into the next level
continue;
}
// It is not there, so create it
try
{
FileInfo folderInfo = serverProxy.fileFolderRemote.makeFolders(
serverProxy.ticket,
currentParentNodeRef,
Collections.singletonList(aFolderPath),
ContentModel.TYPE_FOLDER);
currentParentNodeRef = folderInfo.getNodeRef();
} catch (FileExistsException e)
{
currentParentNodeRef = pathCache.get(currentKey);
}
// Cache the new node
pathCache.put(currentKey, currentParentNodeRef);
}
// Done
return currentParentNodeRef;
}
/**
* Run before record stats
*/
protected void doBefore(LoaderServerProxy loaderServerProxy, NodeRef nodeRef) throws Exception
{
}
/**
* Run after record stats
*/
protected void doAfter(LoaderServerProxy loaderServerProxy, NodeRef nodeRef) throws Exception
{
}
}

View File

@@ -1,461 +0,0 @@
/*
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.model.filefolder.loader;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.cmr.repository.StoreRef;
/**
* A class that communicates with the remote FileFolder interface to perform
* loading of the system using the standard models.
* <p>
* TODO: The transport interface must be hidden behind and implementation
* of the standard FileFolderService interface.
*
* @author Derek Hulley
* @since 2.1
*/
public class FileFolderRemoteLoader
{
private static final String STORE_PROTOCOL = "FileFolderRemoteLoader";
private Properties properties;
private String username;
private String password;
private LoaderSession session;
private AbstractLoaderThread[] threads;
public FileFolderRemoteLoader(Properties properties, String username, String password)
{
this.properties = properties;
this.username = username;
this.password = password;
}
public synchronized void initialize() throws Exception
{
if (session != null || threads != null)
{
throw new AlfrescoRuntimeException("Application already initialized");
}
session = FileFolderRemoteLoader.makeSession(username, password, properties);
threads = FileFolderRemoteLoader.makeThreads(session, properties);
// Log the initial summaries
String summary = session.getSummary();
session.logVerbose(summary, true);
session.logSummary(summary);
session.logError(summary);
// Header the outputs
session.logVerbose(LoaderSession.getLineEnding(), true);
session.logVerbose(COLUMNS_VERBOSE, true);
session.logSummary(LoaderSession.getLineEnding());
session.logSummary(COLUMNS_SUMMARY);
}
private static final String COLUMNS_VERBOSE =
String.format("%40s\t%15s\t%15s\t%15s\t%15s\t%15s",
"NAME", "COUNT", "TIME", "AVERAGE TIME", "PER SECOND", "DESCRIPTION");
private static final String COLUMNS_SUMMARY =
String.format("%40s\t%15s\t%15s\t%15s\t%15s\t%15s",
"NAME", "COUNT", "TOTAL TIME", "AVERAGE TIME", "PER SECOND", "DESCRIPTION");
public synchronized void start()
{
if (session == null || threads == null)
{
throw new AlfrescoRuntimeException("Application not initialized");
}
// Fire up the threads
for (Thread thread : threads)
{
thread.start();
}
}
public synchronized void stop()
{
// Stop the threads
for (AbstractLoaderThread thread : threads)
{
thread.setStop();
}
// Now join each thread to make sure they all finish their current operation
for (AbstractLoaderThread thread : threads)
{
// Notify any waits
synchronized(thread)
{
thread.notifyAll();
}
try
{
thread.join();
}
catch (InterruptedException e) {}
}
// Log each thread's summary
for (AbstractLoaderThread thread : threads)
{
String summary = thread.getSummary();
session.logSummary(summary);
}
}
public void dumpThreadSummaries()
{
System.out.println("");
System.out.println(COLUMNS_SUMMARY);
// Dump each thread's summary
for (AbstractLoaderThread thread : threads)
{
String summary = thread.getSummary();
System.out.println(summary);
}
}
public static final String PROP_SESSION_NAME = "session.name";
public static final String PROP_SESSION_SOURCE_DIR = "session.sourceDir";
public static final String PROP_SESSION_STORE_IDENTIFIERS = "session.storeIdentifiers";
public static final String PROP_SESSION_RMI_URLS = "session.rmiUrls";
public static final String PROP_SESSION_FOLDER_PROFILE = "session.folderProfile";
/**
* Factory method to construct a session using the given properties.
*/
private static LoaderSession makeSession(String username, String password, Properties properties) throws Exception
{
// Name
String name = properties.getProperty(PROP_SESSION_NAME);
FileFolderRemoteLoader.checkProperty(PROP_SESSION_STORE_IDENTIFIERS, name);
// Source files
String sourceDirStr = properties.getProperty(PROP_SESSION_SOURCE_DIR);
File sourceDir = new File(sourceDirStr);
// Stores
String storeIdentifiersStr = properties.getProperty(PROP_SESSION_STORE_IDENTIFIERS);
FileFolderRemoteLoader.checkProperty(PROP_SESSION_STORE_IDENTIFIERS, storeIdentifiersStr);
StringTokenizer tokenizer = new StringTokenizer(storeIdentifiersStr, ",");
Set<StoreRef> storeRefs = new HashSet<StoreRef>();
while (tokenizer.hasMoreTokens())
{
String storeIdentifier = tokenizer.nextToken().trim();
storeRefs.add(new StoreRef(STORE_PROTOCOL, storeIdentifier));
}
FileFolderRemoteLoader.checkProperty(PROP_SESSION_STORE_IDENTIFIERS, storeRefs);
// RMI URLs
String rmiUrlsStr = properties.getProperty(PROP_SESSION_RMI_URLS);
FileFolderRemoteLoader.checkProperty(PROP_SESSION_RMI_URLS, rmiUrlsStr);
tokenizer = new StringTokenizer(rmiUrlsStr, ",");
Set<String> rmiUrls = new HashSet<String>();
while (tokenizer.hasMoreTokens())
{
String rmiUrl = tokenizer.nextToken().trim();
rmiUrls.add(rmiUrl);
}
FileFolderRemoteLoader.checkProperty(PROP_SESSION_STORE_IDENTIFIERS, rmiUrls);
// RMI URLs
String folderProfilesStr = properties.getProperty(PROP_SESSION_FOLDER_PROFILE);
FileFolderRemoteLoader.checkProperty(PROP_SESSION_FOLDER_PROFILE, folderProfilesStr);
tokenizer = new StringTokenizer(folderProfilesStr, ",");
ArrayList<Integer> folderProfilesList = new ArrayList<Integer>(5);
while (tokenizer.hasMoreTokens())
{
String folderProfileStr = tokenizer.nextToken().trim();
Integer folderProfile = Integer.valueOf(folderProfileStr);
folderProfilesList.add(folderProfile);
}
FileFolderRemoteLoader.checkProperty(PROP_SESSION_FOLDER_PROFILE, folderProfilesList);
int[] folderProfiles = new int[folderProfilesList.size()];
for (int i = 0; i < folderProfiles.length; i++)
{
folderProfiles[i] = folderProfilesList.get(i);
}
if (folderProfiles.length == 0 || folderProfiles[0] != 1)
{
throw new LoaderClientException(
"'" + PROP_SESSION_FOLDER_PROFILE + "' must always start with '1', " +
"which represents the root of the hierarchy, and have at least one other value. " +
"E.g. '1, 3'");
}
// Construct
LoaderSession session = new LoaderSession(
username,
password,
name,
rmiUrls,
storeRefs,
sourceDir,
folderProfiles);
// Initialize the session
session.initialize();
// Done
return session;
}
/**
* Factory method to construct the worker threads.
*/
private static AbstractLoaderThread[] makeThreads(LoaderSession session, Properties properties) throws Exception
{
ArrayList<AbstractLoaderThread> threads = new ArrayList<AbstractLoaderThread>(3);
// Iterate over the properties and pick out the thread descriptors
for (Object o : properties.keySet())
{
String propertyName = (String)o;
if (!propertyName.startsWith("test.load."))
{
continue;
}
String name = propertyName;
// Get the type of the test
int lastIndex = propertyName.indexOf(".", 10);
if (lastIndex < 0)
{
throw new LoaderClientException(
"Invalid test loader property. " +
"It should be of the form 'test.load.upload.xyz=...': " + propertyName);
}
String type = propertyName.substring(10, lastIndex);
// Get the values
String valuesStr = properties.getProperty(propertyName);
FileFolderRemoteLoader.checkProperty(propertyName, valuesStr);
// Parse it into the well-known values
String[] strValues = new String[] {"1", "0", "0", "1", "false", "1"};
int index = 0;
StringTokenizer tokenizer = new StringTokenizer(valuesStr, ",");
while (tokenizer.hasMoreTokens())
{
String value = tokenizer.nextToken().trim();
if (value.length() > 0)
{
strValues[index] = value;
}
index++;
if (index >= strValues.length)
{
break;
}
}
long testCount = 1L;
long testPeriod = 0L;
long testTotal = 0L;
long testDepth = 1L;
boolean testVerbose = false;
long filesPerIteration = 1;
try
{
testCount = Long.parseLong(strValues[0]);
testPeriod = Long.parseLong(strValues[1]);
testTotal = Long.parseLong(strValues[2]);
testDepth = Long.parseLong(strValues[3]);
testVerbose = Boolean.parseBoolean(strValues[4]);
filesPerIteration = Long.parseLong(strValues[5]);
}
catch (Throwable e)
{
throw new LoaderClientException(
"Unable to parse the loader configuration for '" + name + "'. " + LoaderSession.getLineEnding() +
"The correct format is [threadCount], [period(ms)], [total], [folder depth], [verbose]<, [filesPerIteration]>");
}
// Construct
for (int i = 0; i < testCount; i++)
{
AbstractLoaderThread thread = null;
if (type.equals("upload"))
{
thread = new LoaderUploadThread(session, name, testPeriod, testTotal, testDepth, testVerbose, filesPerIteration);
}
else if (type.equals("totals"))
{
thread = new LoaderTotalsThread(session, name, testPeriod, testTotal, testDepth, testVerbose);
}
else if (type.equals("listFolders"))
{
thread = new LoaderListFoldersThread(session, name, testPeriod, testTotal, testDepth, testVerbose);
}
else if(type.equals("delete"))
{
thread = new LoaderDeleteThread(session, name, testPeriod, testTotal, testDepth, testVerbose, filesPerIteration);
}
else if(type.equals("update"))
{
thread = new LoaderUpdateThread(session, name, testPeriod, testTotal, testDepth, testVerbose, filesPerIteration);
}
else if(type.equals("coci"))
{
thread = new LoaderCOCIThread(session, name, testPeriod, testTotal, testDepth, testVerbose, filesPerIteration);
}
else
{
throw new LoaderClientException("Unknown test type: " + name);
}
threads.add(thread);
}
}
// Done
AbstractLoaderThread[] ret = new AbstractLoaderThread[threads.size()];
return threads.toArray(ret);
}
/**
* Checks for null values and empty collections.
*/
private static void checkProperty(String propertyName, Object propertyValue) throws LoaderClientException
{
if (propertyValue == null)
{
throw new LoaderClientException("'" + propertyName + "' must be provided.");
}
else if (propertyValue instanceof Collection)
{
Collection propertyCollection = (Collection) propertyValue;
int size = propertyCollection.size();
if (size == 0)
{
throw new LoaderClientException("'" + propertyName + "' does not have any values.");
}
}
}
public static void main(String ... args)
{
Map<String, String> argMap = ripArgs(args);
String username = argMap.get("username");
String password = argMap.get("password");
String config = argMap.get("config");
if (username == null || password == null || config == null)
{
printUsage();
System.exit(1);
}
try
{
File propertiesFile = new File(config);
if (!propertiesFile.exists())
{
System.err.println("Unable to find config file: " + config);
}
Properties properties = new Properties();
properties.load(new FileInputStream(propertiesFile));
FileFolderRemoteLoader app = new FileFolderRemoteLoader(properties, username, password);
// Initialize
app.initialize();
// Run
app.start();
// Now lower this threads priority
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
// Wait for a quit signal
System.out.println("Running test " + app.session.getName() + ".");
System.out.println(" Enter 'q' to quit.");
System.out.println(" Enter 's' to dump a thread summary.");
while (true)
{
int keyPress = System.in.read();
if (keyPress == 'Q' || keyPress == 'q')
{
break;
}
else if (keyPress == 'S' || keyPress == 's')
{
app.dumpThreadSummaries();
}
else if (System.in.available() > 0)
{
// Don't wait, just process
continue;
}
// No more keypresses so just wait
Thread.yield();
}
// Finish off
app.stop();
System.out.println("The test is complete.");
}
catch (LoaderClientException e)
{
System.err.println(e.getMessage());
System.exit(1);
}
catch (Throwable e)
{
System.err.println("A failure prevented proper execution.");
e.printStackTrace();
System.exit(1);
}
System.exit(0);
}
private static Map<String, String> ripArgs(String ... args)
{
Map<String, String> argsMap = new HashMap<String, String>(5);
for (String arg : args)
{
int index = arg.indexOf('=');
if (!arg.startsWith("--") || index < 0 || index == arg.length() - 1)
{
// Ignore it
continue;
}
String name = arg.substring(2, index);
String value = arg.substring(index + 1, arg.length());
argsMap.put(name, value);
}
return argsMap;
}
private static void printUsage()
{
StringBuilder sb = new StringBuilder();
sb.append("\n")
.append("Usage\n")
.append(" java -jar ... --username=<username> --password=<password> --config=<config file> \n");
System.out.println(sb.toString());
}
}

View File

@@ -1,107 +0,0 @@
/*
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.model.filefolder.loader;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.GUID;
import org.alfresco.model.ContentModel;
import org.springframework.util.FileCopyUtils;
import java.util.*;
import java.io.Serializable;
import java.io.File;
/**
* Loader thread that coci documents to the remote repository.
*/
public class LoaderCOCIThread extends AbstractLoaderThread
{
private int filesPerIteration;
private FileInfo[] filesInfo;
public LoaderCOCIThread(LoaderSession session, String loaderName, long testPeriod, long testTotal, long testLoadDepth, boolean verbose, long filesPerIteration)
{
super(session, loaderName, testPeriod, testTotal, testLoadDepth, verbose);
this.filesPerIteration = (int) filesPerIteration;
}
@Override
protected String doLoading(LoaderServerProxy serverProxy, NodeRef workingRootNodeRef) throws Exception
{
List<HashMap<String, Serializable>> arrVersionProp = new ArrayList<HashMap<String, Serializable>>();
byte[][] bytes = new byte[filesPerIteration][];
for (int i = 0; i < filesPerIteration; i++)
{
File file = getFile();
bytes[i] = FileCopyUtils.copyToByteArray(file);
arrVersionProp.add(new HashMap<String, Serializable>());
}
serverProxy.loaderRemote.coci(serverProxy.ticket, getNodesRef(filesInfo), bytes, arrVersionProp);
return String.format("update version %d files in folder: %s", filesPerIteration, workingRootNodeRef.toString());
}
@Override
protected void doBefore(LoaderServerProxy loaderServerProxy, NodeRef nodeRef) throws Exception
{
// Get a random folder
List<String> folderPath = super.chooseFolderPath();
//makeFolders
NodeRef folderNodeRef = makeFolders(loaderServerProxy.ticket, loaderServerProxy, nodeRef, folderPath);
String[] fileNames = new String[filesPerIteration];
NodeRef[] parentNodeRefs = new NodeRef[filesPerIteration];
QName[] types = new QName[filesPerIteration];
// Build a set of files to coci
for (int i = 0; i < filesPerIteration; i++)
{
fileNames[i] = GUID.generate();
parentNodeRefs[i] = folderNodeRef;
types[i] = ContentModel.TYPE_CONTENT;
}
filesInfo = loaderServerProxy.fileFolderRemote.create(loaderServerProxy.ticket, parentNodeRefs, fileNames, types);
}
public String getSummary()
{
String summary = super.getSummary();
summary += String.format("%d files per iteration", filesPerIteration);
return summary;
}
NodeRef[] getNodesRef(FileInfo[] filesInfoList)
{
NodeRef[] nr = new NodeRef[filesInfoList.length];
for (int i = 0; i < filesInfoList.length; i++)
{
nr[i] = (filesInfoList[i].getNodeRef());
}
return nr;
}
}

View File

@@ -1,34 +0,0 @@
/*
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.model.filefolder.loader;
/**
* Helper class to catch non-critical issues.
*
* @author Derek Hulley
*/
public class LoaderClientException extends Exception
{
private static final long serialVersionUID = -3306363763048881956L;
public LoaderClientException(String msg)
{
super(msg);
}
}

View File

@@ -1,109 +0,0 @@
/*
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.model.filefolder.loader;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.GUID;
import org.springframework.util.FileCopyUtils;
import java.io.File;
import java.util.List;
/**
* Loader thread that deletes documents to the remote repository.
*/
public class LoaderDeleteThread extends AbstractLoaderThread
{
private FileInfo[] filesInfo;
private int filesPerIteration;
public LoaderDeleteThread(
LoaderSession loaderSession,
String loaderName,
long testPeriod,
long testTotal,
long testLoadDepth,
boolean verbose,
long filesPerIteration)
{
super(loaderSession, loaderName, testPeriod, testTotal, testLoadDepth, verbose);
this.filesPerIteration = (int) filesPerIteration;
}
@Override
protected String doLoading(LoaderServerProxy loaderServerProxy, NodeRef nodeRef) throws Exception
{
// Delete it
loaderServerProxy.fileFolderRemote.delete(loaderServerProxy.ticket, getNodesRef(filesInfo));
// Done
String msg = String.format("Deleted %d files from folder: %s", filesInfo.length, nodeRef.toString());
return msg;
}
@Override
protected void doBefore(LoaderServerProxy loaderServerProxy, NodeRef workingRootNodeRef) throws Exception
{
// Get a random folder
List<String> folderPath = super.chooseFolderPath();
//makeFolders
NodeRef folderNodeRef = makeFolders(loaderServerProxy.ticket, loaderServerProxy, workingRootNodeRef, folderPath);
byte[][] bytes = new byte[filesPerIteration][];
String[] fileNames = new String[filesPerIteration];
NodeRef[] parentNodeRefs = new NodeRef[filesPerIteration];
QName[] types = new QName[filesPerIteration];
// Build a set of files to delete
for (int i = 0; i < filesPerIteration; i++)
{
File file = getFile();
bytes[i] = FileCopyUtils.copyToByteArray(file);
fileNames[i] = GUID.generate();
parentNodeRefs[i] = folderNodeRef;
types[i] = ContentModel.TYPE_CONTENT;
}
filesInfo = loaderServerProxy.fileFolderRemote.create(loaderServerProxy.ticket, parentNodeRefs, fileNames, types);
loaderServerProxy.fileFolderRemote.putContent(loaderServerProxy.ticket, getNodesRef(filesInfo), bytes, fileNames);
}
NodeRef[] getNodesRef(FileInfo[] filesInfoList)
{
NodeRef[] nr = new NodeRef[filesInfoList.length];
for (int i = 0; i < filesInfoList.length; i++)
{
nr[i] = (filesInfoList[i].getNodeRef());
}
return nr;
}
public String getSummary()
{
String summary = super.getSummary();
summary += (String.format("%d files per iteration", filesPerIteration));
return summary;
}
}

View File

@@ -1,80 +0,0 @@
/*
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.model.filefolder.loader;
import java.util.List;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* A loader thread that retrieves the folders beneath each directory from
* the root. This is an expensive process but should reach a stable execution time
* once the folders in the profile have all been created.
* @since 2.2
*
* @author Derek Hulley
*/
public class LoaderListFoldersThread extends AbstractLoaderThread
{
public LoaderListFoldersThread(
LoaderSession session,
String loaderName,
long testPeriod,
long testTotal,
long testLoadDepth,
boolean verbose)
{
super(session, loaderName, testPeriod, testTotal, testLoadDepth, verbose);
}
/**
* Go to a directory and get a listing of the folders beneath it.
*/
@Override
protected String doLoading(LoaderServerProxy serverProxy, NodeRef workingRootNodeRef) throws Exception
{
int count = listFoldersRecursive(serverProxy, workingRootNodeRef, 0);
// Done
String msg = String.format("Found %d folders below node %s", count, workingRootNodeRef.toString());
return msg;
}
/**
* Recursive method to list all folders in the hierarchy.
* @return Returns the number of folders listed
*/
private int listFoldersRecursive(LoaderServerProxy serverProxy, NodeRef parentNodeRef, int count)
{
List<FileInfo> fileInfos = serverProxy.fileFolderRemote.listFolders(
serverProxy.ticket,
parentNodeRef);
for (FileInfo info : fileInfos)
{
if (!info.isFolder())
{
// Ooops
continue;
}
count += listFoldersRecursive(serverProxy, info.getNodeRef(), count);
}
return count;
}
}

View File

@@ -1,48 +0,0 @@
/*
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.model.filefolder.loader;
import org.alfresco.service.cmr.remote.FileFolderRemote;
import org.alfresco.service.cmr.remote.LoaderRemote;
/**
* Helper class to store remote service connections.
*
* @author Derek Hulley
*/
public class LoaderServerProxy
{
public final String rmiUrl;
public final String ticket;
public final FileFolderRemote fileFolderRemote;
public final LoaderRemote loaderRemote;
public LoaderServerProxy(
String rmiUrl,
String ticket,
FileFolderRemote fileFolderRemote,
LoaderRemote loaderRemote)
{
this.rmiUrl = rmiUrl;
this.ticket = ticket;
this.fileFolderRemote = fileFolderRemote;
this.loaderRemote = loaderRemote;
}
}

View File

@@ -1,440 +0,0 @@
/*
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.model.filefolder.loader;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.error.StackTraceUtil;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.remote.FileFolderRemoteClient;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.remote.LoaderRemote;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.springframework.remoting.rmi.RmiProxyFactoryBean;
/**
* A description of session details.
*
* @author Derek Hulley
* @since 2.2
*/
public class LoaderSession
{
public static final ThreadGroup THREAD_GROUP = new ThreadGroup("FileFolderRemoteLoader");
private String username;
private String password;
private String name;
private Set<String> rmiUrls;
private Set<StoreRef> storeRefs;
private File outputFile;
private File sourceDir;
private int[] folderProfiles;
private List<LoaderServerProxy> remoteServers;
private List<NodeRef> workingRootNodeRefs;
private File[] sourceFiles;
private OutputStream outVerbose;
private OutputStream outSummary;
private OutputStream outError;
private long startTime;
/**
*
*/
public LoaderSession(
String username,
String password,
String name,
Set<String> rmiUrls,
Set<StoreRef> storeRefs,
File sourceDir,
int[] folderProfiles)
{
this.username = username;
this.password = password;
this.name = name;
this.rmiUrls = rmiUrls;
this.storeRefs = storeRefs;
this.sourceDir = sourceDir;
this.folderProfiles = folderProfiles;
}
public String getName()
{
return name;
}
public List<LoaderServerProxy> getRemoteServers()
{
return remoteServers;
}
public List<NodeRef> getWorkingRootNodeRefs()
{
return workingRootNodeRefs;
}
public File[] getSourceFiles()
{
return sourceFiles;
}
public int[] getFolderProfiles()
{
return folderProfiles;
}
/**
* Initialize the object before first use.
*/
public synchronized void initialize() throws Exception
{
if (remoteServers != null)
{
throw new AlfrescoRuntimeException("The client has already been initialized");
}
remoteServers = LoaderSession.connect(rmiUrls, username, password);
workingRootNodeRefs = LoaderSession.makeStores(remoteServers, storeRefs);
LoaderSession.checkClustering(remoteServers, workingRootNodeRefs);
// Create the output file, if necessary
if (outputFile != null)
{
File outputDir = outputFile.getParentFile();
if (!outputDir.exists())
{
outputDir.mkdirs();
}
if (outputFile.exists())
{
System.out.println("The output file " + outputFile + " already exists.");
System.out.println("Are you sure you want to overwrite the file?");
int in = System.in.read();
if (in != 'Y' && in != 'y')
{
throw new LoaderClientException("The output file " + outputFile + " already exists");
}
}
}
// Get the source files
sourceFiles = LoaderSession.getSourceFiles(sourceDir);
// Construct output and error files
long time = System.currentTimeMillis();
File fileVerbose = new File("./LoaderSession-" + name + "-"+ time + "-verbose.tsv");
File fileSummary = new File("./LoaderSession-" + name + "-"+ time + "-summary.tsv");
File fileError = new File("./LoaderSession-" + name + "-"+ time + "-error.tsv");
outVerbose = new BufferedOutputStream(new FileOutputStream(fileVerbose));
outSummary = new BufferedOutputStream(new FileOutputStream(fileSummary));
outError = new BufferedOutputStream(new FileOutputStream(fileError));
// Record the start time
startTime = System.currentTimeMillis();
}
public synchronized void close()
{
try { outVerbose.close(); } catch (Throwable e) {}
try { outSummary.close(); } catch (Throwable e) {}
try { outError.close(); } catch (Throwable e) {}
outVerbose = null;
outSummary = null;
outError = null;
}
/**
* Connect to the remote servers.
*/
private static List<LoaderServerProxy> connect(Set<String> rmiUrls, String username, String password) throws Exception
{
List<LoaderServerProxy> remoteServers = new ArrayList<LoaderServerProxy>(rmiUrls.size());
for (String rmiUrl : rmiUrls)
{
try
{
// Ensure the RMI URL is consistent
if (!rmiUrl.endsWith("/"))
{
rmiUrl += "/";
}
// Get the FileFolderServiceTransport
FileFolderRemoteClient fileFolderRemote = new FileFolderRemoteClient(rmiUrl);
// Get the LoaderServiceTransport
RmiProxyFactoryBean loaderFactory = new RmiProxyFactoryBean();
loaderFactory.setRefreshStubOnConnectFailure(true);
loaderFactory.setServiceInterface(LoaderRemote.class);
loaderFactory.setServiceUrl(rmiUrl + LoaderRemote.SERVICE_NAME);
loaderFactory.afterPropertiesSet();
LoaderRemote loaderRemote = (LoaderRemote) loaderFactory.getObject();
// Authenticate
String ticket = loaderRemote.authenticate(username, password);
// Store the service references
LoaderServerProxy remoteServer = new LoaderServerProxy(
rmiUrl,
ticket,
fileFolderRemote,
loaderRemote);
remoteServers.add(remoteServer);
}
catch (Throwable e)
{
// Failed to connect.
System.err.println("\n" +
"ERROR: Failed to establish connection to server: \n" +
" Server: " + rmiUrl + "\n" +
" Error: " + e.getMessage());
e.printStackTrace();
}
}
// Check that there is at least one server
if (remoteServers.size() == 0)
{
throw new LoaderClientException("No remote servers are available");
}
return remoteServers;
}
private static List<NodeRef> makeStores(List<LoaderServerProxy> remoteServers, Set<StoreRef> storeRefs) throws Exception
{
// Take the first server and ensure that all the stores are available
LoaderServerProxy remoteServer = remoteServers.get(0);
List<NodeRef> workingRootNodeRefs = new ArrayList<NodeRef>(10);
for (StoreRef storeRef : storeRefs)
{
NodeRef workingRootNodeRef = remoteServer.loaderRemote.getOrCreateWorkingRoot(remoteServer.ticket, storeRef);
workingRootNodeRefs.add(workingRootNodeRef);
}
// Done
return workingRootNodeRefs;
}
private static void checkClustering(
List<LoaderServerProxy> remoteServers,
List<NodeRef> workingRootNodeRefs) throws Exception
{
List<String> problems = new ArrayList<String>(10);
for (LoaderServerProxy remoteServer : remoteServers)
{
String ticket = remoteServer.ticket;
for (NodeRef workingRootNodeRef : workingRootNodeRefs)
{
try
{
// Get the working root node. If the cluster is correctly configured,
// it will be available on all the servers.
FileInfo fileInfo = remoteServer.fileFolderRemote.getFileInfo(ticket, workingRootNodeRef);
if (fileInfo == null)
{
problems.add("Cannot find the working root node on server: " + remoteServer.rmiUrl);
continue;
}
// Now look for and create a file against which to store some content
String sampleFilename = "InitialSample.txt";
String sampleContent = "Sample content";
NodeRef sampleNodeRef = remoteServer.fileFolderRemote.searchSimple(ticket, workingRootNodeRef, sampleFilename);
if (sampleNodeRef == null)
{
FileInfo sampleFileInfo = remoteServer.fileFolderRemote.create(
ticket, workingRootNodeRef, sampleFilename, ContentModel.TYPE_CONTENT);
sampleNodeRef = sampleFileInfo.getNodeRef();
// Write some content
byte[] bytes = sampleContent.getBytes("UTF-8");
remoteServer.fileFolderRemote.putContent(ticket, sampleNodeRef, bytes, sampleFilename);
}
// Get the content and ensure that it is the same
byte[] bytes = remoteServer.fileFolderRemote.getContent(ticket, sampleNodeRef);
if (bytes == null)
{
problems.add("Sample content was not found on server: " + remoteServer.rmiUrl);
continue;
}
String checkContent = new String(bytes, "UTF-8");
if (!checkContent.equals(sampleContent))
{
problems.add("The sample content differed from expected: " + remoteServer.rmiUrl);
continue;
}
}
catch (Throwable e)
{
System.err.println("ERROR: Failure whilst checking server: " + remoteServer.rmiUrl);
e.printStackTrace();
problems.add(e.getMessage());
}
}
}
// Check for issues
if (problems.size() > 0)
{
StringBuilder sb = new StringBuilder();
sb.append("\n")
.append("The working root node references could not be found on all the remote servers.\n")
.append("Please ensure that all the remote servers listed are active in a single cluster.");
for (String problem : problems)
{
sb.append("\n")
.append(" ").append(problem);
}
throw new LoaderClientException(sb.toString());
}
}
private static File[] getSourceFiles(File sourceDir) throws Exception
{
// Ensure that the source directory is present, if specified
if (sourceDir != null)
{
if (!sourceDir.exists())
{
throw new LoaderClientException("The source directory to contain upload files is missing: " + sourceDir);
}
// Check that there is something in it
File[] allFiles = sourceDir.listFiles();
ArrayList<File> sourceFiles = new ArrayList<File>(allFiles.length);
for (File file : allFiles)
{
if (file.isDirectory())
{
continue;
}
sourceFiles.add(file);
}
File[] ret = new File[sourceFiles.size()];
return sourceFiles.toArray(ret);
}
else
{
return new File[] {};
}
}
public static String getLineEnding()
{
return System.getProperty("line.separator", "\n");
}
public synchronized void logVerbose(String msg, boolean verbose)
{
if (!verbose || outVerbose == null)
{
return;
}
try
{
byte[] bytes = msg.getBytes("UTF-8");
outVerbose.write(bytes);
outVerbose.write(getLineEnding().getBytes("UTF-8"));
outVerbose.flush();
}
catch (Throwable e)
{
System.err.println("Failed to write message to verbose file: " + e.getMessage());
}
}
public synchronized void logSummary(String msg)
{
if (outSummary == null)
{
return;
}
try
{
byte[] bytes = msg.getBytes("UTF-8");
outSummary.write(bytes);
outSummary.write(getLineEnding().getBytes("UTF-8"));
outSummary.flush();
}
catch (Throwable e)
{
System.err.println("Failed to write message to summary file: " + e.getMessage());
}
}
public synchronized void logError(String msg)
{
if (outSummary == null)
{
return;
}
try
{
byte[] bytes = msg.getBytes("UTF-8");
outError.write(bytes);
outError.write(getLineEnding().getBytes("UTF-8"));
outError.flush();
}
catch (Throwable e)
{
System.err.println("Failed to write message to error file: " + e.getMessage());
}
}
public synchronized void logError(String msg, Throwable e)
{
if (outSummary == null)
{
return;
}
try
{
StringBuilder sb = new StringBuilder(1024);
StackTraceUtil.buildStackTrace(msg, e.getStackTrace(), sb, 50);
byte[] bytes = sb.toString().getBytes("UTF-8");
outError.write(bytes);
outError.write(getLineEnding().getBytes("UTF-8"));
outError.flush();
}
catch (Throwable ee)
{
System.err.println("Failed to write message to error file: " + e.getMessage());
}
}
public String getSummary()
{
List<Integer> folderProfilesAsList = new ArrayList<Integer>(10);
for (int folderProfile : folderProfiles)
{
folderProfilesAsList.add(Integer.valueOf(folderProfile));
}
StringBuilder sb = new StringBuilder();
sb.append("Session name: ").append(name).append(getLineEnding())
.append("RMI URLS: ").append(rmiUrls).append(getLineEnding())
.append("Store References: ").append(storeRefs).append(getLineEnding())
.append("Folder Profiles: ").append(folderProfilesAsList).append(getLineEnding())
.append("Start Time: ").append(new Date(startTime));
return sb.toString();
}
}

View File

@@ -1,78 +0,0 @@
/*
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.model.filefolder.loader;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
/**
* A loader thread that merely reports the size of the remote repository.
* @since 2.2
*
* @author Derek Hulley
*/
public class LoaderTotalsThread extends AbstractLoaderThread
{
public LoaderTotalsThread(
LoaderSession session,
String loaderName,
long testPeriod,
long testTotal,
long testLoadDepth,
boolean verbose)
{
super(session, loaderName, testPeriod, testTotal, testLoadDepth, verbose);
}
/**
* Gets the remote repository sizes and dumps those.
*/
@Override
protected String doLoading(LoaderServerProxy serverProxy, NodeRef workingRootNodeRef) throws Exception
{
return getTotalsMessage();
}
@Override
public String getSummary()
{
return super.getSummary() + getTotalsMessage();
}
private String getTotalsMessage()
{
LoaderServerProxy serverProxy = session.getRemoteServers().get(0);
StringBuilder sb = new StringBuilder();
// Get total
int totalNodeCount = serverProxy.loaderRemote.getNodeCount(
serverProxy.ticket);
sb.append(String.format("Total=%d", totalNodeCount));
// Get totals for each store
for (NodeRef nodeRef : session.getWorkingRootNodeRefs())
{
StoreRef storeRef = nodeRef.getStoreRef();
int storeNodeCount = serverProxy.loaderRemote.getNodeCount(
serverProxy.ticket,
storeRef);
sb.append(", ").append(storeRef.getIdentifier()).append("=").append(storeNodeCount);
}
// Done
return sb.toString();
}
}

View File

@@ -1,105 +0,0 @@
/*
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.model.filefolder.loader;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.GUID;
import org.alfresco.model.ContentModel;
import org.springframework.util.FileCopyUtils;
import java.util.List;
import java.io.File;
/**
* Loader thread that updates documents to the remote repository.
*/
public class LoaderUpdateThread extends AbstractLoaderThread
{
private FileInfo[] filesInfo;
private int filesPerIteration;
public LoaderUpdateThread(
LoaderSession session,
String loaderName,
long testPeriod,
long testTotal,
long testLoadDepth,
boolean verbose,
long filesPerIteration)
{
super(session, loaderName, testPeriod, testTotal, testLoadDepth, verbose);
this.filesPerIteration = (int)filesPerIteration;
}
@Override
protected void doBefore(LoaderServerProxy loaderServerProxy, NodeRef nodeRef) throws Exception
{
// Get a random folder
List<String> folderPath = super.chooseFolderPath();
//makeFolders
NodeRef folderNodeRef = makeFolders(loaderServerProxy.ticket, loaderServerProxy, nodeRef, folderPath);
String[] fileNames = new String[filesPerIteration];
NodeRef[] pareNodeRefs = new NodeRef[filesPerIteration];
QName[] types = new QName[filesPerIteration];
// Build a set of files to update
for (int i = 0; i < filesPerIteration; i++)
{
fileNames[i] = GUID.generate();
pareNodeRefs[i] = folderNodeRef;
types[i] = ContentModel.TYPE_CONTENT;
}
filesInfo = loaderServerProxy.fileFolderRemote.create(loaderServerProxy.ticket, pareNodeRefs, fileNames, types);
}
@Override
protected String doLoading(LoaderServerProxy loaderServerProxy, NodeRef nodeRef) throws Exception
{
byte[][] bytes = new byte[filesPerIteration][];
String[] fileNames = new String[filesPerIteration];
NodeRef[] nodeRefs = new NodeRef[filesPerIteration];
for (int i = 0; i < filesPerIteration; i++)
{
File file = getFile();
bytes[i] = FileCopyUtils.copyToByteArray(file);
fileNames[i] = filesInfo[i].getName();
nodeRefs[i] = filesInfo[i].getNodeRef();
}
//Update it
loaderServerProxy.fileFolderRemote.putContent(loaderServerProxy.ticket, nodeRefs, bytes, fileNames);
// Done
return String.format("Updated %d files in folder: %s", filesInfo.length, nodeRef.toString());
}
public String getSummary()
{
String summary = super.getSummary();
summary += (String.format("%d files per iteration", filesPerIteration));
return summary;
}
}

View File

@@ -1,98 +0,0 @@
/*
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.model.filefolder.loader;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.util.GUID;
import org.springframework.util.FileCopyUtils;
import java.io.File;
import java.util.List;
/**
* Loader thread that puts documents to the remote repository.
*
* @author Derek Hulley
* @since 2.2
*/
public class LoaderUploadThread extends AbstractLoaderThread
{
private int filesPerUpload;
public LoaderUploadThread(
LoaderSession session,
String loaderName,
long testPeriod,
long testTotal,
long testLoadDepth,
boolean verbose,
long filesPerUpload)
{
super(session, loaderName, testPeriod, testTotal, testLoadDepth, verbose);
this.filesPerUpload = (int) filesPerUpload;
}
@Override
protected String doLoading(LoaderServerProxy serverProxy, NodeRef workingRootNodeRef) throws Exception
{
// Get a random folder
List<String> folderPath = super.chooseFolderPath();
// Make sure the folder exists
NodeRef folderNodeRef = makeFolders(serverProxy.ticket, serverProxy, workingRootNodeRef, folderPath);
// Build a set of files to upload
byte[][] bytes = new byte[filesPerUpload][];
String[] filenames = new String[filesPerUpload];
for (int i = 0; i < filesPerUpload; i++)
{
// Get a random file
File file = getFile();
bytes[i] = FileCopyUtils.copyToByteArray(file);
// Get the extension
filenames[i] = GUID.generate();
int index = file.getName().lastIndexOf('.');
if (index > 0)
{
String ext = file.getName().substring(index + 1, file.getName().length());
filenames[i] += ("." + ext);
}
}
// Upload it
FileInfo[] fileInfos = serverProxy.loaderRemote.uploadContent(
serverProxy.ticket,
folderNodeRef,
filenames,
bytes);
// Done
String msg = String.format("Uploaded %d files to folder: %s", fileInfos.length, folderPath.toString());
return msg;
}
@Override
public String getSummary()
{
String summary = super.getSummary();
summary += (String.format("%d files per iteration", filesPerUpload));
return summary;
}
}

View File

@@ -1,24 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<ehcache>
<diskStore
path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="5000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
>
</defaultCache>
<cache
name="org.alfresco.LoaderUploadThread.PathCache"
maxElementsInMemory="100000"
eternal="true"
overflowToDisk="true"
diskPersistent="true"
/>
</ehcache>