[pacman-dev] [PATCH] Allow UseDelta option to specify a delta ratio

Dan McGee dan at archlinux.org
Wed Jan 11 16:42:55 EST 2012


Rework the frontend and backend to allow passing a ratio value in for
UseDelta rather than having a hardcoded #define-d 0.7 value always used.
This is useful for those with fast connections, who would likely benefit
from tuning this ratio to lower values; it is also useful for general
testing purposes.

The libalpm API changes for this, but we do support the old config file
format with a no-value 'UseDelta' option; in this case we simply use the
old default of 0.7.

We clamp the ratio values to a sane range between 0.0 and 2.0, allowing
ratios above 1.0 for testing purposes.

Signed-off-by: Dan McGee <dan at archlinux.org>
---
 doc/pacman.conf.5.txt |   10 +++++++---
 etc/pacman.conf.in    |    2 +-
 lib/libalpm/alpm.h    |    4 ++--
 lib/libalpm/delta.c   |    3 ++-
 lib/libalpm/delta.h   |    3 ---
 lib/libalpm/handle.c  |   12 ++++++++----
 lib/libalpm/handle.h  |    2 +-
 lib/libalpm/sync.c    |    4 ++--
 src/pacman/conf.c     |   19 ++++++++++++++++---
 src/pacman/conf.h     |    2 +-
 10 files changed, 40 insertions(+), 21 deletions(-)

diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt
index 2c1a24b..3913292 100644
--- a/doc/pacman.conf.5.txt
+++ b/doc/pacman.conf.5.txt
@@ -168,9 +168,13 @@ Options
 	Log action messages through syslog(). This will insert log entries into
 	+{localstatedir}/log/messages+ or equivalent.
 
-*UseDelta*::
-	Download delta files instead of complete packages if possible.  Requires
-	the xdelta3 program to be installed.
+*UseDelta* [= ratio]::
+	Download delta files instead of complete packages if possible. Requires
+	the `xdelta3` program to be installed. If a ratio is specified (e.g.,
+	`0.5`), then it is used as a cutoff for determining whether to use deltas.
+	Allowed values are between `0.0` and `2.0`; sensible values are between
+	`0.2` and `0.9`.  Using a value above `1.0` is not recommended.  The
+	default is `0.7` if left unspecified.
 
 *TotalDownload*::
 	When downloading, display the amount downloaded, download rate, ETA,
diff --git a/etc/pacman.conf.in b/etc/pacman.conf.in
index 932140f..7f9db1b 100644
--- a/etc/pacman.conf.in
+++ b/etc/pacman.conf.in
@@ -20,6 +20,7 @@ SyncFirst   = pacman
 #XferCommand = /usr/bin/curl -C - -f %u > %o
 #XferCommand = /usr/bin/wget --passive-ftp -c -O %o %u
 #CleanMethod = KeepInstalled
+#UseDelta    = 0.7
 Architecture = auto
 
 # Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup
@@ -31,7 +32,6 @@ Architecture = auto
 
 # Misc options
 #UseSyslog
-#UseDelta
 #TotalDownload
 CheckSpace
 #VerbosePkgLists
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index 95c817e..9ffdebc 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -535,8 +535,8 @@ const char *alpm_option_get_arch(alpm_handle_t *handle);
 /** Sets the targeted architecture. */
 int alpm_option_set_arch(alpm_handle_t *handle, const char *arch);
 
-int alpm_option_get_usedelta(alpm_handle_t *handle);
-int alpm_option_set_usedelta(alpm_handle_t *handle, int usedelta);
+double alpm_option_get_deltaratio(alpm_handle_t *handle);
+int alpm_option_set_deltaratio(alpm_handle_t *handle, double ratio);
 
 int alpm_option_get_checkspace(alpm_handle_t *handle);
 int alpm_option_set_checkspace(alpm_handle_t *handle, int checkspace);
