[pacman-dev] [PATCH 3/4] Download delta files if UseDelta is set.

Dan McGee dpmcgee at gmail.com
Mon Oct 15 22:50:57 EDT 2007


On 10/15/07, Nathan Jones <nathanj at insightbb.com> wrote:
> Signed-off-by: Nathan Jones <nathanj at insightbb.com>
> ---
>  lib/libalpm/alpm.h   |    1 +
>  lib/libalpm/handle.c |    6 +++
>  lib/libalpm/handle.h |    1 +
>  lib/libalpm/sync.c   |  115 +++++++++++++++++++++++++++++++++++++++++++++++++-
>  src/pacman/pacman.c  |    3 +
>  5 files changed, 124 insertions(+), 2 deletions(-)
>
> diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
> index 527822d..85c0905 100644
> --- a/lib/libalpm/alpm.h
> +++ b/lib/libalpm/alpm.h
> @@ -138,6 +138,7 @@ void alpm_option_set_xfercommand(const char *cmd);
>
>  unsigned short alpm_option_get_nopassiveftp();
>  void alpm_option_set_nopassiveftp(unsigned short nopasv);
> +void alpm_option_set_usedelta(unsigned short usedelta);
>
>  pmdb_t *alpm_option_get_localdb();
>  alpm_list_t *alpm_option_get_syncdbs();
> diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c
> index e8f2147..242bbe5 100644
> --- a/lib/libalpm/handle.c
> +++ b/lib/libalpm/handle.c
> @@ -64,6 +64,7 @@ pmhandle_t *_alpm_handle_new()
>         handle->cachedirs = NULL;
>         handle->lockfile = NULL;
>         handle->logfile = NULL;
> +       handle->usedelta = 0;
>
>         return(handle);
>  }
> @@ -496,4 +497,9 @@ void SYMEXPORT alpm_option_set_nopassiveftp(unsigned short nopasv)
>         handle->nopassiveftp = nopasv;
>  }
>
> +void SYMEXPORT alpm_option_set_usedelta(unsigned short usedelta)
> +{
> +       handle->usedelta = usedelta;
> +}
> +
>  /* vim: set ts=2 sw=2 noet: */
> diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h
> index cf2e9d5..d8edf00 100644
> --- a/lib/libalpm/handle.h
> +++ b/lib/libalpm/handle.h
> @@ -61,6 +61,7 @@ typedef struct _pmhandle_t {
>         unsigned short nopassiveftp; /* Don't use PASV ftp connections */
>         time_t upgradedelay;      /* Time to wait before upgrading a package */
>         char *xfercommand;        /* External download command */
> +       unsigned short usedelta;     /* Download deltas if possible */
>  } pmhandle_t;
>
>  extern pmhandle_t *handle;
> diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
> index d24a1e5..8aa197d 100644
> --- a/lib/libalpm/sync.c
> +++ b/lib/libalpm/sync.c
> @@ -48,6 +48,7 @@
>  #include "handle.h"
>  #include "alpm.h"
>  #include "server.h"
> +#include "delta.h"
>
>  pmsyncpkg_t *_alpm_sync_new(int type, pmpkg_t *spkg, void *data)
>  {
> @@ -700,9 +701,54 @@ cleanup:
>         return(ret);
>  }
>
> +/** Returns a list of deltas that should be downloaded instead of the
> + * package.
> + *
> + * Then it tests if a delta path exists between the currently installed
> + * version (if any) and the version to upgrade to. If so, the delta path
> + * is used if its size is below a set percentage of the package size,
> + * Otherwise, an empty list is returned.
> + *
> + * @param newpkg the new package to upgrade to
> + * @param db_local the local database
> + *
> + * @return the list of pmdelta_t * objects. NULL (the empty list) is
> + * returned if the package should be downloaded instead of deltas.
> + */
> +static alpm_list_t *pkg_upgrade_delta_path(pmpkg_t *newpkg, pmdb_t *db_local)
> +{
> +       pmpkg_t *oldpkg = alpm_db_get_pkg(db_local, newpkg->name);
> +
> +       if(oldpkg) {
> +               const char *oldname = alpm_pkg_get_filename(oldpkg);
> +               char *oldpath = _alpm_filecache_find(oldname);
> +
> +               if(oldpath) {
> +                       alpm_list_t *deltas = alpm_shortest_delta_path(
> +                                       alpm_pkg_get_deltas(newpkg),
> +                                       alpm_pkg_get_version(oldpkg),
> +                                       alpm_pkg_get_version(newpkg));
> +
> +                       if(deltas) {
> +                               unsigned long dltsize = _alpm_delta_path_size(deltas);
> +                               unsigned long pkgsize = alpm_pkg_get_size(newpkg);
> +
> +                               if(dltsize < pkgsize * 0.7) {

I'd feel a bit better if this was #defined in util.h. (Something like
MAX_DELTA_RATIO?)

> +                                       return deltas;
> +                               } else {
> +                                       alpm_list_free(deltas);
> +                               }
> +                       }
> +               }
> +       }
> +
> +       return NULL;
> +}
> +
>  int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
>  {
>         alpm_list_t *i, *j, *files = NULL;
> +       alpm_list_t *patches = NULL;
>         pmtrans_t *tr = NULL;
>         int replaces = 0, retval = 0;
>         const char *cachedir = NULL;
> @@ -733,8 +779,39 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
>                                 } else {
>                                         char *fpath = _alpm_filecache_find(fname);
>                                         if(!fpath) {
> -                                               /* file is not in the cache dir, so add it to the list */
> -                                               files = alpm_list_add(files, strdup(fname));
> +                                               if(handle->usedelta) {
> +                                                       alpm_list_t *delta_path = pkg_upgrade_delta_path(spkg, db_local);
> +
> +                                                       if(delta_path) {
> +                                                               alpm_list_t *dlts = NULL;
> +
> +                                                               for(dlts = delta_path; dlts; dlts = alpm_list_next(dlts)) {
> +                                                                       pmdelta_t *d = (pmdelta_t *)alpm_list_getdata(dlts);
> +                                                                       char *fpath2 = _alpm_filecache_find(d->filename);
> +
> +                                                                       if(!fpath2) {
> +                                                                               /* add the delta filename to the download list if
> +                                                                                * it's not in the cache*/
> +                                                                               files = alpm_list_add(files, strdup(d->filename));
> +                                                                       }
> +
> +                                                                       /* save the pkg and delta so that the xdelta patch
> +                                                                        * command can be run after the downloads finish */
> +                                                                       patches = alpm_list_add(patches, spkg);
> +                                                                       patches = alpm_list_add(patches, d);
> +                                                               }
> +
> +                                                               alpm_list_free(delta_path);
> +                                                               delta_path = NULL;
> +                                                       } else {
> +                                                               /* no deltas to download, so add the file to the
> +                                                                * download list */
> +                                                               files = alpm_list_add(files, strdup(fname));
> +                                                       }
> +                                               } else {
> +                                                       /* not using deltas, so add the file to the download list */
> +                                                       files = alpm_list_add(files, strdup(fname));
> +                                               }
>                                         }
>                                         FREE(fpath);
>                                 }
> @@ -750,6 +827,40 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
>                         }
>                         FREELIST(files);
>                 }
> +
> +               if(handle->usedelta) {
> +                       /* now apply any deltas that have been downloaded */
> +                       alpm_list_t *p = patches;
> +                       while(p) {
> +                               pmpkg_t *pkg;
> +                               pmdelta_t *d;
> +                               char command[512];
> +
> +                               pkg = alpm_list_getdata(p);
> +                               p = alpm_list_next(p);
> +
> +                               d = alpm_list_getdata(p);
> +                               p = alpm_list_next(p);
> +
> +                               snprintf(command, 512,

Using PATH_MAX instead of a hardcoded value would probably be best.
Its just a local 1-time alloc so memory usage is not much of a
concern. I might also put a comment here showing an example string we
are buildling.

> +                                               "xdelta patch %s/%s %s/%s-%s-%s.pkg.tar.gz %s/%s-%s-%s.pkg.tar.gz",
> +                                               cachedir, d->filename,
> +                                               cachedir, pkg->name, d->from, pkg->arch,
> +                                               cachedir, pkg->name, d->to, pkg->arch);
> +                               _alpm_log(PM_LOG_DEBUG, _("command: %s\n"), command);
> +
> +                               printf("Generating %s-%s-%s.pkg.tar.gz with %s... ",
> +                                               pkg->name, d->to, pkg->arch, d->filename);
> +                               if(system(command) == 0) {

I don't have much experience with this, so I'd like to have someone
else chime in. Is system() the best call to be making, or should we do
it another way (fork/exec like the scriptlets comes to mind).

> +                                       printf("done.\n");
> +                               } else {
> +                                       printf("failed.\n");
> +                               }
> +                       }
> +
> +                       alpm_list_free(patches);
> +                       patches = NULL;
> +               }
>         }
>         if(trans->flags & PM_TRANS_FLAG_PRINTURIS) {
>                 return(0);
> diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c
> index 8474020..2f6f928 100644
> --- a/src/pacman/pacman.c
> +++ b/src/pacman/pacman.c
> @@ -548,6 +548,9 @@ static int _parseconfig(const char *file, const char *givensection,
>                                 } else if(strcmp(key, "ShowSize") == 0 || strcmp(upperkey, "SHOWSIZE") == 0) {
>                                         config->showsize = 1;
>                                         pm_printf(PM_LOG_DEBUG, "config: showsize\n");
> +                               } else if(strcmp(key, "UseDelta") == 0 || strcmp(upperkey, "USEDELTA") == 0) {
> +                                       alpm_option_set_usedelta(1);
> +                                       pm_printf(PM_LOG_DEBUG, "config: usedelta\n");
>                                 } else {
>                                         pm_printf(PM_LOG_ERROR, _("config file %s, line %d: directive '%s' not recognized.\n"),
>                                                         file, linenum, key);
> --
> 1.5.3.4
>
> _______________________________________________
> pacman-dev mailing list
> pacman-dev at archlinux.org
> http://archlinux.org/mailman/listinfo/pacman-dev
>




More information about the pacman-dev mailing list