Skip to content

Commit e915f2c

Browse files
authored
Merge pull request #5277 from grondo/optparse-size
support `[kKMG]` suffixes in command options that take a bytes argument
2 parents 480a3ab + 7a40e83 commit e915f2c

File tree

15 files changed

+256
-38
lines changed

15 files changed

+256
-38
lines changed

doc/man1/flux-filemap.rst

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,19 @@ OPTIONS
6868

6969
**--small-file-threshold=N**
7070
Set the threshold in bytes over which a regular file is mapped through
71-
the distributed content cache. Set to 0 to always use the content cache.
72-
The default is 4096 (*map* subcommand only).
71+
the distributed content cache. Set to 0 to always use the content cache.
72+
N may be specified as a floating point number with multiplicative suffix
73+
k,K=1024, M=1024\*1024, or G=1024\*1024\*1024 up to ``INT_MAX``.
74+
The default is 4K (*map* subcommand only).
7375

7476
**--disable-mmap**
7577
Never map a regular file through the distributed content cache.
7678

7779
**--chunksize=N**
7880
Limit the content mapped blob size to N bytes. Set to 0 for unlimited.
79-
The default is 1048576 (*map* subcommand only).
81+
N may be specified as a floating point number with multiplicative suffix
82+
k,K=1024, M=1024\*1024, or G=1024\*1024\*1024 up to ``INT_MAX``.
83+
The default is 1M (*map* subcommand only).
8084

8185
**--direct**
8286
Avoid indirection through the content cache when fetching the top level

doc/man1/flux-ping.rst

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,11 @@ OPTIONS
4040
respectively. Default: send to “*any*”.
4141

4242
**-p, --pad**\ *=N*
43-
Include in the payload a string of length *N* bytes. The payload will be
44-
echoed back in the response. This option can be used to explore the
45-
effect of message size on latency. Default: no padding.
43+
Include in the payload a string of length *N* bytes. *N* may be a
44+
floating point number with optional multiplicative suffix k,K=1024,
45+
M=1024\*1024, or G=1024\*1024\*1024. The payload will be echoed back in
46+
the response. This option can be used to explore the effect of message
47+
size on latency. Default: no padding.
4648

4749
**-i, --interval**\ *=N*
4850
Specify the delay, in seconds, between successive requests.

doc/man1/flux-restore.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,10 @@ OPTIONS
5454
store. Performance will vary depending on the content of the archive.
5555

5656
**--size-limit**\ =\ *SIZE*
57-
Skip restoring keys that exceed SIZE bytes (default: no limit).
57+
Skip restoring keys that exceed SIZE bytes (default: no limit). SIZE may
58+
be specified as a floating point number with an optional multiplicative
59+
suffix k or K=1024, M=1024\*1024, or G=1024\*1024\*1024 (up to
60+
``INT_MAX``).
5861

5962
RESOURCES
6063
=========

etc/rc1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ if test $RANK -eq 0; then
4747
flux module load ${backingmod} truncate
4848
fi
4949
echo "restoring content from ${dumpfile}"
50-
flux restore --quiet --checkpoint --size-limit=104857600 ${dumpfile}
50+
flux restore --quiet --checkpoint --size-limit=100M ${dumpfile}
5151
if test -n "${dumplink}"; then
5252
rm -f ${dumplink}
5353
fi

src/cmd/builtin/filemap.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929
#include "src/common/libfilemap/filemap.h"
3030
#include "src/common/libutil/fileref.h"
3131

32-
static const int default_chunksize = 1048576;
33-
static const int default_small_file_threshold = 4096;
32+
static const char *default_chunksize = "1M";
33+
static const char *default_small_file_threshold = "4K";
3434

3535
static json_t *get_list_option (optparse_t *p,
3636
const char *name,
@@ -175,10 +175,12 @@ static int subcmd_map (optparse_t *p, int ac, char *av[])
175175
}
176176
ctx.p = p;
177177
ctx.verbose = optparse_get_int (p, "verbose", 0);
178-
ctx.chunksize = optparse_get_int (p, "chunksize", default_chunksize);
179-
ctx.threshold = optparse_get_int (p,
180-
"small-file-threshold",
181-
default_small_file_threshold);
178+
ctx.chunksize = optparse_get_size_int (p,
179+
"chunksize",
180+
default_chunksize);
181+
ctx.threshold = optparse_get_size_int (p,
182+
"small-file-threshold",
183+
default_small_file_threshold);
182184
ctx.disable_mmap = optparse_hasopt (p, "disable-mmap");
183185
ctx.tags = get_list_option (p, "tags", "main");
184186
ctx.h = builtin_get_flux_handle (p);
@@ -375,12 +377,12 @@ static struct optparse_option map_opts[] = {
375377
.usage = "Change to DIR before mapping", },
376378
{ .name = "verbose", .key = 'v', .has_arg = 2, .arginfo = "[LEVEL]",
377379
.usage = "Increase output detail.", },
378-
{ .name = "chunksize", .has_arg = 1, .arginfo = "N",
380+
{ .name = "chunksize", .has_arg = 1, .arginfo = "N[KMG]",
379381
.usage = "Limit blob size to N bytes with 0=unlimited"
380-
" (default 1048576)", },
381-
{ .name = "small-file-threshold", .has_arg = 1, .arginfo = "N",
382+
" (default 1M)", },
383+
{ .name = "small-file-threshold", .has_arg = 1, .arginfo = "N[KMG]",
382384
.usage = "Adjust the maximum size of a \"small file\" in bytes"
383-
" (default 4096)", },
385+
" (default 4K)", },
384386
{ .name = "disable-mmap", .has_arg = 0,
385387
.usage = "Never mmap(2) files into the content cache", },
386388
{ .name = "tags", .key = 'T', .has_arg = 1, .arginfo = "NAME,...",

src/cmd/builtin/restore.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ static int cmd_restore (optparse_t *p, int ac, char *av[])
366366
content_flags |= CONTENT_FLAG_CACHE_BYPASS;
367367
kvs_checkpoint_flags |= KVS_CHECKPOINT_FLAG_CACHE_BYPASS;
368368
}
369-
blob_size_limit = optparse_get_int (p, "size-limit", 0);
369+
blob_size_limit = optparse_get_size_int (p, "size-limit", "0");
370370

