Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(27)

Unified Diff: init/perf_log.c

Issue 524041: Changes to make upstart log performance stats to a file. (Closed)
Patch Set: More tab/space stuff Created 10 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « init/perf_log.h ('k') | init/tests/test_perf_log.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: init/perf_log.c
diff --git a/init/perf_log.c b/init/perf_log.c
new file mode 100644
index 0000000000000000000000000000000000000000..0c9a33f1e3e3900168b5c158cc04c227cd0d0f95
--- /dev/null
+++ b/init/perf_log.c
@@ -0,0 +1,266 @@
+// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <nih/alloc.h>
+#include <nih/error.h>
+#include <nih/file.h>
+#include <nih/list.h>
+#include <nih/logging.h>
+#include <nih/string.h>
+
+#include "perf_log.h"
+
+static NihList *message_list;
+static const char *perf_log_file;
+static const char *perf_uptime_file;
+static const char *perf_diskstats_file;
+
+/**
+ * load_special_file_contents:
+ * @file: file to load
+ *
+ * Loads an ASCII text file and returns as a string. File must be less than
+ * MAX_FILE_SIZE. Do not use nih_file_read as it requires reading a
+ * normal file whose size is correct (unlike /proc and /sys files).
+ *
+ * Returns: none
+ **/
+static char *
+load_special_file_contents (void *parent,
+ const char *file)
+{
+ const int MAX_FILE_SIZE = 512;
+ size_t len = 0;
+ char *contents;
+ FILE *fp = NULL;
+
+ if (! file) {
+ return NULL;
+ }
+ fp = fopen (file, "r");
+ if (! fp) {
+ return NULL;
+ }
+ contents = NIH_MUST (nih_alloc (parent, MAX_FILE_SIZE + 1));
+ len = fread (contents, 1, MAX_FILE_SIZE, fp);
+ fclose (fp);
+ if (len < 0) {
+ nih_free(contents);
+ return NULL;
+ }
+ contents[len] = '\0';
+ return contents;
+}
+
+/**
+ * get_file_fields:
+ * @parent: parent context
+ * @file: file to load and parse
+ * @delimiters: NULL terminated list of characters that delimits fields
+ * @fields: point to integer that is set to the number of fields found
+ *
+ * Loads @file and returns an array of fields delimited by the given
+ * @delimiters array. Avoid nih_file_read as it requires reading a
+ * normal file whose size is correct (unlike /proc and /sys files).
+ *
+ * Returns: array of delimited fields or NULL on error.
+ **/
+char **
+get_file_fields (void *parent,
+ const char *file,
+ char *delimiters,
+ int *fields)
+{
+ int i;
+ char *result = NULL;
+ char **array = NULL;
+ char *contents = NULL;
+
+ nih_assert (fields != NULL);
+ *fields = 0;
+ contents = load_special_file_contents (NULL,
+ file);
+ if (! contents) {
+ return NULL;
+ }
+ array = nih_str_split (parent,
+ contents,
+ delimiters,
+ TRUE);
+ nih_free (contents);
+ if (! array) {
+ return NULL;
+ }
+ i = 0;
+ while (array[i] != NULL) {
+ ++i;
+ }
+ *fields = i;
+ return array;
+}
+
+/**
+ * perf_log_init:
+ *
+ * Initialise the message_list list.
+ *
+ * Returns: none
+ **/
+void
+perf_log_init (void)
+{
+ if (! message_list) {
+ message_list = NIH_MUST (nih_list_new (NULL));
+ }
+}
+
+/**
+ * perf_log_flush:
+ *
+ * Attempt to write any enqueued perf log messages.
+ *
+ * Returns: none
+ **/
+void
+perf_log_flush (void)
+{
+ FILE *fp = NULL;
+
+ if (perf_log_file)
+ fp = fopen (perf_log_file, "a");
+ if (! fp)
+ return;
+ NIH_LIST_FOREACH_SAFE (message_list, iter) {
+ NihListEntry *entry = (NihListEntry*)iter;
+ int result;
+
+ result = fputs (entry->str, fp);
+ if (result < 0) {
+ /* This is an unexpected error. We retry
+ * writing the message later.
+ */
+ break;
+ }
+ nih_list_remove (iter);
+ nih_free (iter);
+ }
+
+ fclose (fp);
+}
+
+/**
+ * perf_log_message:
+ * @format: format string
+ *
+ * Log the given formatted message. If the file cannot be written at
+ * this time, we enqueue the message and try later. We grab
+ * performance stats now, and those stats are enqueued to write later.
+ * If the performance stats are not readable at this time, we log "-"
+ * instead.
+ *
+ * Returns: none
+ **/
+void
+perf_log_message (const char *format,
+ ...)
+{
+ NihListEntry *new_entry;
+ va_list args;
+ int uptime_fields = 0;
+ char **uptimes;
+ int diskstats_fields = 0;
+ char **diskstats;
+ char *uptime_busy;
+ char *sectors_read;
+ char *message;
+
+ perf_log_init ();
+ uptimes = get_file_fields (NULL,
+ perf_uptime_file,
+ " \n",
+ &uptime_fields);
+ diskstats = get_file_fields (NULL,
+ perf_diskstats_file,
+ " \n",
+ &diskstats_fields);
+
+ if (uptime_fields < 1)
+ uptime_busy = "-";
+ else
+ uptime_busy = uptimes[0];
+ if (diskstats_fields < 3)
+ sectors_read = "-";
+ else
+ sectors_read = diskstats[2];
+
+ va_start (args, format);
+ message = NIH_MUST (nih_vsprintf (NULL,
+ format,
+ args));
+ va_end (args);
+
+ /* Create a log entry and add it to the queue. */
+ new_entry = NIH_MUST (nih_list_entry_new (NULL));
+ new_entry->str = NIH_MUST (nih_sprintf (new_entry, "%s %s %s",
+ uptime_busy, sectors_read,
+ message));
+ nih_list_add (message_list, &new_entry->entry);
+
+ nih_free (message);
+ if (uptimes)
+ nih_free (uptimes);
+ if (diskstats)
+ nih_free (diskstats);
+
+ perf_log_flush ();
+}
+
+/**
+ * perf_log_job_state_change:
+ * @job: job whose state is changing,
+ * @new_state: new state
+ *
+ * Causes the given job's state transition to be logged to the
+ * performance log.
+ *
+ * Returns: none
+ **/
+void
+perf_log_job_state_change (Job *job,
+ JobState new_state)
+{
+ perf_log_message ("statechange %s %s\n",
+ job_name (job),
+ job_state_name (new_state));
+}
+
+/**
+ * perf_log_set_file:
+ * @file: file to write to
+ *
+ * Sets the performance logging file name and writes to it if possible.
+ *
+ * Returns: none
+ **/
+void
+perf_log_set_files (const char *uptime_file,
+ const char *diskstats_file,
+ const char *log_file)
+{
+ perf_log_init ();
+ perf_log_file = log_file;
+ perf_uptime_file = uptime_file;
+ perf_diskstats_file = diskstats_file;
+ perf_log_flush ();
+}
« no previous file with comments | « init/perf_log.h ('k') | init/tests/test_perf_log.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698