Fix issues with installation and unpacking.

When the resource installation phase was added (downloading to _new files and
then moving them over top of the originals once they were validated), this
broke handling of unpacked resources.

Because we don't explicitly track whether a given version of a resource has
been unpacked (would be tricky) we try to piggy back on the download validation
process. But we validate before we install and we need to unpack after we
install, so for resources that are to be installed, we now also unpack and mark
as valid after the install is complete.

Closes #88.
This commit is contained in:
Michael Bayne
2017-11-17 15:01:10 -08:00
parent 065728276f
commit 0fd022d9cc
3 changed files with 34 additions and 40 deletions
@@ -1286,7 +1286,7 @@ public class Application
Set<Resource> toInstall, Set<Resource> toDownload)
throws InterruptedException
{
// resources are verified on backgroudn threads supplied by the thread pool, and progress
// resources are verified on background threads supplied by the thread pool, and progress
// is reported by posting runnable actions to the actions queue which is processed by the
// main (UI) thread
Executor exec = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
@@ -1315,7 +1315,6 @@ public class Application
}
}, sizes);
final boolean noUnpack = SysProps.noUnpack();
final int[] fAlreadyValid = alreadyValid;
final Set<Resource> toInstallAsync = new ConcurrentSkipListSet<>(toInstall);
final Set<Resource> toDownloadAsync = new ConcurrentSkipListSet<>();
@@ -1329,7 +1328,7 @@ public class Application
final int index = ii;
exec.execute(new Runnable() {
public void run () {
verifyResource(rsrc, pagg.startElement(index), fAlreadyValid, noUnpack,
verifyResource(rsrc, pagg.startElement(index), fAlreadyValid,
unpackedAsync, toInstallAsync, toDownloadAsync);
actions.add(new Runnable() {
public void run () {
@@ -1357,7 +1356,7 @@ public class Application
}
private void verifyResource (Resource rsrc, ProgressObserver obs, int[] alreadyValid,
boolean noUnpack, Set<Resource> unpacked,
Set<Resource> unpacked,
Set<Resource> toInstall, Set<Resource> toDownload) {
if (rsrc.isMarkedValid()) {
if (alreadyValid != null) {
@@ -1370,26 +1369,19 @@ public class Application
try {
if (_digest.validateResource(rsrc, obs)) {
// if the resource has a _new file, add it to to-install list
if (!toInstall.contains(rsrc) && rsrc.getLocalNew().exists()) {
if (rsrc.getLocalNew().exists()) {
toInstall.add(rsrc);
return;
}
// unpack this resource if appropriate
if (noUnpack || !rsrc.shouldUnpack()) {
// finally note that this resource is kosher
rsrc.markAsValid();
return;
}
if (rsrc.unpack()) {
unpacked.add(rsrc);
rsrc.markAsValid();
return;
}
log.info("Failure unpacking resource", "rsrc", rsrc);
rsrc.unpackIfNeeded();
unpacked.add(rsrc);
rsrc.markAsValid();
return;
}
} catch (Exception e) {
log.info("Failure validating resource. Requesting redownload...",
log.info("Failure verifying resource. Requesting redownload...",
"rsrc", rsrc, "error", e);
} finally {
@@ -1429,8 +1421,10 @@ public class Application
}
Resource rsrc = rsrcs.get(ii);
ProgressObserver pobs = pagg.startElement(ii);
if (!rsrc.unpack()) {
log.info("Failure unpacking resource", "rsrc", rsrc);
try {
rsrc.unpack();
} catch (IOException ioe) {
log.warning("Failure unpacking resource", "rsrc", rsrc, ioe);
}
pobs.progress(100);
}
@@ -185,12 +185,11 @@ public class Resource implements Comparable<Resource>
}
/**
* Returns true if this resource should be unpacked as a part of the
* validation process.
* Returns true if this resource should be unpacked as a part of the validation process.
*/
public boolean shouldUnpack ()
{
return _unpack;
return _unpack && !SysProps.noUnpack();
}
/**
@@ -255,28 +254,33 @@ public class Resource implements Comparable<Resource>
if (!FileUtil.renameTo(source, dest)) {
throw new IOException("Failed to rename " + source + " to " + dest);
}
// unpack the resource, now that it's installed, and mark it as valid
unpackIfNeeded();
markAsValid();
}
/**
* Unpacks this resource file into the directory that contains it. Returns
* false if an error occurs while unpacking it.
* Unpacks this resource file into the directory that contains it.
*/
public boolean unpack ()
public void unpack () throws IOException
{
// sanity check
if (!_isJar && !_isPacked200Jar) {
log.warning("Requested to unpack non-jar file '" + _local + "'.");
return false;
throw new IOException("Requested to unpack non-jar file '" + _local + "'.");
}
try {
if (_isJar) {
return FileUtil.unpackJar(new JarFile(_local), _unpacked);
} else{
return FileUtil.unpackPacked200Jar(_local, _unpacked);
}
} catch (IOException ioe) {
log.warning("Failed to create JarFile from '" + _local + "': " + ioe);
return false;
if (_isJar) {
FileUtil.unpackJar(new JarFile(_local), _unpacked);
} else{
FileUtil.unpackPacked200Jar(_local, _unpacked);
}
}
/**
* Unpacks this resource if needed.
*/
public void unpackIfNeeded () throws IOException {
if (shouldUnpack()) {
unpack();
}
}
@@ -630,10 +630,6 @@ public abstract class Getdown extends Thread
updateStatus("m.unpacking_java");
vmjar.install();
if (!vmjar.unpack()) {
throw new IOException("m.java_unpack_failed");
}
vmjar.markAsValid();
// these only run on non-Windows platforms, so we use Unix file separators
String localJavaDir = LaunchUtil.LOCAL_JAVA_DIR + "/";