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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « init/perf_log.h ('k') | init/tests/test_perf_log.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifdef HAVE_CONFIG_H
6 # include <config.h>
7 #endif /* HAVE_CONFIG_H */
8
9
10 #include <sys/types.h>
11
12 #include <stdio.h>
13 #include <string.h>
14
15 #include <nih/alloc.h>
16 #include <nih/error.h>
17 #include <nih/file.h>
18 #include <nih/list.h>
19 #include <nih/logging.h>
20 #include <nih/string.h>
21
22 #include "perf_log.h"
23
24 static NihList *message_list;
25 static const char *perf_log_file;
26 static const char *perf_uptime_file;
27 static const char *perf_diskstats_file;
28
29 /**
30 * load_special_file_contents:
31 * @file: file to load
32 *
33 * Loads an ASCII text file and returns as a string. File must be less than
34 * MAX_FILE_SIZE. Do not use nih_file_read as it requires reading a
35 * normal file whose size is correct (unlike /proc and /sys files).
36 *
37 * Returns: none
38 **/
39 static char *
40 load_special_file_contents (void *parent,
41 const char *file)
42 {
43 const int MAX_FILE_SIZE = 512;
44 size_t len = 0;
45 char *contents;
46 FILE *fp = NULL;
47
48 if (! file) {
49 return NULL;
50 }
51 fp = fopen (file, "r");
52 if (! fp) {
53 return NULL;
54 }
55 contents = NIH_MUST (nih_alloc (parent, MAX_FILE_SIZE + 1));
56 len = fread (contents, 1, MAX_FILE_SIZE, fp);
57 fclose (fp);
58 if (len < 0) {
59 nih_free(contents);
60 return NULL;
61 }
62 contents[len] = '\0';
63 return contents;
64 }
65
66 /**
67 * get_file_fields:
68 * @parent: parent context
69 * @file: file to load and parse
70 * @delimiters: NULL terminated list of characters that delimits fields
71 * @fields: point to integer that is set to the number of fields found
72 *
73 * Loads @file and returns an array of fields delimited by the given
74 * @delimiters array. Avoid nih_file_read as it requires reading a
75 * normal file whose size is correct (unlike /proc and /sys files).
76 *
77 * Returns: array of delimited fields or NULL on error.
78 **/
79 char **
80 get_file_fields (void *parent,
81 const char *file,
82 char *delimiters,
83 int *fields)
84 {
85 int i;
86 char *result = NULL;
87 char **array = NULL;
88 char *contents = NULL;
89
90 nih_assert (fields != NULL);
91 *fields = 0;
92 contents = load_special_file_contents (NULL,
93 file);
94 if (! contents) {
95 return NULL;
96 }
97 array = nih_str_split (parent,
98 contents,
99 delimiters,
100 TRUE);
101 nih_free (contents);
102 if (! array) {
103 return NULL;
104 }
105 i = 0;
106 while (array[i] != NULL) {
107 ++i;
108 }
109 *fields = i;
110 return array;
111 }
112
113 /**
114 * perf_log_init:
115 *
116 * Initialise the message_list list.
117 *
118 * Returns: none
119 **/
120 void
121 perf_log_init (void)
122 {
123 if (! message_list) {
124 message_list = NIH_MUST (nih_list_new (NULL));
125 }
126 }
127
128 /**
129 * perf_log_flush:
130 *
131 * Attempt to write any enqueued perf log messages.
132 *
133 * Returns: none
134 **/
135 void
136 perf_log_flush (void)
137 {
138 FILE *fp = NULL;
139
140 if (perf_log_file)
141 fp = fopen (perf_log_file, "a");
142 if (! fp)
143 return;
144 NIH_LIST_FOREACH_SAFE (message_list, iter) {
145 NihListEntry *entry = (NihListEntry*)iter;
146 int result;
147
148 result = fputs (entry->str, fp);
149 if (result < 0) {
150 /* This is an unexpected error. We retry
151 * writing the message later.
152 */
153 break;
154 }
155 nih_list_remove (iter);
156 nih_free (iter);
157 }
158
159 fclose (fp);
160 }
161
162 /**
163 * perf_log_message:
164 * @format: format string
165 *
166 * Log the given formatted message. If the file cannot be written at
167 * this time, we enqueue the message and try later. We grab
168 * performance stats now, and those stats are enqueued to write later.
169 * If the performance stats are not readable at this time, we log "-"
170 * instead.
171 *
172 * Returns: none
173 **/
174 void
175 perf_log_message (const char *format,
176 ...)
177 {
178 NihListEntry *new_entry;
179 va_list args;
180 int uptime_fields = 0;
181 char **uptimes;
182 int diskstats_fields = 0;
183 char **diskstats;
184 char *uptime_busy;
185 char *sectors_read;
186 char *message;
187
188 perf_log_init ();
189 uptimes = get_file_fields (NULL,
190 perf_uptime_file,
191 " \n",
192 &uptime_fields);
193 diskstats = get_file_fields (NULL,
194 perf_diskstats_file,
195 " \n",
196 &diskstats_fields);
197
198 if (uptime_fields < 1)
199 uptime_busy = "-";
200 else
201 uptime_busy = uptimes[0];
202 if (diskstats_fields < 3)
203 sectors_read = "-";
204 else
205 sectors_read = diskstats[2];
206
207 va_start (args, format);
208 message = NIH_MUST (nih_vsprintf (NULL,
209 format,
210 args));
211 va_end (args);
212
213 /* Create a log entry and add it to the queue. */
214 new_entry = NIH_MUST (nih_list_entry_new (NULL));
215 new_entry->str = NIH_MUST (nih_sprintf (new_entry, "%s %s %s",
216 uptime_busy, sectors_read,
217 message));
218 nih_list_add (message_list, &new_entry->entry);
219
220 nih_free (message);
221 if (uptimes)
222 nih_free (uptimes);
223 if (diskstats)
224 nih_free (diskstats);
225
226 perf_log_flush ();
227 }
228
229 /**
230 * perf_log_job_state_change:
231 * @job: job whose state is changing,
232 * @new_state: new state
233 *
234 * Causes the given job's state transition to be logged to the
235 * performance log.
236 *
237 * Returns: none
238 **/
239 void
240 perf_log_job_state_change (Job *job,
241 JobState new_state)
242 {
243 perf_log_message ("statechange %s %s\n",
244 job_name (job),
245 job_state_name (new_state));
246 }
247
248 /**
249 * perf_log_set_file:
250 * @file: file to write to
251 *
252 * Sets the performance logging file name and writes to it if possible.
253 *
254 * Returns: none
255 **/
256 void
257 perf_log_set_files (const char *uptime_file,
258 const char *diskstats_file,
259 const char *log_file)
260 {
261 perf_log_init ();
262 perf_log_file = log_file;
263 perf_uptime_file = uptime_file;
264 perf_diskstats_file = diskstats_file;
265 perf_log_flush ();
266 }
OLDNEW
« 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