This file is indexed.

/usr/bin/seivots-to-csv is in seivot 1.17-1.

This file is owned by root:root, with mode 0o755.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#!/usr/bin/python
# Copyright 2011  Lars Wirzenius
# 
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


import cliapp
import ConfigParser
import csv
import os


class SeivotToCsv(cliapp.Application):

    def add_settings(self):
        self.settings.add_string_setting(['output-dir'],
                                         'write output files into DIR '
                                            '(default: %default)',
                                         metavar='DIR',
                                         default='.')

    def process_args(self, args):
        seivots = []
        for filename in args:
            seivots.append(self.read_seivot(filename))
            
        sizes = self.find_initial_sizes(seivots)
        for size in sorted(sizes):
            group = self.find_seivots_in_size_group(seivots, size)
            group.sort(key=self.getkey)
            for op in ['backup', 'restore', 'list_files', 'forget']:
                filename = os.path.join(self.settings['output-dir'],
                                        '%s-%s.csv' % (op, size))
                f = open(filename, 'wb')
                writer = csv.writer(f, lineterminator='\n')
                writer.writerow(['obnam', 'larch', 'gen0 time (s)', 
                                 'gen0 speed (Mbit/s)',
                                 'gen0 RAM (MiB)', 'slowest inc (s)', 
                                 'slowest inc (Mbit/s)',
                                 'largest RAM inc (MiB)'])
                for seivot in group:
                    row = self.get_row_data(op, seivot)
                    writer.writerow(row)
                f.close()

    def read_seivot(self, filename):
        cp = ConfigParser.ConfigParser()
        cp.read([filename])
        return cp

    def getkey(self, seivot):
        return (seivot.get('meta', 'revision'), 
                 seivot.get('meta', 'larch-revision'))

    def get_size(self, seivot):
        return seivot.getint('0', 'backup.new-data')

    def find_initial_sizes(self, seivots):
        return list(set(self.get_size(s) for s in seivots))

    def find_seivots_in_size_group(self, seivots, size):
        return [s for s in seivots if self.get_size(s) == size]

    def get_row_data(self, op, seivot):
        bytes = seivot.getint('0', '%s.new-data' % op)
        secs = seivot.getfloat('0', '%s.real' % op)
        slowest_inc = self.find_slowest_incremental(op, seivot)
        inc_bytes = seivot.getint(slowest_inc, '%s.new-data' % op)
        inc_secs = seivot.getfloat(slowest_inc, '%s.real' % op)
        row = ['r%s' % seivot.get('meta', 'revision'),
               'r%s' % seivot.get('meta', 'larch-revision'),
               secs,
               self.bitspeed(bytes, secs),
               self.bytesize(seivot.getfloat('0', '%s.maxrss' % op)),
               inc_secs,
               self.bitspeed(inc_bytes, inc_secs),
               self.find_largest_incremental(op, seivot)]
        return row

    def values(self, op, suffix, seivot):
        for section in seivot.sections():
            if section not in ['meta', '0']:
                yield section, seivot.getfloat(section, '%s.%s' % (op,suffix))

    def find_slowest_incremental(self, op, seivot):
        v = list(self.values(op, 'real', seivot))
        if not v:
            return '0'
        return min(v, key=lambda pair: pair[1])[0]

    def find_largest_incremental(self, op, seivot):
        v = self.values(op, 'maxrss', seivot)
        return self.bytesize(min(list(x[1] for x in v) or [0.0]))

    def bytesize(self, kilobytes):
        return '%.1f' % (float(kilobytes) / 1024)

    def bitspeed(self, bytes, seconds):
        return '%.1f' % (8*bytes / seconds / (1000**2))


if __name__ == '__main__':
    SeivotToCsv().run()