371371
h = builtin_get_flux_handle (p);
372372
ar = restore_create (infile);

src/cmd/flux-ping.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -316,9 +316,7 @@ int main (int argc, char *argv[])
316316
if (!(target = strdup (argv[optindex])))
317317
log_msg_exit ("out of memory");
318318

319-
pad_bytes = optparse_get_int (opts, "pad", 0);
320-
if (pad_bytes < 0)
321-
log_msg_exit ("pad must be >= 0");
319+
pad_bytes = optparse_get_size_int (opts, "pad", "0");
322320

323321
ctx.nodeid = FLUX_NODEID_ANY;
324322
if (optparse_hasopt (opts, "rank")) {

src/common/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ libflux_optparse_la_LIBADD = \
111111
$(builddir)/libczmqcontainers/libczmqcontainers.la \
112112
$(builddir)/liblsd/liblsd.la \
113113
$(builddir)/libutil/fsd.lo \
114+
$(builddir)/libutil/parse_size.lo \
114115
$(LIBPTHREAD)
115116
libflux_optparse_la_LDFLAGS = \
116117
-Wl,--version-script=$(srcdir)/libflux-optparse.map \

src/common/liboptparse/optparse.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@
1919
#include <ctype.h>
2020
#include <stdarg.h>
2121
#include <argz.h>
22+
#include <math.h>
2223

2324
#include "src/common/libczmqcontainers/czmq_containers.h"
2425
#include "src/common/libutil/fsd.h"
26+
#include "src/common/libutil/parse_size.h"
2527
#include "ccan/str/str.h"
2628

2729
#include "optparse.h"
@@ -950,6 +952,59 @@ double optparse_get_duration (optparse_t *p, const char *name,
950952
return d;
951953
}
952954

955+
uint64_t optparse_get_size (optparse_t *p,
956+
const char *name,
957+
const char *default_value)
958+
{
959+
int n;
960+
uint64_t result;
961+
const char *s = NULL;
962+
963+
if (default_value == NULL)
964+
default_value = "0";
965+
966+
if ((n = optparse_getopt (p, name, &s)) < 0) {
967+
optparse_fatalmsg (p, 1,
968+
"%s: optparse error: no such argument '%s'\n",
969+
p->program_name, name);
970+
return (uint64_t) -1;
971+
}
972+
if (n == 0)
973+
s = default_value;
974+
if (parse_size (s, &result) < 0) {
975+
optparse_fatalmsg (p, 1,
976+
"%s: invalid argument for option '%s': %s: %s\n",
977+
p->program_name,
978+
name,
979+
s,
980+
strerror (errno));
981+
return (uint64_t) -1;
982+
}
983+
return result;
984+
}
985+
986+
int optparse_get_size_int (optparse_t *p,
987+
const char *name,
988+
const char *default_value)
989+
{
990+
uint64_t val = optparse_get_size (p, name, default_value);
991+
if (val == (uint64_t)-1)
992+
return -1;
993+
if (val > INT_MAX) {
994+
const char *s;
995+
optparse_getopt (p, name, &s);
996+
optparse_fatalmsg (p,
997+
1,
998+
"%s: %s: value %s too large (must be < %s)\n",
999+
p->program_name,
1000+
name,
1001+
s,
1002+
encode_size (INT_MAX+1UL));
1003+
return -1;
1004+
}
1005+
return (int)val;
1006+
}
1007+
9531008
const char *optparse_get_str (optparse_t *p, const char *name,
9541009
const char *default_value)
9551010
{

src/common/liboptparse/optparse.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#define _UTIL_OPTPARSE_H
1313

1414
#include <stdbool.h>
15+
#include <stdint.h>
1516

1617
#ifdef __cplusplus
1718
extern "C" {
@@ -381,6 +382,27 @@ int optparse_get_int (optparse_t *p, const char *name, int default_value);
381382
double optparse_get_duration (optparse_t *p, const char *name,
382383
double default_value);
383384

385+
/*
386+
* Return the option argument parsed as a size in bytes (or other unit)
387+
* with optional multiplicative suffix: k or K=1024, M=1024*1024,
388+
* G=1024*1024*1024, and so on for T, P, and E. The end result is
389+
* truncated and returned as uint64_t. If there was an error parsing
390+
* the size string, then the fatal error function is called.
391+
*
392+
* Return default value if option was unused. default_value=NULL
393+
* is equivalent to default_value="0".
394+
*/
395+
uint64_t optparse_get_size (optparse_t *p, const char *name,
396+
const char *default_value);
397+
398+
/*
399+
* Like optparse_get_size(), but return an int and ensure the provided
400+
* argument does not overflow INT_MAX (calls fatal error function if so).
401+
*/
402+
int optparse_get_size_int (optparse_t *p,
403+
const char *name,
404+
const char *default_value);
405+
384406
/*
385407
* Return the option argument as a double if 'name' was used,
386408
* 'default_value' if not. If the option is unknown, or the argument

0 commit comments

Comments
 (0)