// $Id: FileHoppingManager.java,v 1.3 2006-04-21 11:21:33 patrick Exp $Cg package diskCacheV111.services; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.PrintWriter; import java.net.InetSocketAddress; import java.util.Date; import java.util.Map; import java.util.TreeMap; import java.util.regex.Pattern; import diskCacheV111.vehicles.DCapProtocolInfo; import diskCacheV111.vehicles.Pool2PoolTransferMsg; import diskCacheV111.vehicles.PoolMgrReplicateFileMsg; import diskCacheV111.vehicles.ProtocolInfo; import dmg.cells.nucleus.CellAdapter; import dmg.cells.nucleus.CellMessage; import dmg.cells.nucleus.CellNucleus; import dmg.cells.nucleus.CellPath; import dmg.util.Formats; import org.dcache.util.Args; import org.dcache.vehicles.FileAttributes; import static com.google.common.base.Preconditions.checkArgument; /** * @Author: Patrick Fuhrmann * * The FileHoppingManager receives PoolMgrReplicateFileMsg messages from * write pools and, depending * */ public class FileHoppingManager extends CellAdapter { private static final Logger _log = LoggerFactory.getLogger(FileHoppingManager.class); private final CellNucleus _nucleus; private final Map<String, Entry> _map = new TreeMap<>() ; private final Object _mapLock = new Object() ; private int _totalRequests; private final File _configFile; private final CellPath _defaultDestinationPath = new CellPath("PoolManager"); public FileHoppingManager(String name, String arguments) { super(name, FileHoppingManager.class.getName(), arguments); Args args = getArgs(); checkArgument(args.argc() >= 1, "Usage : <configFileName> OPTIONS "); _configFile = new File(args.argv(0)); _nucleus = getNucleus(); } @Override protected void starting() throws Exception { if (!_configFile.exists()) { File configDir = _configFile.getParentFile(); if ((configDir == null) || !configDir.exists()) { throw new IllegalArgumentException("Config directory doesn't exit : " + configDir); } try { if (!_configFile.createNewFile()) { throw new IllegalArgumentException("Couldn't create config file : " + _configFile); } } catch (Exception ee) { throw new IllegalArgumentException( "Couldn't create config file : " + _configFile + " : " + ee.getMessage()); } } runSetupFile(_configFile); } private void runSetupFile(File setupFile ) throws Exception { if( ! setupFile.exists() ) { throw new IllegalArgumentException("Setup File not found : " + setupFile); } BufferedReader reader = new BufferedReader( new FileReader( setupFile ) ) ; try{ String line; while( ( line = reader.readLine() ) != null ){ if(line.isEmpty()) { continue; } if( line.charAt(0) == '#' ) { continue; } try{ _log.info( "Executing : "+line ) ; String answer = command( line ) ; if(!answer.isEmpty()) { _log.info("Answer : " + answer); } }catch( Exception ee ){ _log.warn("Exception : "+ee.toString() ) ; } } }finally{ try{ reader.close() ; }catch(Exception ee){} } } private void dumpSetup() throws Exception { File setupFile = _configFile.getCanonicalFile() ; File tmpFile = new File( setupFile.getParent() , "."+setupFile.getName() ) ; PrintWriter writer = new PrintWriter( new FileWriter( tmpFile ) ) ; try{ writer.print( "#\n# Setup of " ) ; writer.print(_nucleus.getCellName() ) ; writer.print(" (") ; writer.print(this.getClass().getName()) ; writer.print(") at ") ; writer.println( new Date().toString() ) ; writer.println( "#") ; synchronized( _mapLock ){ for (Object o : _map.values()) { Entry e = (Entry) o; writer.println(e.toCommandString()); } } writer.println( "#" ) ; }catch(Exception ee){ tmpFile.delete() ; throw ee ; }finally{ try{ writer.close() ; }catch(Exception eee ){} } if( ! tmpFile.renameTo( setupFile ) ){ tmpFile.delete() ; throw new IllegalArgumentException( "Rename failed : "+_configFile ) ; } } @Override public void getInfo( PrintWriter pw ){ pw.println(" Cell Name : "+getCellName()); pw.println(" Cell Class : "+this.getClass().getName() ); pw.println(" Version : $Id: FileHoppingManager.java,v 1.3 2006-04-21 11:21:33 patrick Exp $"); pw.println(" Total Requsts : "+_totalRequests ) ; pw.println("Number of Rules : "+_map.size()); } private static class Entry { private String _name; private boolean _retry; private boolean _continue; private final String _patternStr; private final Pattern _pattern; private final int _status; private final String _statusStr; private String _dest; private CellPath _path; private String _source = "write" ; private ProtocolInfo _info; private String _hostName; private String _protType; private int _protMinor; private int _protMajor; private int _hit; private Entry( String name , String patternStr , String modeString ){ _name = name ; _patternStr = patternStr ; _pattern = Pattern.compile(patternStr) ; _statusStr = modeString == null ? "keep" : modeString ; _status = getModeByString( _statusStr ) ; } public String toCommandString(){ StringBuilder sb = new StringBuilder() ; sb.append("define hop ").append(_name).append(" \""). append(_patternStr).append("\" ").append(_statusStr); if( _info != null ){ sb.append(" -host=").append(_hostName). append(" -protType=").append(_protType). append(" -protMinor=").append(_protMinor). append(" -protMajor=").append(_protMajor) ; } if( _dest != null ) { sb.append(" -destination=").append(_dest); } sb.append(" -source=").append(_source) ; if( _continue ) { sb.append(" -continue"); } if( _retry ) { sb.append(" -retry"); } return sb.toString(); } public void setContinue( boolean isContinue ){ _continue = isContinue ; } public void setRetry( boolean isRetry ){ _retry = isRetry ; } public void setSource( String source ){ _source = source ; } public void setDestination( String destination ){ if( destination == null ) { return; } _dest = destination ; _path = new CellPath( _dest ) ; } public int getModeByString( String modeStr ){ int mode; if( modeStr == null ){ mode = Pool2PoolTransferMsg.UNDETERMINED ; }else if( modeStr.equals("precious") ){ mode = Pool2PoolTransferMsg.PRECIOUS ; }else if( modeStr.equals("cached") ){ mode = Pool2PoolTransferMsg.CACHED ; }else if( modeStr.equals("keep") ){ mode = Pool2PoolTransferMsg.UNDETERMINED ; }else{ throw new IllegalArgumentException("Mode string : precious|cached|keep"); } return mode ; } public void setProtocolInfo( String hostName , String protType , String protMajor , String protMinor ){ if( ( hostName != null ) || ( protType != null ) || ( protMinor != null ) || ( protMajor != null ) ){ _hostName = hostName == null ? "localhost" : hostName ; _protType = protType == null ? "DCap" : protType ; _protMinor = protMinor == null ? 0 : Integer.parseInt( protMinor ) ; _protMajor = protMajor == null ? 3 : Integer.parseInt( protMajor ) ; _info = new DCapProtocolInfo( _protType, _protMajor, _protMajor, new InetSocketAddress(hostName , 0) ) ; } } public ProtocolInfo getProtocolInfo(){ return _info ; } public String toString(){ return _name+"=\""+_patternStr+"\";st="+_status+ ";dest="+_path+ ";source="+_source+ ";info="+(_info==null?"None":_info.toString()); } } public static final String fh_define_hop = "define hop OPTIONS <name> <pattern> precious|cached|keep\n"+ " OPTIONS\n"+ " -destination=<cellDestination> # default : PoolManager\n"+ " -overwrite\n"+ " -retry\n"+ " -continue\n"+ " -source=write|restore|* # !!!! for experts only"+ " StorageInfoOptions\n"+ " -host=<destinationHostIp>\n"+ " -protType=dCap|ftp...\n"+ " -protMinor=<minorProtocolVersion>\n"+ " -protMajor=<majorProtocolVersion>\n" ; public static final String hh_define_hop = "OPTONS <name> <pattern> precious|cached|keep # see 'help define hop'" ; public String ac_define_hop_$_3( Args args ){ String name = args.argv(0) ; String patternStr = args.argv(1) ; String modeStr = args.argv(2) ; String destination = args.getOpt("destination") ; boolean overwrite = args.hasOption("overwrite") ; String hostName = args.getOpt("host") ; String protocol = args.getOpt("protType") ; String protMinor = args.getOpt("protMinor") ; String protMajor = args.getOpt("protMajor") ; String source = args.getOpt("source") ; Entry entry = _map.get( name ); if( ( entry != null ) && ! overwrite ) { throw new IllegalArgumentException("Entry already exists : " + name); } entry = new Entry(name, patternStr, modeStr); entry.setProtocolInfo( hostName , protocol , protMajor , protMinor ) ; entry.setDestination( destination ) ; entry.setRetry( args.hasOption("retry") ) ; entry.setContinue( args.hasOption("continue") ) ; if( source != null ) { entry.setSource(source); } synchronized( _mapLock ){ _map.put( name , entry ) ; } return "" ; } public static final String hh_rename_hop = "<oldName> <newName>" ; public String ac_rename_hop_$_2( Args args ){ String oldName = args.argv(0) ; String newName = args.argv(1) ; synchronized( _mapLock ){ Entry oldEntry = _map.remove(oldName); if( oldEntry == null ) { throw new IllegalArgumentException("currentName not found : " + oldName); } Entry newEntry = _map.get(newName); if( newEntry != null ) { throw new IllegalArgumentException("newName already exists: " + newName); } oldEntry._name = newName ; _map.put( newName , oldEntry ) ; } return "" ; } public static final String hh_undefine_hop = "<name>" ; public String ac_undefine_hop_$_1( Args args ){ String name = args.argv(0) ; synchronized( _mapLock ){ _map.remove( name ) ; } return "" ; } @Override public void messageToForward( CellMessage cellMessage ){ _log.info("Message to forward : "+cellMessage.getMessageObject().getClass().getName()); // super.messageToForward(cellMessage); } public void replicateReplyArrived( CellMessage message , PoolMgrReplicateFileMsg replicate ){ _log.info("replicateReplyArrived : "+message); } @Override public void messageArrived( CellMessage message ){ Object request = message.getMessageObject() ; _log.info("messageArrived : "+request+" : "+message); if( request instanceof PoolMgrReplicateFileMsg ){ PoolMgrReplicateFileMsg replicate = (PoolMgrReplicateFileMsg)request ; if( replicate.isReply() ){ replicateReplyArrived( message , replicate ) ; return ; } replicate.setReplyRequired(true); FileAttributes fileAttributes = replicate.getFileAttributes(); _totalRequests ++ ; String storageClass = fileAttributes.getStorageClass()+"@"+fileAttributes.getHsm() ; String replicationSource = fileAttributes.getStorageInfo().getKey("replication.source"); ProtocolInfo originalProtocolInfo = replicate.getProtocolInfo() ; int matchCount = 0 ; synchronized( _mapLock ){ for (Object o : _map.values()) { Entry entry = (Entry) o; if (!entry._pattern.matcher(storageClass).matches()) { continue; } if (!((entry._source.equals("*")) || (entry._source.contains(replicationSource)))) { continue; } matchCount++; _log.info("Entry found for : SC=<" + storageClass + "> source=" + replicationSource + " : " + entry); entry._hit++; CellPath path = entry._path == null ? _defaultDestinationPath : entry._path; replicate.setDestinationFileStatus(entry._status); ProtocolInfo info = entry._info == null ? originalProtocolInfo : entry._info; replicate.setProtocolInfo(info); try { sendMessage(new CellMessage(path.clone(), replicate)); } catch (RuntimeException ee) { _log.warn("Problem : couldn't forward message to : " + entry._path + " : " + ee); } if (!entry._continue) { break; } } } _log.info("Total match count for <"+storageClass+"> was "+matchCount ) ; } } public static final String hh_save = "" ; public String ac_save( Args args ) throws Exception { dumpSetup() ; return "Data written to "+_configFile ; } public static final String hh_ls_hop = "[<ruleName>] -count" ; public String ac_ls_hop_$_0_1( Args args ){ StringBuilder sb = new StringBuilder() ; boolean count = args.hasOption("count") || args.hasOption("c") ; synchronized( _mapLock ){ if( args.argc() == 0 ){ if( count ){ for (Object o : _map.values()) { Entry e = (Entry) o; sb.append(Formats.field(e._name, 15, Formats.RIGHT)). append(" "). append(Formats .field(e._patternStr, 30, Formats.CENTER)). append(" "). append(Formats.field(String.valueOf(e._hit), 7, Formats.RIGHT)) . append("\n"); } }else{ for (Object o : _map.values()) { Entry e = (Entry) o; sb.append(e.toCommandString()).append("\n"); } } }else{ String ruleName = args.argv(0) ; Entry e = _map.get( ruleName ); if( e == null ) { throw new IllegalArgumentException("Rule not found : " + ruleName); } sb.append( e.toCommandString() ).append("\n"); } } return sb.toString(); } }