All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.filesys.server.filesys.cache.FileState Maven / Gradle / Ivy

Go to download

Java file server with SMB, FTP/FTPS and NFS support, virtual filesystems, database filesystems

There is a newer version: 1.4.0
Show newest version
/*
 * Copyright (C) 2006-2010 Alfresco Software Limited.
 * Copyright (C) 2018 GK Spencer
 *
 * 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 .
 */

package org.filesys.server.filesys.cache;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;

import org.filesys.debug.Debug;
import org.filesys.locking.FileLock;
import org.filesys.locking.FileLockList;
import org.filesys.locking.LockConflictException;
import org.filesys.locking.NotLockedException;
import org.filesys.server.filesys.ExistingOpLockException;
import org.filesys.server.filesys.FileName;
import org.filesys.server.filesys.FileOpenParams;
import org.filesys.server.filesys.FileStatus;
import org.filesys.server.filesys.pseudo.PseudoFile;
import org.filesys.server.filesys.pseudo.PseudoFileList;
import org.filesys.server.locking.OpLockDetails;
import org.filesys.smb.SharingMode;

/**
 * File State Class
 *
 * 

Caches information about a file/directory so that the core server does not need * to make calls to the shared device driver. * * @author gkspencer */ public abstract class FileState implements Serializable { // Serialization id private static final long serialVersionUID = 1L; // 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 public final static int UnknownFileId = -1; // File data status codes public enum DataStatus { Unknown, LoadWait, Loading, Available, Updated, SaveWait, Saving, Saved, Deleted, Renamed, DeleteOnClose } // Standard file information keys public static final String FileInformation = "FileInfo"; public static final String StreamsList = "StreamsList"; // File status change reason codes public enum ChangeReason { None, FileCreated, FolderCreated, FileDeleted, FolderDeleted } // 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 FileStatus m_fileStatus; // Open file count private int m_openCount; // Sharing mode and PID (or session/virtual circuit id) of first process to open the file private SharingMode m_sharedAccess = SharingMode.ALL; private long m_pid = -1L; // File lock list, allocated once there are active locks on this file private FileLockList m_lockList; // Oplock details private OpLockDetails m_oplock; // Retention period expiry date/time private long m_retainUntil = -1L; // File timestamps updated only whilst file is open private long m_accessDate; private long m_modifyDate; private long m_changeDate; // File size and allocation size private long m_fileSize = -1; private long m_allocSize; /** * Default constructor */ public FileState() { } /** * Class constructor * * @param fname String * @param caseSensitive boolean */ public FileState(String fname, boolean caseSensitive) { // Normalize the file path setPath(fname, caseSensitive); setExpiryTime(System.currentTimeMillis() + DefTimeout); // Set the file/folder status m_fileStatus = FileStatus.Unknown; } /** * Class constructor * * @param fname String * @param status FileStatus * @param caseSensitive boolean */ public FileState(String fname, FileStatus status, boolean caseSensitive) { // Normalize the file path setPath(fname, caseSensitive); setExpiryTime(System.currentTimeMillis() + DefTimeout); // Set the file/folder status m_fileStatus = status; } /** * Return the file name/path * * @return String */ public final String getPath() { return m_path; } /** * Return the file exists state * * @return boolean */ public final boolean fileExists() { if (m_fileStatus == FileStatus.FileExists || m_fileStatus == FileStatus.DirectoryExists) return true; return false; } /** * Return the file status * * @return FileStatus */ public final FileStatus getFileStatus() { return m_fileStatus; } /** * Return the directory state * * @return boolean */ public final boolean isDirectory() { return m_fileStatus == FileStatus.DirectoryExists ? true : false; } /** * Return the file open count * * @return int */ public int getOpenCount() { return m_openCount; } /** * Get the file id * * @return int */ public abstract int getFileId(); /** * Return the shared access mode * * @return SharingMode */ public final SharingMode getSharedAccess() { return m_sharedAccess; } /** * Return the PID of the first process to open the file, or -1 if the file is not open * * @return long */ public final long getProcessId() { return m_pid; } /** * Return the file data status * * @return DataStatus */ public abstract DataStatus getDataStatus(); /** * 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; } /** * Return the active file locks list * * @return FileLockList */ public final FileLockList getLockList() { return m_lockList; } /** * Check if this file state does not expire * * @return boolean */ public final boolean isPermanentState() { return m_tmo == NoTimeout ? true : false; } /** * Check if the file/folder is under retention * * @return boolean */ public final boolean hasActiveRetentionPeriod() { if (m_retainUntil == -1L) return false; return System.currentTimeMillis() < m_retainUntil ? true : false; } /** * Get the retention period expiry date/time for the file/folder * * @return long */ public final long getRetentionExpiryDateTime() { return m_retainUntil; } /** * Determine if the file/folder exists * * @return boolen */ public final boolean exists() { if (m_fileStatus == FileStatus.FileExists || m_fileStatus == FileStatus.DirectoryExists) return true; return 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.READ_WRITE && params.getAccessMode() == SharingMode.READ_WRITE.intValue()) return true; else if (getSharedAccess().hasRead() && params.isReadOnlyAccess()) return true; else if (getSharedAccess().hasWrite() && params.isWriteOnlyAccess()) return true; // Sharing violation, do not allow the file open return false; } /** * Increment the file open count * * @return int */ public synchronized int incrementOpenCount() { return ++m_openCount; } /** * Decrement the file open count * * @return int */ public synchronized int decrementOpenCount() { if (m_openCount > 0) m_openCount--; 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; } /** * Set the file status * * @param status FileStatus */ public void setFileStatus(FileStatus status) { setFileStatus(status, ChangeReason.None); } /** * Set the file status * * @param status FileStatus * @param reason ChangeReason */ public void setFileStatus(FileStatus status, ChangeReason reason) { m_fileStatus = status; } /** * Set the file identifier * * @param id int */ public abstract void setFileId(int id); /** * Set the file state expiry time * * @param expire long */ public void setExpiryTime(long expire) { m_tmo = expire; } /** * Set the retention period expiry date/time * * @param expires long */ public void setRetentionExpiryDateTime(long expires) { m_retainUntil = expires; } /** * Set the shared access mode, from the first file open * * @param mode SharingMode */ public void setSharedAccess(SharingMode mode) { if (getOpenCount() == 0) m_sharedAccess = mode; } /** * Set the file data status * * @param sts DataStatus */ public abstract void setDataStatus(DataStatus sts); /** * Add an attribute to the file state * * @param name String * @param attr Object */ public final void addAttribute(String name, Object attr) { HashMap stateAttrs = getAttributeMap(true); if (stateAttrs != null) stateAttrs.put(name, attr); } /** * Find an attribute * * @param name String * @return Object */ public final Object findAttribute(String name) { HashMap stateAttrs = getAttributeMap(true); Object attrObj = null; if (stateAttrs != null) attrObj = stateAttrs.get(name); return attrObj; } /** * Return the count of attributes on this file state * * @return int */ public final int numberOfAttributes() { HashMap stateAttrs = getAttributeMap(false); if (stateAttrs != null) return stateAttrs.size(); return 0; } /** * Remove an attribute from the file state * * @param name String * @return Object */ public final Object removeAttribute(String name) { HashMap stateAttrs = getAttributeMap(true); Object attrObj = null; if (stateAttrs != null) attrObj = stateAttrs.remove(name); return attrObj; } /** * Remove all attributes from the file state */ public final void removeAllAttributes() { HashMap stateAttrs = getAttributeMap(false); if (stateAttrs != null) stateAttrs.clear(); } /** * Return the map of additional attribute objects attached to this file state, and * optionally create the map if it does not exist * * @param createMap boolean * @return HashMap */ protected abstract HashMap getAttributeMap(boolean createMap); /** * Set the file path * * @param path String * @param caseSensitive boolean */ public final void setPath(String path, boolean caseSensitive) { // Split the path into directories and file name, only uppercase the directories to normalize // the path. m_path = normalizePath(path, caseSensitive); } /** * Set the file path, using a normalized path, no need to normalize * * @param path String */ public final void setPathInternal(String path) { m_path = path; } /** * Set the PID of the process opening the file * * @param pid int */ public void setProcessId(int pid) { if (getOpenCount() == 0) m_pid = pid; } /** * Set the PID of the process opening the file * * @param pid long */ public void setProcessId(long pid) { if (getOpenCount() == 0) m_pid = pid; } /** * 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 * @throws LockConflictException Lock conflicts with an existing lock */ public 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 * @throws NotLockedException Lock does not exist */ public 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 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 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 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 boolean hasOpLock() { return m_oplock != null ? true : false; } /** * Return the oplock details * * @return OpLockDetails */ public OpLockDetails getOpLock() { return m_oplock; } /** * Set the oplock for this file * * @param oplock OpLockDetails * @throws ExistingOpLockException If there is an active oplock on this file */ public synchronized void setOpLock(OpLockDetails oplock) throws ExistingOpLockException { if (m_oplock == null) m_oplock = oplock; else throw new ExistingOpLockException(); } /** * Clear the oplock */ public synchronized void clearOpLock() { m_oplock = null; } /** * Determine if a folder has pseudo files associated with it * * @return boolean */ public boolean hasPseudoFiles() { PseudoFileList pseudoList = getPseudoFileList(false); if (pseudoList != null) return pseudoList.numberOfFiles() > 0; return false; } /** * Return the pseudo file list * * @return PseudoFileList */ public PseudoFileList getPseudoFileList() { return getPseudoFileList(false); } /** * Return the pseudo file list, optionally create a new list * * @param createList boolean * @return PseudoFileList */ protected abstract PseudoFileList getPseudoFileList(boolean createList); /** * Add a pseudo file to this folder * * @param pfile PseudoFile */ public final void addPseudoFile(PseudoFile pfile) { PseudoFileList pseudoList = getPseudoFileList(true); if (pseudoList != null) pseudoList.addFile(pfile); } /** * 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 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 void updateChangeDateTime() { updateChangeDateTime(System.currentTimeMillis()); } /** * Update the change date/time * * @param changeTime long */ public void updateChangeDateTime(long changeTime) { m_changeDate = changeTime; } /** * 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 void updateModifyDateTime() { long timeNow = System.currentTimeMillis(); updateModifyDateTime(timeNow); m_accessDate = timeNow; } /** * Update the modify date/time * * @param modTime long */ public void updateModifyDateTime(long modTime) { m_modifyDate = modTime; } /** * Check if there is a filesystem object * * @return boolean */ public final boolean hasFilesystemObject() { return getFilesystemObject() != null ? true : false; } /** * Return the filesystem object * * @return Object */ public abstract Object getFilesystemObject(); /** * Set the filesystem object * * @param filesysObj Object */ public abstract void setFilesystemObject(Object filesysObj); /** * Check if this is a copy file state, or the master file state object * * @return boolean */ public abstract boolean isCopyState(); /** * Check if the allocation size has been set * * @return boolean */ public final boolean hasFileSize() { return m_fileSize != -1L ? true : false; } /** * Return the file size * * @return long */ public final long getFileSize() { return m_fileSize; } /** * Set the file size * * @param fileSize long */ public void setFileSize(long fileSize) { m_fileSize = fileSize; } /** * Check if the allocation size has been set * * @return boolean */ public final boolean hasAllocationSize() { return m_allocSize > 0 ? true : false; } /** * Return the allocation size * * @return long */ public final long getAllocationSize() { return m_allocSize; } /** * Set the allocation size * * @param allocSize long */ public void setAllocationSize(long allocSize) { m_allocSize = allocSize; } /** * Set the file open count * * @param count int */ public void setOpenCount(int count) { m_openCount = count; } /** * Check if there is a data update in progress for this file * * @return boolean */ public boolean hasDataUpdateInProgress() { // No update in progress, not required for the default implementation return false; } /** * 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 normalizePath(path, true); } /** * Normalize the path to uppercase the directory names and keep the case of the file name. * * @param path String * @param caseSensitive boolean * @return String */ public final static String normalizePath(String path, boolean caseSensitive) { // Check if the file state names should be case sensitive, if not then just uppercase the whole // path String normPath = path; if (caseSensitive == true) { // Split the path into directories and file name, only uppercase the directories to normalize // the path. if (path.length() > 3) { // Split the path to separate the folders/file name int pos = path.lastIndexOf(FileName.DOS_SEPERATOR); if (pos != -1) { // Get the path and file name parts, normalize the path String pathPart = upperCaseAToZ(path.substring(0, pos)); String namePart = path.substring(pos); // Rebuild the path string normPath = pathPart + namePart; } } } else { // Uppercase the whole path normPath = upperCaseAToZ(path); } // Return the normalized path return normPath; } /** * Uppercase a-z characters only, leave any multi-national characters as is * * @param path String * @return String */ protected static final String upperCaseAToZ(String path) { StringBuilder pathStr = new StringBuilder(path); for (int i = 0; i < pathStr.length(); i++) { char curChar = pathStr.charAt(i); if (Character.isLowerCase(curChar)) pathStr.setCharAt(i, Character.toUpperCase(curChar)); } return pathStr.toString(); } /** * Dump the attributes that are attached to the file state */ public final void DumpAttributes() { // Check if there are any attributes HashMap stateAttrs = getAttributeMap(false); if (stateAttrs != null) { // Enumerate the available attribute objects Iterator names = stateAttrs.keySet().iterator(); while (names.hasNext()) { // Get the current attribute name String name = names.next(); // Get the associated attribute object Object attrib = stateAttrs.get(name); // Output the attribute details Debug.println("++ " + name + " : " + attrib); } } else Debug.println("++ No Attributes"); } /** * 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().name()); str.append(":Opn="); str.append(getOpenCount()); if (getOpenCount() > 0) { str.append("(shr="); str.append(getSharedAccess().name()); str.append(",pid=0x"); str.append(Long.toHexString(getProcessId())); str.append(")"); } str.append(",Fid="); str.append(getFileId()); str.append(",Expire="); str.append(getSecondsToExpire(System.currentTimeMillis())); str.append(",Sts="); str.append(getDataStatus().name()); str.append(",Locks="); str.append(numberOfLocks()); if (hasOpLock()) { str.append(",OpLock="); str.append(getOpLock()); } str.append("]"); return str.toString(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy