src/java.base/share/classes/sun/nio/ch/FileLockTable.java
changeset 48748 4d716bc7ed54
parent 48738 cdd3239a2a61
equal deleted inserted replaced
48747:f7aed48bbbdc 48748:4d716bc7ed54
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package sun.nio.ch;
    26 package sun.nio.ch;
    27 
    27 
    28 import java.nio.channels.*;
       
    29 import java.util.*;
       
    30 import java.util.concurrent.ConcurrentHashMap;
       
    31 import java.lang.ref.*;
       
    32 import java.io.FileDescriptor;
    28 import java.io.FileDescriptor;
    33 import java.io.IOException;
    29 import java.io.IOException;
    34 
    30 import java.lang.ref.ReferenceQueue;
    35 abstract class FileLockTable {
    31 import java.lang.ref.WeakReference;
    36     protected FileLockTable() {
    32 import java.nio.channels.Channel;
    37     }
    33 import java.nio.channels.FileLock;
    38 
    34 import java.nio.channels.OverlappingFileLockException;
    39     /**
    35 import java.util.ArrayList;
    40      * Creates and returns a file lock table for a channel that is connected to
    36 import java.util.HashSet;
    41      * the a system-wide map of all file locks for the Java virtual machine.
    37 import java.util.List;
    42      */
    38 import java.util.Set;
    43     public static FileLockTable newSharedFileLockTable(Channel channel,
    39 import java.util.concurrent.ConcurrentHashMap;
    44                                                        FileDescriptor fd)
       
    45         throws IOException
       
    46     {
       
    47         return new SharedFileLockTable(channel, fd);
       
    48     }
       
    49 
       
    50     /**
       
    51      * Adds a file lock to the table.
       
    52      *
       
    53      * @throws OverlappingFileLockException if the file lock overlaps
       
    54      *         with an existing file lock in the table
       
    55      */
       
    56     public abstract void add(FileLock fl) throws OverlappingFileLockException;
       
    57 
       
    58     /**
       
    59      * Remove an existing file lock from the table.
       
    60      */
       
    61     public abstract void remove(FileLock fl);
       
    62 
       
    63     /**
       
    64      * Removes all file locks from the table.
       
    65      *
       
    66      * @return  The list of file locks removed
       
    67      */
       
    68     public abstract List<FileLock> removeAll();
       
    69 
       
    70     /**
       
    71      * Replaces an existing file lock in the table.
       
    72      */
       
    73     public abstract void replace(FileLock fl1, FileLock fl2);
       
    74 }
       
    75 
       
    76 
    40 
    77 /**
    41 /**
    78  * A file lock table that is over a system-wide map of all file locks.
    42  * A file lock table that is over a system-wide map of all file locks.
    79  */
    43  */
    80 class SharedFileLockTable extends FileLockTable {
    44 class FileLockTable {
    81 
       
    82     /**
    45     /**
    83      * A weak reference to a FileLock.
    46      * A weak reference to a FileLock.
    84      * <p>
    47      * <p>
    85      * SharedFileLockTable uses a list of file lock references to avoid keeping the
    48      * FileLockTable uses a list of file lock references to avoid keeping the
    86      * FileLock (and FileChannel) alive.
    49      * FileLock (and FileChannel) alive.
    87      */
    50      */
    88     private static class FileLockReference extends WeakReference<FileLock> {
    51     private static class FileLockReference extends WeakReference<FileLock> {
    89         private FileKey fileKey;
    52         private FileKey fileKey;
    90 
    53 
   116     private final FileKey fileKey;
    79     private final FileKey fileKey;
   117 
    80 
   118     // Locks obtained for this channel
    81     // Locks obtained for this channel
   119     private final Set<FileLock> locks;
    82     private final Set<FileLock> locks;
   120 
    83 
   121     SharedFileLockTable(Channel channel, FileDescriptor fd) throws IOException {
    84     /**
       
    85      * Creates a file lock table for a channel that is connected to the
       
    86      * system-wide map of all file locks for the Java virtual machine.
       
    87      */
       
    88     FileLockTable(Channel channel, FileDescriptor fd) throws IOException {
   122         this.channel = channel;
    89         this.channel = channel;
   123         this.fileKey = FileKey.create(fd);
    90         this.fileKey = FileKey.create(fd);
   124         this.locks = new HashSet<FileLock>();
    91         this.locks = new HashSet<FileLock>();
   125     }
    92     }
   126 
    93 
   127     @Override
    94     void add(FileLock fl) throws OverlappingFileLockException {
   128     public void add(FileLock fl) throws OverlappingFileLockException {
       
   129         List<FileLockReference> list = lockMap.get(fileKey);
    95         List<FileLockReference> list = lockMap.get(fileKey);
   130 
    96 
   131         for (;;) {
    97         for (;;) {
   132 
    98 
   133             // The key isn't in the map so we try to create it atomically
    99             // The key isn't in the map so we try to create it atomically
   174         if (list.isEmpty()) {
   140         if (list.isEmpty()) {
   175             lockMap.remove(fk);
   141             lockMap.remove(fk);
   176         }
   142         }
   177     }
   143     }
   178 
   144 
   179     @Override
   145     void remove(FileLock fl) {
   180     public void remove(FileLock fl) {
       
   181         assert fl != null;
   146         assert fl != null;
   182 
   147 
   183         // the lock must exist so the list of locks must be present
   148         // the lock must exist so the list of locks must be present
   184         List<FileLockReference> list = lockMap.get(fileKey);
   149         List<FileLockReference> list = lockMap.get(fileKey);
   185         if (list == null) return;
   150         if (list == null) return;
   199                 index++;
   164                 index++;
   200             }
   165             }
   201         }
   166         }
   202     }
   167     }
   203 
   168 
   204     @Override
   169     List<FileLock> removeAll() {
   205     public List<FileLock> removeAll() {
       
   206         List<FileLock> result = new ArrayList<FileLock>();
   170         List<FileLock> result = new ArrayList<FileLock>();
   207         List<FileLockReference> list = lockMap.get(fileKey);
   171         List<FileLockReference> list = lockMap.get(fileKey);
   208         if (list != null) {
   172         if (list != null) {
   209             synchronized (list) {
   173             synchronized (list) {
   210                 int index = 0;
   174                 int index = 0;
   232             }
   196             }
   233         }
   197         }
   234         return result;
   198         return result;
   235     }
   199     }
   236 
   200 
   237     @Override
   201     void replace(FileLock fromLock, FileLock toLock) {
   238     public void replace(FileLock fromLock, FileLock toLock) {
       
   239         // the lock must exist so there must be a list
   202         // the lock must exist so there must be a list
   240         List<FileLockReference> list = lockMap.get(fileKey);
   203         List<FileLockReference> list = lockMap.get(fileKey);
   241         assert list != null;
   204         assert list != null;
   242 
   205 
   243         synchronized (list) {
   206         synchronized (list) {