package org.dcache.srm.qos.lambdastation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.Properties; import org.dcache.srm.AbstractStorageElement; import org.dcache.srm.SRM; import org.dcache.srm.qos.QOSPlugin; import org.dcache.srm.qos.QOSTicket; public class LambdaStationPlugin implements QOSPlugin { private static final Logger logger = LoggerFactory.getLogger(LambdaStationPlugin.class); private LambdaStationMap lambdaStationMap; private String lambdaStationConf; private String lambdaStationScript; private AbstractStorageElement storage; private final Collection<LambdaStationTicket> tickets = new ArrayList<>(); public LambdaStationPlugin(){} @Override public void setSrm(SRM srm) { lambdaStationConf = srm.getConfiguration().getQosConfigFile(); storage = srm.getStorage(); Properties properties = new Properties(); FileInputStream fis; try { fis = new FileInputStream(lambdaStationConf); } catch(FileNotFoundException ex) { logger.error(ex.toString()); return; } try { properties.load(fis); } catch(IOException ex) { logger.error("failed to load configuration ",ex); return; } finally { try { fis.close(); } catch (IOException ex) { logger.error("failed to close "+lambdaStationConf, ex); } } this.lambdaStationScript = properties.getProperty("l_station_script","/opt/d-cache/conf/l_station_script.sh"); this.lambdaStationMap = new LambdaStationMap(properties.getProperty("l_station_map","/opt/d-cache/conf/l_station_map.xml")); } @Override public QOSTicket createTicket( String credential, Long bytes, String srcURL, int srcPortMin, int srcPortMax, String srcProtocol, String dstURL, int dstPortMin, int dstPortMax, String dstProtocol) { LambdaStationTicket ticket = new LambdaStationTicket( credential, dstURL, null, // don't make it hardcoded srcURL, null, // don't make it hardcoded 600, // hardcoded travel time so far lambdaStationMap); ticket.bytes = bytes; return ticket; } @Override public void addTicket(QOSTicket qosTicket) { if (qosTicket instanceof LambdaStationTicket) { LambdaStationTicket ls_ticket = (LambdaStationTicket)qosTicket; tickets.add(ls_ticket); } } @Override public boolean submit() { boolean result = true; for (LambdaStationTicket ls_ticket:tickets) { ls_ticket.OpenTicket(lambdaStationScript); result = !result ? isTicketEnabled(ls_ticket) : result; } return result; } private boolean isTicketEnabled(QOSTicket qosTicket) { if (qosTicket instanceof LambdaStationTicket) { LambdaStationTicket ls_ticket = (LambdaStationTicket)qosTicket; boolean sEnabled = ls_ticket.srcEnabled(); boolean dEnabled = ls_ticket.dstEnabled(); logger.debug("src enabled="+sEnabled+" dst enabled="+dEnabled); return sEnabled && dEnabled && ls_ticket.getLocalTicketID() != 0; } else { return false; } } @Override public void sayStatus(QOSTicket qosTicket) { if (qosTicket instanceof LambdaStationTicket) { LambdaStationTicket ls_ticket = (LambdaStationTicket)qosTicket; if (isTicketEnabled(qosTicket)) { Date now = new Date(); long t = now.getTime(); long time_left = ls_ticket.getActualEndTime() - t/1000; logger.debug("End time="+ls_ticket.getActualEndTime()+" Travel Time="+ls_ticket.TravelTime+" now="+t+" expires in "+time_left); // try to calculate transfer time assuming 1Gb local connection long transfer_time = 0l; long rate_MB = 100000000l; // 1Gb means 100MB if (ls_ticket.bytes != null) { transfer_time = ls_ticket.bytes /rate_MB; } long extend_time = Math.max(transfer_time, 600l); if (time_left - extend_time < 0) { logger.debug("AM: will extend end time by "+extend_time); } else { logger.debug("AM: no need to extend end time"); } } } } }