mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Merged 1.4 to HEAD
svn merge svn://svn.alfresco.com:3691/alfresco/BRANCHES/V1.4@4313 svn://svn.alfresco.com:3691/alfresco/BRANCHES/V1.4@4314 . svn merge svn://svn.alfresco.com:3691/alfresco/BRANCHES/V1.4@4317 svn://svn.alfresco.com:3691/alfresco/BRANCHES/V1.4@4318 . git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@4656 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
525
source/java/org/alfresco/filesys/smb/server/VirtualCircuit.java
Normal file
525
source/java/org/alfresco/filesys/smb/server/VirtualCircuit.java
Normal file
@@ -0,0 +1,525 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
|
||||
package org.alfresco.filesys.smb.server;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import org.alfresco.filesys.server.SrvSession;
|
||||
import org.alfresco.filesys.server.auth.ClientInfo;
|
||||
import org.alfresco.filesys.server.core.DeviceInterface;
|
||||
import org.alfresco.filesys.server.core.SharedDevice;
|
||||
import org.alfresco.filesys.server.filesys.DiskInterface;
|
||||
import org.alfresco.filesys.server.filesys.NetworkFile;
|
||||
import org.alfresco.filesys.server.filesys.SearchContext;
|
||||
import org.alfresco.filesys.server.filesys.TooManyConnectionsException;
|
||||
import org.alfresco.filesys.server.filesys.TreeConnection;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Virtual Circuit Class
|
||||
*
|
||||
* <p>
|
||||
* Represents an authenticated circuit on an SMB/CIFS session. There may be
|
||||
* multiple virtual circuits opened on a single session/socket connection.
|
||||
*/
|
||||
public class VirtualCircuit {
|
||||
|
||||
// Debug logging
|
||||
|
||||
private static Log logger = LogFactory.getLog("org.alfresco.smb.protocol");
|
||||
|
||||
// Default and maximum number of connection slots
|
||||
|
||||
public static final int DefaultConnections = 4;
|
||||
public static final int MaxConnections = 16;
|
||||
|
||||
// Tree ids are 16bit values
|
||||
|
||||
private static final int TreeIdMask = 0x0000FFFF;
|
||||
|
||||
// Default and maximum number of search slots
|
||||
|
||||
private static final int DefaultSearches = 8;
|
||||
private static final int MaxSearches = 256;
|
||||
|
||||
// Invalid UID value
|
||||
|
||||
public static final int InvalidUID = -1;
|
||||
|
||||
// Virtual circuit UID value
|
||||
//
|
||||
// Allocated by the server and sent by the client to identify the virtual circuit
|
||||
|
||||
private int m_uid = -1;
|
||||
|
||||
// Virtual circuit number
|
||||
|
||||
private int m_vcNum;
|
||||
|
||||
// Client information for this virtual circuit
|
||||
|
||||
private ClientInfo m_clientInfo;
|
||||
|
||||
// Active tree connections
|
||||
|
||||
private Hashtable<Integer, TreeConnection> m_connections;
|
||||
|
||||
private int m_treeId;
|
||||
|
||||
// List of active searches
|
||||
|
||||
private SearchContext[] m_search;
|
||||
|
||||
private int m_searchCount;
|
||||
|
||||
// Active transaction details
|
||||
|
||||
private SrvTransactBuffer m_transact;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @param vcNum
|
||||
* int
|
||||
* @param cInfo
|
||||
* ClientInfo
|
||||
*/
|
||||
public VirtualCircuit(int vcNum, ClientInfo cInfo) {
|
||||
m_vcNum = vcNum;
|
||||
m_clientInfo = cInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the virtual circuit UID
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public final int getUID() {
|
||||
return m_uid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the virtual circuit number
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public final int getVCNumber() {
|
||||
return m_vcNum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the client information
|
||||
*
|
||||
* @return ClientInfo
|
||||
*/
|
||||
public final ClientInfo getClientInformation() {
|
||||
return m_clientInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new connection to this virtual circuit. Return the allocated tree
|
||||
* id for the new connection.
|
||||
*
|
||||
* @param shrDev SharedDevice
|
||||
* @return int Allocated tree id (connection id).
|
||||
*/
|
||||
public int addConnection(SharedDevice shrDev)
|
||||
throws TooManyConnectionsException {
|
||||
|
||||
// Check if the connection array has been allocated
|
||||
|
||||
if (m_connections == null)
|
||||
m_connections = new Hashtable<Integer, TreeConnection>(DefaultConnections);
|
||||
|
||||
// Allocate an id for the tree connection
|
||||
|
||||
int treeId = 0;
|
||||
|
||||
synchronized (m_connections) {
|
||||
|
||||
// Check if the tree connection table is full
|
||||
|
||||
if (m_connections.size() == MaxConnections)
|
||||
throw new TooManyConnectionsException();
|
||||
|
||||
// Find a free slot in the connection array
|
||||
|
||||
treeId = (m_treeId++ & TreeIdMask);
|
||||
Integer key = new Integer(treeId);
|
||||
|
||||
while (m_connections.contains(key)) {
|
||||
|
||||
// Try another tree id for the new connection
|
||||
|
||||
treeId = (m_treeId++ & TreeIdMask);
|
||||
key = new Integer(treeId);
|
||||
}
|
||||
|
||||
// Store the new tree connection
|
||||
|
||||
m_connections.put(key, new TreeConnection(shrDev));
|
||||
}
|
||||
|
||||
// Return the allocated tree id
|
||||
|
||||
return treeId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the tree connection details for the specified tree id.
|
||||
*
|
||||
* @return com.starla.smbsrv.TreeConnection
|
||||
* @param treeId
|
||||
* int
|
||||
*/
|
||||
public final TreeConnection findConnection(int treeId) {
|
||||
|
||||
// Check if the tree id and connection array are valid
|
||||
|
||||
if (m_connections == null)
|
||||
return null;
|
||||
|
||||
// Get the required tree connection details
|
||||
|
||||
return m_connections.get(new Integer(treeId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified tree connection from the active connection list.
|
||||
*
|
||||
* @param treeId
|
||||
* int
|
||||
* @param srvSession
|
||||
* SrvSession
|
||||
*/
|
||||
protected void removeConnection(int treeId, SrvSession sess) {
|
||||
|
||||
// Check if the tree id is valid
|
||||
|
||||
if (m_connections == null)
|
||||
return;
|
||||
|
||||
// Close the connection and remove from the connection list
|
||||
|
||||
synchronized (m_connections) {
|
||||
|
||||
// Get the connection
|
||||
|
||||
Integer key = new Integer(treeId);
|
||||
TreeConnection tree = m_connections.get(key);
|
||||
|
||||
// Close the connection, release resources
|
||||
|
||||
if (tree != null) {
|
||||
|
||||
// Close the connection
|
||||
|
||||
tree.closeConnection(sess);
|
||||
|
||||
// Remove the connection from the connection list
|
||||
|
||||
m_connections.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the active tree connection count
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public final int getConnectionCount() {
|
||||
return m_connections != null ? m_connections.size() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a slot in the active searches list for a new search.
|
||||
*
|
||||
* @return int Search slot index, or -1 if there are no more search slots
|
||||
* available.
|
||||
*/
|
||||
public final int allocateSearchSlot() {
|
||||
|
||||
// Check if the search array has been allocated
|
||||
|
||||
if (m_search == null)
|
||||
m_search = new SearchContext[DefaultSearches];
|
||||
|
||||
// Find a free slot for the new search
|
||||
|
||||
int idx = 0;
|
||||
|
||||
while (idx < m_search.length && m_search[idx] != null)
|
||||
idx++;
|
||||
|
||||
// Check if we found a free slot
|
||||
|
||||
if (idx == m_search.length) {
|
||||
|
||||
// The search array needs to be extended, check if we reached the
|
||||
// limit.
|
||||
|
||||
if (m_search.length >= MaxSearches)
|
||||
return -1;
|
||||
|
||||
// Extend the search array
|
||||
|
||||
SearchContext[] newSearch = new SearchContext[m_search.length * 2];
|
||||
System.arraycopy(m_search, 0, newSearch, 0, m_search.length);
|
||||
m_search = newSearch;
|
||||
}
|
||||
|
||||
// Return the allocated search slot index
|
||||
|
||||
m_searchCount++;
|
||||
return idx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deallocate the specified search context/slot.
|
||||
*
|
||||
* @param ctxId
|
||||
* int
|
||||
*/
|
||||
public final void deallocateSearchSlot(int ctxId) {
|
||||
|
||||
// Check if the search array has been allocated and that the index is
|
||||
// valid
|
||||
|
||||
if (m_search == null || ctxId >= m_search.length)
|
||||
return;
|
||||
|
||||
// Close the search
|
||||
|
||||
if (m_search[ctxId] != null)
|
||||
m_search[ctxId].closeSearch();
|
||||
|
||||
// Free the specified search context slot
|
||||
|
||||
m_searchCount--;
|
||||
m_search[ctxId] = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the search context for the specified search id.
|
||||
*
|
||||
* @return com.starla.smbsrv.SearchContext
|
||||
* @param srchId
|
||||
* int
|
||||
*/
|
||||
public final SearchContext getSearchContext(int srchId) {
|
||||
|
||||
// Check if the search array is valid and the search index is valid
|
||||
|
||||
if (m_search == null || srchId >= m_search.length)
|
||||
return null;
|
||||
|
||||
// Return the required search context
|
||||
|
||||
return m_search[srchId];
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the seach context in the specified slot.
|
||||
*
|
||||
* @param slot
|
||||
* Slot to store the search context.
|
||||
* @param srch
|
||||
* com.starla.smbsrv.SearchContext
|
||||
*/
|
||||
public final void setSearchContext(int slot, SearchContext srch) {
|
||||
|
||||
// Check if the search slot id is valid
|
||||
|
||||
if (m_search == null || slot > m_search.length)
|
||||
return;
|
||||
|
||||
// Store the context
|
||||
|
||||
m_search[slot] = srch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of active tree searches.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public final int getSearchCount() {
|
||||
return m_searchCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there is an active transaction
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean hasTransaction() {
|
||||
return m_transact != null ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the active transaction buffer
|
||||
*
|
||||
* @return TransactBuffer
|
||||
*/
|
||||
public final SrvTransactBuffer getTransaction() {
|
||||
return m_transact;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the active transaction buffer
|
||||
*
|
||||
* @param buf
|
||||
* TransactBuffer
|
||||
*/
|
||||
public final void setTransaction(SrvTransactBuffer buf) {
|
||||
m_transact = buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the UID for the circuit
|
||||
*
|
||||
* @param uid
|
||||
* int
|
||||
*/
|
||||
public final void setUID(int uid) {
|
||||
m_uid = uid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the virtual circuit, close active tree connections
|
||||
*
|
||||
* @param sess
|
||||
* SrvSession
|
||||
*/
|
||||
public final void closeCircuit(SrvSession sess) {
|
||||
|
||||
// Debug
|
||||
|
||||
if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_STATE))
|
||||
logger.debug("Cleanup vc=" + getVCNumber() + ", UID=" + getUID() + ", searches=" + getSearchCount()
|
||||
+ ", treeConns=" + getConnectionCount());
|
||||
|
||||
// Check if there are any active searches
|
||||
|
||||
if (m_search != null) {
|
||||
|
||||
// Close all active searches
|
||||
|
||||
for (int idx = 0; idx < m_search.length; idx++) {
|
||||
|
||||
// Check if the current search slot is active
|
||||
|
||||
if (m_search[idx] != null)
|
||||
deallocateSearchSlot(idx);
|
||||
}
|
||||
|
||||
// Release the search context list, clear the search count
|
||||
|
||||
m_search = null;
|
||||
m_searchCount = 0;
|
||||
}
|
||||
|
||||
// Check if there are open tree connections
|
||||
|
||||
if (m_connections != null) {
|
||||
|
||||
synchronized (m_connections) {
|
||||
|
||||
// Close all active tree connections
|
||||
|
||||
Enumeration<TreeConnection> enm = m_connections.elements();
|
||||
|
||||
while (enm.hasMoreElements()) {
|
||||
|
||||
// Get the current tree connection
|
||||
|
||||
TreeConnection tree = (TreeConnection) enm.nextElement();
|
||||
DeviceInterface devIface = tree.getInterface();
|
||||
|
||||
// Check if there are open files on the share
|
||||
|
||||
if (tree.openFileCount() > 0) {
|
||||
|
||||
// Close the open files, release locks
|
||||
|
||||
for (int i = 0; i < tree.getFileTableLength(); i++) {
|
||||
|
||||
// Get an open file
|
||||
|
||||
NetworkFile curFile = tree.findFile(i);
|
||||
if (curFile != null && devIface instanceof DiskInterface) {
|
||||
|
||||
// Access the disk share interface
|
||||
|
||||
DiskInterface diskIface = (DiskInterface) devIface;
|
||||
|
||||
try {
|
||||
|
||||
// Remove the file from the tree connection list
|
||||
|
||||
tree.removeFile(i, sess);
|
||||
|
||||
// Close the file
|
||||
|
||||
diskIface.closeFile(sess, tree, curFile);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Inform the driver that the connection has been closed
|
||||
|
||||
if (devIface != null)
|
||||
devIface.treeClosed(sess, tree);
|
||||
}
|
||||
|
||||
// Clear the tree connection list
|
||||
|
||||
m_connections.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the virtual circuit details as a string
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer str = new StringBuffer();
|
||||
|
||||
str.append("[");
|
||||
str.append(getVCNumber());
|
||||
str.append(":");
|
||||
str.append(getUID());
|
||||
str.append(",");
|
||||
str.append(getClientInformation());
|
||||
str.append(",Tree=");
|
||||
str.append(getConnectionCount());
|
||||
str.append(",Searches=");
|
||||
str.append(getSearchCount());
|
||||
str.append("]");
|
||||
|
||||
return str.toString();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user