aboutsummaryrefslogtreecommitdiff
path: root/deprecated/fdo_scripts/divide_and_merge_profiles.py
blob: 5108aa6fcd13ea0fce06e315dee3f35796c657ad (plain)
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#!/usr/bin/python2
#
# Copyright 2011 Google Inc. All Rights Reserved.
"""Script to divide and merge profiles."""

import copy
import optparse
import os
import pickle
import re
import sys
import tempfile

import build_chrome_browser
import lock_machine
import run_tests
from cros_utils import command_executer
from cros_utils import logger


class ProfileMerger:

  def __init__(self, inputs, output, chunk_size, merge_program, multipliers):
    self._inputs = inputs
    self._output = output
    self._chunk_size = chunk_size
    self._merge_program = merge_program
    self._multipliers = multipliers
    self._ce = command_executer.GetCommandExecuter()
    self._l = logger.GetLogger()

  def _GetFilesSetForInputDir(self, input_dir):
    output_file = tempfile.mktemp()
    command = "find %s -name '*.gcda' -o -name '*.imports' > %s" % (input_dir,
                                                                    output_file)
    self._ce.RunCommand(command)
    files = open(output_file, 'r').read()
    files_set = set([])
    for f in files.splitlines():
      stripped_file = f.replace(input_dir, '', 1)
      stripped_file = stripped_file.lstrip('/')
      files_set.add(stripped_file)
    return files_set

  def _PopulateFilesSet(self):
    self._files_set = set([])
    for i in self._inputs:
      current_files_set = self._GetFilesSetForInputDir(i)
      self._files_set.update(current_files_set)

  def _GetSubset(self):
    ret = []
    for i in range(self._chunk_size):
      if not self._files_set:
        break
      ret.append(self._files_set.pop())
    return ret

  def _CopyFilesTree(self, input_dir, files, output_dir):
    for f in files:
      src_file = os.path.join(input_dir, f)
      dst_file = os.path.join(output_dir, f)
      if not os.path.isdir(os.path.dirname(dst_file)):
        command = 'mkdir -p %s' % os.path.dirname(dst_file)
        self._ce.RunCommand(command)
      command = 'cp %s %s' % (src_file, dst_file)
      self._ce.RunCommand(command)

  def _DoChunkMerge(self, current_files):
    temp_dirs = []
    for i in self._inputs:
      temp_dir = tempfile.mkdtemp()
      temp_dirs.append(temp_dir)
      self._CopyFilesTree(i, current_files, temp_dir)
    # Now do the merge.
    command = ('%s --inputs=%s --output=%s' %
               (self._merge_program, ','.join(temp_dirs), self._output))
    if self._multipliers:
      command = ('%s --multipliers=%s' % (command, self._multipliers))
    ret = self._ce.RunCommand(command)
    assert ret == 0, '%s command failed!' % command
    for temp_dir in temp_dirs:
      command = 'rm -rf %s' % temp_dir
      self._ce.RunCommand(command)

  def DoMerge(self):
    self._PopulateFilesSet()
    while True:
      current_files = self._GetSubset()
      if not current_files:
        break
      self._DoChunkMerge(current_files)


def Main(argv):
  """The main function."""
  # Common initializations
  ###  command_executer.InitCommandExecuter(True)
  command_executer.InitCommandExecuter()
  l = logger.GetLogger()
  ce = command_executer.GetCommandExecuter()
  parser = optparse.OptionParser()
  parser.add_option('--inputs',
                    dest='inputs',
                    help='Comma-separated input profile directories to merge.')
  parser.add_option('--output', dest='output', help='Output profile directory.')
  parser.add_option('--chunk_size',
                    dest='chunk_size',
                    default='50',
                    help='Chunk size to divide up the profiles into.')
  parser.add_option('--merge_program',
                    dest='merge_program',
                    default='/home/xur/bin/profile_merge_v15.par',
                    help='Merge program to use to do the actual merge.')
  parser.add_option('--multipliers',
                    dest='multipliers',
                    help='multipliers to use when merging. (optional)')

  options, _ = parser.parse_args(argv)

  if not all([options.inputs, options.output]):
    l.LogError('Must supply --inputs and --output')
    return 1

  try:
    pm = ProfileMerger(
        options.inputs.split(','), options.output, int(options.chunk_size),
        options.merge_program, options.multipliers)
    pm.DoMerge()
    retval = 0
  except:
    retval = 1
  finally:
    print 'My work is done...'
  return retval


if __name__ == '__main__':
  retval = Main(sys.argv)
  sys.exit(retval)