diff --git a/htroot/ConfigUpdate_p.html b/htroot/ConfigUpdate_p.html index 31aafabba..2be2f3ee6 100644 --- a/htroot/ConfigUpdate_p.html +++ b/htroot/ConfigUpdate_p.html @@ -58,7 +58,8 @@
Download of release #[downloadedRelease]# finished. Restart Initiated.
::
No more recent release found.
::
Omitting update because this is a development environment.
:: -
Omitting update because download of release #[downloadedRelease]# failed.
+
Omitting update because download of release #[downloadedRelease]# failed.
:: +
Omitting update because an error occurred while trying to deploy the release.
#(/autoUpdate)#

diff --git a/htroot/ConfigUpdate_p.java b/htroot/ConfigUpdate_p.java index c70e71f39..f11e6ebab 100644 --- a/htroot/ConfigUpdate_p.java +++ b/htroot/ConfigUpdate_p.java @@ -149,10 +149,14 @@ public class ConfigUpdate_p { sb.getLog().info("AUTO-UPDATE: omitting update because download failed (file cannot be found, is too small or signature was bad)"); prop.put("candeploy_autoUpdate", "4"); } else { - yacyRelease.deployRelease(downloaded); - sb.terminate(10, "manual release update to " + downloaded.getName()); - sb.getLog().info("AUTO-UPDATE: deploy and restart initiated"); - prop.put("candeploy_autoUpdate", "1"); + if(yacyRelease.deployRelease(downloaded)) { + sb.terminate(10, "manual release update to " + downloaded.getName()); + sb.getLog().info("AUTO-UPDATE: deploy and restart initiated"); + prop.put("candeploy_autoUpdate", "1"); + } else { + sb.getLog().info("AUTO-UPDATE: omitting update because an error occurred while trying to deploy the release.."); + prop.put("candeploy_autoUpdate", "5"); + } } } } diff --git a/htroot/Steering.html b/htroot/Steering.html index 34d7f595c..7f6003222 100644 --- a/htroot/Steering.html +++ b/htroot/Steering.html @@ -196,6 +196,12 @@ XDtoU7vQ/wIAAP//AwBb7ktEXQ4nqQAAAABJRU5ErkJggg==" width="128" height="64" alt="K ::

The file you are trying to install is not located in the release directory.
Go back to the System Update page.

+:: +

An error occurred when trying to install release #[release]#
+ Please check your log or go back to the System Update page.

+:: +

You are in a development environment or the file you are trying to install is empty.
+ Go back to the System Update page.

