[pacman-dev] [PATCH] Support parallel download with xfercommand

lesto lestofante88 at gmail.com
Mon Oct 19 23:19:56 UTC 2020


Signed-off-by: lesto <lestofante88 at gmail.com>
---
 lib/libalpm/alpm.h       | 10 ++++++++++
 lib/libalpm/dload.c      |  9 +++++++++
 lib/libalpm/handle.c     | 13 +++++++++++++
 lib/libalpm/handle.h     |  1 +
 src/pacman/conf.c        |  5 ++++-
 src/pacman/conf.h        |  1 +
 src/pacman/pacman-conf.c |  3 +++
 7 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index 614a530c..c2af60e8 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -755,6 +755,11 @@ typedef void (*alpm_cb_totaldl)(off_t total);
 typedef int (*alpm_cb_fetch)(const char *url, const char *localpath,
 		int force);
 
+/** A callback for waiting for download of files
+ * @return 0 on success, -1 on error.
+ */
+typedef int (*alpm_cb_fetch_lock)(void);
+
 /** Fetch a list of remote packages.
  * @param handle the context handle
  * @param urls list of package URLs to download
@@ -787,6 +792,11 @@ alpm_cb_fetch alpm_option_get_fetchcb(alpm_handle_t *handle);
 /** Sets the downloading callback. */
 int alpm_option_set_fetchcb(alpm_handle_t *handle, alpm_cb_fetch cb);
 
+/** Returns the downloading lock callback. */
+alpm_cb_fetch_lock alpm_option_get_fetch_lockcb(alpm_handle_t *handle);
+/** Sets the downloading lock callback. */
+int alpm_option_set_fetch_lockcb(alpm_handle_t *handle, alpm_cb_fetch_lock cb);
+
 /** Returns the callback used to report total download size. */
 alpm_cb_totaldl alpm_option_get_totaldlcb(alpm_handle_t *handle);
 /** Sets the callback used to report total download size. */
diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c
index 673e769f..174d559d 100644
--- a/lib/libalpm/dload.c
+++ b/lib/libalpm/dload.c
@@ -824,6 +824,15 @@ int _alpm_download(alpm_handle_t *handle,
 				RET_ERR(handle, ALPM_ERR_EXTERNAL_DOWNLOAD, -1);
 			}
 		}
+
+		if (handle->fetch_lockcb != NULL) {
+			// if fetch_lockcb is set, fetchcb is non-blocking; here we wait for all download to complete
+			int ret = handle->fetch_lockcb();
+			if (ret == -1) {
+				RET_ERR(handle, ALPM_ERR_EXTERNAL_DOWNLOAD, -1);
+			}
+		}
+
 		return 0;
 	}
 }
diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c
index 1310601a..683e678d 100644
--- a/lib/libalpm/handle.c
+++ b/lib/libalpm/handle.c
@@ -174,6 +174,12 @@ alpm_cb_fetch SYMEXPORT alpm_option_get_fetchcb(alpm_handle_t *handle)
 	return handle->fetchcb;
 }
 
+alpm_cb_fetch_lock SYMEXPORT alpm_option_get_fetch_lockcb(alpm_handle_t *handle)
+{
+	CHECK_HANDLE(handle, return NULL);
+	return handle->fetch_lockcb;
+}
+
 alpm_cb_totaldl SYMEXPORT alpm_option_get_totaldlcb(alpm_handle_t *handle)
 {
 	CHECK_HANDLE(handle, return NULL);
@@ -321,6 +327,13 @@ int SYMEXPORT alpm_option_set_fetchcb(alpm_handle_t *handle, alpm_cb_fetch cb)
 	return 0;
 }
 
+int SYMEXPORT alpm_option_set_fetch_lockcb(alpm_handle_t *handle, alpm_cb_fetch_lock cb)
+{
+	CHECK_HANDLE(handle, return -1);
+	handle->fetch_lockcb = cb;
+	return 0;
+}
+
 int SYMEXPORT alpm_option_set_totaldlcb(alpm_handle_t *handle, alpm_cb_totaldl cb)
 {
 	CHECK_HANDLE(handle, return -1);
diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h
index 9fef0fbf..dc00751b 100644
--- a/lib/libalpm/handle.h
+++ b/lib/libalpm/handle.h
@@ -73,6 +73,7 @@ struct __alpm_handle_t {
 	alpm_cb_download dlcb;      /* Download callback function */
 	alpm_cb_totaldl totaldlcb;  /* Total download callback function */
 	alpm_cb_fetch fetchcb;      /* Download file callback function */
+	alpm_cb_fetch_lock fetch_lockcb;        /* Download lock file callback function */
 	alpm_cb_event eventcb;
 	alpm_cb_question questioncb;
 	alpm_cb_progress progresscb;
diff --git a/src/pacman/conf.c b/src/pacman/conf.c
index 3a3ef605..53de73b8 100644
--- a/src/pacman/conf.c
+++ b/src/pacman/conf.c
@@ -157,6 +157,7 @@ int config_free(config_t *oldconfig)
 	FREELIST(oldconfig->hookdirs);
 	FREELIST(oldconfig->cachedirs);
 	free(oldconfig->xfercommand);
+	free(oldconfig->xferlockcommand);
 	free(oldconfig->print_format);
 	free(oldconfig->arch);
 	wordsplit_free(oldconfig->xfercommand_argv);
@@ -319,7 +320,9 @@ static int download_with_xfercommand(const char *url, const char *localpath,
 	for(i = 0; i <= config->xfercommand_argc; i++) {
 		const char *val = config->xfercommand_argv[i];
 		if(val && strcmp(val, "%o") == 0) {
-			usepart = 1;
+			if (config->xferlockcommand == NULL) {
+				usepart = 1;
+			}
 			val = tempfile;
 		} else if(val && strcmp(val, "%u") == 0) {
 			val = url;
diff --git a/src/pacman/conf.h b/src/pacman/conf.h
index b8a451ad..1a9d637d 100644
--- a/src/pacman/conf.h
+++ b/src/pacman/conf.h
@@ -130,6 +130,7 @@ typedef struct __config_t {
 	char *xfercommand;
 	char **xfercommand_argv;
 	size_t xfercommand_argc;
+	char *xferlockcommand;
 
 	/* our connection to libalpm */
 	alpm_handle_t *handle;
diff --git a/src/pacman/pacman-conf.c b/src/pacman/pacman-conf.c
index 463badf1..7c4f4cc9 100644
--- a/src/pacman/pacman-conf.c
+++ b/src/pacman/pacman-conf.c
@@ -259,6 +259,7 @@ static void dump_config(void)
 
 	show_str("Architecture", config->arch);
 	show_str("XferCommand", config->xfercommand);
+	show_str("XferLockCommand", config->xferlockcommand);
 
 	show_bool("UseSyslog", config->usesyslog);
 	show_bool("Color", config->color);
@@ -366,6 +367,8 @@ static int list_directives(void)
 			show_str("Architecture", config->arch);
 		} else if(strcasecmp(i->data, "XferCommand") == 0) {
 			show_str("XferCommand", config->xfercommand);
+		} else if(strcasecmp(i->data, "XferLockCommand") == 0) {
+			show_str("XferLockCommand", config->xferlockcommand);
 
 		} else if(strcasecmp(i->data, "UseSyslog") == 0) {
 			show_bool("UseSyslog", config->usesyslog);
-- 
2.28.0


More information about the pacman-dev mailing list