The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/usr/bin/perl

=head1 NAME

yars_generate_diskmap -- generate a mapping from servers + hosts to buckets for yars.

=head1 SYNOPSIS

    yars_generate_diskmap <number of hex digits>
    host1 /disk1
    host1 /disk2
    host2 /disk1
    host2 /disk2

    echo "host1 /disk/1" | yars_generate_diskmap 1

=head1 DESCRIPTION

Given a list of hosts and disks, distribute 16^n buckets onto the disks.

=head1 EXAMPLES

clad -a testarch df -kh|grep archive | awk '{print $1 " " $7}' |  ./yars_generate_diskmap 2

=head1 SEE ALSO

Clustericious::Admin

=cut

use strict;
use warnings;
use JSON::XS;
use feature 'say';

&main;

sub main {
    my %servers;
    my $port = 9001;
    my $digits = shift @ARGV or die "no number of digits given";
    my @all;
    while (<>) {
        chomp;
        my ($host,$disk) = split;
        $host =~ tr/a-zA-Z0-9._//dc;
        die "could not parse line : $_" unless $host && $disk;
        $servers{$host}{$disk} = [];
        push @all, $servers{$host}{$disk};
    }

    my $i = 0;
    for my $bucket (0..16**$digits-1) {
        my $b = sprintf( '%0'.$digits.'x',$bucket);
        push @{ $all[$i] }, "$b";
        $i++;
        $i = 0 if $i==@all;
    }

    say '---';
    say 'servers :';
    for my $host (sort keys %servers) {
        say "- url : http://$host:$port";
        say "  disks :";
        for my $root (sort keys %{ $servers{$host} }) {
            say "  - root : $root";
            print "    buckets : [";
            my $i = 1;
            for my $bucket (@{ $servers{$host}{$root} }) {
                print "\n               " if $i++%14 == 0;
                print " $bucket";
                print "," unless $i==@{ $servers{$host}{$root} }+1;
            }
            say " ]";
        }
    }
}

sub dense {
    my %servers = @_;
    # Alternative unreadable representation
    my @conf;
    for my $host (sort keys %servers) {
        push @conf, +{ url => "http://$host:9001", disks => [
            map +{ root => $_, buckets => $servers{$host}{$_} }, keys %{ $servers{$host} }
        ]};
    }

    my $out = JSON::XS->new->space_after->encode({ servers => \@conf });
    $out =~ s/{/\n{/g;
    $out =~ s/\[/\n[/g;
    $out =~ s/\],/],\n/g;
    print $out,"\n";
}

1;