summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre Habouzit <madcoder@debian.org>2009-07-22 11:17:20 +0200
committerJoey Hess <joey@gnu.kitenet.net>2009-07-25 09:59:37 +0200
commit2470d063c10dc25daeedb31bcd77865da06d65fd (patch)
tree7708c601765b8bda9137fb52a6d825673776238d
parentf933ad5fa6a1a400426763576895f050da32ccbf (diff)
downloadmoreutils-2470d063c10dc25daeedb31bcd77865da06d65fd.tar.gz
support -n option
This makes parallel stuff more than one argument to the subcommands. It's very useful when subcommands are slow to start and are able to process multiple files at once, that tasks are small but plenty. For example: $ ./parallel -n 3 echo -- a b c d e f g h a b c d e f g h Signed-off-by: Pierre Habouzit <madcoder@debian.org>
-rw-r--r--parallel.c46
-rw-r--r--parallel.docbook8
2 files changed, 39 insertions, 15 deletions
diff --git a/parallel.c b/parallel.c
index 8045e22..99a9727 100644
--- a/parallel.c
+++ b/parallel.c
@@ -38,7 +38,7 @@ void usage() {
exit(1);
}
-void exec_child(char **command, char *argument, int replace_cb) {
+void exec_child(char **command, char **arguments, int replace_cb, int nargs) {
char **argv;
int argc = 0;
int i;
@@ -48,14 +48,14 @@ void exec_child(char **command, char *argument, int replace_cb) {
}
if (replace_cb == 0)
argc++;
- argv = calloc(sizeof(char*), argc+1);
+ argv = calloc(sizeof(char*), argc + nargs);
for (i = 0; i < argc; i++) {
argv[i] = command[i];
if (replace_cb && (strcmp(argv[i], "{}") == 0))
- argv[i] = argument;
+ argv[i] = arguments[0];
}
if (replace_cb == 0)
- argv[i-1] = argument;
+ memcpy(argv + i - 1, arguments, nargs * sizeof(char *));
if (fork() == 0) {
/* Child */
execvp(argv[0], argv);
@@ -81,16 +81,18 @@ int main(int argc, char **argv) {
int maxjobs = -1;
int curjobs = 0;
int maxload = -1;
+ int argsatonce = 1;
int opt;
char **command = calloc(sizeof(char*), argc);
char **arguments = NULL;
int argidx = 0;
+ int arglen = 0;
int cidx = 0;
int returncode = 0;
int replace_cb = 0;
char *t;
- while ((opt = getopt(argc, argv, "+hij:l:")) != -1) {
+ while ((opt = getopt(argc, argv, "+hij:l:n:")) != -1) {
switch (opt) {
case 'h':
usage();
@@ -116,12 +118,26 @@ int main(int argc, char **argv) {
exit(2);
}
break;
+ case 'n':
+ errno = 0;
+ argsatonce = strtoul(optarg, &t, 0);
+ if (errno != 0 || argsatonce < 1 || (t-optarg) != strlen(optarg)) {
+ fprintf(stderr, "option '%s' is not a positive number\n",
+ optarg);
+ exit(2);
+ }
+ break;
default: /* ’?’ */
usage();
break;
}
}
+ if (replace_cb && argsatonce > 1) {
+ fprintf(stderr, "options -i and -n are incomaptible\n");
+ exit(2);
+ }
+
if (maxjobs < 0) {
#ifdef _SC_NPROCESSORS_ONLN
maxjobs = sysconf(_SC_NPROCESSORS_ONLN);
@@ -134,18 +150,15 @@ int main(int argc, char **argv) {
while (optind < argc) {
if (strcmp(argv[optind], "--") == 0) {
int i;
- size_t mem = (sizeof (char*)) * (argc - optind);
- arguments = malloc(mem);
+ optind++;
+ arglen = argc - optind;
+ arguments = calloc(sizeof(char *), arglen);
if (! arguments) {
exit(1);
}
- memset(arguments, 0, mem);
- optind++; /* Skip the -- separator, skip after
- * malloc so we have a trailing
- * null */
- for (i = 0; i < argc - optind; i++) {
+ for (i = 0; i < arglen; i++) {
arguments[i] = strdup(argv[optind + i]);
}
optind += i;
@@ -157,15 +170,18 @@ int main(int argc, char **argv) {
optind++;
}
- while (arguments[argidx] != 0) {
+ while (argidx < arglen) {
double load;
getloadavg(&load, 1);
if ((maxjobs > 0 && curjobs < maxjobs) ||
(maxload > 0 && load < maxload)) {
- exec_child(command, arguments[argidx], replace_cb);
- argidx++;
+ if (argsatonce > arglen - argidx)
+ argsatonce = arglen - argidx;
+ exec_child(command, arguments + argidx,
+ replace_cb, argsatonce);
+ argidx += argsatonce;
curjobs++;
}
diff --git a/parallel.docbook b/parallel.docbook
index 2fa5a5c..6da57bb 100644
--- a/parallel.docbook
+++ b/parallel.docbook
@@ -84,6 +84,14 @@ Written by Joey Hess
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>-n</option></term>
+ <listitem>
+ <para>Number of arguments to pass to one command at
+ once. Incompatible with -i</para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</refsect1>