commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mt...@apache.org
Subject svn commit: r823572 - in /commons/sandbox/runtime/trunk/src/main: java/org/apache/commons/runtime/exception/ java/org/apache/commons/runtime/io/ native/os/unix/
Date Fri, 09 Oct 2009 14:48:22 GMT
Author: mturk
Date: Fri Oct  9 14:48:22 2009
New Revision: 823572

URL: http://svn.apache.org/viewvc?rev=823572&view=rev
Log:
Add FileLock class similar to NIO FileLock

Added:
    commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/exception/OverlappingFileLockException.java
  (with props)
    commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/FileLock.java
  (with props)
Modified:
    commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/File.java
    commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/FileInstance.java
    commons/sandbox/runtime/trunk/src/main/native/os/unix/fsysio.c

Added: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/exception/OverlappingFileLockException.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/exception/OverlappingFileLockException.java?rev=823572&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/exception/OverlappingFileLockException.java
(added)
+++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/exception/OverlappingFileLockException.java
Fri Oct  9 14:48:22 2009
@@ -0,0 +1,42 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.apache.commons.runtime.exception;
+
+/**
+ * An {@code OverlappingFileLockException} is thrown when attempting to acquire
+ * a lock that overlaps an existing or pending lock held by this process.
+ */
+public class OverlappingFileLockException extends IllegalStateException
+{
+
+    /**
+     * Constructs a {@code OverlappingFileLockException}.
+     */
+    public OverlappingFileLockException()
+    {
+        super();
+    }
+
+    /**
+     * Constructs a {@code OverlappingFileLockException}.
+     */
+    public OverlappingFileLockException(String msg)
+    {
+        super(msg);
+    }
+
+}

Propchange: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/exception/OverlappingFileLockException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/File.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/File.java?rev=823572&r1=823571&r2=823572&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/File.java (original)
+++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/File.java Fri
Oct  9 14:48:22 2009
@@ -16,6 +16,7 @@
 
 package org.apache.commons.runtime.io;
 
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.net.URI;
 import java.util.EnumSet;
@@ -527,6 +528,47 @@
     }
 
     /**
+     * Create new temporary {@code FileInstance} inide {@code path}.
+     *
+     * @param path directory abstract path.
+     * @param prefix temporary file prefix.
+     * @param sufix temporary file sufix.
+     * @param preserve if {@code true} do not delete file on {@code close}.
+     *
+     * @return new temporary {@code FileInstance}.
+     */
+    public static FileInstance createTempFile(File path, String prefix,
+                                              String sufix, boolean preserve)
+        throws FileNotFoundException, IOException, IllegalArgumentException,
+               SecurityException
+    {
+        if (prefix == null) {
+            throw new IllegalArgumentException();
+        }
+        Descriptor fd = FileWrapper.mktemp(path, prefix, sufix, preserve);
+        return new FileInstance(fd);
+    }
+
+    /**
+     * Create new temporary {@code FileInstance} inside current directory.
+     *
+     * @param prefix file prefix.
+     *
+     * @return new temporary {@code FileInstance}.
+     */
+    public static FileInstance createTempFile(String prefix, String sufix,
+                                              boolean preserve)
+        throws FileNotFoundException, IOException, IllegalArgumentException,
+               SecurityException
+    {
+        if (prefix == null) {
+            throw new IllegalArgumentException();
+        }
+        Descriptor fd = FileWrapper.mktemp(prefix, sufix, preserve);
+        return new FileInstance(fd);
+    }
+
+    /**
      * Return target pathname of this abstract {@code File} instance.
      *
      * @return Pathname this {@code File} points to.

Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/FileInstance.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/FileInstance.java?rev=823572&r1=823571&r2=823572&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/FileInstance.java
(original)
+++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/FileInstance.java
Fri Oct  9 14:48:22 2009
@@ -21,6 +21,7 @@
 import org.apache.commons.runtime.exception.ClosedDescriptorException;
 import org.apache.commons.runtime.exception.AsyncClosedDescriptorException;
 import org.apache.commons.runtime.exception.InvalidDescriptorException;
+import org.apache.commons.runtime.exception.OverlappingFileLockException;
 import org.apache.commons.runtime.exception.TimeoutException;
 import org.apache.commons.runtime.util.StringManager;
 import java.io.Closeable;
@@ -29,7 +30,9 @@
 import java.io.IOException;
 import java.io.SyncFailedException;
 import java.nio.ByteBuffer;
+import java.util.Enumeration;
 import java.util.EnumSet;
+import java.util.Vector;
 
 /**
  * Allows reading from and writing to a file in a random-access manner.
@@ -47,6 +50,10 @@
     /* File's object lock
      */
     private Object sync = new Object();
