mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
Refactor of the file state cache code. (Part 2 of 2).
Removed the repo specific file state cache code. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@19949 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -62,7 +62,6 @@
|
|||||||
<property name="sysAdminParams"><ref bean="sysAdminParams"/></property>
|
<property name="sysAdminParams"><ref bean="sysAdminParams"/></property>
|
||||||
<property name="fileFolderService"><ref bean="FileFolderService" /></property>
|
<property name="fileFolderService"><ref bean="FileFolderService" /></property>
|
||||||
<property name="serviceRegistry"><ref bean="ServiceRegistry"/></property>
|
<property name="serviceRegistry"><ref bean="ServiceRegistry"/></property>
|
||||||
<property name="stateReaper"><ref bean="fileStateReaper"/></property>
|
|
||||||
<property name="nodeMonitorFactory"><ref bean="nodeMonitorFactory"/></property>
|
<property name="nodeMonitorFactory"><ref bean="nodeMonitorFactory"/></property>
|
||||||
<property name="nodeArchiveService"><ref bean="nodeArchiveService" /></property>
|
<property name="nodeArchiveService"><ref bean="nodeArchiveService" /></property>
|
||||||
<property name="lockService"><ref bean="lockService" /></property>
|
<property name="lockService"><ref bean="lockService" /></property>
|
||||||
@@ -93,7 +92,6 @@
|
|||||||
<property name="authenticationService"><ref bean="authenticationService"/></property>
|
<property name="authenticationService"><ref bean="authenticationService"/></property>
|
||||||
<property name="mimetypeService"><ref bean="mimetypeService"/></property>
|
<property name="mimetypeService"><ref bean="mimetypeService"/></property>
|
||||||
<property name="serviceRegistry"><ref bean="ServiceRegistry"/></property>
|
<property name="serviceRegistry"><ref bean="ServiceRegistry"/></property>
|
||||||
<property name="stateReaper"><ref bean="fileStateReaper"/></property>
|
|
||||||
<property name="nodeService"><ref bean="NodeService"/></property>
|
<property name="nodeService"><ref bean="NodeService"/></property>
|
||||||
|
|
||||||
<property name="createStoreListener"><ref bean="createStoreTxnListener"/></property>
|
<property name="createStoreListener"><ref bean="createStoreTxnListener"/></property>
|
||||||
@@ -101,9 +99,4 @@
|
|||||||
<property name="createVersionListener"><ref bean="createVersionTxnListener"/></property>
|
<property name="createVersionListener"><ref bean="createVersionTxnListener"/></property>
|
||||||
<property name="purgeVersionListener"><ref bean="purgeVersionTxnListener"/></property>
|
<property name="purgeVersionListener"><ref bean="purgeVersionTxnListener"/></property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<!-- File State Reaper -->
|
|
||||||
<bean id="fileStateReaper" class="org.alfresco.filesys.state.FileStateReaper"
|
|
||||||
destroy-method="shutdownRequest"/>
|
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
@@ -1925,6 +1925,15 @@ public class ServerConfigurationBean extends AbstractServerConfigurationBean {
|
|||||||
|
|
||||||
filesys = new DiskSharedDevice(filesysName, filesysDriver, filesysContext);
|
filesys = new DiskSharedDevice(filesysName, filesysDriver, filesysContext);
|
||||||
|
|
||||||
|
// Check if the filesystem uses the file state cache, if so then add to the file state reaper
|
||||||
|
|
||||||
|
if ( filesysContext.hasStateCache()) {
|
||||||
|
|
||||||
|
// Register the state cache with the reaper thread
|
||||||
|
|
||||||
|
fsysConfig.addFileStateCache( filesysName, filesysContext.getStateCache());
|
||||||
|
}
|
||||||
|
|
||||||
// Start the filesystem
|
// Start the filesystem
|
||||||
|
|
||||||
filesysContext.startFilesystem(filesys);
|
filesysContext.startFilesystem(filesys);
|
||||||
@@ -1999,6 +2008,15 @@ public class ServerConfigurationBean extends AbstractServerConfigurationBean {
|
|||||||
|
|
||||||
filesysContext.enableChangeHandler(changeNotify);
|
filesysContext.enableChangeHandler(changeNotify);
|
||||||
|
|
||||||
|
// Check if the filesystem uses the file state cache, if so then add to the file state reaper
|
||||||
|
|
||||||
|
if ( filesysContext.hasStateCache()) {
|
||||||
|
|
||||||
|
// Register the state cache with the reaper thread
|
||||||
|
|
||||||
|
fsysConfig.addFileStateCache( filesysName, filesysContext.getStateCache());
|
||||||
|
}
|
||||||
|
|
||||||
// Start the filesystem
|
// Start the filesystem
|
||||||
|
|
||||||
filesysContext.startFilesystem(filesys);
|
filesysContext.startFilesystem(filesys);
|
||||||
@@ -2046,10 +2064,10 @@ public class ServerConfigurationBean extends AbstractServerConfigurationBean {
|
|||||||
|
|
||||||
if ( fsysConfig.getShares().findShare( storeName, ShareType.DISK, true) == null)
|
if ( fsysConfig.getShares().findShare( storeName, ShareType.DISK, true) == null)
|
||||||
{
|
{
|
||||||
// Create the new share for the store
|
// Create the new share for the store
|
||||||
|
|
||||||
AVMContext avmContext = new AVMContext( storeName, storeName + ":/", AVMContext.VERSION_HEAD);
|
AVMContext avmContext = new AVMContext( storeName, storeName + ":/", AVMContext.VERSION_HEAD);
|
||||||
avmContext.enableStateTable( true, avmDriver.getStateReaper());
|
avmContext.enableStateCache( true);
|
||||||
|
|
||||||
// Create the shared filesystem
|
// Create the shared filesystem
|
||||||
|
|
||||||
|
@@ -24,8 +24,6 @@ import java.util.StringTokenizer;
|
|||||||
|
|
||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
import org.alfresco.filesys.config.GlobalDesktopActionConfigBean;
|
import org.alfresco.filesys.config.GlobalDesktopActionConfigBean;
|
||||||
import org.alfresco.filesys.state.FileStateReaper;
|
|
||||||
import org.alfresco.filesys.state.FileStateTable;
|
|
||||||
import org.alfresco.jlan.server.filesys.DiskDeviceContext;
|
import org.alfresco.jlan.server.filesys.DiskDeviceContext;
|
||||||
import org.alfresco.jlan.server.filesys.DiskInterface;
|
import org.alfresco.jlan.server.filesys.DiskInterface;
|
||||||
import org.alfresco.jlan.server.filesys.FileSystem;
|
import org.alfresco.jlan.server.filesys.FileSystem;
|
||||||
@@ -58,11 +56,6 @@ public abstract class AlfrescoContext extends DiskDeviceContext
|
|||||||
|
|
||||||
private static final String m_filesysDebugStr[] = { "FILE", "FILEIO", "SEARCH", "INFO", "LOCK", "PSEUDO", "RENAME" };
|
private static final String m_filesysDebugStr[] = { "FILE", "FILEIO", "SEARCH", "INFO", "LOCK", "PSEUDO", "RENAME" };
|
||||||
|
|
||||||
// File state table and associated file state reaper
|
|
||||||
|
|
||||||
private FileStateTable m_stateTable;
|
|
||||||
private FileStateReaper m_stateReaper;
|
|
||||||
|
|
||||||
// URL pseudo file web path prefix (server/port/webapp) and link file name
|
// URL pseudo file web path prefix (server/port/webapp) and link file name
|
||||||
|
|
||||||
private String m_urlFileName;
|
private String m_urlFileName;
|
||||||
@@ -147,57 +140,6 @@ public abstract class AlfrescoContext extends DiskDeviceContext
|
|||||||
return FileSystem.TypeNTFS;
|
return FileSystem.TypeNTFS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if the file state table is enabled
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public final boolean hasStateTable()
|
|
||||||
{
|
|
||||||
return m_stateTable != null ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the file state table
|
|
||||||
*
|
|
||||||
* @return FileStateTable
|
|
||||||
*/
|
|
||||||
public final FileStateTable getStateTable()
|
|
||||||
{
|
|
||||||
return m_stateTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enable/disable the file state table
|
|
||||||
*
|
|
||||||
* @param ena boolean
|
|
||||||
* @param stateReaper FileStateReaper
|
|
||||||
*/
|
|
||||||
public final void enableStateTable(boolean ena, FileStateReaper stateReaper)
|
|
||||||
{
|
|
||||||
if ( ena == false)
|
|
||||||
{
|
|
||||||
// Remove the state table from the reaper
|
|
||||||
|
|
||||||
stateReaper.removeStateTable( getShareName());
|
|
||||||
m_stateTable = null;
|
|
||||||
}
|
|
||||||
else if ( m_stateTable == null)
|
|
||||||
{
|
|
||||||
// Create the file state table
|
|
||||||
|
|
||||||
m_stateTable = new FileStateTable();
|
|
||||||
|
|
||||||
// Register with the file state reaper
|
|
||||||
|
|
||||||
stateReaper.addStateTable( getShareName(), m_stateTable);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save the reaper, for deregistering when the filesystem is closed
|
|
||||||
|
|
||||||
m_stateReaper = stateReaper;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if the pseudo file interface is enabled
|
* Determine if the pseudo file interface is enabled
|
||||||
*
|
*
|
||||||
@@ -482,19 +424,4 @@ public abstract class AlfrescoContext extends DiskDeviceContext
|
|||||||
{
|
{
|
||||||
return (m_debug & flg) != 0 ? true : false;
|
return (m_debug & flg) != 0 ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Close the filesystem context
|
|
||||||
*/
|
|
||||||
public void CloseContext() {
|
|
||||||
|
|
||||||
// Deregister the file state table from the reaper
|
|
||||||
|
|
||||||
if ( m_stateTable != null)
|
|
||||||
enableStateTable( false, m_stateReaper);
|
|
||||||
|
|
||||||
// Call the base class
|
|
||||||
|
|
||||||
super.CloseContext();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -22,7 +22,6 @@ import javax.transaction.Status;
|
|||||||
import javax.transaction.UserTransaction;
|
import javax.transaction.UserTransaction;
|
||||||
|
|
||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
import org.alfresco.filesys.state.FileStateReaper;
|
|
||||||
import org.alfresco.jlan.server.SrvSession;
|
import org.alfresco.jlan.server.SrvSession;
|
||||||
import org.alfresco.jlan.server.core.DeviceContext;
|
import org.alfresco.jlan.server.core.DeviceContext;
|
||||||
import org.alfresco.jlan.server.core.DeviceContextException;
|
import org.alfresco.jlan.server.core.DeviceContextException;
|
||||||
@@ -56,10 +55,6 @@ public abstract class AlfrescoDiskDriver implements IOCtlInterface, Transactiona
|
|||||||
|
|
||||||
private ServiceRegistry m_serviceRegistry;
|
private ServiceRegistry m_serviceRegistry;
|
||||||
|
|
||||||
// File state reaper
|
|
||||||
|
|
||||||
private FileStateReaper m_stateReaper;
|
|
||||||
|
|
||||||
// Transaction service
|
// Transaction service
|
||||||
|
|
||||||
private TransactionService m_transactionService;
|
private TransactionService m_transactionService;
|
||||||
@@ -74,16 +69,6 @@ public abstract class AlfrescoDiskDriver implements IOCtlInterface, Transactiona
|
|||||||
return m_serviceRegistry;
|
return m_serviceRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the file state reaper
|
|
||||||
*
|
|
||||||
* @return FileStateReaper
|
|
||||||
*/
|
|
||||||
public final FileStateReaper getStateReaper()
|
|
||||||
{
|
|
||||||
return m_stateReaper;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the transaction service
|
* Return the transaction service
|
||||||
*
|
*
|
||||||
@@ -104,16 +89,6 @@ public abstract class AlfrescoDiskDriver implements IOCtlInterface, Transactiona
|
|||||||
m_serviceRegistry = serviceRegistry;
|
m_serviceRegistry = serviceRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the file state reaper
|
|
||||||
*
|
|
||||||
* @param stateReaper FileStateReaper
|
|
||||||
*/
|
|
||||||
public final void setStateReaper(FileStateReaper stateReaper)
|
|
||||||
{
|
|
||||||
m_stateReaper = stateReaper;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param transactionService the transaction service
|
* @param transactionService the transaction service
|
||||||
*/
|
*/
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
package org.alfresco.filesys.alfresco;
|
package org.alfresco.filesys.alfresco;
|
||||||
|
|
||||||
import org.alfresco.jlan.server.filesys.NetworkFile;
|
import org.alfresco.jlan.server.filesys.NetworkFile;
|
||||||
import org.alfresco.filesys.state.FileState;
|
import org.alfresco.jlan.server.filesys.cache.FileState;
|
||||||
|
import org.alfresco.jlan.server.filesys.cache.NetworkFileStateInterface;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2007-2010 Alfresco Software Limited.
|
* Copyright (C) 2007-2010 Alfresco Software Limited.
|
||||||
@@ -27,7 +28,7 @@ import org.alfresco.filesys.state.FileState;
|
|||||||
*
|
*
|
||||||
* <p>Adds Alfresco extensions to the network file.
|
* <p>Adds Alfresco extensions to the network file.
|
||||||
*/
|
*/
|
||||||
public abstract class AlfrescoNetworkFile extends NetworkFile {
|
public abstract class AlfrescoNetworkFile extends NetworkFile implements NetworkFileStateInterface {
|
||||||
|
|
||||||
// Associated file state
|
// Associated file state
|
||||||
|
|
||||||
|
@@ -352,7 +352,7 @@ public class HomeShareMapper implements ShareMapper
|
|||||||
ContentDiskDriver diskDrv = ( ContentDiskDriver) getRepoDiskInterface();
|
ContentDiskDriver diskDrv = ( ContentDiskDriver) getRepoDiskInterface();
|
||||||
ContentContext diskCtx = new ContentContext( getHomeFolderName(), "", "", client.getHomeFolder());
|
ContentContext diskCtx = new ContentContext( getHomeFolderName(), "", "", client.getHomeFolder());
|
||||||
|
|
||||||
diskCtx.enableStateTable( true, diskDrv.getStateReaper());
|
diskCtx.enableStateCache( true);
|
||||||
|
|
||||||
// Create a temporary shared device for the users home directory
|
// Create a temporary shared device for the users home directory
|
||||||
|
|
||||||
|
@@ -420,7 +420,7 @@ public class MultiTenantShareMapper implements ShareMapper, ConfigurationListene
|
|||||||
|
|
||||||
// Enable file state caching
|
// Enable file state caching
|
||||||
|
|
||||||
diskCtx.enableStateTable( true, diskDrv.getStateReaper());
|
diskCtx.enableStateCache( true);
|
||||||
|
|
||||||
// Initialize the I/O control handler
|
// Initialize the I/O control handler
|
||||||
|
|
||||||
|
@@ -23,14 +23,15 @@ import java.util.Enumeration;
|
|||||||
import org.alfresco.jlan.server.SrvSession;
|
import org.alfresco.jlan.server.SrvSession;
|
||||||
import org.alfresco.jlan.server.filesys.FileName;
|
import org.alfresco.jlan.server.filesys.FileName;
|
||||||
import org.alfresco.jlan.server.filesys.TreeConnection;
|
import org.alfresco.jlan.server.filesys.TreeConnection;
|
||||||
|
import org.alfresco.jlan.server.filesys.cache.FileState;
|
||||||
import org.alfresco.jlan.server.filesys.pseudo.MemoryPseudoFile;
|
import org.alfresco.jlan.server.filesys.pseudo.MemoryPseudoFile;
|
||||||
import org.alfresco.jlan.server.filesys.pseudo.PseudoFile;
|
import org.alfresco.jlan.server.filesys.pseudo.PseudoFile;
|
||||||
import org.alfresco.jlan.server.filesys.pseudo.PseudoFileInterface;
|
import org.alfresco.jlan.server.filesys.pseudo.PseudoFileInterface;
|
||||||
import org.alfresco.jlan.smb.server.SMBSrvSession;
|
import org.alfresco.jlan.smb.server.SMBSrvSession;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.filesys.alfresco.DesktopAction;
|
import org.alfresco.filesys.alfresco.DesktopAction;
|
||||||
import org.alfresco.filesys.alfresco.DesktopActionTable;
|
import org.alfresco.filesys.alfresco.DesktopActionTable;
|
||||||
import org.alfresco.filesys.repo.ContentContext;
|
import org.alfresco.filesys.repo.ContentContext;
|
||||||
import org.alfresco.filesys.state.FileState;
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
@@ -170,7 +171,7 @@ public class PseudoFileImpl implements PseudoFileInterface
|
|||||||
// If the file state is null create a file state for the path
|
// If the file state is null create a file state for the path
|
||||||
|
|
||||||
if ( fstate == null)
|
if ( fstate == null)
|
||||||
ctx.getStateTable().findFileState( path, true, true);
|
ctx.getStateCache().findFileState( path, true);
|
||||||
|
|
||||||
// Add the desktop action pseudo files
|
// Add the desktop action pseudo files
|
||||||
|
|
||||||
@@ -205,17 +206,18 @@ public class PseudoFileImpl implements PseudoFileInterface
|
|||||||
{
|
{
|
||||||
// Make sure the state has the associated node details
|
// Make sure the state has the associated node details
|
||||||
|
|
||||||
if ( fstate.getNodeRef() != null)
|
if ( fstate.hasFilesystemObject())
|
||||||
{
|
{
|
||||||
// Build the URL file data
|
// Build the URL file data
|
||||||
|
|
||||||
|
NodeRef nodeRef = (NodeRef) fstate.getFilesystemObject();
|
||||||
StringBuilder urlStr = new StringBuilder();
|
StringBuilder urlStr = new StringBuilder();
|
||||||
|
|
||||||
urlStr.append("[InternetShortcut]\r\n");
|
urlStr.append("[InternetShortcut]\r\n");
|
||||||
urlStr.append("URL=");
|
urlStr.append("URL=");
|
||||||
urlStr.append(ctx.getURLPrefix());
|
urlStr.append(ctx.getURLPrefix());
|
||||||
urlStr.append("navigate/browse/workspace/SpacesStore/");
|
urlStr.append("navigate/browse/workspace/SpacesStore/");
|
||||||
urlStr.append( fstate.getNodeRef().getId());
|
urlStr.append( nodeRef.getId());
|
||||||
urlStr.append("\r\n");
|
urlStr.append("\r\n");
|
||||||
|
|
||||||
// Create the in memory pseudo file for the URL link
|
// Create the in memory pseudo file for the URL link
|
||||||
@@ -282,11 +284,11 @@ public class PseudoFileImpl implements PseudoFileInterface
|
|||||||
|
|
||||||
FileState fstate = null;
|
FileState fstate = null;
|
||||||
|
|
||||||
if ( ctx.hasStateTable())
|
if ( ctx.hasStateCache())
|
||||||
{
|
{
|
||||||
// Get the file state for a file/folder
|
// Get the file state for a file/folder
|
||||||
|
|
||||||
fstate = ctx.getStateTable().findFileState(path);
|
fstate = ctx.getStateCache().findFileState(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the file state
|
// Return the file state
|
||||||
|
@@ -25,12 +25,12 @@ import org.alfresco.error.AlfrescoRuntimeException;
|
|||||||
import org.alfresco.filesys.alfresco.AlfrescoContext;
|
import org.alfresco.filesys.alfresco.AlfrescoContext;
|
||||||
import org.alfresco.filesys.alfresco.AlfrescoDiskDriver;
|
import org.alfresco.filesys.alfresco.AlfrescoDiskDriver;
|
||||||
import org.alfresco.filesys.alfresco.IOControlHandler;
|
import org.alfresco.filesys.alfresco.IOControlHandler;
|
||||||
import org.alfresco.filesys.state.FileState;
|
|
||||||
import org.alfresco.filesys.state.FileStateTable;
|
|
||||||
import org.alfresco.jlan.server.filesys.DiskInterface;
|
import org.alfresco.jlan.server.filesys.DiskInterface;
|
||||||
import org.alfresco.jlan.server.filesys.FileName;
|
import org.alfresco.jlan.server.filesys.FileName;
|
||||||
import org.alfresco.jlan.server.filesys.FileSystem;
|
import org.alfresco.jlan.server.filesys.FileSystem;
|
||||||
import org.alfresco.jlan.server.filesys.NotifyChange;
|
import org.alfresco.jlan.server.filesys.NotifyChange;
|
||||||
|
import org.alfresco.jlan.server.filesys.cache.FileState;
|
||||||
|
import org.alfresco.jlan.server.filesys.cache.FileStateCache;
|
||||||
import org.alfresco.jlan.util.StringList;
|
import org.alfresco.jlan.util.StringList;
|
||||||
import org.alfresco.repo.avm.CreateStoreCallback;
|
import org.alfresco.repo.avm.CreateStoreCallback;
|
||||||
import org.alfresco.repo.avm.CreateVersionCallback;
|
import org.alfresco.repo.avm.CreateVersionCallback;
|
||||||
@@ -440,13 +440,13 @@ public class AVMContext extends AlfrescoContext
|
|||||||
|
|
||||||
// Make sure the file state cache is enabled
|
// Make sure the file state cache is enabled
|
||||||
|
|
||||||
FileStateTable fsTable = getStateTable();
|
FileStateCache fsTable = getStateCache();
|
||||||
if ( fsTable == null)
|
if ( fsTable == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Find the file state for the root folder
|
// Find the file state for the root folder
|
||||||
|
|
||||||
FileState rootState = fsTable.findFileState( FileName.DOS_SEPERATOR_STR, true, true);
|
FileState rootState = fsTable.findFileState( FileName.DOS_SEPERATOR_STR, true);
|
||||||
|
|
||||||
if ( rootState != null)
|
if ( rootState != null)
|
||||||
{
|
{
|
||||||
@@ -481,7 +481,7 @@ public class AVMContext extends AlfrescoContext
|
|||||||
|
|
||||||
// Make sure the file state cache is enabled
|
// Make sure the file state cache is enabled
|
||||||
|
|
||||||
FileStateTable fsTable = getStateTable();
|
FileStateCache fsTable = getStateCache();
|
||||||
if ( fsTable == null)
|
if ( fsTable == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -542,7 +542,7 @@ public class AVMContext extends AlfrescoContext
|
|||||||
|
|
||||||
// Make sure the file state cache is enabled
|
// Make sure the file state cache is enabled
|
||||||
|
|
||||||
FileStateTable fsTable = getStateTable();
|
FileStateCache fsTable = getStateCache();
|
||||||
if ( fsTable == null)
|
if ( fsTable == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -612,7 +612,7 @@ public class AVMContext extends AlfrescoContext
|
|||||||
|
|
||||||
// Make sure the file state cache is enabled
|
// Make sure the file state cache is enabled
|
||||||
|
|
||||||
FileStateTable fsTable = getStateTable();
|
FileStateCache fsTable = getStateCache();
|
||||||
if ( fsTable == null)
|
if ( fsTable == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@@ -29,7 +29,6 @@ import javax.transaction.UserTransaction;
|
|||||||
|
|
||||||
import org.springframework.extensions.config.ConfigElement;
|
import org.springframework.extensions.config.ConfigElement;
|
||||||
import org.alfresco.filesys.alfresco.AlfrescoDiskDriver;
|
import org.alfresco.filesys.alfresco.AlfrescoDiskDriver;
|
||||||
import org.alfresco.filesys.state.FileState;
|
|
||||||
import org.alfresco.jlan.server.SrvSession;
|
import org.alfresco.jlan.server.SrvSession;
|
||||||
import org.alfresco.jlan.server.auth.ClientInfo;
|
import org.alfresco.jlan.server.auth.ClientInfo;
|
||||||
import org.alfresco.jlan.server.core.DeviceContext;
|
import org.alfresco.jlan.server.core.DeviceContext;
|
||||||
@@ -47,6 +46,7 @@ import org.alfresco.jlan.server.filesys.NetworkFile;
|
|||||||
import org.alfresco.jlan.server.filesys.PathNotFoundException;
|
import org.alfresco.jlan.server.filesys.PathNotFoundException;
|
||||||
import org.alfresco.jlan.server.filesys.SearchContext;
|
import org.alfresco.jlan.server.filesys.SearchContext;
|
||||||
import org.alfresco.jlan.server.filesys.TreeConnection;
|
import org.alfresco.jlan.server.filesys.TreeConnection;
|
||||||
|
import org.alfresco.jlan.server.filesys.cache.FileState;
|
||||||
import org.alfresco.jlan.server.filesys.pseudo.PseudoFile;
|
import org.alfresco.jlan.server.filesys.pseudo.PseudoFile;
|
||||||
import org.alfresco.jlan.server.filesys.pseudo.PseudoFileList;
|
import org.alfresco.jlan.server.filesys.pseudo.PseudoFileList;
|
||||||
import org.alfresco.jlan.server.filesys.pseudo.PseudoFolderNetworkFile;
|
import org.alfresco.jlan.server.filesys.pseudo.PseudoFolderNetworkFile;
|
||||||
@@ -394,7 +394,7 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface
|
|||||||
|
|
||||||
// Enable file state caching
|
// Enable file state caching
|
||||||
|
|
||||||
context.enableStateTable(true, getStateReaper());
|
context.enableStateCache( true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -452,7 +452,7 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface
|
|||||||
{
|
{
|
||||||
// Enable file state caching
|
// Enable file state caching
|
||||||
|
|
||||||
context.enableStateTable(true, getStateReaper());
|
context.enableStateCache(true);
|
||||||
|
|
||||||
// Plug the virtualization view context into the various store/version call back listeners
|
// Plug the virtualization view context into the various store/version call back listeners
|
||||||
// so that store/version pseudo folders can be kept in sync with AVM
|
// so that store/version pseudo folders can be kept in sync with AVM
|
||||||
@@ -584,7 +584,7 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface
|
|||||||
|
|
||||||
// Enable file state caching
|
// Enable file state caching
|
||||||
|
|
||||||
context.enableStateTable(true, getStateReaper());
|
context.enableStateCache(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit the transaction
|
// Commit the transaction
|
||||||
@@ -2111,7 +2111,7 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface
|
|||||||
|
|
||||||
// Get the root folder file state
|
// Get the root folder file state
|
||||||
|
|
||||||
fstate = avmCtx.getStateTable().findFileState(FileName.DOS_SEPERATOR_STR);
|
fstate = avmCtx.getStateCache().findFileState(FileName.DOS_SEPERATOR_STR);
|
||||||
|
|
||||||
if (fstate != null && fstate.hasPseudoFiles())
|
if (fstate != null && fstate.hasPseudoFiles())
|
||||||
psFile = fstate.getPseudoFileList().findFile(avmPath.getStoreName(), false);
|
psFile = fstate.getPseudoFileList().findFile(avmPath.getStoreName(), false);
|
||||||
@@ -2329,7 +2329,7 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface
|
|||||||
|
|
||||||
// Get the root path file state
|
// Get the root path file state
|
||||||
|
|
||||||
fstate = avmCtx.getStateTable().findFileState( FileName.DOS_SEPERATOR_STR);
|
fstate = avmCtx.getStateCache().findFileState( FileName.DOS_SEPERATOR_STR);
|
||||||
|
|
||||||
// Check if the root file state is valid
|
// Check if the root file state is valid
|
||||||
|
|
||||||
@@ -2337,7 +2337,7 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface
|
|||||||
{
|
{
|
||||||
// Create a file state for the root folder
|
// Create a file state for the root folder
|
||||||
|
|
||||||
fstate = avmCtx.getStateTable().findFileState( FileName.DOS_SEPERATOR_STR, true, true);
|
fstate = avmCtx.getStateCache().findFileState( FileName.DOS_SEPERATOR_STR, true);
|
||||||
fstate.setExpiryTime( FileState.NoTimeout);
|
fstate.setExpiryTime( FileState.NoTimeout);
|
||||||
|
|
||||||
// Get a list of the available AVM stores
|
// Get a list of the available AVM stores
|
||||||
@@ -2565,13 +2565,13 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface
|
|||||||
// Search for the file state for the store pseudo folder
|
// Search for the file state for the store pseudo folder
|
||||||
|
|
||||||
relPath = str.toString();
|
relPath = str.toString();
|
||||||
fstate = avmCtx.getStateTable().findFileState( relPath);
|
fstate = avmCtx.getStateCache().findFileState( relPath);
|
||||||
|
|
||||||
if ( fstate == null)
|
if ( fstate == null)
|
||||||
{
|
{
|
||||||
// Create a file state for the store path
|
// Create a file state for the store path
|
||||||
|
|
||||||
fstate = avmCtx.getStateTable().findFileState( str.toString(), true, true);
|
fstate = avmCtx.getStateCache().findFileState( str.toString(), true);
|
||||||
|
|
||||||
// Add a pseudo file for the head version
|
// Add a pseudo file for the head version
|
||||||
|
|
||||||
@@ -2606,13 +2606,13 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface
|
|||||||
|
|
||||||
relPath = str.toString();
|
relPath = str.toString();
|
||||||
|
|
||||||
fstate = avmCtx.getStateTable().findFileState( relPath);
|
fstate = avmCtx.getStateCache().findFileState( relPath);
|
||||||
|
|
||||||
if ( fstate == null)
|
if ( fstate == null)
|
||||||
{
|
{
|
||||||
// Create a file state for the store head folder path
|
// Create a file state for the store head folder path
|
||||||
|
|
||||||
fstate = avmCtx.getStateTable().findFileState( str.toString(), true, true);
|
fstate = avmCtx.getStateCache().findFileState( str.toString(), true);
|
||||||
|
|
||||||
// Add a pseudo file for the data pseudo folder
|
// Add a pseudo file for the data pseudo folder
|
||||||
|
|
||||||
@@ -2650,7 +2650,7 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface
|
|||||||
// Create a file state for the store path
|
// Create a file state for the store path
|
||||||
|
|
||||||
relPath = str.toString();
|
relPath = str.toString();
|
||||||
fstate = avmCtx.getStateTable().findFileState( relPath, true, true);
|
fstate = avmCtx.getStateCache().findFileState( relPath, true);
|
||||||
|
|
||||||
// Add pseudo folders if the list is empty
|
// Add pseudo folders if the list is empty
|
||||||
|
|
||||||
@@ -2720,13 +2720,13 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface
|
|||||||
// Search for the file state for the version pseudo folder
|
// Search for the file state for the version pseudo folder
|
||||||
|
|
||||||
relPath = str.toString();
|
relPath = str.toString();
|
||||||
fstate = avmCtx.getStateTable().findFileState( relPath);
|
fstate = avmCtx.getStateCache().findFileState( relPath);
|
||||||
|
|
||||||
if ( fstate == null)
|
if ( fstate == null)
|
||||||
{
|
{
|
||||||
// Create a file state for the version folder path
|
// Create a file state for the version folder path
|
||||||
|
|
||||||
fstate = avmCtx.getStateTable().findFileState( str.toString(), true, true);
|
fstate = avmCtx.getStateCache().findFileState( str.toString(), true);
|
||||||
|
|
||||||
// Add a pseudo file for the data pseudo folder
|
// Add a pseudo file for the data pseudo folder
|
||||||
|
|
||||||
@@ -2852,7 +2852,7 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface
|
|||||||
|
|
||||||
// Get root file state, get the store pseudo folder details
|
// Get root file state, get the store pseudo folder details
|
||||||
|
|
||||||
FileState rootState = avmCtx.getStateTable().findFileState( FileName.DOS_SEPERATOR_STR);
|
FileState rootState = avmCtx.getStateCache().findFileState( FileName.DOS_SEPERATOR_STR);
|
||||||
if ( rootState == null){
|
if ( rootState == null){
|
||||||
|
|
||||||
// Recreate the root file state, new stores may have been added
|
// Recreate the root file state, new stores may have been added
|
||||||
@@ -3073,7 +3073,7 @@ public class AVMDiskDriver extends AlfrescoDiskDriver implements DiskInterface
|
|||||||
|
|
||||||
// Get the root folder file state
|
// Get the root folder file state
|
||||||
|
|
||||||
FileState fstate = avmCtx.getStateTable().findFileState( FileName.DOS_SEPERATOR_STR, true, false);
|
FileState fstate = avmCtx.getStateCache().findFileState( FileName.DOS_SEPERATOR_STR, true);
|
||||||
if ( fstate == null)
|
if ( fstate == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@@ -284,7 +284,7 @@ public class AVMShareMapper implements ShareMapper, InitializingBean {
|
|||||||
// Create a dynamic share mapped to the AVM store/version
|
// Create a dynamic share mapped to the AVM store/version
|
||||||
|
|
||||||
AVMContext avmCtx = new AVMContext( name, storePath, storeVersion);
|
AVMContext avmCtx = new AVMContext( name, storePath, storeVersion);
|
||||||
avmCtx.enableStateTable( true, m_driver.getStateReaper());
|
avmCtx.enableStateCache( true);
|
||||||
|
|
||||||
// Create a dynamic shared device for the store version
|
// Create a dynamic shared device for the store version
|
||||||
|
|
||||||
|
@@ -62,6 +62,7 @@ import org.alfresco.jlan.server.core.DeviceContext;
|
|||||||
import org.alfresco.jlan.server.core.DeviceContextException;
|
import org.alfresco.jlan.server.core.DeviceContextException;
|
||||||
import org.alfresco.jlan.server.core.ShareMapper;
|
import org.alfresco.jlan.server.core.ShareMapper;
|
||||||
import org.alfresco.jlan.server.core.ShareType;
|
import org.alfresco.jlan.server.core.ShareType;
|
||||||
|
import org.alfresco.jlan.server.filesys.DiskDeviceContext;
|
||||||
import org.alfresco.jlan.server.filesys.DiskSharedDevice;
|
import org.alfresco.jlan.server.filesys.DiskSharedDevice;
|
||||||
import org.alfresco.jlan.server.filesys.FilesystemsConfigSection;
|
import org.alfresco.jlan.server.filesys.FilesystemsConfigSection;
|
||||||
import org.alfresco.jlan.server.thread.ThreadRequestPool;
|
import org.alfresco.jlan.server.thread.ThreadRequestPool;
|
||||||
@@ -1559,6 +1560,17 @@ public class ServerConfigurationBean extends AbstractServerConfigurationBean
|
|||||||
|
|
||||||
filesys = new DiskSharedDevice(filesystem.getDeviceName(), filesysDriver, (AVMContext)filesystem);
|
filesys = new DiskSharedDevice(filesystem.getDeviceName(), filesysDriver, (AVMContext)filesystem);
|
||||||
|
|
||||||
|
// Check if the filesystem uses the file state cache, if so then add to the file state reaper
|
||||||
|
|
||||||
|
DiskDeviceContext diskCtx = (DiskDeviceContext) filesystem;
|
||||||
|
|
||||||
|
if ( diskCtx.hasStateCache()) {
|
||||||
|
|
||||||
|
// Register the state cache with the reaper thread
|
||||||
|
|
||||||
|
fsysConfig.addFileStateCache( filesystem.getDeviceName(), diskCtx.getStateCache());
|
||||||
|
}
|
||||||
|
|
||||||
// Start the filesystem
|
// Start the filesystem
|
||||||
|
|
||||||
((AVMContext)filesystem).startFilesystem(filesys);
|
((AVMContext)filesystem).startFilesystem(filesys);
|
||||||
@@ -1596,6 +1608,15 @@ public class ServerConfigurationBean extends AbstractServerConfigurationBean
|
|||||||
|
|
||||||
filesys.setAccessControlList(acls);
|
filesys.setAccessControlList(acls);
|
||||||
|
|
||||||
|
// Check if the filesystem uses the file state cache, if so then add to the file state reaper
|
||||||
|
|
||||||
|
if ( filesysContext.hasStateCache()) {
|
||||||
|
|
||||||
|
// Register the state cache with the reaper thread
|
||||||
|
|
||||||
|
fsysConfig.addFileStateCache( filesystem.getDeviceName(), filesysContext.getStateCache());
|
||||||
|
}
|
||||||
|
|
||||||
// Start the filesystem
|
// Start the filesystem
|
||||||
|
|
||||||
filesysContext.startFilesystem(filesys);
|
filesysContext.startFilesystem(filesys);
|
||||||
@@ -1647,7 +1668,7 @@ public class ServerConfigurationBean extends AbstractServerConfigurationBean
|
|||||||
// Create the new share for the store
|
// Create the new share for the store
|
||||||
|
|
||||||
AVMContext avmContext = new AVMContext(storeName, storeName + ":/", AVMContext.VERSION_HEAD);
|
AVMContext avmContext = new AVMContext(storeName, storeName + ":/", AVMContext.VERSION_HEAD);
|
||||||
avmContext.enableStateTable(true, avmDriver.getStateReaper());
|
avmContext.enableStateCache(true);
|
||||||
|
|
||||||
// Create the shared filesystem
|
// Create the shared filesystem
|
||||||
|
|
||||||
|
@@ -21,9 +21,9 @@ package org.alfresco.filesys.repo;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.alfresco.filesys.state.FileState;
|
|
||||||
import org.alfresco.filesys.state.FileStateTable;
|
|
||||||
import org.alfresco.jlan.server.filesys.FileInfo;
|
import org.alfresco.jlan.server.filesys.FileInfo;
|
||||||
|
import org.alfresco.jlan.server.filesys.cache.FileState;
|
||||||
|
import org.alfresco.jlan.server.filesys.cache.FileStateCache;
|
||||||
import org.alfresco.jlan.server.filesys.pseudo.PseudoFileList;
|
import org.alfresco.jlan.server.filesys.pseudo.PseudoFileList;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
@@ -45,7 +45,7 @@ public class CacheLookupSearchContext extends ContentSearchContext {
|
|||||||
|
|
||||||
// File state cache
|
// File state cache
|
||||||
|
|
||||||
private FileStateTable m_stateCache;
|
private FileStateCache m_stateCache;
|
||||||
|
|
||||||
// File information for the '.' and '..' pseduo entries, returned during a wildcard search
|
// File information for the '.' and '..' pseduo entries, returned during a wildcard search
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ public class CacheLookupSearchContext extends ContentSearchContext {
|
|||||||
String searchStr,
|
String searchStr,
|
||||||
PseudoFileList pseudoList,
|
PseudoFileList pseudoList,
|
||||||
String relPath,
|
String relPath,
|
||||||
FileStateTable stateCache)
|
FileStateCache stateCache)
|
||||||
{
|
{
|
||||||
super(cifsHelper, results, searchStr, pseudoList, relPath);
|
super(cifsHelper, results, searchStr, pseudoList, relPath);
|
||||||
super.setSearchString(searchStr);
|
super.setSearchString(searchStr);
|
||||||
|
@@ -33,9 +33,6 @@ import org.alfresco.error.AlfrescoRuntimeException;
|
|||||||
import org.alfresco.filesys.alfresco.AlfrescoContext;
|
import org.alfresco.filesys.alfresco.AlfrescoContext;
|
||||||
import org.alfresco.filesys.alfresco.AlfrescoDiskDriver;
|
import org.alfresco.filesys.alfresco.AlfrescoDiskDriver;
|
||||||
import org.alfresco.filesys.alfresco.AlfrescoNetworkFile;
|
import org.alfresco.filesys.alfresco.AlfrescoNetworkFile;
|
||||||
import org.alfresco.filesys.state.FileState;
|
|
||||||
import org.alfresco.filesys.state.FileStateLockManager;
|
|
||||||
import org.alfresco.filesys.state.FileState.FileStateStatus;
|
|
||||||
import org.alfresco.jlan.server.SrvSession;
|
import org.alfresco.jlan.server.SrvSession;
|
||||||
import org.alfresco.jlan.server.core.DeviceContext;
|
import org.alfresco.jlan.server.core.DeviceContext;
|
||||||
import org.alfresco.jlan.server.core.DeviceContextException;
|
import org.alfresco.jlan.server.core.DeviceContextException;
|
||||||
@@ -53,7 +50,8 @@ import org.alfresco.jlan.server.filesys.FileStatus;
|
|||||||
import org.alfresco.jlan.server.filesys.NetworkFile;
|
import org.alfresco.jlan.server.filesys.NetworkFile;
|
||||||
import org.alfresco.jlan.server.filesys.SearchContext;
|
import org.alfresco.jlan.server.filesys.SearchContext;
|
||||||
import org.alfresco.jlan.server.filesys.TreeConnection;
|
import org.alfresco.jlan.server.filesys.TreeConnection;
|
||||||
import org.alfresco.jlan.server.filesys.db.DBFileInfo;
|
import org.alfresco.jlan.server.filesys.cache.FileState;
|
||||||
|
import org.alfresco.jlan.server.filesys.cache.FileStateLockManager;
|
||||||
import org.alfresco.jlan.server.filesys.pseudo.MemoryNetworkFile;
|
import org.alfresco.jlan.server.filesys.pseudo.MemoryNetworkFile;
|
||||||
import org.alfresco.jlan.server.filesys.pseudo.PseudoFile;
|
import org.alfresco.jlan.server.filesys.pseudo.PseudoFile;
|
||||||
import org.alfresco.jlan.server.filesys.pseudo.PseudoFileInterface;
|
import org.alfresco.jlan.server.filesys.pseudo.PseudoFileInterface;
|
||||||
@@ -102,7 +100,7 @@ import org.springframework.extensions.config.ConfigElement;
|
|||||||
*
|
*
|
||||||
* <p>Provides a filesystem interface for various protocols such as SMB/CIFS and FTP.
|
* <p>Provides a filesystem interface for various protocols such as SMB/CIFS and FTP.
|
||||||
*
|
*
|
||||||
* @author Derek Hulley
|
* @author gkspencer
|
||||||
*/
|
*/
|
||||||
public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterface, FileLockingInterface, OpLockInterface
|
public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterface, FileLockingInterface, OpLockInterface
|
||||||
{
|
{
|
||||||
@@ -116,6 +114,21 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
private static final String KEY_ROOT_PATH = "rootPath";
|
private static final String KEY_ROOT_PATH = "rootPath";
|
||||||
private static final String KEY_RELATIVE_PATH = "relativePath";
|
private static final String KEY_RELATIVE_PATH = "relativePath";
|
||||||
|
|
||||||
|
// File status values used in the file state cache
|
||||||
|
|
||||||
|
public static final int FileUnknown = FileStatus.Unknown;
|
||||||
|
public static final int FileNotExist = FileStatus.NotExist;
|
||||||
|
public static final int FileExists = FileStatus.FileExists;
|
||||||
|
public static final int DirectoryExists = FileStatus.DirectoryExists;
|
||||||
|
|
||||||
|
public static final int CustomFileStatus= FileStatus.MaxStatus + 1;
|
||||||
|
public static final int FileRenamed = CustomFileStatus;
|
||||||
|
public static final int DeleteOnClose = CustomFileStatus + 1;
|
||||||
|
|
||||||
|
// File state attributes
|
||||||
|
|
||||||
|
public static final String AttrLinkNode = "ContentLinkNode";
|
||||||
|
|
||||||
// Services and helpers
|
// Services and helpers
|
||||||
|
|
||||||
private CifsHelper cifsHelper;
|
private CifsHelper cifsHelper;
|
||||||
@@ -139,7 +152,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
// Lock manager
|
// Lock manager
|
||||||
|
|
||||||
private static FileStateLockManager _lockManager = new FileStateLockManager();
|
private static FileStateLockManager _lockManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class constructor
|
* Class constructor
|
||||||
@@ -626,7 +639,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
// Enable file state caching
|
// Enable file state caching
|
||||||
|
|
||||||
context.enableStateTable( true, getStateReaper());
|
context.enableStateCache( true);
|
||||||
|
|
||||||
// Initialize the I/O control handler
|
// Initialize the I/O control handler
|
||||||
|
|
||||||
@@ -643,15 +656,13 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
context.setNodeMonitor( nodeMonitor);
|
context.setNodeMonitor( nodeMonitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create the lock manager
|
||||||
|
|
||||||
|
_lockManager = new FileStateLockManager( context.getStateCache());
|
||||||
|
|
||||||
// Check if oplocks are enabled
|
// Check if oplocks are enabled
|
||||||
|
|
||||||
if ( context.getDisableOplocks() == false) {
|
if ( context.getDisableOplocks() == true)
|
||||||
|
|
||||||
// Enable oplock support
|
|
||||||
|
|
||||||
_lockManager.setStateTable( context.getStateTable());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
logger.warn("Oplock support disabled for filesystem " + ctx.getDeviceName());
|
logger.warn("Oplock support disabled for filesystem " + ctx.getDeviceName());
|
||||||
|
|
||||||
// Start the quota manager, if enabled
|
// Start the quota manager, if enabled
|
||||||
@@ -749,7 +760,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
// Make sure the parent folder has a file state, and the path exists
|
// Make sure the parent folder has a file state, and the path exists
|
||||||
|
|
||||||
String[] paths = FileName.splitPath( path);
|
String[] paths = FileName.splitPath( path);
|
||||||
FileState fstate = ctx.getStateTable().findFileState( paths[0]);
|
FileState fstate = ctx.getStateCache().findFileState( paths[0]);
|
||||||
|
|
||||||
if ( fstate == null)
|
if ( fstate == null)
|
||||||
{
|
{
|
||||||
@@ -764,10 +775,10 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
// Create the file state
|
// Create the file state
|
||||||
|
|
||||||
fstate = ctx.getStateTable().findFileState( paths[0], true, true);
|
fstate = ctx.getStateCache().findFileState( paths[0], true);
|
||||||
|
|
||||||
fstate.setFileStatus( FileStatus.DirectoryExists);
|
fstate.setFileStatus( DirectoryExists);
|
||||||
fstate.setNodeRef( nodeRef);
|
fstate.setFilesystemObject( nodeRef);
|
||||||
|
|
||||||
// Add pseudo files to the folder
|
// Add pseudo files to the folder
|
||||||
|
|
||||||
@@ -782,11 +793,11 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
{
|
{
|
||||||
// Make sure the file state has the node ref
|
// Make sure the file state has the node ref
|
||||||
|
|
||||||
if ( fstate.hasNodeRef() == false)
|
if ( fstate.hasFilesystemObject() == false)
|
||||||
{
|
{
|
||||||
// Get the node for the folder path
|
// Get the node for the folder path
|
||||||
|
|
||||||
fstate.setNodeRef( getNodeForPath( tree, paths[0]));
|
fstate.setFilesystemObject( getNodeForPath( tree, paths[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add pseudo files for the parent folder
|
// Add pseudo files for the parent folder
|
||||||
@@ -897,9 +908,12 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
// Create a file state for the file/folder
|
// Create a file state for the file/folder
|
||||||
|
|
||||||
fstate = ctx.getStateTable().findFileState( path, finfo.isDirectory(), true);
|
fstate = ctx.getStateCache().findFileState( path, true);
|
||||||
|
if ( finfo.isDirectory())
|
||||||
fstate.setNodeRef( nodeRef);
|
fstate.setFileStatus( DirectoryExists);
|
||||||
|
else
|
||||||
|
fstate.setFileStatus( FileExists);
|
||||||
|
fstate.setFilesystemObject( nodeRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -971,7 +985,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
String[] paths = FileName.splitPath(searchPath);
|
String[] paths = FileName.splitPath(searchPath);
|
||||||
|
|
||||||
if ( ctx.hasStateTable())
|
if ( ctx.hasStateCache())
|
||||||
{
|
{
|
||||||
// See if the folder to be searched has a file state, we can avoid having to walk the path
|
// See if the folder to be searched has a file state, we can avoid having to walk the path
|
||||||
|
|
||||||
@@ -988,16 +1002,16 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
{
|
{
|
||||||
// Create a file state for the folder
|
// Create a file state for the folder
|
||||||
|
|
||||||
searchFolderState = ctx.getStateTable().findFileState( paths[0], true, true);
|
searchFolderState = ctx.getStateCache().findFileState( paths[0], true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the associated node is set
|
// Make sure the associated node is set
|
||||||
|
|
||||||
if ( searchFolderState.hasNodeRef() == false)
|
if ( searchFolderState.hasFilesystemObject() == false)
|
||||||
{
|
{
|
||||||
// Set the associated node for the folder
|
// Set the associated node for the folder
|
||||||
|
|
||||||
searchFolderState.setNodeRef( nodeRef);
|
searchFolderState.setFilesystemObject( nodeRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add pseudo files to the folder being searched
|
// Add pseudo files to the folder being searched
|
||||||
@@ -1115,16 +1129,16 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
{
|
{
|
||||||
// Use a cache lookup search context
|
// Use a cache lookup search context
|
||||||
|
|
||||||
CacheLookupSearchContext cacheContext = new CacheLookupSearchContext(cifsHelper, results, searchFileSpec, pseudoList, paths[0], ctx.getStateTable());
|
CacheLookupSearchContext cacheContext = new CacheLookupSearchContext(cifsHelper, results, searchFileSpec, pseudoList, paths[0], ctx.getStateCache());
|
||||||
searchCtx = cacheContext;
|
searchCtx = cacheContext;
|
||||||
|
|
||||||
// Set the '.' and '..' pseudo file entry details
|
// Set the '.' and '..' pseudo file entry details
|
||||||
|
|
||||||
if ( searchFolderState != null && searchFolderState.hasNodeRef())
|
if ( searchFolderState != null && searchFolderState.hasFilesystemObject())
|
||||||
{
|
{
|
||||||
// Get the '.' pseudo entry file details
|
// Get the '.' pseudo entry file details
|
||||||
|
|
||||||
FileInfo finfo = cifsHelper.getFileInformation( searchFolderState.getNodeRef());
|
FileInfo finfo = cifsHelper.getFileInformation((NodeRef) searchFolderState.getFilesystemObject());
|
||||||
|
|
||||||
// Blend in any cached timestamps
|
// Blend in any cached timestamps
|
||||||
|
|
||||||
@@ -1166,11 +1180,11 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
// Get the file state for the parent path, if available
|
// Get the file state for the parent path, if available
|
||||||
|
|
||||||
FileState parentState = ctx.getStateTable().findFileState( parentPath);
|
FileState parentState = ctx.getStateCache().findFileState( parentPath);
|
||||||
NodeRef parentNode = null;
|
NodeRef parentNode = null;
|
||||||
|
|
||||||
if ( parentState != null)
|
if ( parentState != null)
|
||||||
parentNode = parentState.getNodeRef();
|
parentNode = (NodeRef) parentState.getFilesystemObject();
|
||||||
|
|
||||||
if ( parentState == null || parentNode == null)
|
if ( parentState == null || parentNode == null)
|
||||||
parentNode = getNodeForPath( tree, parentPath);
|
parentNode = getNodeForPath( tree, parentPath);
|
||||||
@@ -1247,27 +1261,21 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
{
|
{
|
||||||
ContentContext ctx = (ContentContext) tree.getContext();
|
ContentContext ctx = (ContentContext) tree.getContext();
|
||||||
int status = FileStatus.Unknown;
|
int status = FileStatus.Unknown;
|
||||||
|
FileState fstate = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Check for a cached file state
|
// Check for a cached file state
|
||||||
|
|
||||||
FileState fstate = null;
|
if ( ctx.hasStateCache())
|
||||||
|
fstate = ctx.getStateCache().findFileState(name, true);
|
||||||
|
|
||||||
if ( ctx.hasStateTable())
|
if ( fstate != null && fstate.getFileStatus() != FileUnknown)
|
||||||
ctx.getStateTable().findFileState(name);
|
|
||||||
|
|
||||||
if ( fstate != null)
|
|
||||||
{
|
{
|
||||||
FileStateStatus fsts = fstate.getFileStatus();
|
status = fstate.getFileStatus();
|
||||||
|
if ( status >= CustomFileStatus)
|
||||||
|
status = FileNotExist;
|
||||||
|
|
||||||
if ( fsts == FileStateStatus.FileExists)
|
|
||||||
status = FileStatus.FileExists;
|
|
||||||
else if ( fsts == FileStateStatus.FolderExists)
|
|
||||||
status = FileStatus.DirectoryExists;
|
|
||||||
else if ( fsts == FileStateStatus.NotExist || fsts == FileStateStatus.Renamed)
|
|
||||||
status = FileStatus.NotExist;
|
|
||||||
|
|
||||||
// DEBUG
|
// DEBUG
|
||||||
|
|
||||||
if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_INFO))
|
if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_INFO))
|
||||||
@@ -1286,7 +1294,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
// Make sure the parent folder has a file state, and the path exists
|
// Make sure the parent folder has a file state, and the path exists
|
||||||
|
|
||||||
String[] paths = FileName.splitPath( name);
|
String[] paths = FileName.splitPath( name);
|
||||||
fstate = ctx.getStateTable().findFileState( paths[0]);
|
fstate = ctx.getStateCache().findFileState( paths[0]);
|
||||||
|
|
||||||
if ( fstate == null) {
|
if ( fstate == null) {
|
||||||
|
|
||||||
@@ -1296,14 +1304,14 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
{
|
{
|
||||||
// Create the file state
|
// Create the file state
|
||||||
|
|
||||||
fstate = ctx.getStateTable().findFileState( paths[0], true, true);
|
fstate = ctx.getStateCache().findFileState( paths[0], true);
|
||||||
|
|
||||||
fstate.setFileStatus( FileStatus.DirectoryExists);
|
fstate.setFileStatus( DirectoryExists);
|
||||||
|
|
||||||
// Get the node for the folder path
|
// Get the node for the folder path
|
||||||
|
|
||||||
beginReadTransaction( sess);
|
beginReadTransaction( sess);
|
||||||
fstate.setNodeRef( getNodeForPath( tree, paths[0]));
|
fstate.setFilesystemObject( getNodeForPath( tree, paths[0]));
|
||||||
|
|
||||||
// Add pseudo files to the folder
|
// Add pseudo files to the folder
|
||||||
|
|
||||||
@@ -1319,7 +1327,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
{
|
{
|
||||||
// Make sure the file state has the node ref
|
// Make sure the file state has the node ref
|
||||||
|
|
||||||
if ( fstate.hasNodeRef() == false)
|
if ( fstate.hasFilesystemObject() == false)
|
||||||
{
|
{
|
||||||
// Create the transaction
|
// Create the transaction
|
||||||
|
|
||||||
@@ -1327,7 +1335,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
// Get the node for the folder path
|
// Get the node for the folder path
|
||||||
|
|
||||||
fstate.setNodeRef( getNodeForPath( tree, paths[0]));
|
fstate.setFilesystemObject( getNodeForPath( tree, paths[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add pseudo files for the parent folder
|
// Add pseudo files for the parent folder
|
||||||
@@ -1378,12 +1386,19 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
{
|
{
|
||||||
status = FileStatus.FileExists;
|
status = FileStatus.FileExists;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the file state status
|
||||||
|
|
||||||
|
if ( fstate != null)
|
||||||
|
fstate.setFileStatus( status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (FileNotFoundException e)
|
catch (FileNotFoundException e)
|
||||||
{
|
{
|
||||||
status = FileStatus.NotExist;
|
status = FileStatus.NotExist;
|
||||||
|
if ( fstate != null)
|
||||||
|
fstate.setFileStatus( status);
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
@@ -1398,7 +1413,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
// Debug
|
// Debug
|
||||||
|
|
||||||
if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_INFO))
|
if (logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_INFO))
|
||||||
logger.debug("File status determined: name=" + name + " status=" + FileStatus.asString(status));
|
logger.debug("File status determined: name=" + name + " status=" + fileStatusString(fstate.getFileStatus()));
|
||||||
|
|
||||||
// Return the file/folder status
|
// Return the file/folder status
|
||||||
|
|
||||||
@@ -1436,7 +1451,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
// Make sure the parent folder has a file state, and the path exists
|
// Make sure the parent folder has a file state, and the path exists
|
||||||
|
|
||||||
String[] paths = FileName.splitPath( path);
|
String[] paths = FileName.splitPath( path);
|
||||||
FileState fstate = ctx.getStateTable().findFileState( paths[0]);
|
FileState fstate = ctx.getStateCache().findFileState( paths[0]);
|
||||||
|
|
||||||
if ( fstate == null) {
|
if ( fstate == null) {
|
||||||
|
|
||||||
@@ -1446,9 +1461,9 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
{
|
{
|
||||||
// Create the file state and add any pseudo files
|
// Create the file state and add any pseudo files
|
||||||
|
|
||||||
fstate = ctx.getStateTable().findFileState( paths[0], true, true);
|
fstate = ctx.getStateCache().findFileState( paths[0], true);
|
||||||
|
|
||||||
fstate.setFileStatus( FileStatus.DirectoryExists);
|
fstate.setFileStatus( DirectoryExists);
|
||||||
getPseudoFileInterface( ctx).addPseudoFilesToFolder( sess, tree, paths[0]);
|
getPseudoFileInterface( ctx).addPseudoFilesToFolder( sess, tree, paths[0]);
|
||||||
|
|
||||||
// Debug
|
// Debug
|
||||||
@@ -1523,11 +1538,11 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
FileState fstate = null;
|
FileState fstate = null;
|
||||||
|
|
||||||
if ( ctx.hasStateTable())
|
if ( ctx.hasStateCache())
|
||||||
{
|
{
|
||||||
// Check if there is a file state for the file
|
// Check if there is a file state for the file
|
||||||
|
|
||||||
fstate = ctx.getStateTable().findFileState( params.getPath());
|
fstate = ctx.getStateCache().findFileState( params.getPath());
|
||||||
|
|
||||||
if ( fstate != null)
|
if ( fstate != null)
|
||||||
{
|
{
|
||||||
@@ -1540,7 +1555,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
// Create a file state for the path
|
// Create a file state for the path
|
||||||
|
|
||||||
fstate = ctx.getStateTable().findFileState( params.getPath(), false, true);
|
fstate = ctx.getStateCache().findFileState( params.getPath(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the current file open allows the required shared access
|
// Check if the current file open allows the required shared access
|
||||||
@@ -1765,15 +1780,15 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
// Create a file state for the open file
|
// Create a file state for the open file
|
||||||
|
|
||||||
if ( ctx.hasStateTable())
|
if ( ctx.hasStateCache())
|
||||||
{
|
{
|
||||||
if ( fstate == null)
|
if ( fstate == null)
|
||||||
fstate = ctx.getStateTable().findFileState(params.getPath(), params.isDirectory(), true);
|
fstate = ctx.getStateCache().findFileState(params.getPath(), true);
|
||||||
|
|
||||||
// Update the file state, cache the node
|
// Update the file state, cache the node
|
||||||
|
|
||||||
fstate.incrementOpenCount();
|
fstate.incrementOpenCount();
|
||||||
fstate.setNodeRef(nodeRef);
|
fstate.setFilesystemObject(nodeRef);
|
||||||
|
|
||||||
// Store the state with the file
|
// Store the state with the file
|
||||||
|
|
||||||
@@ -1846,7 +1861,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
// If the state table is available then try to find the parent folder node for the new file
|
// If the state table is available then try to find the parent folder node for the new file
|
||||||
// to save having to walk the path
|
// to save having to walk the path
|
||||||
|
|
||||||
if ( ctx.hasStateTable())
|
if ( ctx.hasStateCache())
|
||||||
{
|
{
|
||||||
// See if the parent folder has a file state, we can avoid having to walk the path
|
// See if the parent folder has a file state, we can avoid having to walk the path
|
||||||
|
|
||||||
@@ -1871,8 +1886,8 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
// Get the file state for the parent folder
|
// Get the file state for the parent folder
|
||||||
|
|
||||||
parentState = getStateForPath(tree, paths[0]);
|
parentState = getStateForPath(tree, paths[0]);
|
||||||
if ( parentState == null && ctx.hasStateTable())
|
if ( parentState == null && ctx.hasStateCache())
|
||||||
parentState = ctx.getStateTable().findFileState( paths[0], true, true);
|
parentState = ctx.getStateCache().findFileState( paths[0], true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1904,9 +1919,9 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
// Add a file state for the new file/folder
|
// Add a file state for the new file/folder
|
||||||
|
|
||||||
if ( ctx.hasStateTable())
|
if ( ctx.hasStateCache())
|
||||||
{
|
{
|
||||||
FileState fstate = ctx.getStateTable().findFileState(params.getPath(), false, true);
|
FileState fstate = ctx.getStateCache().findFileState(params.getPath(), true);
|
||||||
if ( fstate != null)
|
if ( fstate != null)
|
||||||
{
|
{
|
||||||
// Save the file sharing mode, needs to be done before the open count is incremented
|
// Save the file sharing mode, needs to be done before the open count is incremented
|
||||||
@@ -1916,9 +1931,9 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
// Indicate that the file is open
|
// Indicate that the file is open
|
||||||
|
|
||||||
fstate.setFileStatus(FileStateStatus.FileExists);
|
fstate.setFileStatus( FileExists);
|
||||||
fstate.incrementOpenCount();
|
fstate.incrementOpenCount();
|
||||||
fstate.setNodeRef(nodeRef);
|
fstate.setFilesystemObject(nodeRef);
|
||||||
|
|
||||||
// Store the file state with the file
|
// Store the file state with the file
|
||||||
|
|
||||||
@@ -2008,7 +2023,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
// If the state table is available then try to find the parent folder node for the new folder
|
// If the state table is available then try to find the parent folder node for the new folder
|
||||||
// to save having to walk the path
|
// to save having to walk the path
|
||||||
|
|
||||||
if ( ctx.hasStateTable())
|
if ( ctx.hasStateCache())
|
||||||
{
|
{
|
||||||
// See if the parent folder has a file state, we can avoid having to walk the path
|
// See if the parent folder has a file state, we can avoid having to walk the path
|
||||||
|
|
||||||
@@ -2033,8 +2048,8 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
// Get the file state for the parent folder
|
// Get the file state for the parent folder
|
||||||
|
|
||||||
parentState = getStateForPath(tree, paths[0]);
|
parentState = getStateForPath(tree, paths[0]);
|
||||||
if ( parentState == null && ctx.hasStateTable())
|
if ( parentState == null && ctx.hasStateCache())
|
||||||
parentState = ctx.getStateTable().findFileState( paths[0], true, true);
|
parentState = ctx.getStateCache().findFileState( paths[0], true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2044,15 +2059,15 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
// Add a file state for the new folder
|
// Add a file state for the new folder
|
||||||
|
|
||||||
if ( ctx.hasStateTable())
|
if ( ctx.hasStateCache())
|
||||||
{
|
{
|
||||||
FileState fstate = ctx.getStateTable().findFileState( params.getPath(), true, true);
|
FileState fstate = ctx.getStateCache().findFileState( params.getPath(), true);
|
||||||
if ( fstate != null)
|
if ( fstate != null)
|
||||||
{
|
{
|
||||||
// Indicate that the file is open
|
// Indicate that the file is open
|
||||||
|
|
||||||
fstate.setFileStatus(FileStateStatus.FolderExists);
|
fstate.setFileStatus( DirectoryExists);
|
||||||
fstate.setNodeRef(nodeRef);
|
fstate.setFilesystemObject(nodeRef);
|
||||||
|
|
||||||
// DEBUG
|
// DEBUG
|
||||||
|
|
||||||
@@ -2131,11 +2146,11 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
// Remove the file state
|
// Remove the file state
|
||||||
|
|
||||||
if ( ctx.hasStateTable())
|
if ( ctx.hasStateCache())
|
||||||
{
|
{
|
||||||
// Remove the file state
|
// Remove the file state
|
||||||
|
|
||||||
ctx.getStateTable().removeFileState(dir);
|
ctx.getStateCache().removeFileState(dir);
|
||||||
|
|
||||||
// Update, or create, a parent folder file state
|
// Update, or create, a parent folder file state
|
||||||
|
|
||||||
@@ -2145,8 +2160,8 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
// Get the file state for the parent folder
|
// Get the file state for the parent folder
|
||||||
|
|
||||||
FileState parentState = getStateForPath(tree, paths[0]);
|
FileState parentState = getStateForPath(tree, paths[0]);
|
||||||
if ( parentState == null && ctx.hasStateTable())
|
if ( parentState == null && ctx.hasStateCache())
|
||||||
parentState = ctx.getStateTable().findFileState( paths[0], true, true);
|
parentState = ctx.getStateCache().findFileState( paths[0], true);
|
||||||
|
|
||||||
// Update the modification timestamp
|
// Update the modification timestamp
|
||||||
|
|
||||||
@@ -2251,32 +2266,32 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ( ctx.hasStateTable())
|
if ( ctx.hasStateCache())
|
||||||
{
|
{
|
||||||
FileState fstate = ctx.getStateTable().findFileState(file.getFullName());
|
FileState fstate = ctx.getStateCache().findFileState(file.getFullName());
|
||||||
if ( fstate != null) {
|
if ( fstate != null) {
|
||||||
|
|
||||||
// If the file open count is now zero then reset the stored sharing mode
|
// If the file open count is now zero then reset the stored sharing mode
|
||||||
|
|
||||||
if ( fstate.decrementOpenCount() == 0)
|
if ( fstate.decrementOpenCount() == 0)
|
||||||
fstate.setSharedAccess( SharingMode.READWRITE + SharingMode.DELETE);
|
fstate.setSharedAccess( SharingMode.READWRITE + SharingMode.DELETE);
|
||||||
|
|
||||||
// Check if there is a cached modification timestamp to be written out
|
// Check if there is a cached modification timestamp to be written out
|
||||||
|
|
||||||
if ( file.hasDeleteOnClose() == false && fstate.hasModifyDateTime() && fstate.hasNodeRef()) {
|
if ( file.hasDeleteOnClose() == false && fstate.hasModifyDateTime() && fstate.hasFilesystemObject()) {
|
||||||
|
|
||||||
// Update the modification date on the file/folder node
|
// Update the modification date on the file/folder node
|
||||||
|
|
||||||
Date modifyDate = new Date( fstate.getModifyDateTime());
|
Date modifyDate = new Date( fstate.getModifyDateTime());
|
||||||
nodeService.setProperty( fstate.getNodeRef(), ContentModel.PROP_MODIFIED, modifyDate);
|
nodeService.setProperty((NodeRef) fstate.getFilesystemObject(), ContentModel.PROP_MODIFIED, modifyDate);
|
||||||
|
|
||||||
// Debug
|
// Debug
|
||||||
|
|
||||||
if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
|
if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_FILE))
|
||||||
logger.debug("Updated modifcation timestamp, " + file.getFullName() + ", modTime=" + modifyDate);
|
logger.debug("Updated modifcation timestamp, " + file.getFullName() + ", modTime=" + modifyDate);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2341,28 +2356,28 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
// Set the file state to indicate a delete on close
|
// Set the file state to indicate a delete on close
|
||||||
|
|
||||||
if ( ctx.hasStateTable())
|
if ( ctx.hasStateCache())
|
||||||
{
|
{
|
||||||
if ( isVersionable == true) {
|
if ( isVersionable == true) {
|
||||||
|
|
||||||
// Get, or create, the file state
|
// Get, or create, the file state
|
||||||
|
|
||||||
FileState fState = ctx.getStateTable().findFileState(file.getFullName(), false, true);
|
FileState fState = ctx.getStateCache().findFileState(file.getFullName(), true);
|
||||||
|
|
||||||
// Indicate that the file was deleted via a delete on close request
|
// Indicate that the file was deleted via a delete on close request
|
||||||
|
|
||||||
fState.setFileStatus(FileStateStatus.DeleteOnClose);
|
fState.setFileStatus( DeleteOnClose);
|
||||||
|
|
||||||
// Make sure the file state is cached for a short while, save the noderef details
|
// Make sure the file state is cached for a short while, save the noderef details
|
||||||
|
|
||||||
fState.setExpiryTime(System.currentTimeMillis() + FileState.RenameTimeout);
|
fState.setExpiryTime(System.currentTimeMillis() + FileState.RenameTimeout);
|
||||||
fState.setNodeRef(nodeRef);
|
fState.setFilesystemObject(nodeRef);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
// Remove the file state
|
// Remove the file state
|
||||||
|
|
||||||
ctx.getStateTable().removeFileState( file.getFullName());
|
ctx.getStateCache().removeFileState( file.getFullName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2444,7 +2459,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
// Remove the file state
|
// Remove the file state
|
||||||
|
|
||||||
if ( ctx.hasStateTable())
|
if ( ctx.hasStateCache())
|
||||||
{
|
{
|
||||||
// Check if the node is versionable, cache the node details for a short while
|
// Check if the node is versionable, cache the node details for a short while
|
||||||
|
|
||||||
@@ -2453,17 +2468,17 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
// Make sure the file state is cached for a short while, a new file may be renamed to the same name
|
// Make sure the file state is cached for a short while, a new file may be renamed to the same name
|
||||||
// in which case we can connect the file to the previous version history
|
// in which case we can connect the file to the previous version history
|
||||||
|
|
||||||
FileState delState = ctx.getStateTable().findFileState( name, false, true);
|
FileState delState = ctx.getStateCache().findFileState( name, true);
|
||||||
|
|
||||||
delState.setExpiryTime(System.currentTimeMillis() + FileState.DeleteTimeout);
|
delState.setExpiryTime(System.currentTimeMillis() + FileState.DeleteTimeout);
|
||||||
delState.setFileStatus(FileStateStatus.DeleteOnClose);
|
delState.setFileStatus( DeleteOnClose);
|
||||||
delState.setNodeRef( nodeRef);
|
delState.setFilesystemObject( nodeRef);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
// Remove the file state
|
// Remove the file state
|
||||||
|
|
||||||
ctx.getStateTable().removeFileState( name);
|
ctx.getStateCache().removeFileState( name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update, or create, a parent folder file state
|
// Update, or create, a parent folder file state
|
||||||
@@ -2474,8 +2489,8 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
// Get the file state for the parent folder
|
// Get the file state for the parent folder
|
||||||
|
|
||||||
FileState parentState = getStateForPath(tree, paths[0]);
|
FileState parentState = getStateForPath(tree, paths[0]);
|
||||||
if ( parentState == null && ctx.hasStateTable())
|
if ( parentState == null && ctx.hasStateCache())
|
||||||
parentState = ctx.getStateTable().findFileState( paths[0], true, true);
|
parentState = ctx.getStateCache().findFileState( paths[0], true);
|
||||||
|
|
||||||
// Update the modification timestamp
|
// Update the modification timestamp
|
||||||
|
|
||||||
@@ -2580,7 +2595,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
// Get the file state for the old file, if available
|
// Get the file state for the old file, if available
|
||||||
|
|
||||||
FileState oldState = ctx.getStateTable().findFileState( oldName);
|
FileState oldState = ctx.getStateCache().findFileState( oldName);
|
||||||
|
|
||||||
// Check if we are renaming a folder, or the rename is to a different folder
|
// Check if we are renaming a folder, or the rename is to a different folder
|
||||||
|
|
||||||
@@ -2594,7 +2609,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
{
|
{
|
||||||
// Update the file state index to use the new name
|
// Update the file state index to use the new name
|
||||||
|
|
||||||
ctx.getStateTable().renameFileState(newName, oldState);
|
ctx.getStateCache().renameFileState(newName, oldState, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rename or move the file/folder
|
// Rename or move the file/folder
|
||||||
@@ -2616,7 +2631,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
// Check if the target file already exists
|
// Check if the target file already exists
|
||||||
|
|
||||||
int newExists = fileExists( sess, tree, newName);
|
int newExists = fileExists( sess, tree, newName);
|
||||||
FileState newState = ctx.getStateTable().findFileState( newName, false, true);
|
FileState newState = ctx.getStateCache().findFileState( newName, true);
|
||||||
|
|
||||||
NodeRef targetNodeRef = null;
|
NodeRef targetNodeRef = null;
|
||||||
|
|
||||||
@@ -2632,7 +2647,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
// Check if the target has a renamed or delete-on-close state
|
// Check if the target has a renamed or delete-on-close state
|
||||||
|
|
||||||
if ( newState.getFileStatus() == FileStateStatus.Renamed) {
|
if ( newState.getFileStatus() == FileRenamed) {
|
||||||
|
|
||||||
// DEBUG
|
// DEBUG
|
||||||
|
|
||||||
@@ -2641,9 +2656,9 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
// Use the renamed node to clone aspects/state
|
// Use the renamed node to clone aspects/state
|
||||||
|
|
||||||
cloneNodeAspects( name, newState.getNodeRef(), nodeToMoveRef, ctx);
|
cloneNodeAspects( name, (NodeRef) newState.getFilesystemObject(), nodeToMoveRef, ctx);
|
||||||
}
|
}
|
||||||
else if ( newState.getFileStatus() == FileStateStatus.DeleteOnClose) {
|
else if ( newState.getFileStatus() == DeleteOnClose) {
|
||||||
|
|
||||||
// DEBUG
|
// DEBUG
|
||||||
|
|
||||||
@@ -2652,7 +2667,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
// Restore the deleted node so we can relink the new version to the old history/properties
|
// Restore the deleted node so we can relink the new version to the old history/properties
|
||||||
|
|
||||||
NodeRef archivedNode = getNodeArchiveService().getArchivedNode( newState.getNodeRef());
|
NodeRef archivedNode = getNodeArchiveService().getArchivedNode((NodeRef) newState.getFilesystemObject());
|
||||||
|
|
||||||
// DEBUG
|
// DEBUG
|
||||||
|
|
||||||
@@ -2672,16 +2687,18 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
// Check if the deleted file had a linked node, due to a rename
|
// Check if the deleted file had a linked node, due to a rename
|
||||||
|
|
||||||
if ( newState.hasLinkNode() && nodeService.exists( newState.getLinkNode())) {
|
NodeRef linkNode = (NodeRef) newState.findAttribute( AttrLinkNode);
|
||||||
|
|
||||||
|
if ( linkNode != null && nodeService.exists( linkNode)) {
|
||||||
|
|
||||||
// Clone aspects from the linked node onto the restored node
|
// Clone aspects from the linked node onto the restored node
|
||||||
|
|
||||||
cloneNodeAspects( name, newState.getLinkNode(), targetNodeRef, ctx);
|
cloneNodeAspects( name, linkNode, targetNodeRef, ctx);
|
||||||
|
|
||||||
// DEBUG
|
// DEBUG
|
||||||
|
|
||||||
if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_RENAME)) {
|
if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_RENAME)) {
|
||||||
logger.debug(" Moved aspects from linked node " + newState.getLinkNode());
|
logger.debug(" Moved aspects from linked node " + linkNode);
|
||||||
|
|
||||||
// Check if the node is a working copy
|
// Check if the node is a working copy
|
||||||
|
|
||||||
@@ -2730,8 +2747,8 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
// Mark the new file as existing
|
// Mark the new file as existing
|
||||||
|
|
||||||
newState.setFileStatus( FileStatus.FileExists);
|
newState.setFileStatus( FileExists);
|
||||||
newState.setNodeRef( nodeToMoveRef);
|
newState.setFilesystemObject( nodeToMoveRef);
|
||||||
|
|
||||||
// Make sure the old file state is cached for a short while, the file may not be open so the
|
// Make sure the old file state is cached for a short while, the file may not be open so the
|
||||||
// file state could be expired
|
// file state could be expired
|
||||||
@@ -2740,8 +2757,8 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
// Indicate that this is a renamed file state, set the node ref of the file that was renamed
|
// Indicate that this is a renamed file state, set the node ref of the file that was renamed
|
||||||
|
|
||||||
oldState.setFileStatus(FileStateStatus.Renamed);
|
oldState.setFileStatus( FileRenamed);
|
||||||
oldState.setNodeRef(nodeToMoveRef);
|
oldState.setFilesystemObject(nodeToMoveRef);
|
||||||
|
|
||||||
// DEBUG
|
// DEBUG
|
||||||
|
|
||||||
@@ -2770,8 +2787,8 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
// Mark the new file as existing
|
// Mark the new file as existing
|
||||||
|
|
||||||
newState.setFileStatus( FileStatus.FileExists);
|
newState.setFileStatus( FileExists);
|
||||||
newState.setNodeRef( targetNodeRef);
|
newState.setFilesystemObject( targetNodeRef);
|
||||||
|
|
||||||
// Delete the old file
|
// Delete the old file
|
||||||
|
|
||||||
@@ -2784,12 +2801,12 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
// Indicate that this is a deleted file state, set the node ref of the file that was renamed
|
// Indicate that this is a deleted file state, set the node ref of the file that was renamed
|
||||||
|
|
||||||
oldState.setFileStatus(FileStateStatus.DeleteOnClose);
|
oldState.setFileStatus( DeleteOnClose);
|
||||||
oldState.setNodeRef(nodeToMoveRef);
|
oldState.setFilesystemObject(nodeToMoveRef);
|
||||||
|
|
||||||
// Link to the new node, a new file may be renamed into place, we need to transfer aspect/locks
|
// Link to the new node, a new file may be renamed into place, we need to transfer aspect/locks
|
||||||
|
|
||||||
oldState.setLinkNode( targetNodeRef);
|
oldState.addAttribute( AttrLinkNode, targetNodeRef);
|
||||||
|
|
||||||
// DEBUG
|
// DEBUG
|
||||||
|
|
||||||
@@ -3259,16 +3276,16 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
ContentContext ctx = (ContentContext) tree.getContext();
|
ContentContext ctx = (ContentContext) tree.getContext();
|
||||||
|
|
||||||
if ( ctx.hasStateTable())
|
if ( ctx.hasStateCache())
|
||||||
{
|
{
|
||||||
// Try and get the node ref from an in memory file state
|
// Try and get the node ref from an in memory file state
|
||||||
|
|
||||||
FileState fstate = ctx.getStateTable().findFileState(path);
|
FileState fstate = ctx.getStateCache().findFileState(path);
|
||||||
if ( fstate != null && fstate.hasNodeRef() && fstate.exists() )
|
if ( fstate != null && fstate.hasFilesystemObject() && fstate.exists() )
|
||||||
{
|
{
|
||||||
// Check that the node exists
|
// Check that the node exists
|
||||||
|
|
||||||
if (fileFolderService.exists(fstate.getNodeRef()))
|
if (fileFolderService.exists((NodeRef) fstate.getFilesystemObject()))
|
||||||
{
|
{
|
||||||
// Bump the file states expiry time
|
// Bump the file states expiry time
|
||||||
|
|
||||||
@@ -3276,11 +3293,11 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
|
|
||||||
// Return the cached noderef
|
// Return the cached noderef
|
||||||
|
|
||||||
return fstate.getNodeRef();
|
return (NodeRef) fstate.getFilesystemObject();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ctx.getStateTable().removeFileState(path);
|
ctx.getStateCache().removeFileState(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3344,11 +3361,11 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
ContentContext ctx = (ContentContext) tree.getContext();
|
ContentContext ctx = (ContentContext) tree.getContext();
|
||||||
FileState fstate = null;
|
FileState fstate = null;
|
||||||
|
|
||||||
if ( ctx.hasStateTable())
|
if ( ctx.hasStateCache())
|
||||||
{
|
{
|
||||||
// Get the file state for a file/folder
|
// Get the file state for a file/folder
|
||||||
|
|
||||||
fstate = ctx.getStateTable().findFileState(path);
|
fstate = ctx.getStateCache().findFileState(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the file state
|
// Return the file state
|
||||||
@@ -3548,5 +3565,38 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
|
|||||||
if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_RENAME))
|
if ( logger.isDebugEnabled() && ctx.hasDebug(AlfrescoContext.DBG_RENAME))
|
||||||
logger.debug(" Removed versionable aspect from temp file");
|
logger.debug(" Removed versionable aspect from temp file");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the file state status as a string
|
||||||
|
*
|
||||||
|
* @param sts int
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
private final String fileStatusString( int sts) {
|
||||||
|
String fstatus = "Unknown";
|
||||||
|
|
||||||
|
switch ( sts) {
|
||||||
|
case FileUnknown:
|
||||||
|
fstatus = "Unknown";
|
||||||
|
break;
|
||||||
|
case FileNotExist:
|
||||||
|
fstatus = "NotExist";
|
||||||
|
break;
|
||||||
|
case FileExists:
|
||||||
|
fstatus = "FileExists";
|
||||||
|
break;
|
||||||
|
case DirectoryExists:
|
||||||
|
fstatus = "DirectoryExists";
|
||||||
|
break;
|
||||||
|
case FileRenamed:
|
||||||
|
fstatus = "FileRenamed";
|
||||||
|
break;
|
||||||
|
case DeleteOnClose:
|
||||||
|
fstatus = "DeleteOnClose";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fstatus;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -389,7 +389,7 @@ public class HomeShareMapper implements ShareMapper, InitializingBean
|
|||||||
// Create the disk driver and context
|
// Create the disk driver and context
|
||||||
|
|
||||||
ContentContext diskCtx = new ContentContext( getHomeFolderName(), "", "", alfClient.getHomeFolder());
|
ContentContext diskCtx = new ContentContext( getHomeFolderName(), "", "", alfClient.getHomeFolder());
|
||||||
diskCtx.enableStateTable( true, m_driver.getStateReaper());
|
diskCtx.enableStateCache( true);
|
||||||
|
|
||||||
// Create a temporary shared device for the users home directory
|
// Create a temporary shared device for the users home directory
|
||||||
|
|
||||||
|
@@ -22,10 +22,10 @@ package org.alfresco.filesys.repo;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.alfresco.filesys.state.FileState;
|
|
||||||
import org.alfresco.filesys.state.FileStateTable;
|
|
||||||
import org.alfresco.jlan.server.filesys.FileStatus;
|
import org.alfresco.jlan.server.filesys.FileStatus;
|
||||||
import org.alfresco.jlan.server.filesys.NotifyChange;
|
import org.alfresco.jlan.server.filesys.NotifyChange;
|
||||||
|
import org.alfresco.jlan.server.filesys.cache.FileState;
|
||||||
|
import org.alfresco.jlan.server.filesys.cache.FileStateCache;
|
||||||
import org.alfresco.jlan.smb.server.notify.NotifyChangeHandler;
|
import org.alfresco.jlan.smb.server.notify.NotifyChangeHandler;
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.repo.node.NodeServicePolicies;
|
import org.alfresco.repo.node.NodeServicePolicies;
|
||||||
@@ -88,7 +88,7 @@ public class NodeMonitor extends TransactionListenerAdapter
|
|||||||
|
|
||||||
// File state table and change notification handler
|
// File state table and change notification handler
|
||||||
|
|
||||||
private FileStateTable m_stateTable;
|
private FileStateCache m_stateTable;
|
||||||
private NotifyChangeHandler m_changeHandler;
|
private NotifyChangeHandler m_changeHandler;
|
||||||
|
|
||||||
// Root node path and store
|
// Root node path and store
|
||||||
@@ -188,7 +188,7 @@ public class NodeMonitor extends TransactionListenerAdapter
|
|||||||
|
|
||||||
// Get the file state table and change notification handler, if enabled
|
// Get the file state table and change notification handler, if enabled
|
||||||
|
|
||||||
m_stateTable = m_filesysCtx.getStateTable();
|
m_stateTable = m_filesysCtx.getStateCache();
|
||||||
m_changeHandler = m_filesysCtx.getChangeHandler();
|
m_changeHandler = m_filesysCtx.getChangeHandler();
|
||||||
|
|
||||||
// Start the event processing thread
|
// Start the event processing thread
|
||||||
|
@@ -26,11 +26,11 @@ import org.alfresco.filesys.alfresco.DesktopAction;
|
|||||||
import org.alfresco.filesys.alfresco.DesktopParams;
|
import org.alfresco.filesys.alfresco.DesktopParams;
|
||||||
import org.alfresco.filesys.alfresco.DesktopResponse;
|
import org.alfresco.filesys.alfresco.DesktopResponse;
|
||||||
import org.alfresco.filesys.alfresco.DesktopTarget;
|
import org.alfresco.filesys.alfresco.DesktopTarget;
|
||||||
import org.alfresco.filesys.state.FileState;
|
|
||||||
import org.alfresco.filesys.state.FileStateTable;
|
|
||||||
import org.alfresco.jlan.server.filesys.FileName;
|
import org.alfresco.jlan.server.filesys.FileName;
|
||||||
import org.alfresco.jlan.server.filesys.FileStatus;
|
import org.alfresco.jlan.server.filesys.FileStatus;
|
||||||
import org.alfresco.jlan.server.filesys.NotifyChange;
|
import org.alfresco.jlan.server.filesys.NotifyChange;
|
||||||
|
import org.alfresco.jlan.server.filesys.cache.FileState;
|
||||||
|
import org.alfresco.jlan.server.filesys.cache.FileStateCache;
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
|
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
@@ -183,12 +183,12 @@ public class CheckInOutDesktopAction extends DesktopAction {
|
|||||||
|
|
||||||
// Update cached state for the working copy to indicate the file exists
|
// Update cached state for the working copy to indicate the file exists
|
||||||
|
|
||||||
FileStateTable stateTable = getContext().getStateTable();
|
FileStateCache stateCache = getContext().getStateCache();
|
||||||
if ( stateTable != null) {
|
if ( stateCache != null) {
|
||||||
|
|
||||||
// Update any cached state for the working copy file
|
// Update any cached state for the working copy file
|
||||||
|
|
||||||
FileState fstate = stateTable.findFileState( fileName);
|
FileState fstate = stateCache.findFileState( fileName);
|
||||||
if ( fstate != null)
|
if ( fstate != null)
|
||||||
fstate.setFileStatus( FileStatus.FileExists);
|
fstate.setFileStatus( FileStatus.FileExists);
|
||||||
}
|
}
|
||||||
|
@@ -1,841 +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.filesys.state;
|
|
||||||
|
|
||||||
import org.alfresco.jlan.locking.FileLock;
|
|
||||||
import org.alfresco.jlan.locking.FileLockList;
|
|
||||||
import org.alfresco.jlan.locking.LockConflictException;
|
|
||||||
import org.alfresco.jlan.locking.NotLockedException;
|
|
||||||
import org.alfresco.jlan.server.filesys.ExistingOpLockException;
|
|
||||||
import org.alfresco.jlan.server.filesys.FileOpenParams;
|
|
||||||
import org.alfresco.jlan.server.filesys.FileStatus;
|
|
||||||
import org.alfresco.jlan.server.filesys.pseudo.PseudoFile;
|
|
||||||
import org.alfresco.jlan.server.filesys.pseudo.PseudoFileList;
|
|
||||||
import org.alfresco.jlan.server.locking.OpLockDetails;
|
|
||||||
import org.alfresco.jlan.smb.SharingMode;
|
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* File State Class
|
|
||||||
*
|
|
||||||
* <p>Keeps track of file state across all sessions on the server, to keep track of file sharing modes,
|
|
||||||
* file locks and also for synchronizing access to files/folders.
|
|
||||||
*
|
|
||||||
* @author gkspencer
|
|
||||||
*/
|
|
||||||
public class FileState
|
|
||||||
{
|
|
||||||
private static final Log logger = LogFactory.getLog(FileState.class);
|
|
||||||
|
|
||||||
// File state constants
|
|
||||||
|
|
||||||
public final static long NoTimeout = -1L;
|
|
||||||
public final static long DefTimeout = 2 * 60000L; // 2 minutes
|
|
||||||
public final static long RenameTimeout = 1 * 60000L; // 1 minute
|
|
||||||
public final static long DeleteTimeout = 15000L; // 15 seconds
|
|
||||||
|
|
||||||
// File status
|
|
||||||
|
|
||||||
public enum FileStateStatus { NotExist, FileExists, FolderExists, Renamed, DeleteOnClose };
|
|
||||||
|
|
||||||
// File name/path
|
|
||||||
|
|
||||||
private String m_path;
|
|
||||||
|
|
||||||
// File state timeout, -1 indicates no timeout
|
|
||||||
|
|
||||||
private long m_tmo;
|
|
||||||
|
|
||||||
// File status, indicates if the file/folder exists and if it is a file or folder.
|
|
||||||
|
|
||||||
private FileStateStatus m_fileStatus = FileStateStatus.NotExist;
|
|
||||||
|
|
||||||
// Open file count
|
|
||||||
|
|
||||||
private int m_openCount;
|
|
||||||
|
|
||||||
// Sharing mode and PID of first process to open the file
|
|
||||||
|
|
||||||
private int m_sharedAccess = SharingMode.READWRITE + SharingMode.DELETE;
|
|
||||||
private int m_pid = -1;
|
|
||||||
|
|
||||||
// File lock list, allocated once there are active locks on this file
|
|
||||||
|
|
||||||
private FileLockList m_lockList;
|
|
||||||
|
|
||||||
// Oplock details
|
|
||||||
|
|
||||||
private OpLockDetails m_oplock;
|
|
||||||
|
|
||||||
// Node for this file
|
|
||||||
|
|
||||||
private NodeRef m_nodeRef;
|
|
||||||
|
|
||||||
// Link to the new file state when a file is renamed
|
|
||||||
|
|
||||||
private FileState m_newNameState;
|
|
||||||
|
|
||||||
// Pseudo file list
|
|
||||||
|
|
||||||
private PseudoFileList m_pseudoFiles;
|
|
||||||
|
|
||||||
// File timestamps updated only whilst file is open
|
|
||||||
|
|
||||||
private long m_accessDate;
|
|
||||||
private long m_modifyDate;
|
|
||||||
private long m_changeDate;
|
|
||||||
|
|
||||||
// Keep track of the node we are linked to, when deleted
|
|
||||||
|
|
||||||
private NodeRef m_linkNode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class constructor
|
|
||||||
*
|
|
||||||
* @param fname String
|
|
||||||
* @param isdir boolean
|
|
||||||
*/
|
|
||||||
public FileState(String fname, boolean isdir)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Normalize the file path
|
|
||||||
|
|
||||||
setPath(fname);
|
|
||||||
setExpiryTime(System.currentTimeMillis() + DefTimeout);
|
|
||||||
|
|
||||||
// Set the file/folder status
|
|
||||||
|
|
||||||
setFileStatus( isdir ? FileStateStatus.FolderExists : FileStateStatus.FileExists);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the file name/path
|
|
||||||
*
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public final String getPath()
|
|
||||||
{
|
|
||||||
return m_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the file status
|
|
||||||
*
|
|
||||||
* @return FileStateStatus
|
|
||||||
*/
|
|
||||||
public final FileStateStatus getFileStatus()
|
|
||||||
{
|
|
||||||
return m_fileStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if the file/folder exists
|
|
||||||
*
|
|
||||||
* @return boolen
|
|
||||||
*/
|
|
||||||
public final boolean exists()
|
|
||||||
{
|
|
||||||
if ( m_fileStatus == FileStateStatus.FileExists ||
|
|
||||||
m_fileStatus == FileStateStatus.FolderExists)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the directory state
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public final boolean isDirectory()
|
|
||||||
{
|
|
||||||
return m_fileStatus == FileStateStatus.FolderExists ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if the associated node has been set
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public final boolean hasNodeRef()
|
|
||||||
{
|
|
||||||
return m_nodeRef != null ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the associated node
|
|
||||||
*
|
|
||||||
* @return NodeRef
|
|
||||||
*/
|
|
||||||
public final NodeRef getNodeRef()
|
|
||||||
{
|
|
||||||
return m_nodeRef;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the file open count
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public final int getOpenCount()
|
|
||||||
{
|
|
||||||
return m_openCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the shared access mode
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public final int getSharedAccess()
|
|
||||||
{
|
|
||||||
return m_sharedAccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the PID of the first process to open the file, or -1 if the file is not open
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public final int getProcessId()
|
|
||||||
{
|
|
||||||
return m_pid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if there are active locks on this file
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public final boolean hasActiveLocks()
|
|
||||||
{
|
|
||||||
if (m_lockList != null && m_lockList.numberOfLocks() > 0)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if this file state does not expire
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public final boolean hasNoTimeout()
|
|
||||||
{
|
|
||||||
return m_tmo == NoTimeout ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the file can be opened depending on any current file opens and the sharing mode of
|
|
||||||
* the first file open
|
|
||||||
*
|
|
||||||
* @param params FileOpenParams
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public final boolean allowsOpen(FileOpenParams params)
|
|
||||||
{
|
|
||||||
|
|
||||||
// If the file is not currently open then allow the file open
|
|
||||||
|
|
||||||
if (getOpenCount() == 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// Check the shared access mode
|
|
||||||
|
|
||||||
if (getSharedAccess() == SharingMode.READWRITE && params.getSharedAccess() == SharingMode.READWRITE)
|
|
||||||
return true;
|
|
||||||
else if ((getSharedAccess() & SharingMode.READ) != 0 && params.isReadOnlyAccess())
|
|
||||||
return true;
|
|
||||||
else if ((getSharedAccess() & SharingMode.WRITE) != 0 && params.isWriteOnlyAccess())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// Sharing violation, do not allow the file open
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Increment the file open count
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public final synchronized int incrementOpenCount()
|
|
||||||
{
|
|
||||||
return m_openCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decrement the file open count
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public final synchronized int decrementOpenCount()
|
|
||||||
{
|
|
||||||
|
|
||||||
// Debug
|
|
||||||
|
|
||||||
if (m_openCount <= 0)
|
|
||||||
logger.debug("@@@@@ File close name=" + getPath() + ", count=" + m_openCount + " <<ERROR>>");
|
|
||||||
else
|
|
||||||
m_openCount--;
|
|
||||||
|
|
||||||
// Clear the PID if the file is no longer open
|
|
||||||
|
|
||||||
if ( m_openCount == 0)
|
|
||||||
m_pid = -1;
|
|
||||||
|
|
||||||
return m_openCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the file state has expired
|
|
||||||
*
|
|
||||||
* @param curTime long
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public final boolean hasExpired(long curTime)
|
|
||||||
{
|
|
||||||
if (m_tmo == NoTimeout)
|
|
||||||
return false;
|
|
||||||
if (curTime > m_tmo)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the number of seconds left before the file state expires
|
|
||||||
*
|
|
||||||
* @param curTime long
|
|
||||||
* @return long
|
|
||||||
*/
|
|
||||||
public final long getSecondsToExpire(long curTime)
|
|
||||||
{
|
|
||||||
if (m_tmo == NoTimeout)
|
|
||||||
return -1;
|
|
||||||
return (m_tmo - curTime) / 1000L;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if the file state has an associated rename state
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public final boolean hasRenameState()
|
|
||||||
{
|
|
||||||
return m_newNameState != null ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the associated rename state
|
|
||||||
*
|
|
||||||
* @return FileState
|
|
||||||
*/
|
|
||||||
public final FileState getRenameState()
|
|
||||||
{
|
|
||||||
return m_newNameState;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if a folder has pseudo files associated with it
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public final boolean hasPseudoFiles()
|
|
||||||
{
|
|
||||||
if ( m_pseudoFiles != null)
|
|
||||||
return m_pseudoFiles.numberOfFiles() > 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the pseudo file list
|
|
||||||
*
|
|
||||||
* @return PseudoFileList
|
|
||||||
*/
|
|
||||||
public final PseudoFileList getPseudoFileList()
|
|
||||||
{
|
|
||||||
return m_pseudoFiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a pseudo file to this folder
|
|
||||||
*
|
|
||||||
* @param pfile PseudoFile
|
|
||||||
*/
|
|
||||||
public final void addPseudoFile(PseudoFile pfile)
|
|
||||||
{
|
|
||||||
if ( m_pseudoFiles == null)
|
|
||||||
m_pseudoFiles = new PseudoFileList();
|
|
||||||
m_pseudoFiles.addFile( pfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the file status
|
|
||||||
*
|
|
||||||
* @param status FileStateStatus
|
|
||||||
*/
|
|
||||||
public final void setFileStatus(FileStateStatus status)
|
|
||||||
{
|
|
||||||
m_fileStatus = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the file status
|
|
||||||
*
|
|
||||||
* @param fsts int
|
|
||||||
*/
|
|
||||||
public final void setFileStatus(int fsts)
|
|
||||||
{
|
|
||||||
if ( fsts == FileStatus.FileExists)
|
|
||||||
m_fileStatus = FileStateStatus.FileExists;
|
|
||||||
else if ( fsts == FileStatus.DirectoryExists)
|
|
||||||
m_fileStatus = FileStateStatus.FolderExists;
|
|
||||||
else if ( fsts == FileStatus.NotExist)
|
|
||||||
m_fileStatus = FileStateStatus.NotExist;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the file state expiry time
|
|
||||||
*
|
|
||||||
* @param expire long
|
|
||||||
*/
|
|
||||||
public final void setExpiryTime(long expire)
|
|
||||||
{
|
|
||||||
m_tmo = expire;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the node ref for the file/folder
|
|
||||||
*
|
|
||||||
* @param nodeRef NodeRef
|
|
||||||
*/
|
|
||||||
public final void setNodeRef(NodeRef nodeRef)
|
|
||||||
{
|
|
||||||
m_nodeRef = nodeRef;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the associated file state when a file is renamed, this is the link to the new file state
|
|
||||||
*
|
|
||||||
* @param fstate FileState
|
|
||||||
*/
|
|
||||||
public final void setRenameState(FileState fstate)
|
|
||||||
{
|
|
||||||
m_newNameState = fstate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the shared access mode, from the first file open
|
|
||||||
*
|
|
||||||
* @param mode int
|
|
||||||
*/
|
|
||||||
public final void setSharedAccess(int mode)
|
|
||||||
{
|
|
||||||
if (getOpenCount() == 0)
|
|
||||||
m_sharedAccess = mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the PID of the process opening the file
|
|
||||||
*
|
|
||||||
* @param pid int
|
|
||||||
*/
|
|
||||||
public final void setProcessId(int pid)
|
|
||||||
{
|
|
||||||
if ( getOpenCount() == 0)
|
|
||||||
m_pid = pid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the file path
|
|
||||||
*
|
|
||||||
* @param path String
|
|
||||||
*/
|
|
||||||
public final void setPath(String path)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Split the path into directories and file name, only uppercase the directories to
|
|
||||||
// normalize the path.
|
|
||||||
|
|
||||||
m_path = normalizePath(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the count of active locks on this file
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public final int numberOfLocks()
|
|
||||||
{
|
|
||||||
if (m_lockList != null)
|
|
||||||
return m_lockList.numberOfLocks();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a lock to this file
|
|
||||||
*
|
|
||||||
* @param lock FileLock
|
|
||||||
* @exception LockConflictException
|
|
||||||
*/
|
|
||||||
public final void addLock(FileLock lock) throws LockConflictException
|
|
||||||
{
|
|
||||||
|
|
||||||
// Check if the lock list has been allocated
|
|
||||||
|
|
||||||
if (m_lockList == null)
|
|
||||||
{
|
|
||||||
|
|
||||||
synchronized (this)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Allocate the lock list, check if the lock list has been allocated elsewhere
|
|
||||||
// as we may have been waiting for the lock
|
|
||||||
|
|
||||||
if (m_lockList == null)
|
|
||||||
m_lockList = new FileLockList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the lock to the list, check if there are any lock conflicts
|
|
||||||
|
|
||||||
synchronized (m_lockList)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Check if the new lock overlaps with any existing locks
|
|
||||||
|
|
||||||
if (m_lockList.allowsLock(lock))
|
|
||||||
{
|
|
||||||
|
|
||||||
// Add the new lock to the list
|
|
||||||
|
|
||||||
m_lockList.addLock(lock);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
throw new LockConflictException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a lock on this file
|
|
||||||
*
|
|
||||||
* @param lock FileLock
|
|
||||||
* @exception NotLockedException
|
|
||||||
*/
|
|
||||||
public final void removeLock(FileLock lock) throws NotLockedException
|
|
||||||
{
|
|
||||||
|
|
||||||
// Check if the lock list has been allocated
|
|
||||||
|
|
||||||
if (m_lockList == null)
|
|
||||||
throw new NotLockedException();
|
|
||||||
|
|
||||||
// Remove the lock from the active list
|
|
||||||
|
|
||||||
synchronized (m_lockList)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Remove the lock, check if we found the matching lock
|
|
||||||
|
|
||||||
if (m_lockList.removeLock(lock) == null)
|
|
||||||
throw new NotLockedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the access date/time has been set
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public final boolean hasAccessDateTime() {
|
|
||||||
return m_accessDate != 0L ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the access date/time
|
|
||||||
*
|
|
||||||
* @return long
|
|
||||||
*/
|
|
||||||
public final long getAccessDateTime() {
|
|
||||||
return m_accessDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the access date/time
|
|
||||||
*/
|
|
||||||
public final void updateAccessDateTime() {
|
|
||||||
m_accessDate = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the change date/time has been set
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public final boolean hasChangeDateTime() {
|
|
||||||
return m_changeDate != 0L ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the change date/time
|
|
||||||
*
|
|
||||||
* @return long
|
|
||||||
*/
|
|
||||||
public final long getChangeDateTime() {
|
|
||||||
return m_changeDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the change date/time
|
|
||||||
*/
|
|
||||||
public final void updateChangeDateTime() {
|
|
||||||
m_changeDate = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the modification date/time has been set
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public final boolean hasModifyDateTime() {
|
|
||||||
return m_modifyDate != 0L ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the modify date/time
|
|
||||||
*
|
|
||||||
* @return long
|
|
||||||
*/
|
|
||||||
public final long getModifyDateTime() {
|
|
||||||
return m_modifyDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the modify date/time
|
|
||||||
*/
|
|
||||||
public final void updateModifyDateTime() {
|
|
||||||
m_modifyDate = System.currentTimeMillis();
|
|
||||||
m_accessDate = m_modifyDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the modify date/time
|
|
||||||
*
|
|
||||||
* @param modTime long
|
|
||||||
*/
|
|
||||||
public final void updateModifyDateTime( long modTime) {
|
|
||||||
m_modifyDate = modTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the file is linked to another node
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public final boolean hasLinkNode() {
|
|
||||||
return m_linkNode != null ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the node that the file is linked to
|
|
||||||
*
|
|
||||||
* @return NodeRef
|
|
||||||
*/
|
|
||||||
public final NodeRef getLinkNode() {
|
|
||||||
return m_linkNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the node that this file is linked to
|
|
||||||
*
|
|
||||||
* @param node NodeRef
|
|
||||||
*/
|
|
||||||
public final void setLinkNode( NodeRef node) {
|
|
||||||
m_linkNode = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the file is readable for the specified section of the file and process id
|
|
||||||
*
|
|
||||||
* @param offset long
|
|
||||||
* @param len long
|
|
||||||
* @param pid int
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public final boolean canReadFile(long offset, long len, int pid)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Check if the lock list is valid
|
|
||||||
|
|
||||||
if (m_lockList == null)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// Check if the file section is readable by the specified process
|
|
||||||
|
|
||||||
boolean readOK = false;
|
|
||||||
|
|
||||||
synchronized (m_lockList)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Check if the file section is readable
|
|
||||||
|
|
||||||
readOK = m_lockList.canReadFile(offset, len, pid);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the read status
|
|
||||||
|
|
||||||
return readOK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the file is writeable for the specified section of the file and process id
|
|
||||||
*
|
|
||||||
* @param offset long
|
|
||||||
* @param len long
|
|
||||||
* @param pid int
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public final boolean canWriteFile(long offset, long len, int pid)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Check if the lock list is valid
|
|
||||||
|
|
||||||
if (m_lockList == null)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// Check if the file section is writeable by the specified process
|
|
||||||
|
|
||||||
boolean writeOK = false;
|
|
||||||
|
|
||||||
synchronized (m_lockList)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Check if the file section is writeable
|
|
||||||
|
|
||||||
writeOK = m_lockList.canWriteFile(offset, len, pid);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the write status
|
|
||||||
|
|
||||||
return writeOK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the file has an active oplock
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public final boolean hasOpLock() {
|
|
||||||
return m_oplock != null ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the oplock details
|
|
||||||
*
|
|
||||||
* @return OpLockDetails
|
|
||||||
*/
|
|
||||||
public final OpLockDetails getOpLock() {
|
|
||||||
return m_oplock;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the oplock for this file
|
|
||||||
*
|
|
||||||
* @param oplock OpLockDetails
|
|
||||||
* @exception ExistingOpLockException If there is an active oplock on this file
|
|
||||||
*/
|
|
||||||
public final synchronized void setOpLock(OpLockDetails oplock)
|
|
||||||
throws ExistingOpLockException {
|
|
||||||
|
|
||||||
if ( m_oplock == null)
|
|
||||||
m_oplock = oplock;
|
|
||||||
else
|
|
||||||
throw new ExistingOpLockException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear the oplock
|
|
||||||
*/
|
|
||||||
public final synchronized void clearOpLock() {
|
|
||||||
m_oplock = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Normalize the path to uppercase the directory names and keep the case of the file name.
|
|
||||||
*
|
|
||||||
* @param path String
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public final static String normalizePath(String path)
|
|
||||||
{
|
|
||||||
return path.toUpperCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the file state as a string
|
|
||||||
*
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
StringBuffer str = new StringBuffer();
|
|
||||||
|
|
||||||
str.append("[");
|
|
||||||
str.append(getPath());
|
|
||||||
str.append(",");
|
|
||||||
str.append(getFileStatus());
|
|
||||||
str.append(":Opn=");
|
|
||||||
str.append(getOpenCount());
|
|
||||||
str.append("/");
|
|
||||||
str.append(getProcessId());
|
|
||||||
|
|
||||||
str.append(",Expire=");
|
|
||||||
str.append(getSecondsToExpire(System.currentTimeMillis()));
|
|
||||||
|
|
||||||
str.append(",Locks=");
|
|
||||||
str.append(numberOfLocks());
|
|
||||||
|
|
||||||
str.append(",Ref=");
|
|
||||||
if ( hasNodeRef())
|
|
||||||
str.append(getNodeRef().getId());
|
|
||||||
else
|
|
||||||
str.append("Null");
|
|
||||||
|
|
||||||
str.append(",Shr=0x");
|
|
||||||
str.append(Integer.toHexString(getSharedAccess()));
|
|
||||||
|
|
||||||
if ( isDirectory())
|
|
||||||
{
|
|
||||||
str.append(",Pseudo=");
|
|
||||||
if ( hasPseudoFiles())
|
|
||||||
str.append(getPseudoFileList().numberOfFiles());
|
|
||||||
else
|
|
||||||
str.append(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( hasOpLock()) {
|
|
||||||
str.append(",OpLock=");
|
|
||||||
str.append(getOpLock());
|
|
||||||
}
|
|
||||||
|
|
||||||
str.append("]");
|
|
||||||
|
|
||||||
return str.toString();
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2006-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.filesys.state;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* File State Listener Interface
|
|
||||||
*
|
|
||||||
* @author gkspencer
|
|
||||||
*/
|
|
||||||
public interface FileStateListener {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* File state has expired. The listener can control whether the file state is removed
|
|
||||||
* from the cache, or not.
|
|
||||||
*
|
|
||||||
* @param state FileState
|
|
||||||
* @return true to remove the file state from the cache, or false to leave the file state in the cache
|
|
||||||
*/
|
|
||||||
public boolean fileStateExpired(FileState state);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* File state cache is closing down, any resources attached to the file state must be released.
|
|
||||||
*
|
|
||||||
* @param state FileState
|
|
||||||
*/
|
|
||||||
public void fileStateClosed(FileState state);
|
|
||||||
}
|
|
@@ -1,490 +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.filesys.state;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.Hashtable;
|
|
||||||
|
|
||||||
import org.alfresco.jlan.debug.Debug;
|
|
||||||
import org.alfresco.jlan.locking.FileLock;
|
|
||||||
import org.alfresco.jlan.locking.LockConflictException;
|
|
||||||
import org.alfresco.jlan.locking.NotLockedException;
|
|
||||||
import org.alfresco.jlan.server.SrvSession;
|
|
||||||
import org.alfresco.jlan.server.filesys.ExistingOpLockException;
|
|
||||||
import org.alfresco.jlan.server.filesys.NetworkFile;
|
|
||||||
import org.alfresco.jlan.server.filesys.TreeConnection;
|
|
||||||
import org.alfresco.jlan.server.filesys.pseudo.MemoryNetworkFile;
|
|
||||||
import org.alfresco.jlan.server.locking.LockManager;
|
|
||||||
import org.alfresco.jlan.server.locking.OpLockDetails;
|
|
||||||
import org.alfresco.jlan.server.locking.OpLockManager;
|
|
||||||
import org.alfresco.jlan.smb.OpLock;
|
|
||||||
import org.alfresco.jlan.smb.SMBStatus;
|
|
||||||
import org.alfresco.jlan.smb.server.SMBSrvPacket;
|
|
||||||
import org.alfresco.jlan.smb.server.SMBSrvSession;
|
|
||||||
import org.alfresco.filesys.alfresco.AlfrescoNetworkFile;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* File State Lock Manager Class
|
|
||||||
*
|
|
||||||
* <p>Implementation of a lock manager that uses the file state cache to track locks on a file.
|
|
||||||
*
|
|
||||||
* @author gkspencer
|
|
||||||
*/
|
|
||||||
public class FileStateLockManager implements LockManager, OpLockManager, Runnable {
|
|
||||||
|
|
||||||
// Oplock break timeout
|
|
||||||
|
|
||||||
private static final long OpLockBreakTimeout = 5000L; // 5 seconds
|
|
||||||
|
|
||||||
// File state cache used for byte range locks/oplocks
|
|
||||||
|
|
||||||
private FileStateTable m_stateCache;
|
|
||||||
|
|
||||||
// Oplock breaks in progress
|
|
||||||
|
|
||||||
private Hashtable<String, OpLockDetails> m_oplockQueue;
|
|
||||||
|
|
||||||
// Oplock break timeout thread
|
|
||||||
|
|
||||||
private Thread m_expiryThread;
|
|
||||||
private boolean m_shutdown;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Lock a byte range within a file, or the whole file.
|
|
||||||
*
|
|
||||||
* @param sess SrvSession
|
|
||||||
* @param tree TreeConnection
|
|
||||||
* @param file NetworkFile
|
|
||||||
* @param lock FileLock
|
|
||||||
* @exception LockConflictException
|
|
||||||
* @exception IOException
|
|
||||||
*/
|
|
||||||
public void lockFile(SrvSession sess, TreeConnection tree, NetworkFile file, FileLock lock)
|
|
||||||
throws LockConflictException, IOException {
|
|
||||||
|
|
||||||
// Get the file state associated with the file
|
|
||||||
|
|
||||||
FileState fstate = null;
|
|
||||||
|
|
||||||
if ( file instanceof AlfrescoNetworkFile) {
|
|
||||||
AlfrescoNetworkFile alfFile = (AlfrescoNetworkFile) file;
|
|
||||||
fstate = alfFile.getFileState();
|
|
||||||
}
|
|
||||||
else if ( file instanceof MemoryNetworkFile) {
|
|
||||||
file.addLock(lock);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( fstate == null)
|
|
||||||
throw new IOException("Open file without state (lock)");
|
|
||||||
|
|
||||||
// Add the lock to the active lock list for the file, check if the new lock conflicts with
|
|
||||||
// any existing locks. Add the lock to the file instance so that locks can be removed if the
|
|
||||||
// file is closed/session abnormally terminates.
|
|
||||||
|
|
||||||
fstate.addLock(lock);
|
|
||||||
file.addLock(lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unlock a byte range within a file, or the whole file
|
|
||||||
*
|
|
||||||
* @param sess SrvSession
|
|
||||||
* @param tree TreeConnection
|
|
||||||
* @param file NetworkFile
|
|
||||||
* @param lock FileLock
|
|
||||||
* @exception NotLockedException
|
|
||||||
* @exception IOException
|
|
||||||
*/
|
|
||||||
public void unlockFile(SrvSession sess, TreeConnection tree, NetworkFile file, FileLock lock)
|
|
||||||
throws NotLockedException, IOException {
|
|
||||||
|
|
||||||
// Get the file state associated with the file
|
|
||||||
|
|
||||||
FileState fstate = null;
|
|
||||||
|
|
||||||
if ( file instanceof AlfrescoNetworkFile) {
|
|
||||||
AlfrescoNetworkFile alfFile = (AlfrescoNetworkFile) file;
|
|
||||||
fstate = alfFile.getFileState();
|
|
||||||
}
|
|
||||||
else if ( file instanceof MemoryNetworkFile) {
|
|
||||||
file.removeLock(lock);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( fstate == null)
|
|
||||||
throw new IOException("Open file without state (unlock)");
|
|
||||||
|
|
||||||
// Remove the lock from the active lock list for the file, and the file instance
|
|
||||||
|
|
||||||
fstate.removeLock(lock);
|
|
||||||
file.removeLock(lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a lock object, use the standard FileLock object.
|
|
||||||
*
|
|
||||||
* @param sess SrvSession
|
|
||||||
* @param tree TreeConnection
|
|
||||||
* @param file NetworkFile
|
|
||||||
* @param offset long
|
|
||||||
* @param len long
|
|
||||||
* @param pid int
|
|
||||||
*/
|
|
||||||
public FileLock createLockObject(SrvSession sess, TreeConnection tree, NetworkFile file, long offset, long len, int pid) {
|
|
||||||
|
|
||||||
// Create a lock object to represent the file lock
|
|
||||||
|
|
||||||
return new FileLock(offset, len, pid);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Release all locks that a session has on a file. This method is called to perform cleanup if a file
|
|
||||||
* is closed that has active locks or if a session abnormally terminates.
|
|
||||||
*
|
|
||||||
* @param sess SrvSession
|
|
||||||
* @param tree TreeConnection
|
|
||||||
* @param file NetworkFile
|
|
||||||
*/
|
|
||||||
public void releaseLocksForFile(SrvSession sess, TreeConnection tree, NetworkFile file) {
|
|
||||||
|
|
||||||
// Check if the file has active locks
|
|
||||||
|
|
||||||
if ( file.hasLocks())
|
|
||||||
{
|
|
||||||
|
|
||||||
synchronized ( file)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Enumerate the locks and remove
|
|
||||||
|
|
||||||
while ( file.numberOfLocks() > 0)
|
|
||||||
{
|
|
||||||
// Get the current file lock
|
|
||||||
|
|
||||||
FileLock curLock = file.getLockAt(0);
|
|
||||||
|
|
||||||
// Remove the lock, ignore errors
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
|
|
||||||
// Unlock will remove the lock from the global list and the local files list
|
|
||||||
|
|
||||||
unlockFile(sess, tree, file, curLock);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enable oplock support by setting the file state table
|
|
||||||
*
|
|
||||||
* @param stateTable FileStateTable
|
|
||||||
*/
|
|
||||||
public final void setStateTable(FileStateTable stateTable) {
|
|
||||||
|
|
||||||
m_stateCache = stateTable;
|
|
||||||
|
|
||||||
// Create the oplock break queue
|
|
||||||
|
|
||||||
m_oplockQueue = new Hashtable<String, OpLockDetails>();
|
|
||||||
|
|
||||||
// Start the oplock break expiry thread
|
|
||||||
|
|
||||||
m_expiryThread = new Thread(this);
|
|
||||||
m_expiryThread.setDaemon(true);
|
|
||||||
m_expiryThread.setName("OpLockExpire");
|
|
||||||
m_expiryThread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if there is an oplock for the specified path, return the oplock type.
|
|
||||||
*
|
|
||||||
* @param path String
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public int hasOpLock(String path) {
|
|
||||||
|
|
||||||
// Check if oplocks/state cache are enabled
|
|
||||||
|
|
||||||
if ( m_stateCache == null)
|
|
||||||
return OpLock.TypeNone;
|
|
||||||
|
|
||||||
// Get the file state
|
|
||||||
|
|
||||||
FileState fstate = m_stateCache.findFileState(path);
|
|
||||||
if ( fstate != null && fstate.hasOpLock()) {
|
|
||||||
|
|
||||||
// Return the oplock type
|
|
||||||
|
|
||||||
OpLockDetails oplock = fstate.getOpLock();
|
|
||||||
if ( oplock != null)
|
|
||||||
return oplock.getLockType();
|
|
||||||
}
|
|
||||||
|
|
||||||
// No oplock
|
|
||||||
|
|
||||||
return OpLock.TypeNone;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the oplock details for a path, or null if there is no oplock on the path
|
|
||||||
*
|
|
||||||
* @param path String
|
|
||||||
* @return OpLockDetails
|
|
||||||
*/
|
|
||||||
public OpLockDetails getOpLockDetails(String path) {
|
|
||||||
|
|
||||||
// Check if oplocks/state cache are enabled
|
|
||||||
|
|
||||||
if ( m_stateCache == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
// Get the file state
|
|
||||||
|
|
||||||
FileState fstate = m_stateCache.findFileState(path);
|
|
||||||
if ( fstate != null)
|
|
||||||
return fstate.getOpLock();
|
|
||||||
|
|
||||||
// No oplock
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Grant an oplock, store the oplock details
|
|
||||||
*
|
|
||||||
* @param path String
|
|
||||||
* @param oplock OpLockDetails
|
|
||||||
* @return boolean
|
|
||||||
* @exception ExistingOpLockException If the file already has an oplock
|
|
||||||
*/
|
|
||||||
public boolean grantOpLock(String path, OpLockDetails oplock)
|
|
||||||
throws ExistingOpLockException {
|
|
||||||
|
|
||||||
// Check if oplocks/state cache are enabled
|
|
||||||
|
|
||||||
if ( m_stateCache == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Get, or create, a file state
|
|
||||||
|
|
||||||
FileState fstate = m_stateCache.findFileState(path, false, true);
|
|
||||||
|
|
||||||
// Check if the file is already in use
|
|
||||||
|
|
||||||
if ( fstate.getOpenCount() != 1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Set the oplock
|
|
||||||
|
|
||||||
fstate.setOpLock( oplock);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inform the oplock manager that an oplock break is in progress for the specified file/oplock
|
|
||||||
*
|
|
||||||
* @param path String
|
|
||||||
* @param oplock OpLockDetails
|
|
||||||
*/
|
|
||||||
public void informOpLockBreakInProgress(String path, OpLockDetails oplock) {
|
|
||||||
|
|
||||||
// Check if oplocks/state cache are enabled
|
|
||||||
|
|
||||||
if ( m_stateCache == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Add the oplock to the break in progress queue
|
|
||||||
|
|
||||||
synchronized ( m_oplockQueue) {
|
|
||||||
m_oplockQueue.put( path, oplock);
|
|
||||||
m_oplockQueue.notify();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Release an oplock
|
|
||||||
*
|
|
||||||
* @param path String
|
|
||||||
*/
|
|
||||||
public void releaseOpLock(String path) {
|
|
||||||
|
|
||||||
// Check if oplocks/state cache are enabled
|
|
||||||
|
|
||||||
if ( m_stateCache == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Get the file state
|
|
||||||
|
|
||||||
FileState fstate = m_stateCache.findFileState(path);
|
|
||||||
if ( fstate != null)
|
|
||||||
fstate.clearOpLock();
|
|
||||||
|
|
||||||
// Remove from the pending oplock break queue
|
|
||||||
|
|
||||||
synchronized ( m_oplockQueue) {
|
|
||||||
m_oplockQueue.remove( path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check for expired oplock break requests
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public int checkExpiredOplockBreaks() {
|
|
||||||
|
|
||||||
// Check if there are ny oplock breaks in progress
|
|
||||||
|
|
||||||
if ( m_oplockQueue.size() == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Check for oplock break requests that have expired
|
|
||||||
|
|
||||||
int expireCnt = 0;
|
|
||||||
|
|
||||||
long timeNow = System.currentTimeMillis();
|
|
||||||
Enumeration<String> opBreakKeys = m_oplockQueue.keys();
|
|
||||||
|
|
||||||
while ( opBreakKeys.hasMoreElements()) {
|
|
||||||
|
|
||||||
// Check the current oplock break
|
|
||||||
|
|
||||||
String path = opBreakKeys.nextElement();
|
|
||||||
OpLockDetails opLock = m_oplockQueue.get( path);
|
|
||||||
if ( opLock != null) {
|
|
||||||
|
|
||||||
// Check if the oplock break has timed out
|
|
||||||
|
|
||||||
if ( opLock.hasDeferredSession() && (opLock.getOplockBreakTime() + OpLockBreakTimeout) <= timeNow) {
|
|
||||||
|
|
||||||
// Get the deferred request details
|
|
||||||
|
|
||||||
SMBSrvSession sess = opLock.getDeferredSession();
|
|
||||||
SMBSrvPacket pkt = opLock.getDeferredPacket();
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
// Return an error for the deferred file open request
|
|
||||||
|
|
||||||
if ( sess.sendAsyncErrorResponseSMB( pkt, SMBStatus.NTAccessDenied, SMBStatus.NTErr) == true) {
|
|
||||||
|
|
||||||
// DEBUG
|
|
||||||
|
|
||||||
if ( Debug.EnableDbg && sess.hasDebug( SMBSrvSession.DBG_OPLOCK))
|
|
||||||
sess.debugPrintln( "Oplock break timeout, oplock=" + opLock);
|
|
||||||
|
|
||||||
// Release the packet back to the pool
|
|
||||||
|
|
||||||
sess.getPacketPool().releasePacket( pkt);
|
|
||||||
}
|
|
||||||
else if ( Debug.EnableDbg && sess.hasDebug( SMBSrvSession.DBG_OPLOCK))
|
|
||||||
sess.debugPrintln( "Failed to send open reject, oplock break timed out, oplock=" + opLock);
|
|
||||||
}
|
|
||||||
catch ( IOException ex) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the oplock break from the queue
|
|
||||||
|
|
||||||
m_oplockQueue.remove( path);
|
|
||||||
|
|
||||||
// Clear the deferred packet details
|
|
||||||
|
|
||||||
opLock.clearDeferredSession();
|
|
||||||
|
|
||||||
// Mark the oplock has having a failed oplock break
|
|
||||||
|
|
||||||
opLock.setOplockBreakFailed();
|
|
||||||
|
|
||||||
// Update the expired oplock break count
|
|
||||||
|
|
||||||
expireCnt++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the count of expired oplock breaks
|
|
||||||
|
|
||||||
return expireCnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run the oplock break expiry
|
|
||||||
*/
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
// Loop forever
|
|
||||||
|
|
||||||
m_shutdown = false;
|
|
||||||
|
|
||||||
while ( m_shutdown == false)
|
|
||||||
{
|
|
||||||
// Wait for an oplock break or sleep for a while if there are active oplock break requests
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
synchronized ( m_oplockQueue) {
|
|
||||||
if ( m_oplockQueue.size() == 0)
|
|
||||||
m_oplockQueue.wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Oplock break added to the queue, wait a while before checking the queue
|
|
||||||
|
|
||||||
if ( m_oplockQueue.size() > 0)
|
|
||||||
Thread.sleep( OpLockBreakTimeout);
|
|
||||||
}
|
|
||||||
catch (InterruptedException ex)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for shutdown
|
|
||||||
|
|
||||||
if ( m_shutdown == true)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Check for expired oplock break requests
|
|
||||||
|
|
||||||
checkExpiredOplockBreaks();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Request the oplock break expiry thread to shutdown
|
|
||||||
*/
|
|
||||||
public final void shutdownRequest() {
|
|
||||||
m_shutdown = true;
|
|
||||||
|
|
||||||
if ( m_expiryThread != null)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
m_expiryThread.interrupt();
|
|
||||||
}
|
|
||||||
catch (Exception ex) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,216 +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.filesys.state;
|
|
||||||
|
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.Hashtable;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* File State Reaper Class
|
|
||||||
*
|
|
||||||
* <p>FileStateTable objects register with the file state reaper to periodically check for expired file states.
|
|
||||||
*
|
|
||||||
* @author gkspencer
|
|
||||||
*/
|
|
||||||
public class FileStateReaper implements Runnable {
|
|
||||||
|
|
||||||
// Logging
|
|
||||||
|
|
||||||
private static final Log logger = LogFactory.getLog(FileStateReaper.class);
|
|
||||||
|
|
||||||
// Default expire check thread interval
|
|
||||||
|
|
||||||
private static final long DEFAULT_EXPIRECHECK = 15000;
|
|
||||||
|
|
||||||
// Wakeup interval for the expire file state checker thread
|
|
||||||
|
|
||||||
private long m_expireInterval = DEFAULT_EXPIRECHECK;
|
|
||||||
|
|
||||||
// File state checker thread
|
|
||||||
|
|
||||||
private Thread m_thread;
|
|
||||||
|
|
||||||
// Shutdown request flag
|
|
||||||
|
|
||||||
private boolean m_shutdown;
|
|
||||||
|
|
||||||
// List of file state tables to be scanned for expired file states
|
|
||||||
|
|
||||||
private Hashtable<String, FileStateTable> m_stateTables;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default constructor
|
|
||||||
*/
|
|
||||||
public FileStateReaper()
|
|
||||||
{
|
|
||||||
// Create the reaper thread
|
|
||||||
|
|
||||||
m_thread = new Thread(this);
|
|
||||||
m_thread.setDaemon(true);
|
|
||||||
m_thread.setName("FileStateReaper");
|
|
||||||
m_thread.start();
|
|
||||||
|
|
||||||
// Create the file state table list
|
|
||||||
|
|
||||||
m_stateTables = new Hashtable<String, FileStateTable>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the expired file state checker interval, in milliseconds
|
|
||||||
*
|
|
||||||
* @return long
|
|
||||||
*/
|
|
||||||
public final long getCheckInterval()
|
|
||||||
{
|
|
||||||
return m_expireInterval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the expired file state checker interval, in milliseconds
|
|
||||||
*
|
|
||||||
* @param chkIntval long
|
|
||||||
*/
|
|
||||||
public final void setCheckInterval(long chkIntval)
|
|
||||||
{
|
|
||||||
m_expireInterval = chkIntval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a file state table to the reaper list
|
|
||||||
*
|
|
||||||
* @param filesysName String
|
|
||||||
* @param stateTable FileStateTable
|
|
||||||
*/
|
|
||||||
public final void addStateTable( String filesysName, FileStateTable stateTable)
|
|
||||||
{
|
|
||||||
// DEBUG
|
|
||||||
|
|
||||||
if ( logger.isDebugEnabled())
|
|
||||||
logger.debug( "Added file state table for " + filesysName);
|
|
||||||
|
|
||||||
m_stateTables.put( filesysName, stateTable);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a state table from the reaper list
|
|
||||||
*
|
|
||||||
* @param filesysName String
|
|
||||||
*/
|
|
||||||
public final void removeStateTable( String filesysName)
|
|
||||||
{
|
|
||||||
m_stateTables.remove( filesysName);
|
|
||||||
|
|
||||||
// DEBUG
|
|
||||||
|
|
||||||
if ( logger.isDebugEnabled())
|
|
||||||
logger.debug( "Removed file state table for " + filesysName);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Expired file state checker thread
|
|
||||||
*/
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
// Loop forever
|
|
||||||
|
|
||||||
m_shutdown = false;
|
|
||||||
|
|
||||||
while ( m_shutdown == false)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Sleep for the required interval
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Thread.sleep(getCheckInterval());
|
|
||||||
}
|
|
||||||
catch (InterruptedException ex)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for shutdown
|
|
||||||
|
|
||||||
if ( m_shutdown == true)
|
|
||||||
{
|
|
||||||
// Debug
|
|
||||||
|
|
||||||
if ( logger.isDebugEnabled())
|
|
||||||
logger.debug("FileStateReaper thread closing");
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if there are any state tables registered
|
|
||||||
|
|
||||||
if ( m_stateTables != null && m_stateTables.size() > 0)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Loop through the registered file state tables and remove expired file states
|
|
||||||
|
|
||||||
Enumeration<String> filesysNames = m_stateTables.keys();
|
|
||||||
|
|
||||||
while ( filesysNames.hasMoreElements())
|
|
||||||
{
|
|
||||||
// Get the current filesystem name and associated state table
|
|
||||||
|
|
||||||
String filesysName = filesysNames.nextElement();
|
|
||||||
FileStateTable stateTable = m_stateTables.get( filesysName);
|
|
||||||
|
|
||||||
// Check for expired file states
|
|
||||||
|
|
||||||
int cnt = stateTable.removeExpiredFileStates();
|
|
||||||
|
|
||||||
// Debug
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled() && cnt > 0)
|
|
||||||
logger.debug("Expired " + cnt + " file states for " + filesysName + ", cache=" + stateTable.numberOfStates());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
// Log errors if not shutting down
|
|
||||||
|
|
||||||
if ( m_shutdown == false)
|
|
||||||
logger.debug(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Request the file state checker thread to shutdown
|
|
||||||
*/
|
|
||||||
public final void shutdownRequest() {
|
|
||||||
m_shutdown = true;
|
|
||||||
|
|
||||||
if ( m_thread != null)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
m_thread.interrupt();
|
|
||||||
}
|
|
||||||
catch (Exception ex) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,419 +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.filesys.state;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* File State Table Class
|
|
||||||
*
|
|
||||||
* <p>Contains an indexed list of the currently open files/folders.
|
|
||||||
*
|
|
||||||
* @author gkspencer
|
|
||||||
*/
|
|
||||||
public class FileStateTable
|
|
||||||
{
|
|
||||||
private static final Log logger = LogFactory.getLog(FileStateTable.class);
|
|
||||||
|
|
||||||
// Initial allocation size for the state cache
|
|
||||||
|
|
||||||
private static final int INITIAL_SIZE = 100;
|
|
||||||
|
|
||||||
// File state table, keyed by file path
|
|
||||||
|
|
||||||
private Hashtable<String, FileState> m_stateTable;
|
|
||||||
|
|
||||||
// File state expiry time in seconds
|
|
||||||
|
|
||||||
private long m_cacheTimer = 2 * 60000L; // 2 minutes default
|
|
||||||
|
|
||||||
// File state listener, can veto expiring of file states
|
|
||||||
|
|
||||||
private FileStateListener m_stateListener;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class constructor
|
|
||||||
*/
|
|
||||||
public FileStateTable()
|
|
||||||
{
|
|
||||||
m_stateTable = new Hashtable<String, FileState>(INITIAL_SIZE);
|
|
||||||
|
|
||||||
// Start the expired file state checker thread
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the file state cache timer, in milliseconds
|
|
||||||
*
|
|
||||||
* @return long
|
|
||||||
*/
|
|
||||||
public final long getCacheTimer()
|
|
||||||
{
|
|
||||||
return m_cacheTimer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the number of states in the cache
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public final int numberOfStates()
|
|
||||||
{
|
|
||||||
return m_stateTable.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the default file state cache timer, in milliseconds
|
|
||||||
*
|
|
||||||
* @param tmo long
|
|
||||||
*/
|
|
||||||
public final void setCacheTimer(long tmo)
|
|
||||||
{
|
|
||||||
m_cacheTimer = tmo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a new file state
|
|
||||||
*
|
|
||||||
* @param fstate FileState
|
|
||||||
*/
|
|
||||||
public final synchronized void addFileState(FileState fstate)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Check if the file state already exists in the cache
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled() && m_stateTable.get(fstate.getPath()) != null)
|
|
||||||
logger.debug("***** addFileState() state=" + fstate.toString() + " - ALREADY IN CACHE *****");
|
|
||||||
|
|
||||||
// DEBUG
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled() && fstate == null)
|
|
||||||
{
|
|
||||||
logger.debug("addFileState() NULL FileState");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the file state timeout and add to the cache
|
|
||||||
|
|
||||||
fstate.setExpiryTime(System.currentTimeMillis() + getCacheTimer());
|
|
||||||
m_stateTable.put(fstate.getPath(), fstate);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find the file state for the specified path
|
|
||||||
*
|
|
||||||
* @param path String
|
|
||||||
* @return FileState
|
|
||||||
*/
|
|
||||||
public final synchronized FileState findFileState(String path)
|
|
||||||
{
|
|
||||||
FileState fstate = m_stateTable.get(FileState.normalizePath(path));
|
|
||||||
|
|
||||||
if ( fstate != null)
|
|
||||||
fstate.updateAccessDateTime();
|
|
||||||
|
|
||||||
return fstate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find the file state for the specified path, and optionally create a new file state if not
|
|
||||||
* found
|
|
||||||
*
|
|
||||||
* @param path String
|
|
||||||
* @param isdir boolean
|
|
||||||
* @param create boolean
|
|
||||||
* @return FileState
|
|
||||||
*/
|
|
||||||
public final synchronized FileState findFileState(String path, boolean isdir, boolean create)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Find the required file state, if it exists
|
|
||||||
|
|
||||||
FileState state = m_stateTable.get(FileState.normalizePath(path));
|
|
||||||
|
|
||||||
// Check if we should create a new file state
|
|
||||||
|
|
||||||
if (state == null && create == true)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Create a new file state
|
|
||||||
|
|
||||||
state = new FileState(path, isdir);
|
|
||||||
|
|
||||||
// Set the file state timeout and add to the cache
|
|
||||||
|
|
||||||
state.setExpiryTime(System.currentTimeMillis() + getCacheTimer());
|
|
||||||
m_stateTable.put(state.getPath(), state);
|
|
||||||
|
|
||||||
// DEBUG
|
|
||||||
|
|
||||||
if ( logger.isDebugEnabled() && state.getPath().length() > 0 && state.getPath().indexOf("\\") == -1) {
|
|
||||||
logger.debug("*** File state path is not relative - " + state.getPath() + " ***");
|
|
||||||
Thread.dumpStack();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the access date/time if valid
|
|
||||||
|
|
||||||
if ( state != null)
|
|
||||||
state.updateAccessDateTime();
|
|
||||||
|
|
||||||
// Return the file state
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the name that a file state is cached under, and the associated file state
|
|
||||||
*
|
|
||||||
* @param oldName String
|
|
||||||
* @param newName String
|
|
||||||
* @return FileState
|
|
||||||
*/
|
|
||||||
public final synchronized FileState updateFileState(String oldName, String newName)
|
|
||||||
{
|
|
||||||
// Find the current file state
|
|
||||||
|
|
||||||
FileState state = m_stateTable.remove(FileState.normalizePath(oldName));
|
|
||||||
|
|
||||||
// Rename the file state and add it back into the cache using the new name
|
|
||||||
|
|
||||||
if (state != null)
|
|
||||||
{
|
|
||||||
state.setPath(newName);
|
|
||||||
addFileState(state);
|
|
||||||
|
|
||||||
// Update the access date/time
|
|
||||||
|
|
||||||
state.updateAccessDateTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the updated file state
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enumerate the file state cache
|
|
||||||
*
|
|
||||||
* @return Enumeration<String>
|
|
||||||
*/
|
|
||||||
public final Enumeration<String> enumerate()
|
|
||||||
{
|
|
||||||
return m_stateTable.keys();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the file state for the specified path
|
|
||||||
*
|
|
||||||
* @param path String
|
|
||||||
* @return FileState
|
|
||||||
*/
|
|
||||||
public final synchronized FileState removeFileState(String path)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Remove the file state from the cache
|
|
||||||
|
|
||||||
FileState state = m_stateTable.remove(FileState.normalizePath(path));
|
|
||||||
|
|
||||||
// Return the removed file state
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rename a file state, remove the existing entry, update the path and add the state back into
|
|
||||||
* the cache using the new path.
|
|
||||||
*
|
|
||||||
* @param newPath String
|
|
||||||
* @param state FileState
|
|
||||||
*/
|
|
||||||
public final synchronized void renameFileState(String newPath, FileState state)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Remove the existing file state from the cache, using the original name
|
|
||||||
|
|
||||||
m_stateTable.remove(state.getPath());
|
|
||||||
|
|
||||||
// Update the file state path and add it back to the cache using the new name
|
|
||||||
|
|
||||||
state.setPath(FileState.normalizePath(newPath));
|
|
||||||
m_stateTable.put(state.getPath(), state);
|
|
||||||
|
|
||||||
// Updaet the access date/time
|
|
||||||
|
|
||||||
state.updateAccessDateTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove all file states from the cache
|
|
||||||
*/
|
|
||||||
public final synchronized void removeAllFileStates()
|
|
||||||
{
|
|
||||||
|
|
||||||
// Check if there are any items in the cache
|
|
||||||
|
|
||||||
if (m_stateTable == null || m_stateTable.size() == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Enumerate the file state cache and remove expired file state objects
|
|
||||||
|
|
||||||
Enumeration<String> enm = m_stateTable.keys();
|
|
||||||
|
|
||||||
while (enm.hasMoreElements())
|
|
||||||
{
|
|
||||||
|
|
||||||
// Get the file state
|
|
||||||
|
|
||||||
FileState state = m_stateTable.get(enm.nextElement());
|
|
||||||
|
|
||||||
// Check if there is a state listener
|
|
||||||
|
|
||||||
if ( m_stateListener != null)
|
|
||||||
m_stateListener.fileStateClosed(state);
|
|
||||||
|
|
||||||
// DEBUG
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("++ Closed: " + state.getPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove all the file states
|
|
||||||
|
|
||||||
m_stateTable.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove expired file states from the cache
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public final int removeExpiredFileStates()
|
|
||||||
{
|
|
||||||
|
|
||||||
// Check if there are any items in the cache
|
|
||||||
|
|
||||||
if (m_stateTable == null || m_stateTable.size() == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Enumerate the file state cache and remove expired file state objects
|
|
||||||
|
|
||||||
Enumeration<String> enm = m_stateTable.keys();
|
|
||||||
long curTime = System.currentTimeMillis();
|
|
||||||
|
|
||||||
int expiredCnt = 0;
|
|
||||||
|
|
||||||
while (enm.hasMoreElements())
|
|
||||||
{
|
|
||||||
|
|
||||||
// Get the file state
|
|
||||||
|
|
||||||
FileState state = m_stateTable.get(enm.nextElement());
|
|
||||||
|
|
||||||
if (state != null && state.hasNoTimeout() == false)
|
|
||||||
{
|
|
||||||
|
|
||||||
synchronized (state)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Check if the file state has expired and there are no open references to the
|
|
||||||
// file
|
|
||||||
|
|
||||||
if (state.hasExpired(curTime) && state.getOpenCount() == 0)
|
|
||||||
{
|
|
||||||
// Check with the state listener before removing the file state, if enabled
|
|
||||||
|
|
||||||
if ( hasStateListener() == false || m_stateListener.fileStateExpired( state) == true)
|
|
||||||
{
|
|
||||||
// Remove the expired file state
|
|
||||||
|
|
||||||
m_stateTable.remove(state.getPath());
|
|
||||||
|
|
||||||
// DEBUG
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Expired file state: " + state);
|
|
||||||
|
|
||||||
// Update the expired count
|
|
||||||
|
|
||||||
expiredCnt++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the count of expired file states that were removed
|
|
||||||
|
|
||||||
return expiredCnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dump the state cache entries to the specified stream
|
|
||||||
*/
|
|
||||||
public final void Dump()
|
|
||||||
{
|
|
||||||
|
|
||||||
// Dump the file state cache entries to the specified stream
|
|
||||||
|
|
||||||
if (m_stateTable.size() > 0)
|
|
||||||
logger.debug("FileStateCache Entries:");
|
|
||||||
|
|
||||||
Enumeration<String> enm = m_stateTable.keys();
|
|
||||||
long curTime = System.currentTimeMillis();
|
|
||||||
|
|
||||||
while (enm.hasMoreElements())
|
|
||||||
{
|
|
||||||
String fname = enm.nextElement();
|
|
||||||
FileState state = m_stateTable.get(fname);
|
|
||||||
|
|
||||||
logger.debug(" " + fname + "(" + state.getSecondsToExpire(curTime) + ") : " + state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a file state listener
|
|
||||||
*
|
|
||||||
* @param l FileStateListener
|
|
||||||
*/
|
|
||||||
public final void addStateListener(FileStateListener l) {
|
|
||||||
m_stateListener = l;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a file state listener
|
|
||||||
*
|
|
||||||
* @param l FileStateListener
|
|
||||||
*/
|
|
||||||
public final void removeStateListener(FileStateListener l) {
|
|
||||||
if ( m_stateListener == l)
|
|
||||||
m_stateListener = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the file state listener is set
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public final boolean hasStateListener() {
|
|
||||||
return m_stateListener != null ? true : false;
|
|
||||||
}
|
|
||||||
}
|
|
Reference in New Issue
Block a user