[pve-devel] applied: [PATCH common v3] Tools: add `convert_size` for generic byte conversion

Wolfgang Bumiller w.bumiller at proxmox.com
Mon Sep 11 11:24:17 CEST 2017


applied

On Mon, Sep 11, 2017 at 10:41:34AM +0200, Thomas Lamprecht wrote:
> We often need to convert between file sizes, for formatting output,
> but also code-internal. Some methods expect kilobytes, some gigabytes
> and sometimes we need bytes.
> 
> While conversion from smaller to bigger units can be simply done with
> a left-shift, the opposite conversion may need more attention -
> depending on the used context.
> 
> If we allocate disks this is quite critical. For example, if we need
> to allocate a disk with size 1023 bytes using the
> PVE::Storage::vdisk_alloc method (which expects kilobytes) a
> right shift by 10 (<=> division by 1024) would result in "0", which
> obviously fails.
> 
> Thus we round up the converted value if a remainder was lost on the
> transformation in this new method. This behaviour is opt-out, to be
> on the safe side.
> 
> The method can be used in a clear way, as it gives information about
> the source and target unit size, unlike "$var *= 1024", which doesn't
> gives direct information at all, if not commented or derived
> somewhere from its context.
> 
> For example:
>  > my $size = convert_unit($value, 'gb' => 'kb');
> is more clear than:
>  > my $size = $value*1024*1024;
> 
> Signed-off-by: Thomas Lamprecht <t.lamprecht at proxmox.com>
> ---
> 
> changes v2 -> v3:
>  * remove returning the remainder, it will not get used yet and feels
>    not clean. If we want such behavior we can add it easily later and
>    then, with a real use case, we should be able to create a better
>    interface then
>  * die if from or to was not fount in unit hash, normally from/to are
>    constant not dynamic so this is more convenience for the dev.
> 
> I did not resent the qemu-server part as it was not change in this
> iteration
> 
>  src/PVE/Tools.pm | 33 +++++++++++++++++++++++++++++++++
>  1 file changed, 33 insertions(+)
> 
> diff --git a/src/PVE/Tools.pm b/src/PVE/Tools.pm
> index 9ddcfda..81662b1 100644
> --- a/src/PVE/Tools.pm
> +++ b/src/PVE/Tools.pm
> @@ -1617,4 +1617,37 @@ sub encrypt_pw {
>      return crypt(encode("utf8", $pw), "\$5\$$salt\$");
>  }
>  
> +# intended usage: convert_size($val, "kb" => "gb")
> +# on reduction (converting to a bigger unit) we round up by default if
> +# information got lost. E.g. `convert_size(1023, "b" => "kb")` returns 1
> +# use $no_round_up to switch this off, above example would then return 0
> +sub convert_size {
> +    my ($value, $from, $to, $no_round_up) = @_;
> +
> +    my $units = {
> +	b  => 0,
> +	kb => 1,
> +	mb => 2,
> +	gb => 3,
> +	tb => 4,
> +	pb => 5,
> +    };
> +
> +    $from = lc($from); $to = lc($to);
> +    die "unknown 'from' and/or 'to' units ($from => $to)"
> +	if !(defined($units->{$from}) && defined($units->{$to}));
> +
> +    my $shift_amount = $units->{$from} - $units->{$to};
> +
> +    if ($shift_amount > 0) {
> +	$value <<= ($shift_amount * 10);
> +    } elsif ($shift_amount < 0) {
> +	my $remainder = ($value & (1 << abs($shift_amount)*10) - 1);
> +	$value >>= abs($shift_amount) * 10;
> +	$value++ if $remainder && !$no_round_up;
> +    }
> +
> +    return $value;
> +}
> +
>  1;
> -- 
> 2.11.0




More information about the pve-devel mailing list