< prev index next >

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

Print this page

        

*** 1,7 **** /* ! * Copyright (c) 2005, 2009, 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 --- 1,7 ---- /* ! * 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
*** 23,38 **** * questions. */ package sun.nio.ch; - import java.nio.channels.*; - import java.util.*; - import java.util.concurrent.ConcurrentHashMap; - import java.lang.ref.*; import java.io.FileDescriptor; import java.io.IOException; abstract class FileLockTable { protected FileLockTable() { } --- 23,42 ---- * questions. */ package sun.nio.ch; import java.io.FileDescriptor; import java.io.IOException; + import java.lang.ref.ReferenceQueue; + import java.lang.ref.WeakReference; + import java.nio.channels.Channel; + import java.nio.channels.FileLock; + import java.nio.channels.OverlappingFileLockException; + import java.util.ArrayList; + import java.util.List; + import java.util.concurrent.ConcurrentHashMap; abstract class FileLockTable { protected FileLockTable() { }
*** 83,105 **** * A weak reference to a FileLock. * <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; FileLockReference(FileLock referent, ReferenceQueue<FileLock> queue, FileKey key) { super(referent, queue); this.fileKey = key; } FileKey fileKey() { return fileKey; } } // 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. --- 87,140 ---- * A weak reference to a FileLock. * <p> * SharedFileLockTable uses a list of file lock references to avoid keeping the * FileLock (and FileChannel) alive. */ ! private static class FileLockReference extends WeakReference<FileLock> ! implements FileLockListener { private FileKey fileKey; + // Mirror of FileLock state for use when the lock object is no longer + // weakly reachable but the native lock has not yet been released. + private final long position; + private final long size; + private boolean isLockReleased; + FileLockReference(FileLock referent, ReferenceQueue<FileLock> queue, FileKey key) { super(referent, queue); this.fileKey = key; + this.position = referent.position(); + this.size = referent.size(); + this.isLockReleased = !referent.isValid(); + if (referent instanceof FileLockImpl) { + ((FileLockImpl)referent).setFileLockListener(this); + } } FileKey fileKey() { return fileKey; } + + // FileLockListener implementation + public void invalidate() { + this.isLockReleased = true; + } + + boolean isLockReleased() { + return this.isLockReleased; + } + + // Copy of FileLock.overlaps(long,long) + 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.
*** 211,220 **** --- 246,258 ---- ref.clear(); list.remove(index); // add to result result.add(lock); + } else if (lock == null && !ref.isLockReleased()) { + ref.clear(); + list.remove(index); } else { index++; } }
*** 249,272 **** throws OverlappingFileLockException { assert Thread.holdsLock(list); for (FileLockReference ref: list) { FileLock fl = ref.get(); ! if (fl != null && fl.overlaps(position, size)) throw new OverlappingFileLockException(); } } // Process the reference queue private void removeStaleEntries() { FileLockReference ref; while ((ref = (FileLockReference)queue.poll()) != null) { FileKey fk = ref.fileKey(); List<FileLockReference> list = lockMap.get(fk); if (list != null) { synchronized (list) { list.remove(ref); removeKeyIfEmpty(fk, list); } } } } --- 287,318 ---- throws OverlappingFileLockException { assert Thread.holdsLock(list); for (FileLockReference ref: list) { FileLock fl = ref.get(); ! // Check for overlap if the FileLock instance has not been collected ! // or the underlying lock has not been released to the file system. ! if ((fl != null || !ref.isLockReleased()) ! && ref.overlaps(position, size)) { throw new OverlappingFileLockException(); } } + } // Process the reference queue private void removeStaleEntries() { FileLockReference ref; while ((ref = (FileLockReference)queue.poll()) != null) { FileKey fk = ref.fileKey(); List<FileLockReference> list = lockMap.get(fk); if (list != null) { synchronized (list) { + // Retain the reference in the list if it refers to a + // FileLock which was collected without being released. + if (ref.isLockReleased()) { list.remove(ref); + } removeKeyIfEmpty(fk, list); } } } }
< prev index next >