diff --git a/source/java/org/alfresco/filesys/server/filesys/NetworkFile.java b/source/java/org/alfresco/filesys/server/filesys/NetworkFile.java index 4860ea1e97..d5af35f120 100644 --- a/source/java/org/alfresco/filesys/server/filesys/NetworkFile.java +++ b/source/java/org/alfresco/filesys/server/filesys/NetworkFile.java @@ -28,6 +28,7 @@ import java.io.IOException; import org.alfresco.filesys.locking.FileLock; import org.alfresco.filesys.locking.FileLockList; +import org.alfresco.filesys.server.state.FileState; /** *
@@ -111,6 +112,10 @@ public abstract class NetworkFile private int m_flags; + // Associated file state + + private FileState m_state; + /** * Create a network file object with the specified file identifier. * @@ -207,6 +212,16 @@ public abstract class NetworkFile return (int) (m_fileSize & 0x0FFFFFFFFL); } + /** + * Return the associated file state + * + * @return FileState + */ + public final FileState getFileState() + { + return m_state; + } + /** * Return the full name, relative to the share. * @@ -533,6 +548,16 @@ public abstract class NetworkFile m_fileSize = (long) siz; } + /** + * Set the associated file state + * + * @param state FileState + */ + public final void setFileState( FileState state) + { + m_state = state; + } + /** * Set the full file name, relative to the share. * diff --git a/source/java/org/alfresco/filesys/server/state/FileStateLockManager.java b/source/java/org/alfresco/filesys/server/state/FileStateLockManager.java new file mode 100644 index 0000000000..7c7d329614 --- /dev/null +++ b/source/java/org/alfresco/filesys/server/state/FileStateLockManager.java @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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 General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.filesys.server.state; + +import java.io.IOException; + +import org.alfresco.filesys.locking.FileLock; +import org.alfresco.filesys.locking.LockConflictException; +import org.alfresco.filesys.locking.NotLockedException; +import org.alfresco.filesys.server.SrvSession; +import org.alfresco.filesys.server.filesys.NetworkFile; +import org.alfresco.filesys.server.filesys.TreeConnection; +import org.alfresco.filesys.server.locking.LockManager; + +/** + * File State Lock Manager Class + * + *
Implementation of a lock manager that uses the file state cache to track locks on a file. + * + * @author gkspencer + */ +public class FileStateLockManager implements LockManager { + + /** + * 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 = file.getFileState(); + + 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 = file.getFileState(); + + 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) + { + } + } + } + } + } +} diff --git a/source/java/org/alfresco/filesys/smb/server/NTProtocolHandler.java b/source/java/org/alfresco/filesys/smb/server/NTProtocolHandler.java index 644d6bb867..a8b5d942ac 100644 --- a/source/java/org/alfresco/filesys/smb/server/NTProtocolHandler.java +++ b/source/java/org/alfresco/filesys/smb/server/NTProtocolHandler.java @@ -666,7 +666,7 @@ public class NTProtocolHandler extends CoreProtocolHandler // Map the IPC$ share to the admin pipe type - if (servType == ShareType.NAMEDPIPE && share.getShareName().compareTo("IPC$") == 0) + if (share.getShareName().compareTo("IPC$") == 0) servType = ShareType.ADMINPIPE; // Check if the session is a null session, only allow access to the IPC$ named pipe share @@ -1194,7 +1194,7 @@ public class NTProtocolHandler extends CoreProtocolHandler // Map the IPC$ share to the admin pipe type - if (servType == ShareType.NAMEDPIPE && shareName.compareTo("IPC$") == 0) + if (shareName.compareTo("IPC$") == 0) servType = ShareType.ADMINPIPE; // Check if the session is a null session, only allow access to the IPC$ named pipe share @@ -2096,7 +2096,7 @@ public class NTProtocolHandler extends CoreProtocolHandler // Return an error status - m_sess.sendErrorResponseSMB(SMBStatus.DOSNotLocked, SMBStatus.ErrDos); + m_sess.sendErrorResponseSMB(SMBStatus.NTRangeNotLocked, SMBStatus.DOSNotLocked, SMBStatus.ErrDos); return; } catch (LockConflictException ex) @@ -2104,9 +2104,7 @@ public class NTProtocolHandler extends CoreProtocolHandler // Return an error status - m_sess - .sendErrorResponseSMB(SMBStatus.NTLockNotGranted, SMBStatus.DOSLockConflict, - SMBStatus.ErrDos); + m_sess.sendErrorResponseSMB(SMBStatus.NTLockNotGranted, SMBStatus.DOSLockConflict, SMBStatus.ErrDos); return; } catch (IOException ex) @@ -2136,7 +2134,7 @@ public class NTProtocolHandler extends CoreProtocolHandler // Return an error status - m_sess.sendErrorResponseSMB(SMBStatus.DOSNotLocked, SMBStatus.ErrDos); + m_sess.sendErrorResponseSMB(SMBStatus.NTRangeNotLocked, SMBStatus.DOSNotLocked, SMBStatus.ErrDos); return; } } diff --git a/source/java/org/alfresco/filesys/smb/server/repo/ContentDiskDriver.java b/source/java/org/alfresco/filesys/smb/server/repo/ContentDiskDriver.java index 4e6b1de78c..c4a894c6ef 100644 --- a/source/java/org/alfresco/filesys/smb/server/repo/ContentDiskDriver.java +++ b/source/java/org/alfresco/filesys/smb/server/repo/ContentDiskDriver.java @@ -50,12 +50,15 @@ import org.alfresco.filesys.server.filesys.FileStatus; import org.alfresco.filesys.server.filesys.NetworkFile; import org.alfresco.filesys.server.filesys.SearchContext; import org.alfresco.filesys.server.filesys.TreeConnection; +import org.alfresco.filesys.server.locking.FileLockingInterface; +import org.alfresco.filesys.server.locking.LockManager; import org.alfresco.filesys.server.pseudo.MemoryNetworkFile; import org.alfresco.filesys.server.pseudo.PseudoFile; import org.alfresco.filesys.server.pseudo.PseudoFileInterface; import org.alfresco.filesys.server.pseudo.PseudoFileList; import org.alfresco.filesys.server.pseudo.PseudoNetworkFile; import org.alfresco.filesys.server.state.FileState; +import org.alfresco.filesys.server.state.FileStateLockManager; import org.alfresco.filesys.server.state.FileState.FileStateStatus; import org.alfresco.filesys.smb.SharingMode; import org.alfresco.filesys.smb.server.SMBSrvSession; @@ -84,7 +87,7 @@ import org.apache.commons.logging.LogFactory; * * @author Derek Hulley */ -public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterface +public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterface, FileLockingInterface { // Logging @@ -113,6 +116,10 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa private AuthenticationComponent authComponent; private AuthenticationService authService; + + // Lock manager + + private static LockManager _lockManager = new FileStateLockManager(); /** * Class constructor @@ -1288,6 +1295,10 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa fstate.incrementOpenCount(); fstate.setNodeRef(nodeRef); + + // Store the state with the file + + netFile.setFileState( fstate); } // If the file has been opened for overwrite then truncate the file to zero length, this will @@ -1415,6 +1426,10 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa fstate.incrementOpenCount(); fstate.setNodeRef(nodeRef); + // Store the file state with the file + + netFile.setFileState( fstate); + // DEBUG if ( logger.isDebugEnabled()) @@ -2367,4 +2382,15 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa { // Nothing to do } + + /** + * Return the lock manager used by this filesystem + * + * @param sess SrvSession + * @param tree TreeConnection + * @return LockManager + */ + public LockManager getLockManager(SrvSession sess, TreeConnection tree) { + return _lockManager; + } }