package org.dcache.chimera.nfsv41.mover; import diskCacheV111.util.CacheException; import dmg.cells.nucleus.CellPath; import java.lang.ref.WeakReference; import org.dcache.cells.AbstractMessageCallback; import org.dcache.chimera.nfs.v4.xdr.stateid4; import org.dcache.vehicles.DoorValidateMoverMessage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A {@code DoorValidateMoverMessage} callback handler for NFS transfer service. */ public class NfsMoverValidationCallback extends AbstractMessageCallback<DoorValidateMoverMessage<org.dcache.chimera.nfs.v4.xdr.stateid4>> { private final Logger LOGGER = LoggerFactory.getLogger(NfsMoverValidationCallback.class); /** * A weak reference to the mover. If mover will be killed by some * other path (admin command or from the door), then we can simply * forget about it. */ private final WeakReference<NfsMover> moverRef; public NfsMoverValidationCallback(NfsMover mover) { moverRef = new WeakReference<>(mover); } @Override public void success(DoorValidateMoverMessage<stateid4> message) { if (!message.isIsValid()) { kill(); } } @Override public void failure(int rc, Object error) { // effective NOP, as we can't safely decide to kill the mover LOGGER.info("Failed to send validation requests: {} ({})", error, rc); } @Override public void noroute(CellPath path) { // door is dead. All states (movers) are invalid. kill(); } private void kill() { NfsMover mover = moverRef.get(); if (mover != null) { LOGGER.warn("Killing abandoned mover: {}", mover); mover.disable(new CacheException(CacheException.THIRD_PARTY_TRANSFER_FAILED, "Abandoned mover")); } } }