You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
140 lines
4.3 KiB
140 lines
4.3 KiB
#!/usr/bin/python |
|
# |
|
# 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)
|
|
|