package org.dcache.chimera.nfsv41.door; import com.google.common.collect.ImmutableSet; import java.net.InetSocketAddress; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.concurrent.locks.ReentrantReadWriteLock; import org.dcache.nfs.v4.xdr.deviceid4; import org.dcache.chimera.nfsv41.door.NFSv41Door.PoolDS; import org.dcache.nfs.v4.xdr.nfs4_prot; import org.dcache.util.Bytes; /** * A mapping between pool name, nfs device id and pool's ip addresses. */ public class PoolDeviceMap { /** * next device id, 0 reserved for MDS */ private int _nextDeviceID = 1; /** * dCache-friendly NFS device id to pool name mapping */ private final Map<String, PoolDS> _poolNameToIpMap = new HashMap<>(); /** * All known devices */ private final Map<deviceid4, PoolDS> _deviceMap = new HashMap<>(); /* * as there are mostly reads, use read-write locks to increase concurrency */ private final ReentrantReadWriteLock _lock = new ReentrantReadWriteLock(); private final ReentrantReadWriteLock.ReadLock _rlock = _lock.readLock(); private final ReentrantReadWriteLock.WriteLock _wlock = _lock.writeLock(); static deviceid4 deviceidOf(int id) { byte[] deviceidBytes = new byte[nfs4_prot.NFS4_DEVICEID4_SIZE]; Bytes.putInt(deviceidBytes, 0, id); return new deviceid4(deviceidBytes); } Collection<PoolDS> getDevices() { _rlock.lock(); try { return ImmutableSet.copyOf(_poolNameToIpMap.values()); } finally { _rlock.unlock(); } } Collection<deviceid4> getDeviceIds() { _rlock.lock(); try { return ImmutableSet.copyOf(_deviceMap.keySet()); } finally { _rlock.unlock(); } } PoolDS getOrCreateDS(String name, long verifier, InetSocketAddress[] poolAddress) { _wlock.lock(); try { PoolDS ds = _poolNameToIpMap.get(name); if (ds != null && ds.getVerifier() == verifier) { return ds; } if (ds != null) { // remove old mapping _deviceMap.remove(ds.getDeviceId()); } deviceid4 deviceid = deviceidOf(_nextDeviceID++); ds = new PoolDS(deviceid, poolAddress, verifier); _poolNameToIpMap.put(name, ds); _deviceMap.put(ds.getDeviceId(), ds); return ds; } finally { _wlock.unlock(); } } PoolDS getByDeviceId(deviceid4 deviceId) { _rlock.lock(); try { return _deviceMap.get(deviceId); } finally { _rlock.unlock(); } } Collection<Map.Entry<String,PoolDS>> getEntries() { _rlock.lock(); try { return ImmutableSet.copyOf(_poolNameToIpMap.entrySet()); } finally { _rlock.unlock(); } } PoolDS remove(String pool) { _wlock.lock(); try { PoolDS ds = _poolNameToIpMap.remove(pool); if (ds != null) { _deviceMap.remove(ds.getDeviceId()); } return ds; } finally { _wlock.unlock(); } } }