+    /*
+     * List of all lock regions to this file.
+     */
+    private Vector<FileLock> locks = new Vector<FileLock>(2);
 
     /**
      * Return the {@link Descriptor} accosicated with this file.
@@ -364,8 +371,34 @@
         return FileWrapper.name(fd);
     }
 
+    private boolean regionOverlaps(long offset, long length)
+    {
+        for (Enumeration<FileLock> e = locks.elements(); e.hasMoreElements();) {
+            try {
+                FileLock lck = e.nextElement();
+                /* Check if we already have the valid lock
+                 * for the requested region.
+                 */
+                if (lck.isValid()) {
+                    if (lck.overlaps(offset, length)) {
+                        return true;
+                    }
+                }
+                else {
+                    locks.remove(lck);
+                }
+            } catch (Throwable te) {
+            }
+        }
+        return false;
+    }
+
     /**
      * Lock the entire file.
+     * <p>
+     * To simulate the {@link java.nio.channels.FileChannel#tryLock} use
+     * the {@link FileLockType#NONBLOCK} type.
+     * </p>
      *
      * @param type
      *          {@code FileLockType} to acquire.
@@ -379,12 +412,24 @@
      *          If lock operation times out.
      * @throws IOException
      *          If some other I/O error occurs.
-     * @see #unlock
+     * @see FileLock#release
      */
-    public void lock(EnumSet<FileLockType> type)
-        throws IOException
+    public FileLock lock(EnumSet<FileLockType> type)
+        throws OverlappingFileLockException, IOException
     {
+        if (regionOverlaps(0L, -1L)) {
+            /* We already have at least one lock, so we cannot
+             * lock the entire file.
+             */
+            throw new OverlappingFileLockException();
+        }
+
         FileWrapper.lock(fd, type);
+        FileLock lock = new FileLock(fd, type);
+        /* Add the FileLock to the list of locks
+         */
+        locks.add(lock);
+        return lock;
     }
 
     /**
@@ -418,67 +463,26 @@
      *          If read operation times out.
      * @throws IOException
      *          If some other I/O error occurs.
-     * @see #unlock
+     * @see FileLock#release
      */