#(/info)# \ No newline at end of file diff --git a/htroot/Steering.java b/htroot/Steering.java index d4d48edb9..fc9dbdfee 100644 --- a/htroot/Steering.java +++ b/htroot/Steering.java @@ -80,10 +80,16 @@ public class Steering { final File releaseFile = new File(sb.releasePath, releaseFileName); if (FileUtils.isInDirectory(releaseFile, sb.releasePath)) { if ((!devenvironment) && (releaseFileName.length() > 0) && (releaseFile.exists())) { - yacyRelease.deployRelease(releaseFile); + if(yacyRelease.deployRelease(releaseFile)) { + prop.put("info", "5"); + prop.putHTML("info_release", releaseFileName); + } else { + prop.put("info", "7"); + prop.putHTML("info_release", releaseFileName); + } + } else { + prop.put("info", "8"); } - prop.put("info", "5"); - prop.putHTML("info_release", releaseFileName); } else { prop.put("info", "6"); } diff --git a/source/net/yacy/peers/operation/yacyRelease.java b/source/net/yacy/peers/operation/yacyRelease.java index 5884c2092..9fe6b8e72 100644 --- a/source/net/yacy/peers/operation/yacyRelease.java +++ b/source/net/yacy/peers/operation/yacyRelease.java @@ -476,11 +476,13 @@ public final class yacyRelease extends yacyVersion { /** * stop yacy and run a batch script, applies a new release and restarts yacy - * @param releaseFile + * @param releaseFile release file to apply + * @return true when release file has been successfully extracted and asynchronous update has been triggered */ - public static void deployRelease(final File releaseFile) { + public static boolean deployRelease(final File releaseFile) { + boolean restartTriggered = false; if (yacyBuildProperties.isPkgManager()) { - return; + return restartTriggered; } try { final Switchboard sb = Switchboard.getSwitchboard(); @@ -488,7 +490,7 @@ public final class yacyRelease extends yacyVersion { try{ tarTools.unTar(tarTools.getInputStream(releaseFile), sb.getDataPath() + "/DATA/RELEASE/".replace("/", File.separator)); } catch (final Exception e){ - ConcurrentLog.severe("UNTAR", "failed", e); + throw new IOException("Could not untar release file", e); } String script = null; String scriptFileName = null; @@ -560,12 +562,14 @@ public final class yacyRelease extends yacyVersion { OS.deployScript(scriptFile, script); ConcurrentLog.info("UPDATE", "wrote update-script to " + scriptFile.getAbsolutePath()); OS.execAsynchronous(scriptFile); + restartTriggered = true; ConcurrentLog.info("UPDATE", "script is running"); sb.setConfig("update.time.deploy", System.currentTimeMillis()); sb.terminate(10, "auto-deploy for " + releaseFile.getName()); } catch (final IOException e) { ConcurrentLog.severe("UPDATE", "update failed", e); } + return restartTriggered; } public static void main(final String[] args) { diff --git a/source/net/yacy/search/Switchboard.java b/source/net/yacy/search/Switchboard.java index b55fe3340..f13091249 100644 --- a/source/net/yacy/search/Switchboard.java +++ b/source/net/yacy/search/Switchboard.java @@ -2498,9 +2498,13 @@ public final class Switchboard extends serverSwitch { this.log .info("AUTO-UPDATE: omitting update because download failed (file cannot be found, is too small or signature is bad)"); } else { - yacyRelease.deployRelease(downloaded); - terminate(10, "auto-update to install " + downloaded.getName()); - this.log.info("AUTO-UPDATE: deploy and restart initiated"); + if(yacyRelease.deployRelease(downloaded)) { + terminate(10, "auto-update to install " + downloaded.getName()); + this.log.info("AUTO-UPDATE: deploy and restart initiated"); + } else { + this.log + .info("AUTO-UPDATE: omitting update because an error occurred while trying to deploy the release."); + } } } @@ -4032,6 +4036,11 @@ public final class Switchboard extends serverSwitch { } } + /** + * Triggers asynchronous shutdown occurring after a given delay + * @param delay delay time in milliseconds + * @param reason shutdown reason for log information + */ public void terminate(final long delay, final String reason) { if ( delay <= 0 ) { throw new IllegalArgumentException("The shutdown delay must be greater than 0."); diff --git a/source/net/yacy/utils/tarTools.java b/source/net/yacy/utils/tarTools.java index 9af805e3b..fabbf1777 100644 --- a/source/net/yacy/utils/tarTools.java +++ b/source/net/yacy/utils/tarTools.java @@ -28,6 +28,7 @@ package net.yacy.utils; import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -39,69 +40,138 @@ import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; import org.apache.commons.io.IOUtils; - +/** + * Tar archives utilities for YaCy + */ public class tarTools { - - public static InputStream getInputStream(final String tarFileName) throws Exception{ - if (tarFileName.endsWith(".gz")) { - try { - return new GZIPInputStream(new FileInputStream(new File(tarFileName))); - } catch (final IOException e) { + + /** + * Convenience method to open a stream on a tar archive file eventually + * compressed with gzip. + * + * @param tarPath + * .tar or .tar.gz file path + * @return an opened input stream + * @throws FileNotFoundException + * when the file does not exist, is a directory rather than a + * regular file, or for some other reason cannot be opened for + * reading. + */ + public static InputStream getInputStream(final String tarPath) throws FileNotFoundException { + if (tarPath.endsWith(".gz")) { + try { + return new GZIPInputStream(new FileInputStream(new File(tarPath))); + } catch (FileNotFoundException e) { + /* + * FileNotFoundException is is a subClass of IOException but the + * following behavior does not apply + */ + throw e; + } catch (final IOException e) { // this might happen if the stream is not in gzip format. // there may be a 'gz' extension, but it may still be a raw tar file // this can be caused by 'one too much gzip-content header' that was attached // by a release file server, so just try to open is as normal stream - return new FileInputStream(new File(tarFileName)); - } + return new FileInputStream(new File(tarPath)); + } } - return new FileInputStream(new File(tarFileName)); + return new FileInputStream(new File(tarPath)); } - public static InputStream getInputStream(final File tarFileName) throws Exception{ - return getInputStream(tarFileName.toString()); - } - /** - * untar for any archive, overwrites existing data - * @param in use getInputStream() for convenience - * @param untarDir destination path - * @throws Exception (IOException or FileNotFoundException) + * Convenience method to open a stream on a tar archive file eventually + * compressed with gzip. + * + * @param tarFile + * .tar or .tar.gz file + * @return an opened input stream + * @throws FileNotFoundException + * when the file does not exist, is a directory rather than a + * regular file, or for some other reason cannot be opened for + * reading. */ - public static void unTar(final InputStream in, final String untarDir) throws Exception{ + public static InputStream getInputStream(final File tarFile) throws Exception { + return getInputStream(tarFile.toString()); + } + + /** + * Untar for any tar archive, overwrites existing data. Closes the + * InputStream once terminated. + * + * @param in + * input stream. Must not be null. (use + * {@link #getInputStream(String)} for convenience) + * @param untarDir + * destination path. Must not be null. + * @throws IOException + * when a read/write error occurred + * @throws FileNotFoundException + * when the untarDir does not exists + * @throws NullPointerException + * when a parameter is null + */ + public static void unTar(final InputStream in, final String untarDir) throws IOException { ConcurrentLog.info("UNTAR", "starting"); - if(new File(untarDir).exists()){ + if (new File(untarDir).exists()) { final TarArchiveInputStream tin = new TarArchiveInputStream(in); - TarArchiveEntry tarEntry = tin.getNextTarEntry(); - while(tarEntry != null){ - final File destPath = new File(untarDir + File.separator + tarEntry.getName()); - if (!tarEntry.isDirectory()) { - new File(destPath.getParent()).mkdirs(); // create missing subdirectories - final FileOutputStream fout = new FileOutputStream(destPath); - IOUtils.copyLarge(tin,fout,0,tarEntry.getSize()); - fout.close(); - } else { - destPath.mkdir(); + try { + TarArchiveEntry tarEntry = tin.getNextTarEntry(); + if (tarEntry == null) { + throw new IOException("tar archive is empty or corrupted"); + } + while(tarEntry != null){ + final File destPath = new File(untarDir + File.separator + tarEntry.getName()); + if (!tarEntry.isDirectory()) { + new File(destPath.getParent()).mkdirs(); // create missing subdirectories + final FileOutputStream fout = new FileOutputStream(destPath); + IOUtils.copyLarge(tin,fout,0,tarEntry.getSize()); + fout.close(); + } else { + destPath.mkdir(); + } + tarEntry = tin.getNextTarEntry(); + } + } finally { + try { + tin.close(); + } catch (IOException ignored) { + ConcurrentLog.warn("UNTAR", "InputStream could not be closed"); } - tarEntry = tin.getNextTarEntry(); } - tin.close(); } else { // untarDir doesn't exist ConcurrentLog.warn("UNTAR", "destination " + untarDir + " doesn't exist."); + /* Still have to close the input stream */ + try { + in.close(); + } catch (IOException ignored) { + ConcurrentLog.warn("UNTAR", "InputStream could not be closed"); + } + throw new FileNotFoundException("Output untar directory not found : " + untarDir); } ConcurrentLog.info("UNTAR", "finished"); } - + + /** + * Untar a tar archive. + * @param args + *
    + *
  1. args[0] : source file path
  2. + *
  3. args[1] : destination directory path
  4. + *
+ */ public static void main(final String args[]) { - // @arg0 source - // @arg1 destination - if(args.length == 2){ try { - unTar(getInputStream(args[0]), args[1]); - } catch (final Exception e) { - System.out.println(e); - } - } else { - System.out.println("usage: "); + if (args.length == 2) { + try { + unTar(getInputStream(args[0]), args[1]); + } catch (final Exception e) { + System.out.println(e); + } + } else { + System.out.println("usage: "); + } + } finally { + ConcurrentLog.shutdown(); } } }