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 |