From 5fd83771641d15c418f747bd343ba6738d3875f7 Mon Sep 17 00:00:00 2001 From: Cameron Katri Date: Sun, 9 May 2021 14:20:58 -0400 Subject: Import macOS userland adv_cmds-176 basic_cmds-55 bootstrap_cmds-116.100.1 developer_cmds-66 diskdev_cmds-667.40.1 doc_cmds-53.60.1 file_cmds-321.40.3 mail_cmds-35 misc_cmds-34 network_cmds-606.40.1 patch_cmds-17 remote_cmds-63 shell_cmds-216.60.1 system_cmds-880.60.2 text_cmds-106 --- file_cmds/mtree/metrics.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 file_cmds/mtree/metrics.c (limited to 'file_cmds/mtree/metrics.c') diff --git a/file_cmds/mtree/metrics.c b/file_cmds/mtree/metrics.c new file mode 100644 index 0000000..01a9fe2 --- /dev/null +++ b/file_cmds/mtree/metrics.c @@ -0,0 +1,155 @@ +/* +* Copyright (c) 2020 Apple Inc. All rights reserved. +* +* @APPLE_LICENSE_HEADER_START@ +* +* This file contains Original Code and/or Modifications of Original Code +* as defined in and that are subject to the Apple Public Source License +* Version 2.0 (the 'License'). You may not use this file except in +* compliance with the License. Please obtain a copy of the License at +* http://www.opensource.apple.com/apsl/ and read it before using this +* file. +* +* The Original Code and all software distributed under the License are +* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +* Please see the License for the specific language governing rights and +* limitations under the License. +* +* @APPLE_LICENSE_HEADER_END@ +*/ + +#include +#include + +#include "metrics.h" + +#define MAX_WARNINGS_LOGGED 5 +#define MAX_ERRORS_LOGGED 5 +#define WARN_FIRST -1 + +#ifndef ROUNDUP +#define ROUNDUP(COUNT, MULTIPLE) ((((COUNT) + (MULTIPLE) - 1) / (MULTIPLE)) * (MULTIPLE)) +#endif + +typedef struct failure_info { + int location; + int code; +} failure_info_t; + +typedef struct metrics { + FILE *file; + time_t start_time; + int warning_count; + failure_info_t warnings[MAX_WARNINGS_LOGGED]; + int error_count; + failure_info_t errors[MAX_ERRORS_LOGGED]; + int last_error_location; + char *path; + int result; +} metrics_t; +metrics_t metrics = {}; + +void +set_metrics_file(FILE *file) +{ + metrics.file = file; +} + +void +set_metric_start_time(time_t time) +{ + metrics.start_time = time; +} + +void +set_metric_path(char *path) +{ + metrics.path = strdup(path); +} + +void +mtree_record_failure(int location, int code) +{ + if (code <= WARN_FIRST) { + if (metrics.warning_count < MAX_WARNINGS_LOGGED) { + metrics.warning_count++; + } else { + // Shift up the warnings to make space for the latest one. + for (int index = 0; index < MAX_ERRORS_LOGGED - 1; index++) { + metrics.warnings[index] = metrics.warnings[index + 1]; + } + } + metrics.warnings[metrics.warning_count - 1].location = location; + metrics.warnings[metrics.warning_count - 1].code = code; + } else { + int error_index = -1; + if (metrics.error_count <= MAX_ERRORS_LOGGED) { + if (metrics.error_count > 0) { + // Log all but the last error which occured in the location and + // code arrays. The last (location, error) is logged in + // (metrics.last_error_location, metrics.error) + error_index = metrics.error_count - 1; + } + metrics.error_count++; + } else { + // Shift up the errors to make space for the latest one. + for (int index = 0; index < MAX_ERRORS_LOGGED - 1; index++) { + metrics.errors[index] = metrics.errors[index + 1]; + } + error_index = MAX_ERRORS_LOGGED - 1; + } + if (error_index >= 0) { + metrics.errors[error_index].location = metrics.last_error_location; + metrics.errors[error_index].code = metrics.result; + } + metrics.last_error_location = location; + metrics.result = code; + } +} +/* + * Note on format of metric string + * 1) dev points to the path + * 2) result is the overall result code from mtree + * 3) warnings and errors (upto 5 each) are printed in the format : + * w:(location1:code1),(location2:code2).... and + * e:(location1:code1),(location2:code2).... respectively. + * 4) fl is the last failure location of the run which is 0 if there is no failure + * 5) time is the total time taken for the run + */ +void +print_metrics_to_file(void) +{ + if (metrics.file == NULL) { + return; + } + + fprintf(metrics.file, "dev=%s result=%d ", + metrics.path ? metrics.path : "", metrics.result); + if (metrics.warning_count) { + fprintf(metrics.file, "w:"); + for (int index = 0; index < metrics.warning_count; index++) { + fprintf(metrics.file, "(%d:%d)", + metrics.warnings[index].location, metrics.warnings[index].code); + } + fprintf(metrics.file, " "); + } + if (metrics.error_count > 1) { + fprintf(metrics.file, "e:"); + for (int index = 0; index < metrics.error_count - 1; index++) { + fprintf(metrics.file, "(%d:%d)", + metrics.errors[index].location, metrics.errors[index].code); + } + fprintf(metrics.file, " "); + } + fprintf(metrics.file, "fl=%d time=%ld\n", + metrics.last_error_location, ROUNDUP((time(NULL) - metrics.start_time), 60) / 60); + + fclose(metrics.file); + if (metrics.path) { + free(metrics.path); + metrics.path = NULL; + } +} -- cgit v1.2.3-56-ge451