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:
Gary Spencer
2010-04-22 12:16:04 +00:00
parent ebc24ad0e0
commit c18a123228
22 changed files with 287 additions and 2310 deletions

View File

@@ -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>

View File

@@ -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

View File

@@ -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();
}
} }

View File

@@ -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
*/ */

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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;
}
} }

View File

@@ -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

View File

@@ -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

View File

@@ -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);
} }

View File

@@ -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();
}
}

View File

@@ -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);
}

View File

@@ -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) {
}
}
}
}

View File

@@ -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) {
}
}
}
}

View File

@@ -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;
}
}