/* * Copyright (C) 2006-2008 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.jlan.server.filesys.loader; import java.io.File; import java.io.IOException; import org.alfresco.jlan.debug.Debug; /** * File Segment Info Class * * <p>Contains the details of a file segment that may be shared by many users/sessions. * * @author gkspencer */ public class FileSegmentInfo { // Segment load/save status public final static int Initial = 0; public final static int LoadWait = 1; public final static int Loading = 2; public final static int Available = 3; public final static int SaveWait = 4; public final static int Saving = 5; public final static int Saved = 6; public final static int Error = 7; // Flags private static final int Updated = 0x0001; private static final int RequestQueued = 0x0002; private static final int DeleteOnStore = 0x0004; // Segment status strings private static final String[] _statusStr = { "Initial", "LoadWait", "Loading", "Available", "SaveWait", "Saving", "Saved", "Error"}; // Temporary file path private String m_tempFile; // Flags to indicate if this segment has been updated, queued private int m_flags; // Segment status private int m_status = Initial; // Amount of valid data in the file, used to allow reads during data loading private long m_readable; /** * Default constructor */ public FileSegmentInfo() { m_status = Initial; } /** * Class constructor * * @param tempFile String */ public FileSegmentInfo(String tempFile) { m_status = Initial; setTemporaryFile(tempFile); } /** * Return the temporary file path * * @return String */ public final String getTemporaryFile() { return m_tempFile; } /** * Check if the segment has been updated * * @return boolean */ public final boolean isUpdated() { return (m_flags & Updated) != 0 ? true : false; } /** * Check if the segment has a file request queued * * @return boolean */ public final boolean isQueued() { return (m_flags & RequestQueued) != 0 ? true : false; } /** * Check if the file data is available * * @return boolean */ public final boolean isDataAvailable() { if ( hasStatus() >= FileSegmentInfo.Available && hasStatus() < FileSegmentInfo.Error) return true; return false; } /** * Check if the associated temporary file should be deleted once the data store * has completed successfully. * * @return boolean */ public final boolean hasDeleteOnStore() { return (m_flags & DeleteOnStore) != 0 ? true : false; } /** * Delete the temporary file used by the file segment * * @exception IOException */ public final void deleteTemporaryFile() throws IOException { // DEBUG if ( isQueued()) { Debug.println("@@ Delete queued file segment, " + this); Thread.dumpStack(); } // Delete the temporary file used by the file segment File tempFile = new File(getTemporaryFile()); if ( tempFile.exists() && tempFile.delete() == false) { // DEBUG Debug.println("** Failed to delete " + toString() + " **"); // Throw an exception, delete failed throw new IOException("Failed to delete file " + getTemporaryFile()); } } /** * Return the segment status * * @return int */ public final int hasStatus() { return m_status; } /** * Return the temporary file length * * @return long * @exception IOException */ public final long getFileLength() throws IOException { // Get the file length File tempFile = new File(getTemporaryFile()); return tempFile.length(); } /** * Return the readable file data length * * @return long */ public final long getReadableLength() { return m_readable; } /** * Set the readable data length for the file, used during data loading to allow the file to be read before * the file load completes. * * @param readable long */ public final void setReadableLength(long readable) { m_readable = readable; } /** * Set the segment load/update status * * @param sts int */ public synchronized final void setStatus(int sts) { m_status = sts; notifyAll(); } /** * Set the temporary file that is used to hold the local copy of the file data * * @param tempFile String */ public final void setTemporaryFile(String tempFile) { m_tempFile = tempFile; } /** * Set/clear the updated segment flag * * @param sts boolean */ public synchronized final void setUpdated(boolean sts) { setFlag(Updated, sts); } /** * Set/clear the request queued flag * * @param qd boolean */ public synchronized final void setQueued(boolean qd) { setFlag(RequestQueued, qd); } /** * Set the delete on store flag so that the temporary file is deleted as soon as the * data store has completed successfully. */ public final synchronized void setDeleteOnStore() { if ( hasDeleteOnStore() == false) setFlag(DeleteOnStore, true); } /** * Set/clear the specified flag * * @param flag int * @param sts boolean */ protected final synchronized void setFlag(int flag, boolean sts) { boolean state = (m_flags & flag) != 0 ? true : false; if ( state && sts == false) m_flags -= flag; else if ( state == false && sts == true) m_flags += flag; } /** * Wait for another thread to load the file data * * @param tmo long */ public final void waitForData(long tmo) { // Check if the file data has been loaded, if not then wait if ( isDataAvailable() == false) { synchronized ( this) { try { // Wait for file data wait(tmo); } catch ( InterruptedException ex) { } } } } /** * Signal that the file data is available, any threads using the waitForData() method * will return so that the threads can access the file data. * */ public final synchronized void signalDataAvailable() { // Notify any waiting threads that the file data ia available notifyAll(); } /** * Return the file segment details as a string * * @return String */ public String toString() { StringBuffer str = new StringBuffer(); str.append("["); str.append(getTemporaryFile()); str.append(":"); str.append(_statusStr[hasStatus()]); str.append(","); if ( isUpdated()) str.append(",Updated"); if ( isQueued()) str.append(",Queued"); str.append("]"); return str.toString(); } }