extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/release/FileServerOutputLocation.java

Code
Comments
Other
Rev Date Author Line
4344 08 Feb 17 nicklas 1 package net.sf.basedb.reggie.plugins.release;
4344 08 Feb 17 nicklas 2
4344 08 Feb 17 nicklas 3 import java.io.IOException;
4344 08 Feb 17 nicklas 4 import java.io.OutputStream;
4423 27 Mar 17 nicklas 5 import java.util.HashMap;
4344 08 Feb 17 nicklas 6 import java.util.HashSet;
4423 27 Mar 17 nicklas 7 import java.util.Map;
4344 08 Feb 17 nicklas 8 import java.util.Set;
4344 08 Feb 17 nicklas 9 import java.util.zip.GZIPOutputStream;
4344 08 Feb 17 nicklas 10
4344 08 Feb 17 nicklas 11 import net.sf.basedb.core.FileServer;
6962 19 Dec 22 nicklas 12 import net.sf.basedb.core.ProgressReporter;
4344 08 Feb 17 nicklas 13 import net.sf.basedb.core.plugin.ExportOutputStream;
4344 08 Feb 17 nicklas 14 import net.sf.basedb.opengrid.CmdResult;
4344 08 Feb 17 nicklas 15 import net.sf.basedb.opengrid.OpenGrid;
4344 08 Feb 17 nicklas 16 import net.sf.basedb.opengrid.RemoteHost;
4344 08 Feb 17 nicklas 17 import net.sf.basedb.opengrid.RemoteSession;
4344 08 Feb 17 nicklas 18 import net.sf.basedb.opengrid.config.ConnectionInfo;
4344 08 Feb 17 nicklas 19 import net.sf.basedb.opengrid.filetransfer.FilePermission;
4423 27 Mar 17 nicklas 20 import net.sf.basedb.reggie.grid.ScriptUtil;
4344 08 Feb 17 nicklas 21
4344 08 Feb 17 nicklas 22 /**
4344 08 Feb 17 nicklas 23   An output location that write files to a remote 
4344 08 Feb 17 nicklas 24   FileServer (assuming that the FileServer is reachable 
4344 08 Feb 17 nicklas 25   with SSH).
4344 08 Feb 17 nicklas 26   
4344 08 Feb 17 nicklas 27   @author nicklas
4344 08 Feb 17 nicklas 28   @since 4.10
4344 08 Feb 17 nicklas 29 */
4344 08 Feb 17 nicklas 30 public class FileServerOutputLocation 
4344 08 Feb 17 nicklas 31   extends OutputLocation
4344 08 Feb 17 nicklas 32 {
4344 08 Feb 17 nicklas 33   
4344 08 Feb 17 nicklas 34   private final FileServer server;
4344 08 Feb 17 nicklas 35   private final RemoteSession session;
4430 28 Mar 17 nicklas 36   private final String releaseVersion;
6019 12 Oct 20 nicklas 37   private final int searchTimeout;
4344 08 Feb 17 nicklas 38   private final String rootPath;
4421 24 Mar 17 nicklas 39   private final String releasePath;
4344 08 Feb 17 nicklas 40   private final Set<String> mkdirs;
4423 27 Mar 17 nicklas 41   private Map<String, String> releasedFiles;
4344 08 Feb 17 nicklas 42   
4344 08 Feb 17 nicklas 43   /**
4344 08 Feb 17 nicklas 44     Create a new location on the given file server.
4421 24 Mar 17 nicklas 45     The release directory is created by taking the
4421 24 Mar 17 nicklas 46     server root path and adding a subdirectory with the
4421 24 Mar 17 nicklas 47     release version.
6019 12 Oct 20 nicklas 48     @param searchTimeout Timeout in seconds when searching for existing files
6962 19 Dec 22 nicklas 49       (should be between 60 and 600 seconds).
4344 08 Feb 17 nicklas 50   */
6019 12 Oct 20 nicklas 51   public FileServerOutputLocation(FileServer server, String releaseVersion, int searchTimeout)
4344 08 Feb 17 nicklas 52   {
4344 08 Feb 17 nicklas 53     this.server = server;
4430 28 Mar 17 nicklas 54     this.releaseVersion = releaseVersion;
6962 19 Dec 22 nicklas 55     this.searchTimeout = Math.min(600, Math.max(60, searchTimeout));
4423 27 Mar 17 nicklas 56     this.rootPath = ScriptUtil.checkValidPath(server.getRootPath(), true, false);
4421 24 Mar 17 nicklas 57     this.releasePath = makePath(rootPath, releaseVersion);
4344 08 Feb 17 nicklas 58     this.mkdirs = new HashSet<String>();
4344 08 Feb 17 nicklas 59     
4344 08 Feb 17 nicklas 60     ConnectionInfo ci = new ConnectionInfo(server);
4344 08 Feb 17 nicklas 61     RemoteHost host = new RemoteHost(ci);
4344 08 Feb 17 nicklas 62     this.session = host.connect(5);
4344 08 Feb 17 nicklas 63   }
4344 08 Feb 17 nicklas 64   
4421 24 Mar 17 nicklas 65   
4344 08 Feb 17 nicklas 66   @Override
4421 24 Mar 17 nicklas 67   public String getRootPath() 
4421 24 Mar 17 nicklas 68   {
4421 24 Mar 17 nicklas 69     return rootPath;
4421 24 Mar 17 nicklas 70   }
4421 24 Mar 17 nicklas 71
4421 24 Mar 17 nicklas 72   @Override
4421 24 Mar 17 nicklas 73   public String getReleasePath()
4421 24 Mar 17 nicklas 74   {
4421 24 Mar 17 nicklas 75     return releasePath;
4421 24 Mar 17 nicklas 76   }
4421 24 Mar 17 nicklas 77   
6962 19 Dec 22 nicklas 78   /**
6962 19 Dec 22 nicklas 79     Search the current release archive for existing file items.
6962 19 Dec 22 nicklas 80   */
4421 24 Mar 17 nicklas 81   @Override
6962 19 Dec 22 nicklas 82   public void init(ProgressReporter progress) 
4421 24 Mar 17 nicklas 83   {
6962 19 Dec 22 nicklas 84     releasedFiles = new HashMap<>();
6962 19 Dec 22 nicklas 85     
6962 19 Dec 22 nicklas 86     // Find top-level directories for *.0 releases. Each directory corresponds
6962 19 Dec 22 nicklas 87     // to one release.
6962 19 Dec 22 nicklas 88     // The -L parameter is important since it allows us to symlink releases
6962 19 Dec 22 nicklas 89     // if the original disk gets full
6962 19 Dec 22 nicklas 90     // -printf format gives us one release version number per line 
6962 19 Dec 22 nicklas 91     // The final 'sort' is required since if, for some reason, a REAL file is present
6962 19 Dec 22 nicklas 92     // in more than one relase we link to the latest file we find (-n = numerical sort)
6963 19 Dec 22 nicklas 93     String findReleases = "find -L " + rootPath + " -mindepth 1 -maxdepth 1 -type d -executable \\( -name '*.0' -o -name '2.2' \\) -printf \"%P\\n\" | sort -n";
6962 19 Dec 22 nicklas 94     CmdResult<String> find = session.executeCmd(findReleases, 10);
6962 19 Dec 22 nicklas 95     find.throwExceptionIfNonZeroExitStatus();
6962 19 Dec 22 nicklas 96     
6962 19 Dec 22 nicklas 97     String[] allReleases = find.getResult().split("\n");
6962 19 Dec 22 nicklas 98     int numReleases = allReleases.length;
6962 19 Dec 22 nicklas 99     int releaseNo = 0;
6962 19 Dec 22 nicklas 100     for (String version : allReleases)
4423 27 Mar 17 nicklas 101     {
6962 19 Dec 22 nicklas 102       releaseNo++;
6962 19 Dec 22 nicklas 103       // If the current release already exists, ignore it
6962 19 Dec 22 nicklas 104       if (version.equals(releaseVersion)) continue;
4423 27 Mar 17 nicklas 105       
6962 19 Dec 22 nicklas 106       if (progress != null)
6962 19 Dec 22 nicklas 107       {
6962 19 Dec 22 nicklas 108         progress.display(2+10*releaseNo/numReleases, "Finding files in existing release "+version+"...");
6962 19 Dec 22 nicklas 109       }
6962 19 Dec 22 nicklas 110       
6962 19 Dec 22 nicklas 111       // For each release we will find all REAL files in the release
6962 19 Dec 22 nicklas 112       // Symlinks that are pointing to older releases are ignored
6962 19 Dec 22 nicklas 113       // -H parameter is important since it allows us to follow the symlink 
6962 19 Dec 22 nicklas 114       // for the top-level release directory (if any) but not for individual files
6962 19 Dec 22 nicklas 115       // -printf format gives us the path to the file relative the release directory
6962 19 Dec 22 nicklas 116       // including an important forward slash at the start
6962 19 Dec 22 nicklas 117       String findFiles = "find -H " + makePath(rootPath, version) + " -type d ! -executable -prune , -type f -readable -printf \"/%P\\n\"";
6962 19 Dec 22 nicklas 118       find = session.executeCmd(findFiles, searchTimeout);
4423 27 Mar 17 nicklas 119       find.throwExceptionIfNonZeroExitStatus();
6962 19 Dec 22 nicklas 120
6962 19 Dec 22 nicklas 121       String[] allFiles = find.getResult().split("\n");
6962 19 Dec 22 nicklas 122       for (String filePath : allFiles)
4423 27 Mar 17 nicklas 123       {
6962 19 Dec 22 nicklas 124         // For example: /S00001/l.r.m.c.lib.g/S00001.l.r.m.c.lib.g_R1.fastq.gz --> 1.0
6962 19 Dec 22 nicklas 125         releasedFiles.put(filePath, version);
4423 27 Mar 17 nicklas 126       }
4423 27 Mar 17 nicklas 127     }
4423 27 Mar 17 nicklas 128
6962 19 Dec 22 nicklas 129   }
6962 19 Dec 22 nicklas 130
6962 19 Dec 22 nicklas 131
6962 19 Dec 22 nicklas 132   @Override
6962 19 Dec 22 nicklas 133   public String findReleasedFile(String path)
6962 19 Dec 22 nicklas 134   {
6962 19 Dec 22 nicklas 135     if (releasedFiles == null) init(null);
4423 27 Mar 17 nicklas 136     return releasedFiles.get(path);
4421 24 Mar 17 nicklas 137   }
4421 24 Mar 17 nicklas 138   
4421 24 Mar 17 nicklas 139   @Override
4427 27 Mar 17 nicklas 140   public ExportOutputStream getOutputStream(String path, boolean executable)
4344 08 Feb 17 nicklas 141   {
4421 24 Mar 17 nicklas 142     String fullPath = makePath(releasePath, path);
4344 08 Feb 17 nicklas 143     if (getCompress()) fullPath += ".gz";
4344 08 Feb 17 nicklas 144     
4344 08 Feb 17 nicklas 145     // Check if directory needs to be created
4344 08 Feb 17 nicklas 146     String dir = fullPath.substring(0,  fullPath.lastIndexOf('/'));
4344 08 Feb 17 nicklas 147     if (!mkdirs.contains(dir))
4344 08 Feb 17 nicklas 148     {
4344 08 Feb 17 nicklas 149       CmdResult<String> r = session.mkdirs(FilePermission.USER_RWX, dir);
4344 08 Feb 17 nicklas 150       r.throwExceptionIfNonZeroExitStatus();
4344 08 Feb 17 nicklas 151       mkdirs.add(dir);
4344 08 Feb 17 nicklas 152     }
4344 08 Feb 17 nicklas 153     
4427 27 Mar 17 nicklas 154     OutputStream out = session.writeFile(fullPath, getOverwrite(), null, executable ? FilePermission.USER_RWX : FilePermission.USER_RW);
4344 08 Feb 17 nicklas 155     if (getCompress()) 
4344 08 Feb 17 nicklas 156     {
4344 08 Feb 17 nicklas 157       try
4344 08 Feb 17 nicklas 158       {
4344 08 Feb 17 nicklas 159         out = new GZIPOutputStream(out);
4344 08 Feb 17 nicklas 160       }
4344 08 Feb 17 nicklas 161       catch (IOException ex)
4344 08 Feb 17 nicklas 162       {
4344 08 Feb 17 nicklas 163         throw new RuntimeException(ex);
4344 08 Feb 17 nicklas 164       }
4344 08 Feb 17 nicklas 165     }
4344 08 Feb 17 nicklas 166     return new ExportOutputStream(out);
4344 08 Feb 17 nicklas 167   }
4344 08 Feb 17 nicklas 168   
4344 08 Feb 17 nicklas 169   @Override
4344 08 Feb 17 nicklas 170   public void close()
4344 08 Feb 17 nicklas 171   {
4344 08 Feb 17 nicklas 172     OpenGrid.close(session);
4344 08 Feb 17 nicklas 173   }
4344 08 Feb 17 nicklas 174
4421 24 Mar 17 nicklas 175
4344 08 Feb 17 nicklas 176 }