-    public void lock(EnumSet<FileLockType> type, long offset, long length)
-        throws IllegalArgumentException, IOException
+    public FileLock lock(EnumSet<FileLockType> type, long offset, long length)
+        throws OverlappingFileLockException, IllegalArgumentException,
+               IOException
     {
         if (offset < 0 || length < 0 || offset < length) {
             // unlock position is negative
             throw new IllegalArgumentException();
         }
-        FileWrapper.lock(fd, type, offset, length);
-    }
-
-    /**
-     * Unlock the file.
-     *
-     * @throws ClosedDescriptorException
-     *          If this file is closed.
-     * @throws AsyncClosedDescriptorException
-     *          If another thread closes this file while the unlock
-     *          operation is in progress.
-     * @throws TimeoutException
-     *          If unlock operation times out.
-     * @throws IOException
-     *          If some other I/O error occurs.
-     * @see #lock
-     */
-    public void unlock()
-        throws IOException
-    {
-        FileWrapper.unlock(fd);
-    }
-
-    /**
-     * Unlock the file region.
-     *
-     * @param offset
-     *          The offset in bytes where the locked region begins.
-     * @param length
-     *          The length of the byte region to be unlocked.
-     *
-     * @throws IllegalArgumentException
-     *          If {@code offset < 0} or {@code length < 0}.
-     * @throws ClosedDescriptorException
-     *          If this file is closed.
-     * @throws AsyncClosedDescriptorException
-     *          If another thread closes this file while the unlock
-     *          operation is in progress.
-     * @throws TimeoutException
-     *          If read operation times out.
-     * @throws IOException
-     *          If some other I/O error occurs.
-     * @see #lock
-     */
-    public void unlock(long offset, long length)
-        throws IllegalArgumentException, IOException
-    {
-        if (offset < 0 || length < 0 || offset < length) {
-            // unlock position is negative
-            throw new IllegalArgumentException();
+        if (regionOverlaps(offset, length)) {
+            /* We already have locked overlapping region.
+             */
+            throw new OverlappingFileLockException();
         }
-        FileWrapper.unlock(fd, offset, length);
+        FileLock lock = new FileLock(fd, type, offset, length);
+        /* Add the FileLock to the list of locks
+         */
+        locks.add(lock);
+        return lock;
     }
 
     /**

Added: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/FileLock.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/FileLock.java?rev=823572&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/FileLock.java
(added)
+++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/FileLock.java
Fri Oct  9 14:48:22 2009
@@ -0,0 +1,246 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.apache.commons.runtime.io;
+
+import org.apache.commons.runtime.Descriptor;
+import org.apache.commons.runtime.exception.ClosedDescriptorException;
+import org.apache.commons.runtime.exception.AsyncClosedDescriptorException;
+import org.apache.commons.runtime.exception.InvalidDescriptorException;
+import org.apache.commons.runtime.exception.TimeoutException;
+import java.io.IOException;
+import java.util.EnumSet;
+
+/**
+ * A {@code FileLock} represents a locked region of a file.
+ * <p>
+ * Locks have certain properties that enable collaborating processes to avoid
+ * the lost update problem or reading inconsistent data. Logically, a file lock
+ * can be <em>exclusive</em> or <em>shared</em>. Multiple processes
can hold
+ * shared locks on the same region of a file, but only a single process can hold
+ * an exclusive lock on a given region of a file and no other process can
+ * simultaneously hold a shared lock overlapping the exclusive lock. An
+ * application can determine whether a {@code FileLock} is shared or exclusive
+ * via the {@code isShared()} method.
+ * <p>
+ * Locks held by a particular process cannot overlap one another. Applications
+ * can determine whether a proposed lock will overlap by using the {@code
+ * overlaps(long, long)}) method. Locks held in other processes may overlap
+ * locks held in this process. Locks are shared amongst all threads in the
+ * acquiring process, and are therefore unsuitable for intra-process
+ * synchronization.
+ * <p>
+ * Once a lock is acquired, it is immutable in all its state except {@code
+ * isValid()}. The lock will initially be valid, but may be rendered invalid by
+ * explicit removal of the lock, using {@code release()}, or implicitly by
+ * closing the channel or exiting the process (terminating the virtual machine).
+ * <h3>Platform dependencies</h3>
+ * <p>
+ * Locks are intended to be true platform operating system file locks, and
+ * therefore locks held by the virtual machine process will be visible to other
+ * operating system processes.
+ * <p>
+ * The characteristics of the underlying operating system locks will show
+ * through in the Java implementation. For example, some platforms' locks are
+ * 'mandatory' -- meaning the operating system enforces the locks on processes
+ * that attempt to access locked regions of files; whereas other platforms'
+ * locks are only 'advisory' -- meaning that processes are required to
+ * collaborate to ensure locks are acquired and there is a potential for
+ * processes to not play well. To be on the safe side, it is best to assume that
+ * the platform is adopting advisory locks and always acquire shared locks when
+ * reading a region of a file.
+ * <p>
+ * On some platforms, the presence of a lock will prevent the file from being
+ * memory-mapped. On some platforms, closing a channel on a given file handle
+ * will release all the locks held on that file -- even if there are other
+ * channels open on the same file; their locks will also be released. The safe
+ * option here is to ensure that you only acquire locks on a single channel for
+ * a particular file and that becomes the synchronization point.
+ * <p>
+ * Further care should be exercised when locking files maintained on network
+ * file systems, since they often have further limitations.
+ */
+public class FileLock
+{
+
+    /*
+     * The lock starting position.
+     */
+    private final long  offset;
+    /*
+     * The lock length in bytes.
+     */
+    private final long  length;
+    /*
+     * File Descriptor for this lock.
+     */
+    private Descriptor  fd;
+    /*
+     * FileLockType flags.
+     */
+    private EnumSet<FileLockType> mode;
+
+    /**
+     * Create new {@code FileLock} that locks the entire file.
+     *
+     * @param fd
+     *          the file {@code Descriptor} this lock is attached to.
+     * @param mode
+     *          file lock mode.
+     */
+    protected FileLock(Descriptor fd, EnumSet<FileLockType> mode)
+    {
+        this.fd   = fd;
+        this.mode = mode;
+        offset    =  0;
+        length    = -1;
+    }
+
+    /**
+     * Create new {@code FileLock} that locks the region of file.
+     *
+     * @param fd
+     *          the file {@code Descriptor} this lock is attached to.
+     * @param mode
+     *          file lock mode.
+     * @param start
+     *          the starting position for the lock.
+     * @param len
+     *          the length of the lock.
+     */
+    protected FileLock(Descriptor fd, EnumSet<FileLockType> mode,
+                       long start, long len)
+    {
+        this.fd   = fd;
+        this.mode = mode;
+        offset    = start;
+        length    = len;
+    }
+
+    /**
+     * Indicates if the receiver's lock region overlaps the region described
+     * in the parameter list.
+     *
+     * @param start
+     *          the starting position for the comparative lock.
+     * @param len
+     *          the length of the comparative lock.
+     * @return {@code true} if there is an overlap, {@code false} otherwise.
+     */
+    public final boolean overlaps(long start, long len)
+    {
+        /*
+         * Negative length means the entire file
+         * so it will always overlap with another lock
+         */
+        if (length < 0 || len < 0)
+            return true;
+        final long end = offset + length - 1;
+        final long siz = start  + len    - 1;
+        if (end < start || offset > siz) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Indicates whether this lock is a valid file lock. The lock is
+     * valid unless the underlying Descriptor has been closed or it has been
+     * explicitly released.
+     *
+     * @return {@code true} if the lock is valid, {@code false} otherwise.
+     */
+    public boolean isValid()
+    {
+        if (fd == null)
+            return false;
+        else
+            return fd.valid();
+    }
+
+    /**
+     * Returns the lock's starting position in the file.
+     *
+     * @return the lock position.
+     */
+    public final long position()
+    {
+        return offset;
+    }
+
+    /**
+     * Returns the length of the file lock in bytes.
+     *
+     * @return the size of the file lock in bytes.
+     */
+    public final long size()
+    {
+        return length;
+    }
+
+    /**
+     * Indicates if the file lock is shared with other processes
+     * or if it is exclusive.
+     *
+     * @return {@code true} if the lock is a shared lock,
+     *          {@code false} if it is exclusive.
+     */
+    public boolean isShared()
+    {
+        return mode.contains(FileLockType.SHARED);
+    }
+
+    /**
+     * Indicates if the file lock is blocking or non-blocking.
+     *
+     * @return {@code true} if the lock is blocking lock,
+     *          {@code false} if it is non-blocking.
+     */
+    public boolean isBlocking()
+    {
+        return !mode.contains(FileLockType.NONBLOCK);
+    }
+
+    /**
+     * Releases this particular lock on the file.
+     * If the lock is invalid then this method has no effect.
+     * Once released, the lock becomes invalid.
+     *
+     * @throws ClosedDescriptorException
+     *          If this file is closed.
+     * @throws AsyncClosedDescriptorException
+     *          If another thread closes this file while the unlock
+     *          operation is in progress.
+     * @throws TimeoutException
+     *          If unlock operation times out.
+     * @throws IOException
+     *          If some other I/O error occurs.
+     */
+    public void release()
+        throws IOException
+    {
+        if (fd == null) {
+            // Already released
+            return;
+        }
+        if (length < 0)
+            FileWrapper.unlock(fd);
+        else
+            FileWrapper.unlock(fd, offset, length);
+        fd = null;
+    }
+
+}

Propchange: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/FileLock.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: commons/sandbox/runtime/trunk/src/main/native/os/unix/fsysio.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/fsysio.c?rev=823572&r1=823571&r2=823572&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/unix/fsysio.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/unix/fsysio.c Fri Oct  9 14:48:22 2009
@@ -760,7 +760,7 @@
             rc = ACR_TIMEUP;
     }
     if (rd == 0) {
-        ACR_DescriptorSetErrEx(_E, f->descriptor, 0);
+        ACR_DescriptorSetErrEx(_E, f->descriptor, ACR_EOF);
         f->eof = 1;
         return  -1;
     }



Mime
View raw message