Issue #2862 Implements locks on case creation.

Change-Id: Ic0975b699e54b30f152422782e11ac04c310cb1b

Former-commit-id: 5570261d74 [formerly b10c78a4f3cb7abb265d8c383c6bc2912d166720]
Former-commit-id: cfea0489d7
This commit is contained in:
Roger Ferrel 2014-04-10 13:39:16 -05:00
parent 0fa4180959
commit d66a346c65
10 changed files with 928 additions and 57 deletions

View file

@ -27,8 +27,13 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.zip.GZIPOutputStream;
@ -59,15 +64,22 @@ import org.eclipse.swt.widgets.Shell;
import com.raytheon.uf.common.archive.config.ArchiveConfigManager;
import com.raytheon.uf.common.archive.config.ArchiveConstants;
import com.raytheon.uf.common.archive.config.DisplayData;
import com.raytheon.uf.common.dataquery.requests.SharedLockRequest;
import com.raytheon.uf.common.dataquery.requests.SharedLockRequest.RequestType;
import com.raytheon.uf.common.dataquery.responses.SharedLockResponse;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.util.ITimer;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.common.util.FileUtil;
import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.requests.ThriftClient;
import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
/**
* This class performs the desired type of case creation and display a
* This class performs the desired type of case creation and displays a
* progress/status message dialog.
*
* <pre>
@ -81,7 +93,8 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
* archive and category directory and
* implementation of compression.
* Oct 08, 2013 2442 rferrel Remove category directory.
* Feb 04, 2013 2270 rferrel Move HDF files to parent's directory.
* Feb 04, 2014 2270 rferrel Move HDF files to parent's directory.
* Apr 03, 2014 2862 rferrel Logic for shared locking of top level directories.
*
* </pre>
*
@ -91,12 +104,12 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
public class GenerateCaseDlg extends CaveSWTDialog {
/** Extension for HDF files. */
private static final String hdfExt = ".h5";
private final IUFStatusHandler statusHandler = UFStatus
.getHandler(GenerateCaseDlg.class);
/** Extension for HDF files. */
private static final String hdfExt = ".h5";
/** Use to display the current state of the case generation. */
private Label stateLbl;
@ -121,7 +134,7 @@ public class GenerateCaseDlg extends CaveSWTDialog {
/** End time for the case. */
private final Calendar endCal;
/** Data list for the case. */
/** Data list for the case sorted by archive and category names. */
private final DisplayData[] sourceDataList;
/** When true compress the case directory. */
@ -372,24 +385,74 @@ public class GenerateCaseDlg extends CaveSWTDialog {
}
/**
* The performs the work of generating the case on a non-UI thread.
* This performs the work of generating the case on a non-UI thread.
*/
private class GenerateJob extends Job {
/** Parent flag to shutdown the job. */
private final AtomicBoolean shutdown = new AtomicBoolean(false);
/** How long to wait before making another request for a plug-in lock. */
private final long LOCK_RETRY_TIME = 2 * TimeUtil.MILLIS_PER_MINUTE;
/** Files/directories needing plug-in locks in order to copy. */
private final Map<CopyInfo, Map<String, List<File>>> caseCopyMap = new HashMap<CopyInfo, Map<String, List<File>>>();
/** Timer to determine when to send another request for a plug-in lock. */
private final ITimer retrytimer = TimeUtil.getTimer();
/** Timer to update current lock's last execute time. */
private Timer updateTimer = null;
/**
* Constructor.
*/
public GenerateJob() {
super("Generate Case");
}
@Override
protected IStatus run(IProgressMonitor monitor) {
if (monitor.isCanceled()) {
return Status.OK_STATUS;
/**
* Add file to the caseCopyMap.
*
* @param copyInfo
* @param plugin
* @param file
* @return
*/
private boolean putFile(CopyInfo copyInfo, String plugin, File file) {
if (caseCopyMap.size() == 0) {
retrytimer.start();
}
Map<String, List<File>> pluginMap = caseCopyMap.get(copyInfo);
if (pluginMap == null) {
pluginMap = new HashMap<String, List<File>>();
caseCopyMap.put(copyInfo, pluginMap);
}
List<File> files = pluginMap.get(plugin);
if (files == null) {
files = new ArrayList<File>();
pluginMap.put(plugin, files);
}
return files.add(file);
}
/**
* @param copyInfo
* @return true if locks needed to complete the copy.
*/
private boolean keepCaseCopy(CopyInfo copyInfo) {
return caseCopyMap.get(copyInfo) != null;
}
/**
* @return true when valid case directory.
*/
private boolean validateCaseDirectory() {
setStateLbl("Creating: " + caseDir.getName(),
caseDir.getAbsolutePath());
ICaseCopy caseCopy = null;
String errorMessage = null;
if (caseDir.exists()) {
@ -401,38 +464,95 @@ public class GenerateCaseDlg extends CaveSWTDialog {
if (errorMessage != null) {
setStateLbl(errorMessage, caseDir.getAbsolutePath());
setProgressBar(100, SWT.ERROR);
return Status.OK_STATUS;
return false;
}
if (shutdown.get()) {
return false;
}
return true;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.
* IProgressMonitor)
*/
@Override
protected IStatus run(IProgressMonitor monitor) {
if (monitor.isCanceled()) {
return Status.OK_STATUS;
}
if (!validateCaseDirectory()) {
return Status.OK_STATUS;
}
ICaseCopy caseCopy = null;
String currentArchive = null;
String currentCategory = null;
boolean updateDestDir = false;
int rootDirLen = -1;
File rootDir = null;
String plugin = null;
boolean allowCopy = true;
CopyInfo copyInfo = null;
try {
/*
* The sourceDataList is sorted so all the displayDatas for a
* given archive/category are grouped together in the loop.
*/
for (DisplayData displayData : sourceDataList) {
if (shutdown.get()) {
return Status.OK_STATUS;
}
if (!displayData.getArchiveName().equals(currentArchive)) {
updateDestDir = true;
/*
* The current display data is for a different
* archive/category then the previous one.
*/
if (!displayData.getArchiveName().equals(currentArchive)
|| !displayData.getCategoryName().equals(
currentCategory)) {
// Finish up previous archive/category.
if (caseCopy != null) {
if (allowCopy) {
releaseLock(plugin);
}
/*
* The copyInfo needs locks in order to finish.
* Force creation of a new caseCopy for the new
* category.
*/
if (keepCaseCopy(copyInfo)) {
caseCopy = null;
copyInfo = null;
} else {
caseCopy.finishCase();
}
plugin = null;
}
// Set up for new category.
currentArchive = displayData.getArchiveName();
currentCategory = displayData.getCategoryName();
} else if (!displayData.getCategoryName().equals(
currentCategory)) {
updateDestDir = true;
currentCategory = displayData.getCategoryName();
}
rootDir = new File(displayData.getRootDir());
rootDirLen = displayData.getRootDir().length();
allowCopy = true;
if (updateDestDir) {
updateDestDir = false;
if (caseCopy != null) {
caseCopy.finishCase();
} else {
setStateLbl(currentArchive + " | " + currentCategory,
caseDir.getAbsolutePath() + "\n"
+ currentArchive + "\n"
+ currentCategory);
/*
* When caseCopy is not null it is safe to reuse it for
* the new category.
*/
if (caseCopy == null) {
if (!doCompress) {
caseCopy = new CopyMove();
} else if (doMultiFiles) {
@ -440,33 +560,83 @@ public class GenerateCaseDlg extends CaveSWTDialog {
} else {
caseCopy = new CompressCopy();
}
copyInfo = new CopyInfo(caseCopy, currentArchive,
currentCategory, caseDir);
}
caseCopy.startCase(caseDir, displayData, shutdown);
setStateLbl(currentArchive + " | " + currentCategory,
caseDir.getAbsolutePath() + "\n"
+ currentArchive + "\n"
+ currentCategory);
}
List<File> files = archiveManager.getDisplayFiles(
displayData, startCal, endCal);
/*
* Check all files/directories in the displayData and
* attempt a recursive copy.
*/
for (File source : files) {
if (shutdown.get()) {
return Status.OK_STATUS;
}
caseCopy.copy(source);
String dirName = source.getAbsolutePath()
.substring(rootDirLen).split(File.separator)[0];
String newPlugin = (new File(rootDir, dirName))
.getAbsolutePath();
// Have new plugin.
if (!newPlugin.equals(plugin)) {
// Release the current lock.
if (allowCopy && (plugin != null)) {
releaseLock(plugin);
}
allowCopy = requestLock(newPlugin);
plugin = newPlugin;
}
if (allowCopy) {
// Have lock safe to perform recursive copy.
caseCopy.copy(source);
} else {
// No lock add to Map of files needing locks.
putFile(copyInfo, plugin, source);
}
} // End of files loop
/*
* The copy may have taken some time see if any pending
* copies can be completed.
*/
if (retrytimer.getElapsedTime() >= LOCK_RETRY_TIME) {
retryCasesCopy();
}
}
if (caseCopy != null) {
caseCopy.finishCase();
} // End of sourceDataList loop
// Finish up the loop's last plugin.
if (plugin != null) {
if (allowCopy) {
releaseLock(plugin);
}
// Finish last case
if (!keepCaseCopy(copyInfo)) {
caseCopy.finishCase();
}
plugin = null;
}
caseCopy = null;
// Finish pending copies needing locks.
waitForLocks();
if (shutdown.get()) {
return Status.OK_STATUS;
}
setStateLbl("Created: " + caseName, caseDir.getAbsolutePath());
setProgressBar(100, SWT.NORMAL);
} catch (CaseCreateException e) {
} catch (Exception e) {
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
e);
setStateLbl(
@ -474,20 +644,220 @@ public class GenerateCaseDlg extends CaveSWTDialog {
caseDir.getAbsolutePath() + "\n"
+ e.getLocalizedMessage());
setProgressBar(100, SWT.ERROR);
shutdown.set(true);
} finally {
// shutdown the time.
if (updateTimer != null) {
updateTimer.cancel();
updateTimer = null;
}
// Release resources of active case copy.
if (caseCopy != null) {
try {
caseCopy.finishCase();
} catch (CaseCreateException ex) {
// Ignore
if (!keepCaseCopy(copyInfo)) {
try {
// Allow the caseCopy to clean its resources.
caseCopy.finishCase();
} catch (CaseCreateException ex) {
// Ignore
}
caseCopy = null;
}
caseCopy = null;
}
// Release current lock.
if (allowCopy && (plugin != null)) {
releaseLock(plugin);
}
// Release resources of any pending case copy.
if (caseCopyMap.size() > 0) {
for (CopyInfo cpi : caseCopyMap.keySet()) {
try {
cpi.caseCopy.finishCase();
} catch (CaseCreateException ex) {
// Ignore
}
}
caseCopyMap.clear();
}
}
return Status.OK_STATUS;
}
/**
* Finish copying all files needing locks.
*
* @throws CaseCreateException
* @throws InterruptedException
*/
private void waitForLocks() throws CaseCreateException,
InterruptedException {
int retryCount = 0;
boolean updateStatus = true;
while (caseCopyMap.size() > 0) {
if (updateStatus) {
++retryCount;
StringBuilder tooltip = new StringBuilder();
tooltip.append("Waiting to finish ").append(
caseCopyMap.size());
if (caseCopyMap.size() == 1) {
tooltip.append(" category.");
} else {
tooltip.append(" categories.");
}
tooltip.append("\nAttempt: ").append(retryCount);
setStateLbl("Waiting for locks", tooltip.toString());
updateStatus = false;
}
synchronized (this) {
wait(TimeUtil.MILLIS_PER_SECOND / 2L);
}
if (shutdown.get()) {
return;
}
if (retrytimer.getElapsedTime() >= LOCK_RETRY_TIME) {
retryCasesCopy();
updateStatus = true;
}
}
}
/**
* Attempt to copy files still waiting on plug-in locks.
*
* @throws CaseCreateException
*/
private void retryCasesCopy() throws CaseCreateException {
if (shutdown.get()) {
return;
}
if (caseCopyMap.size() > 0) {
retrytimer.stop();
retrytimer.reset();
String lockedPlugin = null;
try {
Iterator<CopyInfo> copyInfoIter = caseCopyMap.keySet()
.iterator();
while (copyInfoIter.hasNext()) {
CopyInfo copyInfo = copyInfoIter.next();
setStateLbl(copyInfo.archive + " | "
+ copyInfo.category,
copyInfo.caseDir.getAbsolutePath() + "\n"
+ copyInfo.archive + "\n"
+ copyInfo.category);
Map<String, List<File>> pluginMap = caseCopyMap
.get(copyInfo);
Iterator<String> pluginIter = pluginMap.keySet()
.iterator();
while (pluginIter.hasNext()) {
String plugin = pluginIter.next();
if (shutdown.get()) {
return;
}
if (requestLock(plugin)) {
lockedPlugin = plugin;
for (File source : pluginMap.get(plugin)) {
copyInfo.caseCopy.copy(source);
if (shutdown.get()) {
return;
}
}
releaseLock(plugin);
lockedPlugin = null;
pluginIter.remove();
}
}
if (pluginMap.size() == 0) {
copyInfo.caseCopy.finishCase();
copyInfoIter.remove();
}
}
} finally {
if (lockedPlugin != null) {
releaseLock(lockedPlugin);
}
}
}
if (caseCopyMap.size() > 0) {
retrytimer.start();
}
}
/**
* Request a lock for the plug-in.
*
* @param details
* @return true when lock obtained otherwise false
*/
private boolean requestLock(String details) {
SharedLockRequest request = new SharedLockRequest(
ArchiveConstants.CLUSTER_NAME, details,
RequestType.READER_LOCK);
try {
Object o = ThriftClient.sendRequest(request);
if (o instanceof SharedLockResponse) {
SharedLockResponse response = (SharedLockResponse) o;
if (response.isSucessful()) {
if (updateTimer == null) {
updateTimer = new Timer(
"Case Creation update timer", true);
}
TimerTask timerTask = new LockUpdateTask(details);
updateTimer.schedule(timerTask,
TimeUtil.MILLIS_PER_MINUTE,
TimeUtil.MILLIS_PER_MINUTE);
return true;
}
}
} catch (VizException e) {
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
e);
}
return false;
}
/**
* Release previously obtained lock for the details.
*
* @param details
* @return true when lock released otherwise false.
*/
private boolean releaseLock(String details) {
SharedLockRequest request = new SharedLockRequest(
ArchiveConstants.CLUSTER_NAME, details,
RequestType.READER_UNLOCK);
try {
if (updateTimer != null) {
updateTimer.cancel();
updateTimer = null;
}
Object o = ThriftClient.sendRequest(request);
if (o instanceof SharedLockResponse) {
SharedLockResponse response = (SharedLockResponse) o;
if (response.isSucessful()) {
details = null;
return true;
}
}
} catch (VizException e) {
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
e);
}
return false;
}
/*
* (non-Javadoc)
*
@ -543,7 +913,7 @@ public class GenerateCaseDlg extends CaveSWTDialog {
copyFile(new File(source, file),
new File(destination, file));
}
} else {
} else if (source.exists()) {
// DR 2270 bump HDF files up a directory.
if (destination.getName().endsWith(hdfExt)) {
destination = new File(destination.getParentFile()
@ -661,7 +1031,7 @@ public class GenerateCaseDlg extends CaveSWTDialog {
tarDirFile.add(file);
addTarFiles(file.listFiles());
}
} else {
} else if (file.exists()) {
// DR 2270 bump HDF files up a directory.
if (name.endsWith(hdfExt)) {
File destination = new File(file.getParentFile()
@ -1091,4 +1461,46 @@ public class GenerateCaseDlg extends CaveSWTDialog {
// }
}
/** Task to update the lock plugin's last execute time. */
private final class LockUpdateTask extends TimerTask {
/** The locked cluster task's details. */
private final String details;
public LockUpdateTask(String details) {
this.details = details;
}
@Override
public void run() {
SharedLockRequest request = new SharedLockRequest(
ArchiveConstants.CLUSTER_NAME, details,
RequestType.READER_UPDATE_TIME);
try {
ThriftClient.sendRequest(request);
} catch (VizException e) {
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(),
e);
}
}
}
/** Information needed to update status when retrying a copy. */
private static class CopyInfo {
protected final ICaseCopy caseCopy;
protected final String archive;
protected final String category;
protected final File caseDir;
public CopyInfo(ICaseCopy caseCopy, String archive, String category,
File caseDir) {
this.caseCopy = caseCopy;
this.archive = archive;
this.category = category;
this.caseDir = caseDir;
}
}
}

View file

@ -34,6 +34,7 @@ import com.raytheon.uf.common.localization.IPathManager;
* ------------ ---------- ----------- --------------------------
* Jul 23, 2013 #2221 rferrel Initial creation
* Aug 26, 2013 #2225 rferrel Added tar extension.
* Apr 11, 2014 #2862 rferrel Added cluster name.
*
* </pre>
*
@ -42,6 +43,8 @@ import com.raytheon.uf.common.localization.IPathManager;
*/
public class ArchiveConstants {
/** The value for the cluster tasks' name column. */
public static final String CLUSTER_NAME = "Archive Shared Lock";
/** Pattern to find slashes in a string. */
private final static Pattern slashPattern = Pattern.compile("[/\\\\]+");

View file

@ -0,0 +1,135 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.dataquery.requests;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
import com.raytheon.uf.common.serialization.comm.IServerRequest;
/**
* The request class to coordinate with the shared locks in the
* awips.custer_task table.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 1, 2014 2862 rferrel Initial creation
*
* </pre>
*
* @author rferrel
* @version 1.0
*/
@DynamicSerialize
public class SharedLockRequest implements IServerRequest {
/** The types of requests. */
public static enum RequestType {
READER_LOCK, READER_UNLOCK, READER_UPDATE_TIME, WRITER_LOCK, WRITER_UNLOCK, WRITER_UPDATE_TIME
}
/** The name column entry. */
@DynamicSerializeElement
private String name;
/** The details column entry. */
@DynamicSerializeElement
private String details;
/* The desired request. */
@DynamicSerializeElement
private RequestType requestType;
/**
* Default constructor should only be used for serialization.
*/
public SharedLockRequest() {
}
/**
* Desired constructor.
*
* @param details
* @param requestType
*/
public SharedLockRequest(String name, String details,
RequestType requestType) {
setName(name);
setDetails(details);
setRequestType(requestType);
}
/**
* Getter.
*
* @return requestType
*/
public RequestType getRequestType() {
return requestType;
}
/**
* Setter should only be used for serialization.
*
* @param requestType
*/
public void setRequestType(RequestType requestType) {
this.requestType = requestType;
}
/**
* Getter.
*
* @return name
*/
public String getName() {
return name;
}
/**
* Setter.
*
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* Getter.
*
* @return details
*/
public String getDetails() {
return details;
}
/**
* Setter should only be used for serialization.
*
* @param details
*/
public void setDetails(String details) {
this.details = details;
}
}

View file

@ -0,0 +1,67 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.dataquery.responses;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
/**
* Response from the shared lock request handler.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 8, 2014 2862 rferrel Initial creation
*
* </pre>
*
* @author rferrel
* @version 1.0
*/
@DynamicSerialize
public class SharedLockResponse {
/** true when request was successful. */
@DynamicSerializeElement
private boolean sucessful;
/** Any error message from the handler. */
@DynamicSerializeElement
private String errorMessage;
public boolean isSucessful() {
return sucessful;
}
public void setSucessful(boolean sucessful) {
this.sucessful = sucessful;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
}

View file

@ -30,6 +30,7 @@ import java.util.TimeZone;
import java.util.Timer;
import java.util.TimerTask;
import com.raytheon.uf.common.archive.config.ArchiveConstants;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.PluginException;
import com.raytheon.uf.common.dataplugin.PluginProperties;
@ -127,8 +128,8 @@ public class DatabaseArchiver implements IPluginArchiver {
@Override
public void run() {
long currentTime = System.currentTimeMillis();
ClusterLockUtils.updateLockTime(SharedLockHandler.name, details,
currentTime);
ClusterLockUtils.updateLockTime(ArchiveConstants.CLUSTER_NAME,
details, currentTime);
}
}
@ -170,8 +171,8 @@ public class DatabaseArchiver implements IPluginArchiver {
*/
private ClusterTask getWriteLock(String details) {
SharedLockHandler lockHandler = new SharedLockHandler(LockType.WRITER);
ClusterTask ct = ClusterLockUtils.lock(SharedLockHandler.name, details,
lockHandler, false);
ClusterTask ct = ClusterLockUtils.lock(ArchiveConstants.CLUSTER_NAME,
details, lockHandler, false);
if (LockState.SUCCESSFUL.equals(ct.getLockState())) {
if (statusHandler.isPriorityEnabled(Priority.INFO)) {
statusHandler.handle(Priority.INFO, String.format(

View file

@ -34,6 +34,7 @@ import org.apache.commons.io.filefilter.IOFileFilter;
import com.raytheon.uf.common.archive.config.ArchiveConfig;
import com.raytheon.uf.common.archive.config.ArchiveConfigManager;
import com.raytheon.uf.common.archive.config.ArchiveConstants;
import com.raytheon.uf.common.archive.config.CategoryConfig;
import com.raytheon.uf.common.archive.config.CategoryFileDateHelper;
import com.raytheon.uf.common.archive.config.DataSetStatus;
@ -264,8 +265,8 @@ public class ArchivePurgeManager {
*/
private ClusterTask getWriteLock(String details) {
SharedLockHandler lockHandler = new SharedLockHandler(LockType.WRITER);
ClusterTask ct = ClusterLockUtils.lock(SharedLockHandler.name, details,
lockHandler, false);
ClusterTask ct = ClusterLockUtils.lock(ArchiveConstants.CLUSTER_NAME,
details, lockHandler, false);
if (ct.getLockState().equals(LockState.SUCCESSFUL)) {
if (statusHandler.isPriorityEnabled(Priority.INFO)) {
statusHandler.handle(Priority.INFO, String.format(

View file

@ -64,8 +64,10 @@ public class ArchiveAdminPrivilegedRequestHandler extends
@Override
public ArchiveAdminAuthRequest handleRequest(ArchiveAdminAuthRequest request)
throws Exception {
// If it reaches this point in the code, then the user is authorized, so
// just return the request object with authorized set to true
/*
* If it reaches this point in the code, then the user is authorized, so
* just return the request object with authorized set to true.
*/
request.setAuthorized(true);
return request;
}
@ -85,14 +87,13 @@ public class ArchiveAdminPrivilegedRequestHandler extends
AuthManager manager = AuthManagerFactory.getInstance().getManager();
IRoleStorage roleStorage = manager.getRoleStorage();
boolean authorized = roleStorage.isAuthorized((request).getRoleId(),
user.uniqueId().toString(), APPLICATION);
boolean authorized = roleStorage.isAuthorized(request.getRoleId(), user
.uniqueId().toString(), APPLICATION);
if (authorized) {
return new AuthorizationResponse(authorized);
} else {
return new AuthorizationResponse(
(request).getNotAuthorizedMessage());
return new AuthorizationResponse(request.getNotAuthorizedMessage());
}
}
}

View file

@ -0,0 +1,15 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<!-- Instantiate the handler class for RemoteScriptList Handler -->
<bean id="SharedLockRequestHandler"
class="com.raytheon.uf.edex.database.handlers.SharedLockRequestHandler"/>
<!-- Register the handler class with the RemoteScriptListRequest Register. -->
<bean id="sharedLockRequest" factory-bean="handlerRegistry" factory-method="register">
<constructor-arg value="com.raytheon.uf.common.dataquery.requests.SharedLockRequest"/>
<constructor-arg ref="SharedLockRequestHandler"/>
</bean>
</beans>

View file

@ -56,9 +56,6 @@ public final class SharedLockHandler extends CurrentTimeClusterLockHandler {
WRITER
};
/** The value for the cluster tasks' name column. */
public static final String name = "Shared Lock";
/**
* Common override time out. Clients need to rely on this value in order to
* update last execution time to maintain the lock.

View file

@ -0,0 +1,239 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.database.handlers;
import java.util.List;
import com.raytheon.uf.common.dataquery.requests.SharedLockRequest;
import com.raytheon.uf.common.dataquery.requests.SharedLockRequest.RequestType;
import com.raytheon.uf.common.dataquery.responses.SharedLockResponse;
import com.raytheon.uf.common.serialization.comm.IRequestHandler;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.edex.database.cluster.ClusterLockUtils;
import com.raytheon.uf.edex.database.cluster.ClusterLockUtils.LockState;
import com.raytheon.uf.edex.database.cluster.ClusterTask;
import com.raytheon.uf.edex.database.cluster.handler.SharedLockHandler;
import com.raytheon.uf.edex.database.cluster.handler.SharedLockHandler.LockType;
/**
* This is the handler class for a shared lock request. It coordinates with the
* shared lock handler to perform the desired request.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 2, 2014 2862 rferrel Initial creation
*
* </pre>
*
* @author rferrel
* @version 1.0
*/
public class SharedLockRequestHandler implements
IRequestHandler<SharedLockRequest> {
private final IUFStatusHandler statusHander = UFStatus
.getHandler(SharedLockRequestHandler.class);
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.serialization.comm.IRequestHandler#handleRequest
* (com.raytheon.uf.common.serialization.comm.IServerRequest)
*/
@Override
public SharedLockResponse handleRequest(SharedLockRequest request)
throws Exception {
SharedLockResponse response = new SharedLockResponse();
String name = request.getName();
String details = request.getDetails();
RequestType type = request.getRequestType();
response.setSucessful(false);
try {
switch (type) {
case READER_LOCK:
if (lock(name, details, LockType.READER)) {
response.setSucessful(true);
} else {
response.setSucessful(false);
response.setErrorMessage(String.format(
"Unable to obtain %s lock.", LockType.READER));
}
break;
case READER_UNLOCK:
if (unlock(name, details, LockType.READER)) {
response.setSucessful(true);
} else {
response.setSucessful(false);
response.setErrorMessage(String.format(
"Unable to unlock %s.", LockType.READER));
}
break;
case READER_UPDATE_TIME:
if (updateTime(name, details, LockType.READER)) {
response.setSucessful(true);
} else {
response.setSucessful(false);
response.setErrorMessage(String.format(
"Unable to update %s last exection time.",
LockType.READER));
}
break;
case WRITER_LOCK:
if (lock(name, details, LockType.WRITER)) {
response.setSucessful(true);
} else {
response.setSucessful(false);
response.setErrorMessage(String.format(
"Unable to obtain %s lock.", LockType.WRITER));
}
break;
case WRITER_UNLOCK:
if (unlock(name, details, LockType.WRITER)) {
response.setSucessful(true);
} else {
response.setSucessful(false);
response.setErrorMessage(String.format(
"Unable to unlock %s.", LockType.WRITER));
}
break;
case WRITER_UPDATE_TIME:
if (updateTime(name, details, LockType.WRITER)) {
response.setSucessful(false);
response.setErrorMessage(String.format(
"Unable to update %s last execution time.",
LockType.WRITER));
}
break;
default:
String message = "Unimplemented request type: " + type;
statusHander.error(message);
response.setErrorMessage(message);
response.setSucessful(false);
}
} catch (Exception ex) {
response.setSucessful(false);
String message = String.format(
"Request type %s for details %s failed %s", type, details,
ex.getMessage());
response.setErrorMessage(message);
if (statusHander.isPriorityEnabled(Priority.PROBLEM)) {
statusHander.handle(Priority.PROBLEM, message, ex);
}
}
return response;
}
/**
* Request details lock of the desired lock type.
*
* @param details
* @param lockType
* @return true when obtaining lock is successful
*/
private boolean lock(String name, String details, LockType lockType) {
SharedLockHandler lockHandler = new SharedLockHandler(lockType);
ClusterTask ct = ClusterLockUtils.lock(name, details, lockHandler,
false);
return LockState.SUCCESSFUL.equals(ct.getLockState());
}
/**
* Release lock for given details. The unlock request is only attempted when
* the details' lock type matches and the count is a positive number.
*
* @param details
* @param lockType
* @return true when successful
*/
private boolean unlock(String name, String details, LockType lockType) {
ClusterTask ct = findCluster(name, details, lockType);
if (ct != null) {
SharedLockHandler handler = (SharedLockHandler) ct.getLockHandler();
if (handler.getLockCount() > 0) {
return ClusterLockUtils.unlock(ct, false);
}
}
return false;
}
/**
* Find the details' cluster task with latest extrainfo and set up its
* handler. The found cluster task is only returned if its lock type matches
* the requested type and it is in the run state.
*
* @param details
* - Whose cluster task to find
* @param lockType
* - Expected lock type for the cluster
* @return ct when found, matches lockType, and is running else null.
*/
private ClusterTask findCluster(String name, String details,
LockType lockType) {
ClusterTask ct = null;
List<ClusterTask> cts = ClusterLockUtils.getLocks(name);
if ((cts != null) && (cts.size() > 0)) {
for (ClusterTask tmpCt : cts) {
if (details.equals(tmpCt.getId().getDetails())) {
if (tmpCt.isRunning()) {
SharedLockHandler handler = new SharedLockHandler(
lockType);
handler.parseExtraInfoString(tmpCt.getExtraInfo());
if (handler.locksMatch()
&& (handler.getLockCount() > 0)) {
ct = tmpCt;
ct.setLockHandler(handler);
}
}
break;
}
}
}
return ct;
}
/**
* Update the last execution time for the detail's lock.
*
* @param details
* @param lockType
* @return true when update successful
*/
private boolean updateTime(String name, String details, LockType lockType) {
ClusterTask ct = findCluster(name, details, lockType);
if (ct != null) {
if (ClusterLockUtils.updateLockTime(ct.getId().getName(), ct
.getId().getDetails(), System.currentTimeMillis())) {
return true;
}
}
return false;
}
}