Further progress on versioned application upgrades.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: Application.java,v 1.8 2004/07/07 16:18:23 mdb Exp $
|
// $Id: Application.java,v 1.9 2004/07/13 02:42:52 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.getdown.data;
|
package com.threerings.getdown.data;
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ public class Application
|
|||||||
try {
|
try {
|
||||||
return createResource(CONFIG_FILE);
|
return createResource(CONFIG_FILE);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException("Booched appbase '" + _appbase + "'!?");
|
throw new RuntimeException("Booched appbase '" + _vappbase + "'!?");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,6 +105,32 @@ public class Application
|
|||||||
return _resources;
|
return _resources;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a resource that can be used to download a patch file that
|
||||||
|
* will bring this application from its current version to the target
|
||||||
|
* version.
|
||||||
|
*/
|
||||||
|
public Resource getPatchResource ()
|
||||||
|
{
|
||||||
|
if (_targetVersion <= _version) {
|
||||||
|
Log.warning("Requested patch resource for up-to-date or " +
|
||||||
|
"non-versioned appliation [cvers=" + _version +
|
||||||
|
", tvers=" + _targetVersion + "].");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String pfile = "patch" + _version + ".dat";
|
||||||
|
try {
|
||||||
|
URL remote = new URL(createVAppBase(_targetVersion), pfile);
|
||||||
|
return new Resource(pfile, remote, getLocalPath(pfile));
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.warning("Failed to create patch resource path [pfile=" + pfile +
|
||||||
|
", appbase=" + _appbase + ", tvers=" + _targetVersion +
|
||||||
|
", error=" + e + "].");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instructs the application to parse its <code>getdown.txt</code>
|
* Instructs the application to parse its <code>getdown.txt</code>
|
||||||
* configuration and prepare itself for operation. The application
|
* configuration and prepare itself for operation. The application
|
||||||
@@ -140,19 +166,13 @@ public class Application
|
|||||||
// first determine our application base, this way if anything goes
|
// first determine our application base, this way if anything goes
|
||||||
// wrong later in the process, our caller can use the appbase to
|
// wrong later in the process, our caller can use the appbase to
|
||||||
// download a new configuration file
|
// download a new configuration file
|
||||||
String appbase = (String)cdata.get("appbase");
|
_appbase = (String)cdata.get("appbase");
|
||||||
if (appbase == null) {
|
if (_appbase == null) {
|
||||||
throw new IOException("m.missing_appbase");
|
throw new IOException("m.missing_appbase");
|
||||||
}
|
}
|
||||||
try {
|
// make sure there's a trailing slash
|
||||||
// make sure there's a trailing slash
|
if (!_appbase.endsWith("/")) {
|
||||||
if (!appbase.endsWith("/")) {
|
_appbase = _appbase + "/";
|
||||||
appbase = appbase + "/";
|
|
||||||
}
|
|
||||||
_appbase = new URL(appbase);
|
|
||||||
} catch (Exception e) {
|
|
||||||
String err = MessageUtil.tcompose("m.invalid_appbase", appbase);
|
|
||||||
throw new NestableIOException(err, e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// extract our version information
|
// extract our version information
|
||||||
@@ -167,16 +187,15 @@ public class Application
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if we are a versioned deployment, create a versioned appbase
|
// if we are a versioned deployment, create a versioned appbase
|
||||||
if (_version < 0) {
|
try {
|
||||||
_vappbase = _appbase;
|
if (_version < 0) {
|
||||||
} else {
|
_vappbase = new URL(_appbase);
|
||||||
try {
|
} else {
|
||||||
_vappbase = new URL(
|
_vappbase = createVAppBase(_version);
|
||||||
StringUtil.replace(_appbase.toString(), "%VERSION%", vstr));
|
|
||||||
} catch (MalformedURLException mue) {
|
|
||||||
String err = MessageUtil.tcompose("m.invalid_appbase", appbase);
|
|
||||||
throw new NestableIOException(err, mue);
|
|
||||||
}
|
}
|
||||||
|
} catch (MalformedURLException mue) {
|
||||||
|
String err = MessageUtil.tcompose("m.invalid_appbase", _appbase);
|
||||||
|
throw new NestableIOException(err, mue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine our application class name
|
// determine our application class name
|
||||||
@@ -271,6 +290,30 @@ public class Application
|
|||||||
downloadControlFile(CONFIG_FILE);
|
downloadControlFile(CONFIG_FILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Downloads and replaces the <code>getdown.txt</code> and
|
||||||
|
* <code>digest.txt</code> files with those for the target version of
|
||||||
|
* our application.
|
||||||
|
*/
|
||||||
|
public void updateMetadata ()
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// update our versioned application base with the target version
|
||||||
|
_vappbase = createVAppBase(_targetVersion);
|
||||||
|
} catch (MalformedURLException mue) {
|
||||||
|
String err = MessageUtil.tcompose("m.invalid_appbase", _appbase);
|
||||||
|
throw new NestableIOException(err, mue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// now re-download our control files; we download the digest first
|
||||||
|
// so that if it fails, our config file will still reference the
|
||||||
|
// old version and re-running the updater will start the whole
|
||||||
|
// process over again
|
||||||
|
downloadControlFile(Digest.DIGEST_FILE);
|
||||||
|
downloadControlFile(CONFIG_FILE);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invokes the process associated with this application definition.
|
* Invokes the process associated with this application definition.
|
||||||
*/
|
*/
|
||||||
@@ -345,7 +388,7 @@ public class Application
|
|||||||
public boolean verifyMetadata ()
|
public boolean verifyMetadata ()
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
Log.info("Verifying application: " + _appbase);
|
Log.info("Verifying application: " + _vappbase);
|
||||||
Log.info("Version: " + _version);
|
Log.info("Version: " + _version);
|
||||||
Log.info("Class: " + _class);
|
Log.info("Class: " + _class);
|
||||||
// Log.info("Code: " + StringUtil.toString(_codes.iterator()));
|
// Log.info("Code: " + StringUtil.toString(_codes.iterator()));
|
||||||
@@ -439,6 +482,25 @@ public class Application
|
|||||||
return (failures.size() == 0) ? null : failures;
|
return (failures.size() == 0) ? null : failures;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears all validation marker files.
|
||||||
|
*/
|
||||||
|
public void clearValidationMarkers ()
|
||||||
|
{
|
||||||
|
clearValidationMarkers(_codes.iterator());
|
||||||
|
clearValidationMarkers(_resources.iterator());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a versioned application base URL for the specified version.
|
||||||
|
*/
|
||||||
|
protected URL createVAppBase (int version)
|
||||||
|
throws MalformedURLException
|
||||||
|
{
|
||||||
|
return new URL(
|
||||||
|
StringUtil.replace(_appbase, "%VERSION%", "" + version));
|
||||||
|
}
|
||||||
|
|
||||||
/** A helper function used by {@link #verifyResources()}. */
|
/** A helper function used by {@link #verifyResources()}. */
|
||||||
protected void verifyResources (Iterator rsrcs, List failures)
|
protected void verifyResources (Iterator rsrcs, List failures)
|
||||||
{
|
{
|
||||||
@@ -463,13 +525,6 @@ public class Application
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Clears all validation marker files. */
|
|
||||||
protected void clearValidationMarkers ()
|
|
||||||
{
|
|
||||||
clearValidationMarkers(_codes.iterator());
|
|
||||||
clearValidationMarkers(_resources.iterator());
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Clears all validation marker files for the resources in the
|
/** Clears all validation marker files for the resources in the
|
||||||
* supplied iterator. */
|
* supplied iterator. */
|
||||||
protected void clearValidationMarkers (Iterator iter)
|
protected void clearValidationMarkers (Iterator iter)
|
||||||
@@ -493,7 +548,7 @@ public class Application
|
|||||||
targetURL = getRemoteURL(path);
|
targetURL = getRemoteURL(path);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.warning("Requested to download invalid control file " +
|
Log.warning("Requested to download invalid control file " +
|
||||||
"[appbase=" + _appbase + ", path=" + path +
|
"[appbase=" + _vappbase + ", path=" + path +
|
||||||
", error=" + e + "].");
|
", error=" + e + "].");
|
||||||
throw new NestableIOException("Invalid path '" + path + "'.", e);
|
throw new NestableIOException("Invalid path '" + path + "'.", e);
|
||||||
}
|
}
|
||||||
@@ -567,7 +622,8 @@ public class Application
|
|||||||
|
|
||||||
protected int _version = -1;
|
protected int _version = -1;
|
||||||
protected int _targetVersion = -1;
|
protected int _targetVersion = -1;
|
||||||
protected URL _appbase, _vappbase;
|
protected String _appbase;
|
||||||
|
protected URL _vappbase;
|
||||||
protected String _class;
|
protected String _class;
|
||||||
|
|
||||||
protected ArrayList _codes = new ArrayList();
|
protected ArrayList _codes = new ArrayList();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: Getdown.java,v 1.6 2004/07/07 10:45:20 mdb Exp $
|
// $Id: Getdown.java,v 1.7 2004/07/13 02:42:52 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.getdown.launcher;
|
package com.threerings.getdown.launcher;
|
||||||
|
|
||||||
@@ -16,6 +16,7 @@ import java.io.IOException;
|
|||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
|
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
@@ -43,6 +44,7 @@ public class Getdown
|
|||||||
public void run ()
|
public void run ()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
// first parses our application deployment file
|
||||||
try {
|
try {
|
||||||
_ifc = _app.init();
|
_ifc = _app.init();
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
@@ -52,29 +54,35 @@ public class Getdown
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int ii = 0; ii < MAX_LOOPS; ii++) {
|
for (int ii = 0; ii < MAX_LOOPS; ii++) {
|
||||||
|
// make sure we have the desired version and that the
|
||||||
|
// metadata files are valid...
|
||||||
if (_app.verifyMetadata()) {
|
if (_app.verifyMetadata()) {
|
||||||
Log.info("Application requires update.");
|
Log.info("Application requires update.");
|
||||||
update();
|
update();
|
||||||
|
// loop back again and reverify the metadata
|
||||||
} else {
|
continue;
|
||||||
Log.info("Metadata verified.");
|
|
||||||
List failures = _app.verifyResources();
|
|
||||||
if (failures == null) {
|
|
||||||
Log.info("Resources verified.");
|
|
||||||
launch();
|
|
||||||
return;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
Log.info(failures.size() + " rsrcs require update.");
|
|
||||||
download(failures);
|
|
||||||
// now we'll loop back and try it all again
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// now verify our resources...
|
||||||
|
List failures = _app.verifyResources();
|
||||||
|
if (failures == null) {
|
||||||
|
Log.info("Resources verified.");
|
||||||
|
launch();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// redownload any that are corrupt or invalid...
|
||||||
|
Log.info(failures.size() + " rsrcs require update.");
|
||||||
|
download(failures);
|
||||||
|
// now we'll loop back and try it all again
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.warning("Pants! We couldn't get the job done.");
|
Log.warning("Pants! We couldn't get the job done.");
|
||||||
|
// TODO: throw exception
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.logStackTrace(e);
|
Log.logStackTrace(e);
|
||||||
|
// TODO: display error to user
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +90,30 @@ public class Getdown
|
|||||||
* Called if the application is determined to be of an old version.
|
* Called if the application is determined to be of an old version.
|
||||||
*/
|
*/
|
||||||
protected void update ()
|
protected void update ()
|
||||||
|
throws IOException
|
||||||
{
|
{
|
||||||
|
// first clear all validation markers
|
||||||
|
_app.clearValidationMarkers();
|
||||||
|
|
||||||
|
// attempt to download the patch file
|
||||||
|
Resource patch = _app.getPatchResource();
|
||||||
|
if (patch != null) {
|
||||||
|
// download the patch file...
|
||||||
|
ArrayList list = new ArrayList();
|
||||||
|
list.add(patch);
|
||||||
|
download(list);
|
||||||
|
|
||||||
|
// and apply it...
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
// if the patch resource is null, that means something was booched
|
||||||
|
// in the application, so we skip the patching process but update
|
||||||
|
// the metadata which will result in a "brute force" upgrade
|
||||||
|
|
||||||
|
// finally update our metadata files...
|
||||||
|
_app.updateMetadata();
|
||||||
|
// ...and reinitialize the application
|
||||||
|
_ifc = _app.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -196,16 +227,21 @@ public class Getdown
|
|||||||
|
|
||||||
public static void main (String[] args)
|
public static void main (String[] args)
|
||||||
{
|
{
|
||||||
// ensure the proper parameters are passed
|
// maybe they specified the appdir in a system property
|
||||||
if (args.length != 1) {
|
String adarg = System.getProperty("appdir");
|
||||||
System.err.println("Usage: java -jar getdown.jar app_dir");
|
// if not, check for a command line argument
|
||||||
System.exit(-1);
|
if (StringUtil.blank(adarg)) {
|
||||||
|
if (args.length != 1) {
|
||||||
|
System.err.println("Usage: java -jar getdown.jar app_dir");
|
||||||
|
System.exit(-1);
|
||||||
|
}
|
||||||
|
adarg = args[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure a valid directory was supplied
|
// ensure a valid directory was supplied
|
||||||
File appDir = new File(args[0]);
|
File appDir = new File(adarg);
|
||||||
if (!appDir.exists() || !appDir.isDirectory()) {
|
if (!appDir.exists() || !appDir.isDirectory()) {
|
||||||
Log.warning("Invalid app_dir '" + args[0] + "'.");
|
Log.warning("Invalid app_dir '" + adarg + "'.");
|
||||||
System.exit(-1);
|
System.exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user