This is one way to allow us to deploy the new split freenet-ext.jar. It's not
the simplest way, but it has certain other advantages, described below.
## Rationale
Unify existing platform-specific and distribution-specific installers and
freenet.jar's updater functionality into a single platform-indepedent
installer+updater that can handle a greater variety of installation layouts.
Most of the existing installers do very similar work, but have slight
differences in how they handle installation layouts and updates, etc. Some work
is platform-specific, such as setting registry keys or cron jobs, but the large
bulk of the work can be unified.
## Overview of new design
Along with freenet.jar, have a update-freenet.jar. This jar will take care of
both the initial installation, and any subsequent updates.
- It will be runnable via java -jar, or double-clicking in windows. (It should
read from stdin after execution so that windows users can see the output.)
- It must be self-contained and include any third-party libraries it depends on.
- It will replace all of the following:
- 1run.sh
- update.sh
- update.cmd
- all the helper *.jars used as part of the pre-install process
The general steps:
- attempt to download a "distribution" of freenet via HTTP into a $TMPDIR
- if $TMPDIR already exists, this is skipped
- if --only-local is given, this is skipped
- verify $TMPDIR using signatures and checksums hard-coded into the updater
- install components and update config files (expanded below)
- if a new wrapper was installed, launch a new one with the same {cwd,env,args}
and stop the current wrapper. this probably needs to be done from a separate
process. (if this turns out to be a problem, it's a problem for all updaters
not just this design.)
### Installing from scratch
Anything not listed above will need to be added to a platform-specific
installer, as is the case currently. The installer can then call
update-freenet.jar at an appropriate time during the overall process.
### Updating
The "updater" functionality within freenet.jar will be reduced to merely
downloading a new distribution from freenet, placing it in $TMPDIR (as
described above), then restarting itself. The update-freenet.jar will pick up
the changes and install them, then re-launch freenet.
This is accomplished by setting wrapper.java.command to a script that does the
equivalent of
if [ -d "$TMPDIR" ]; then
$JAVA -jar $FREENET_UPDATER --only-local
# the wrapper will automatically restart freenet
else
$JAVA "$@"
fi
This should be possible even with windows cmd.exe, but if not we can easily
write a small .exe to do it.
Env vars can be set in wrapper.conf - see [1]. Having $FREENET_UPDATER as an
env var allows us to update the updater in the same way as other components,
which would be necessary if e.g. we change certificates / keys.
[1] http://wrapper.tanukisoftware.com/doc/english/props-envvars.html#definition
## Design of update-freenet.jar
update-freenet.jar works on a "distribution" which is downloaded to a $TMPDIR
first. The distribution contains a manifest file with the following information
<stem> <version> <type>
- stem is something like "freenet-ext-$V.jar"
- version is any string, where ascii sort order determines age
- type is one of "jar", "lib", "bin", "wrapper-bin", "plugin-jar". each type
has an installation policy (expanded later)
Locally, we also need to store the following information in a "register" config
file:
<stem> <version> <fullpath> <in-use>
- fullpath: as installed on the filesystem; the basename must match
- in-use: whether in use by the current set of config files
This lists all the files installed by update-freenet.jar. When files are no
longer in-use, they can be deleted. To ensure safety, this file should be
updated in the same step as e.g. wrapper.conf, and likewise backed-up.
### Update algorithm
- download distro
the HTTP downloader (part of update-freenet.jar) might choose to skip files
if they already exist in the register, but to keep things simple and improve
retention, freenet.jar should probably simply download the entire distro
- touch .update_in_progress
- for each (s, v, t) in $TMPDIR/manifest
if register.inUse(s, v) { continue; }
Policy p = getPolicy(t);
File t = p.getInstallTargetLocation(s, v)
if (!f.exists()) {
register.add(s, v, false);
cp $TMPDIR/(s, v) to f;
} else if register.containsButNotInUse(s, v) {
// incomple install
cp $TMPDIR/(s, v) to f;
} else {
// already exists on system, possibly as a system library
}
- for each config "f"
if (no backup) { backup } else { restore backup /* start from scratch to be
safe */ }
after that, rewrite "f" to point to newly-installed files
- note: this INCLUDES the register, since we need to update the "in-use"
flag; but adding entries for newly-installed components is done above
- for each config "f"
- remove the backup, or move it to an archive folder so it doesn't interfere
with future logic
- rm .update_in_progress
(Of course, there needs to be
### Installation policy
getInstallTargetLocation(s, v) {
- usually this will be simply register.getPath(s, any-version).dirname()
- or register.getPath(any-s-of-same-type, any-version).dirname()
- it should only fall back to a hard-coded default ONLY IF ***all other
options have been exhausted***
### Migrating from the existing install scheme
We can migrate to the new scheme by bundling update-freenet.jar and the
platform-specific stub scripts into freenet.jar itself.
When freenet starts, if it doesn't detect the new scheme (e.g. if wrapper.conf
doesn't already define FREENET_UPDATER), then it can write those resources to
the appropriate places (e.g. the same directory as wrapper.conf).
We also need to initialise the register using existing system information. We
can obtain each <fullpath> as follows:
1. wrapper pid: WrapperManager.getWrapperPID()
2. wrapper bin: via syscall from wrapper pid
3. wrapper.conf: in command line of wrapper proc, via syscall from wrapper pid
4. wrapper lib: wrapper.conf
5. freenet.ini: wrapper.conf
6. freenet jars: wrapper.conf
7. plugin jars: freenet.ini
In this specific case, we can reverse the <stem> <version> from <fullpath>
because we also know what files are currently distributed.
After all of this, the next time freenet restarts, the new updater will be in
effect.
## End
I think that covers everything, or hopefully it gives enough info to
extrapolate solutions for everything else.
X
--
GPG: 4096R/5FBBDBCE
https://github.com/infinity0
https://bitbucket.org/infinity0
https://launchpad.net/~infinity0
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 900 bytes
Desc: OpenPGP digital signature
URL:
<https://emu.freenetproject.org/pipermail/devl/attachments/20120409/c79a8d07/attachment.pgp>