| # Copyright 2024 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import json |
| import logging |
| import os |
| import shutil |
| import string |
| |
| _SHARED_STORAGE_DIR = os.path.abspath( |
| os.path.join(os.path.dirname(__file__), os.pardir)) |
| |
| _PROCESSOR = os.path.abspath( |
| os.path.join(_SHARED_STORAGE_DIR, os.pardir, os.pardir, |
| 'results_processor')) |
| |
| _HISTOGRAMS_RAW = os.path.abspath( |
| os.path.join(_SHARED_STORAGE_DIR, os.pardir, os.pardir, 'histograms.json')) |
| |
| _SHARED_STORAGE_FILE = os.path.abspath( |
| os.path.join(_SHARED_STORAGE_DIR, 'shared_storage.py')) |
| |
| _DATA_DIR = os.path.abspath(os.path.join(_SHARED_STORAGE_DIR, 'data')) |
| |
| _RUN_PATH_FILE = os.path.abspath(os.path.join(_DATA_DIR, 'run_path.txt')) |
| |
| _HISTOGRAMS_EXPECTED = os.path.abspath( |
| os.path.join(_DATA_DIR, 'histograms_expected.json')) |
| |
| _HISTOGRAMS_INFO = os.path.abspath( |
| os.path.join(_DATA_DIR, 'histograms_info.json')) |
| |
| _HISTOGRAMS_AGG = os.path.abspath( |
| os.path.join(_DATA_DIR, 'histograms_aggregated.json')) |
| |
| _HISTOGRAMS_STORY = os.path.abspath( |
| os.path.join(_DATA_DIR, 'histograms_by_story.json')) |
| |
| _HISTOGRAM_COUNTS = os.path.abspath( |
| os.path.join(_DATA_DIR, 'histogram_counts.json')) |
| |
| _HISTOGRAM_COUNT_DELTAS = os.path.abspath( |
| os.path.join(_DATA_DIR, 'histogram_count_deltas.json')) |
| |
| _PROCESSED_FILES = [ |
| _HISTOGRAMS_INFO, |
| _HISTOGRAMS_AGG, |
| _HISTOGRAMS_STORY, |
| _HISTOGRAM_COUNTS, |
| _HISTOGRAM_COUNT_DELTAS, |
| ] |
| |
| |
| def GetProcessor(): |
| return _PROCESSOR |
| |
| |
| def GetRawHistogramsFile(): |
| return _HISTOGRAMS_RAW |
| |
| |
| def GetDataDir(): |
| return _DATA_DIR |
| |
| |
| def GetRunPathFile(): |
| return _RUN_PATH_FILE |
| |
| |
| def GetExpectedHistogramsFile(): |
| return _HISTOGRAMS_EXPECTED |
| |
| |
| def GetHistogramCountDeltasFile(): |
| return _HISTOGRAM_COUNT_DELTAS |
| |
| |
| def GetProcessedFiles(): |
| return _PROCESSED_FILES |
| |
| |
| def EnsureDataDir(): |
| # Ensure that /data exists and is a directory. (Delete and recreate |
| # if it's not a directory.) |
| if os.path.exists(_DATA_DIR) and not os.path.isdir(_DATA_DIR): |
| logging.warning('Deleting %s' % _DATA_DIR) |
| shutil.rmtree(_DATA_DIR) |
| if not os.path.exists(_DATA_DIR): |
| logging.info('Creating directory %s' % _DATA_DIR) |
| os.makedirs(_DATA_DIR) |
| |
| |
| def CleanUpRunPathFile(): |
| # Cleanup any run path file from a previous run. |
| if os.path.exists(_RUN_PATH_FILE) and os.path.isfile(_RUN_PATH_FILE): |
| logging.info('Removing pre-existing file %s' % _RUN_PATH_FILE) |
| os.remove(_RUN_PATH_FILE) |
| elif os.path.exists(_RUN_PATH_FILE) and os.path.isdir(_RUN_PATH_FILE): |
| logging.warning('Deleting directory %s' % _RUN_PATH_FILE) |
| shutil.rmtree(_RUN_PATH_FILE) |
| elif os.path.exists(_RUN_PATH_FILE): |
| msg = 'Encountered existing %s ' % _RUN_PATH_FILE |
| raise RuntimeError(msg + 'that is neither a file nor a directory') |
| |
| |
| def _MovePreviousFile(src_path, |
| dest_path_without_time=None, |
| new_extension='.json'): |
| if not dest_path_without_time: |
| dest_path_without_time = src_path |
| if not os.path.exists(src_path): |
| return |
| |
| if not os.path.isfile(src_path): |
| raise RuntimeError('%s is not a file' % src_path) |
| |
| # Rename a file from a previous run. |
| modified = os.path.getmtime(src_path) |
| destination = ''.join([ |
| dest_path_without_time[:-len(new_extension)], |
| str(modified), new_extension |
| ]) |
| shutil.move(src_path, destination) |
| |
| |
| def MovePreviousExpectedHistogramsFile(): |
| # If expected histograms file exists from a previous run, move it. |
| _MovePreviousFile(_HISTOGRAMS_EXPECTED) |
| |
| |
| def _MovePreviousRawHistogramsFile(): |
| # If histograms.json exists from a previous run, move it. |
| destination = os.path.abspath(os.path.join(_DATA_DIR, 'histograms_.json')) |
| _MovePreviousFile(_HISTOGRAMS_RAW, dest_path_without_time=destination) |
| |
| |
| def _MovePreviousProcessedHistogramsFiles(): |
| for filename in _PROCESSED_FILES: |
| _MovePreviousFile(filename) |
| |
| |
| def MovePreviousHistogramsFiles(): |
| _MovePreviousRawHistogramsFile() |
| _MovePreviousProcessedHistogramsFiles() |
| |
| |
| def GetExpectedHistogramsDictionary(): |
| counts_data = {} |
| with open(_HISTOGRAMS_EXPECTED, 'r') as f: |
| counts_data = json.load(f) |
| return counts_data |
| |
| |
| def GetBenchmarkDBSize(benchmark_name): |
| # We read the file instead of importing to prevent a circular import. |
| benchmark_file = None |
| if (not os.path.exists(_SHARED_STORAGE_FILE) |
| or not os.path.isfile(_SHARED_STORAGE_FILE)): |
| raise RuntimeError('%s does not exist or is not a file' % |
| _SHARED_STORAGE_FILE) |
| with open(_SHARED_STORAGE_FILE, 'r') as f: |
| benchmark_file = f.read() |
| |
| name_pos = benchmark_file.find(benchmark_name) |
| if name_pos < 0: |
| raise ValueError('benchmark_name %s not found' % benchmark_name) |
| size_prefix = 'SIZE = ' |
| size_prefix_pos = benchmark_file.rfind(size_prefix, 0, name_pos - 1) |
| if size_prefix_pos < 0: |
| raise RuntimeError("%s not found before benchmark name" % size_prefix) |
| start_pos = size_prefix_pos + len(size_prefix) |
| end_pos = start_pos + 1 |
| while end_pos < name_pos and benchmark_file[end_pos] in string.digits: |
| end_pos += 1 |
| size_str = benchmark_file[start_pos:end_pos] |
| if not size_str.isdigit(): |
| raise RuntimeError('Expected %s to be castable to an integer' % size_str) |
| return int(size_str) |