package diskCacheV111.util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import org.dcache.alarms.AlarmMarkerFactory; import org.dcache.alarms.PredefinedAlarm; import org.dcache.util.NetworkUtils; /** * Utility class for invoking an HSM integration script. */ public class HsmRunSystem extends RunSystem { private static final Logger LOGGER = LoggerFactory.getLogger(HsmRunSystem.class); private static final String PNFSID_TAG = "pnfsid_file="; private static final String BFID_TAG = "bfid="; private final String storageName; public HsmRunSystem(String storageName, int maxLines, long timeout, String ... exec) { super(maxLines, timeout, exec); this.storageName = storageName; } public String execute() throws IOException, CacheException { go(); int returnCode = getExitValue(); try { switch (returnCode) { case 0: break; case 71: throw new CacheException(CacheException.HSM_DELAY_ERROR, "HSM script failed (script reported 71: " + getErrorString() + ")"); case 72: throw new InProgressCacheException(72, "HSM script requested retry (script reported 72: " + getErrorString() + ")"); case 143: throw new TimeoutCacheException( "HSM script was killed (script reported 143: " + getErrorString() + ")"); default: throw new CacheException(returnCode, "HSM script failed (script reported: " + returnCode + ": " + getErrorString()); } } catch (InProgressCacheException e) { throw e; } catch (CacheException e) { LOGGER.error(AlarmMarkerFactory.getMarker(PredefinedAlarm.HSM_SCRIPT_FAILURE, NetworkUtils.getCanonicalHostName(), storageName, extractPossibleEnstoreIds(getErrorString())), e.getMessage()); throw e; } return getOutputString(); } private String extractPossibleEnstoreIds(String error) { StringBuilder ids = new StringBuilder(); /* * FIXME this method should not really be in this class, * but in an enstore-specific script utility. * The check for the end tag is a provisional work-around. * * NOTE: I am not sure whether the mere presence of the ampersand * here denotes an enstore error string or not, so I've left * each check as self-contained for the moment. */ int start = error.indexOf(PNFSID_TAG); if (start >= 0) { start += PNFSID_TAG.length(); int end = error.indexOf('&', start); if (end >= 0) { ids.append(PNFSID_TAG) .append(error.substring(start, end)); } } start = error.indexOf(BFID_TAG); if (start >= 0) { start += BFID_TAG.length(); int end = error.indexOf('&', start); if (end > 0) { ids.append(BFID_TAG) .append(error.substring(start, end)); } } /* * if the message does not contain data based on f_enstore2uri * then just enforce a match on the error string. */ if (ids.length() == 0) { ids.append(error); } return ids.toString(); } }