< prev index next >

src/java.base/share/classes/sun/nio/ch/FileLockTable.java

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -84,22 +84,43 @@
      * <p>
      * SharedFileLockTable uses a list of file lock references to avoid keeping the
      * FileLock (and FileChannel) alive.
      */
     private static class FileLockReference extends WeakReference<FileLock> {
-        private FileKey fileKey;
+        private final FileKey fileKey;
+        final long position;
+        final long size;
+        private volatile boolean invalid;
 
         FileLockReference(FileLock referent,
                           ReferenceQueue<FileLock> queue,
                           FileKey key) {
             super(referent, queue);
             this.fileKey = key;
+            this.position = referent.position();
+            this.size = referent.size();
         }
 
         FileKey fileKey() {
             return fileKey;
         }
+
+        void invalidate() {
+            invalid = true;
+        }
+
+        boolean isValid() {
+            return !invalid;
+        }
+
+        boolean overlaps(long position, long size) {
+            if (position + size <= this.position)
+                return false;               // That is below this
+            if (this.position + this.size <= position)
+                return false;               // This is below that
+            return true;
+        }
     }
 
     // The system-wide map is a ConcurrentHashMap that is keyed on the FileKey.
     // The map value is a list of file locks represented by FileLockReferences.
     // All access to the list must be synchronized on the list.

@@ -184,10 +205,11 @@
                 FileLockReference ref = list.get(index);
                 FileLock lock = ref.get();
                 if (lock == fl) {
                     assert (lock != null) && (lock.acquiredBy() == channel);
                     ref.clear();
+                    ref.invalidate();
                     list.remove(index);
                     break;
                 }
                 index++;
             }

@@ -207,10 +229,11 @@
 
                     // remove locks obtained by this channel
                     if (lock != null && lock.acquiredBy() == channel) {
                         // remove the lock from the list
                         ref.clear();
+                        ref.invalidate();
                         list.remove(index);
 
                         // add to result
                         result.add(lock);
                     } else {

@@ -249,11 +272,11 @@
         throws OverlappingFileLockException
     {
         assert Thread.holdsLock(list);
         for (FileLockReference ref: list) {
             FileLock fl = ref.get();
-            if (fl != null && fl.overlaps(position, size))
+            if ((fl != null || ref.isValid()) && ref.overlaps(position, size))
                 throw new OverlappingFileLockException();
         }
     }
 
     // Process the reference queue

@@ -262,11 +285,13 @@
         while ((ref = (FileLockReference)queue.poll()) != null) {
             FileKey fk = ref.fileKey();
             List<FileLockReference> list = lockMap.get(fk);
             if (list != null) {
                 synchronized (list) {
+                    if (!ref.isValid()) {
                     list.remove(ref);
+                    }
                     removeKeyIfEmpty(fk, list);
                 }
             }
         }
     }
< prev index next >