151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* 251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved. 351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it 651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as 751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation. Oracle designates this 851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided 951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code. 1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT 1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that 1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code). 1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version 1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation, 1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any 2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions. 2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage sun.nio.ch; 2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.nio.channels.*; 2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.*; 3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.concurrent.ConcurrentHashMap; 3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.lang.ref.*; 3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.FileDescriptor; 3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.IOException; 3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiabstract class FileLockTable { 3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski protected FileLockTable() { 3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Creates and returns a file lock table for a channel that is connected to 4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the a system-wide map of all file locks for the Java virtual machine. 4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static FileLockTable newSharedFileLockTable(Channel channel, 4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski FileDescriptor fd) 4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException 4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new SharedFileLockTable(channel, fd); 4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Adds a file lock to the table. 5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws OverlappingFileLockException if the file lock overlaps 5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * with an existing file lock in the table 5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public abstract void add(FileLock fl) throws OverlappingFileLockException; 5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Remove an existing file lock from the table. 6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public abstract void remove(FileLock fl); 6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Removes all file locks from the table. 6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return The list of file locks removed 6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public abstract List<FileLock> removeAll(); 6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Replaces an existing file lock in the table. 7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public abstract void replace(FileLock fl1, FileLock fl2); 7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski} 7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/** 7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A file lock table that is over a system-wide map of all file locks. 7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiclass SharedFileLockTable extends FileLockTable { 8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A weak reference to a FileLock. 8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * SharedFileLockTable uses a list of file lock references to avoid keeping the 8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FileLock (and FileChannel) alive. 8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static class FileLockReference extends WeakReference<FileLock> { 8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private FileKey fileKey; 9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski FileLockReference(FileLock referent, 9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ReferenceQueue<FileLock> queue, 9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski FileKey key) { 9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski super(referent, queue); 9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.fileKey = key; 9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski FileKey fileKey() { 9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return fileKey; 10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // The system-wide map is a ConcurrentHashMap that is keyed on the FileKey. 10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // The map value is a list of file locks represented by FileLockReferences. 10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // All access to the list must be synchronized on the list. 10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static ConcurrentHashMap<FileKey, List<FileLockReference>> lockMap = 10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski new ConcurrentHashMap<FileKey, List<FileLockReference>>(); 10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // reference queue for cleared refs 11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static ReferenceQueue<FileLock> queue = new ReferenceQueue<FileLock>(); 11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // The connection to which this table is connected 11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final Channel channel; 11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // File key for the file that this channel is connected to 11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final FileKey fileKey; 11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski SharedFileLockTable(Channel channel, FileDescriptor fd) throws IOException { 11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.channel = channel; 12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.fileKey = FileKey.create(fd); 12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski @Override 12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void add(FileLock fl) throws OverlappingFileLockException { 12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski List<FileLockReference> list = lockMap.get(fileKey); 12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (;;) { 12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // The key isn't in the map so we try to create it atomically 13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (list == null) { 13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski list = new ArrayList<FileLockReference>(2); 13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski List<FileLockReference> prev; 13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski synchronized (list) { 13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski prev = lockMap.putIfAbsent(fileKey, list); 13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (prev == null) { 13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // we successfully created the key so we add the file lock 13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski list.add(new FileLockReference(fl, queue, fileKey)); 13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // someone else got there first 14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski list = prev; 14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // There is already a key. It is possible that some other thread 14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // is removing it so we re-fetch the value from the map. If it 14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // hasn't changed then we check the list for overlapping locks 14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // and add the new lock to the list. 14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski synchronized (list) { 15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski List<FileLockReference> current = lockMap.get(fileKey); 15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (list == current) { 15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski checkList(list, fl.position(), fl.size()); 15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski list.add(new FileLockReference(fl, queue, fileKey)); 15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski list = current; 15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // process any stale entries pending in the reference queue 16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski removeStaleEntries(); 16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void removeKeyIfEmpty(FileKey fk, List<FileLockReference> list) { 16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski assert Thread.holdsLock(list); 16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski assert lockMap.get(fk) == list; 16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (list.isEmpty()) { 16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski lockMap.remove(fk); 17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski @Override 17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void remove(FileLock fl) { 17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski assert fl != null; 17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // the lock must exist so the list of locks must be present 17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski List<FileLockReference> list = lockMap.get(fileKey); 17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (list == null) return; 18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski synchronized (list) { 18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int index = 0; 18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (index < list.size()) { 18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski FileLockReference ref = list.get(index); 18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski FileLock lock = ref.get(); 18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (lock == fl) { 18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski assert (lock != null) && (lock.acquiredBy() == channel); 18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ref.clear(); 18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski list.remove(index); 19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski index++; 19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski @Override 19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public List<FileLock> removeAll() { 19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski List<FileLock> result = new ArrayList<FileLock>(); 20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski List<FileLockReference> list = lockMap.get(fileKey); 20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (list != null) { 20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski synchronized (list) { 20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int index = 0; 20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (index < list.size()) { 20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski FileLockReference ref = list.get(index); 20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski FileLock lock = ref.get(); 20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // remove locks obtained by this channel 20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (lock != null && lock.acquiredBy() == channel) { 21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // remove the lock from the list 21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ref.clear(); 21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski list.remove(index); 21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // add to result 21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski result.add(lock); 21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski index++; 21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // once the lock list is empty we remove it from the map 22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski removeKeyIfEmpty(fileKey, list); 22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return result; 22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski @Override 22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void replace(FileLock fromLock, FileLock toLock) { 23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // the lock must exist so there must be a list 23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski List<FileLockReference> list = lockMap.get(fileKey); 23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski assert list != null; 23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski synchronized (list) { 23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int index=0; index<list.size(); index++) { 23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski FileLockReference ref = list.get(index); 23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski FileLock lock = ref.get(); 23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (lock == fromLock) { 23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ref.clear(); 24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski list.set(index, new FileLockReference(toLock, queue, fileKey)); 24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Check for overlapping file locks 24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void checkList(List<FileLockReference> list, long position, long size) 24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws OverlappingFileLockException 25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski assert Thread.holdsLock(list); 25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (FileLockReference ref: list) { 25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski FileLock fl = ref.get(); 25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (fl != null && fl.overlaps(position, size)) 25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new OverlappingFileLockException(); 25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Process the reference queue 26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void removeStaleEntries() { 26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski FileLockReference ref; 26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while ((ref = (FileLockReference)queue.poll()) != null) { 26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski FileKey fk = ref.fileKey(); 26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski List<FileLockReference> list = lockMap.get(fk); 26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (list != null) { 26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski synchronized (list) { 26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski list.remove(ref); 26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski removeKeyIfEmpty(fk, list); 26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski} 274