diff --git a/lib/libalpm/delta.c b/lib/libalpm/delta.c
index 726f03c..e3acc66 100644
--- a/lib/libalpm/delta.c
+++ b/lib/libalpm/delta.c
@@ -264,7 +264,8 @@ static alpm_list_t *find_unused(alpm_list_t *deltas, const char *to, off_t quota
 alpm_list_t SYMEXPORT *alpm_pkg_unused_deltas(alpm_pkg_t *pkg)
 {
 	ASSERT(pkg != NULL, return NULL);
-	return find_unused(pkg->deltas, pkg->filename, pkg->size * MAX_DELTA_RATIO);
+	return find_unused(pkg->deltas, pkg->filename,
+			pkg->size * pkg->handle->deltaratio);
 }
 
 /** @} */
diff --git a/lib/libalpm/delta.h b/lib/libalpm/delta.h
index 1173ddf..37f208b 100644
--- a/lib/libalpm/delta.h
+++ b/lib/libalpm/delta.h
@@ -30,9 +30,6 @@ alpm_delta_t *_alpm_delta_dup(const alpm_delta_t *delta);
 off_t _alpm_shortest_delta_path(alpm_handle_t *handle, alpm_list_t *deltas,
 		const char *to, alpm_list_t **path);
 
-/* max percent of package size to download deltas */
-#define MAX_DELTA_RATIO 0.7
-
 #endif /* _ALPM_DELTA_H */
 
 /* vim: set ts=2 sw=2 noet: */
diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c
index 8e2e3c7..2187dca 100644
--- a/lib/libalpm/handle.c
+++ b/lib/libalpm/handle.c
@@ -43,6 +43,7 @@ alpm_handle_t *_alpm_handle_new(void)
 	alpm_handle_t *handle;
 
 	CALLOC(handle, 1, sizeof(alpm_handle_t), return NULL);
+	handle->deltaratio = 0.0;
 
 	return handle;
 }
@@ -252,10 +253,10 @@ const char SYMEXPORT *alpm_option_get_arch(alpm_handle_t *handle)
 	return handle->arch;
 }
 
-int SYMEXPORT alpm_option_get_usedelta(alpm_handle_t *handle)
+double SYMEXPORT alpm_option_get_deltaratio(alpm_handle_t *handle)
 {
 	CHECK_HANDLE(handle, return -1);
-	return handle->usedelta;
+	return handle->deltaratio;
 }
 
 int SYMEXPORT alpm_option_get_checkspace(alpm_handle_t *handle)
@@ -597,10 +598,13 @@ int SYMEXPORT alpm_option_set_arch(alpm_handle_t *handle, const char *arch)
 	return 0;
 }
 
-int SYMEXPORT alpm_option_set_usedelta(alpm_handle_t *handle, int usedelta)
+int SYMEXPORT alpm_option_set_deltaratio(alpm_handle_t *handle, double ratio)
 {
 	CHECK_HANDLE(handle, return -1);
-	handle->usedelta = usedelta;
+	if(ratio < 0.0 || ratio > 2.0) {
+		RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1);
+	}
+	handle->deltaratio = ratio;
 	return 0;
 }
 
diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h
index a64c5c9..a090ae4 100644
--- a/lib/libalpm/handle.h
+++ b/lib/libalpm/handle.h
@@ -88,8 +88,8 @@ struct __alpm_handle_t {
 
 	/* options */
 	char *arch;              /* Architecture of packages we should allow */
+	double deltaratio;       /* Download deltas if possible; a ratio value */
 	int usesyslog;           /* Use syslog instead of logfile? */ /* TODO move to frontend */
-	int usedelta;            /* Download deltas if possible */
 	int checkspace;          /* Check disk space before installing */
 	alpm_siglevel_t siglevel;   /* Default signature verification level */
 
diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
index 49a3f42..6967b49 100644
--- a/lib/libalpm/sync.c
+++ b/lib/libalpm/sync.c
@@ -318,13 +318,13 @@ static int compute_download_size(alpm_pkg_t *newpkg)
 
 		/* tell the caller that we have a partial */
 		ret = 1;
-	} else if(handle->usedelta) {
+	} else if(handle->deltaratio > 0.0) {
 		off_t dltsize;
 
 		dltsize = _alpm_shortest_delta_path(handle, newpkg->deltas,
 				newpkg->filename, &newpkg->delta_path);
 
-		if(newpkg->delta_path && (dltsize < newpkg->size * MAX_DELTA_RATIO)) {
+		if(newpkg->delta_path && (dltsize < newpkg->size * handle->deltaratio)) {
 			_alpm_log(handle, ALPM_LOG_DEBUG, "using delta size\n");
 			size = dltsize;
 		} else {
diff --git a/src/pacman/conf.c b/src/pacman/conf.c
index 7ba2791..e1bff18 100644
--- a/src/pacman/conf.c
+++ b/src/pacman/conf.c
@@ -52,6 +52,7 @@ config_t *config_new(void)
 	newconfig->op = PM_OP_MAIN;
 	newconfig->logmask = ALPM_LOG_ERROR | ALPM_LOG_WARNING;
 	newconfig->configfile = strdup(CONFFILE);
+	newconfig->deltaratio = 0.0;
 	if(alpm_capabilities() & ALPM_CAPABILITY_SIGNATURES) {
 		newconfig->siglevel = ALPM_SIG_PACKAGE | ALPM_SIG_PACKAGE_OPTIONAL |
 			ALPM_SIG_DATABASE | ALPM_SIG_DATABASE_OPTIONAL;
@@ -397,8 +398,8 @@ static int _parse_options(const char *key, char *value,
 			config->verbosepkglists = 1;
 			pm_printf(ALPM_LOG_DEBUG, "config: verbosepkglists\n");
 		} else if(strcmp(key, "UseDelta") == 0) {
-			config->usedelta = 1;
-			pm_printf(ALPM_LOG_DEBUG, "config: usedelta\n");
+			config->deltaratio = 0.7;
+			pm_printf(ALPM_LOG_DEBUG, "config: usedelta (default 0.7)\n");
 		} else if(strcmp(key, "TotalDownload") == 0) {
 			config->totaldownload = 1;
 			pm_printf(ALPM_LOG_DEBUG, "config: totaldownload\n");
@@ -429,6 +430,18 @@ static int _parse_options(const char *key, char *value,
 			if(!config->arch) {
 				config_set_arch(value);
 			}
+		} else if(strcmp(key, "UseDelta") == 0) {
+			double ratio;
+			char *endptr;
+			ratio = strtod(value, &endptr);
+			if(*endptr != '\0' || ratio < 0.0 || ratio > 2.0) {
+				pm_printf(ALPM_LOG_ERROR,
+						_("config file %s, line %d: invalid value for '%s' : '%s'\n"),
+						file, linenum, "UseDelta", value);
+				return 1;
+			}
+			config->deltaratio = ratio;
+			pm_printf(ALPM_LOG_DEBUG, "config: usedelta = %f\n", ratio);
 		} else if(strcmp(key, "DBPath") == 0) {
 			/* don't overwrite a path specified on the command line */
 			if(!config->dbpath) {
@@ -605,7 +618,7 @@ static int setup_libalpm(void)
 	alpm_option_set_arch(handle, config->arch);
 	alpm_option_set_checkspace(handle, config->checkspace);
 	alpm_option_set_usesyslog(handle, config->usesyslog);
-	alpm_option_set_usedelta(handle, config->usedelta);
+	alpm_option_set_deltaratio(handle, config->deltaratio);
 
 	alpm_option_set_ignorepkgs(handle, config->ignorepkg);
 	alpm_option_set_ignoregroups(handle, config->ignoregrp);
diff --git a/src/pacman/conf.h b/src/pacman/conf.h
index 325fbb6..481132f 100644
--- a/src/pacman/conf.h
+++ b/src/pacman/conf.h
@@ -34,7 +34,7 @@ typedef struct __config_t {
 	unsigned short print;
 	unsigned short checkspace;
 	unsigned short usesyslog;
-	unsigned short usedelta;
+	double deltaratio;
 	char *arch;
 	char *print_format;
 	/* unfortunately, we have to keep track of paths both here and in the library
-- 
1.7.8.3



More information about the pacman-dev mailing list