1 /************************************************************************ 2 Copyright (c) 2015, The Linux Foundation. All rights reserved. 3 4 Redistribution and use in source and binary forms, with or without 5 modification, are permitted provided that the following conditions are 6 met: 7 * Redistributions of source code must retain the above copyright 8 notice, this list of conditions and the following disclaimer. 9 * Redistributions in binary form must reproduce the above 10 copyright notice, this list of conditions and the following 11 disclaimer in the documentation and/or other materials provided 12 with the distribution. 13 * Neither the name of The Linux Foundation nor the names of its 14 contributors may be used to endorse or promote products derived 15 from this software without specific prior written permission. 16 17 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 ************************************************************************/ 29 30 /** 31 * @file datatop_dual_line_poll.c 32 * @brief Adds ability for data collection from dual line files. 33 * 34 * File contains methods for searching and polling data from 35 * dual line files, meaning the first line contains the dp names 36 * while the second line contains the corresponding values. 37 */ 38 39 #include <stdio.h> 40 #include <string.h> 41 #include <stdlib.h> 42 #include "datatop_interface.h" 43 #include "datatop_fileops.h" 44 #include "datatop_str.h" 45 46 #define DTOP_DUAL_SIZE 8192 47 #define DTOP_DUAL_LINE (DTOP_DUAL_SIZE>>2) 48 49 /** 50 * @struct dtop_dual_line_vars 51 * @brief Struct used to hold necessary variables for dual_line_file dpgs. 52 * 53 * @var dtop_dual_line_vars::line 54 * Array of strings where necessary dp names and values are held. 55 * @var dtop_dual_line_vars::line2 56 * Array of strings where necessary dp names and values are held. 57 * @var dtop_dual_line_vars::line_count 58 * Number of lines the file is that the dpg represents. 59 */ 60 struct dtop_dual_line_vars { 61 char **line; 62 char **line2; 63 int line_count; 64 }; 65 66 /** 67 * @brief Stores the data collected from a dual_line file. 68 * 69 * @param dpg Struct that polled data is added to. 70 * @return DTOP_POLL_IO_ERR - Poll of dpg unsuccessful. 71 * @return DTOP_POLL_OK - Poll of dpg successful. 72 */ 73 int dtop_dual_line_poll(struct dtop_data_point_gatherer *dpg) 74 { 75 char *data; 76 int *line_len = malloc(sizeof(int) * 77 ((struct dtop_dual_line_vars *) 78 (dpg->priv))->line_count); 79 int *line_len2 = malloc(sizeof(int) * 80 ((struct dtop_dual_line_vars *) 81 (dpg->priv))->line_count); 82 int read; 83 84 struct dt_procdict *dict = malloc(sizeof(struct dt_procdict) 85 * (((struct dtop_dual_line_vars *) 86 (dpg->priv))->line_count/2)); 87 struct dt_procdict *prefix_dict = malloc(sizeof(struct dt_procdict) 88 * (((struct dtop_dual_line_vars *) 89 (dpg->priv))->line_count/2)); 90 int i, j, k, n, sum, sum2; 91 92 read = dt_read_file(dpg->file, &data, DTOP_DUAL_SIZE); 93 if (read == 0 || data == 0) 94 return DTOP_POLL_IO_ERR; 95 96 sum = 0; 97 sum2 = 0; 98 /* Assigns each line read from the file, a length */ 99 for (n = 0; n < ((struct dtop_dual_line_vars *) 100 (dpg->priv))->line_count; n++) { 101 line_len[n] = dt_read_line(((struct dtop_dual_line_vars *) 102 (dpg->priv))->line[n], 103 DTOP_DUAL_LINE, data, 104 DTOP_DUAL_SIZE, sum); 105 line_len2[n] = dt_read_line(((struct dtop_dual_line_vars *) 106 (dpg->priv))->line2[n], 107 DTOP_DUAL_LINE, data, 108 DTOP_DUAL_SIZE, sum2); 109 if (n <= (((struct dtop_dual_line_vars *) 110 (dpg->priv))->line_count-2)) { 111 sum += (line_len[n] + 1); 112 sum2 += (line_len2[n] + 1); 113 } 114 115 } 116 117 /* Stores dp names and values in dictionary */ 118 for (i = 0; i < (((struct dtop_dual_line_vars *) 119 (dpg->priv))->line_count/2); i++) 120 dt_parse_proc_dictionary(((struct dtop_dual_line_vars *) 121 (dpg->priv))->line[2*i], 122 line_len[2*i], 123 ((struct dtop_dual_line_vars *) 124 (dpg->priv))->line[(2*i)+1], 125 line_len[(2*i)+1], 126 &dict[i]); 127 128 /* Stores dp prefices in dictionary */ 129 for (i = 0; i < (((struct dtop_dual_line_vars *) 130 (dpg->priv))->line_count/2); i++) 131 dt_parse_for_prefix(((struct dtop_dual_line_vars *) 132 (dpg->priv))->line2[2*i], line_len2[2*i], 133 &prefix_dict[i]); 134 135 /* Assigns a dp value to each dp struct */ 136 for (k = 0; k < (((struct dtop_dual_line_vars *) 137 (dpg->priv))->line_count/2); k++) { 138 for (j = 0; j < dpg->data_points_len; j++) { 139 i = dt_find_dict_idx(dpg->data_points[j].name, 140 &dict[k]); 141 if (i >= 0 && i < dict[k].max && 142 (strcmp(dpg->data_points[j].prefix, 143 prefix_dict[k].val[i]) == 0)) 144 145 dtop_store_dp(&(dpg->data_points[j]), 146 dict[k].val[i]); 147 } 148 } 149 150 dt_free(&data); 151 free(line_len); 152 free(line_len2); 153 free(dict); 154 free(prefix_dict); 155 return DTOP_POLL_OK; 156 } 157 158 /** 159 * @brief Frees dynamically allocated dual_line_file dpgs. 160 * 161 * Frees the memory of the dpg along with it's data_points 162 * and other malloc'd memory no longer needed. 163 * 164 * @param dpg Dpg to deconstruct and deallocate memory for. 165 */ 166 static void dtop_dual_line_dpg_deconstructor 167 (struct dtop_data_point_gatherer *dpset) 168 { 169 int i; 170 free(dpset->data_points); 171 for (i = 0; i < ((struct dtop_dual_line_vars *) 172 (dpset->priv))->line_count; i++) { 173 free(((struct dtop_dual_line_vars *)(dpset->priv))->line[i]); 174 free(((struct dtop_dual_line_vars *)(dpset->priv))->line2[i]); 175 } 176 free(((struct dtop_dual_line_vars *)(dpset->priv))->line); 177 free(((struct dtop_dual_line_vars *)(dpset->priv))->line2); 178 free(((struct dtop_dual_line_vars *)(dpset->priv))); 179 free(dpset); 180 } 181 182 /** 183 * @brief Creates a dpg for a dual_line file. 184 * 185 * Dynamically allocates memory for dpg which is then added to a linked list 186 * via the dtop_register(dpg) function call. 187 * 188 * @param name Name of file dpg represents. 189 * @param data_points dtop_data_point struct that dpg points to. 190 * @param storage dtop_dual_line_vars struct that hold relevant dpg variables. 191 * @param dp_count Number of datapoints in dtop_data_point struct array. 192 */ 193 static void construct_dual_line_file_dpg(char *name, struct dtop_data_point 194 *data_points, struct dtop_dual_line_vars *storage, int dp_count) 195 { 196 struct dtop_data_point_gatherer *dpg = malloc 197 (sizeof(struct dtop_data_point_gatherer)); 198 dpg->prefix = name; 199 dpg->file = name; 200 dpg->poll = dtop_dual_line_poll; 201 dpg->data_points = data_points; 202 dpg->priv = (struct dtop_dual_line_vars *)storage; 203 dpg->data_points_len = dp_count; 204 dpg->deconstruct = dtop_dual_line_dpg_deconstructor; 205 206 dtop_register(dpg); 207 } 208 209 /** 210 * @brief Scans a dual_line file for all datapoints and creats dps. 211 * 212 * Searches through a dual_line file (Key on one line with value on next line) 213 * for all available data points to create as dp structs. 214 * 215 * @param name Name of file. 216 * @param storage dtop_dual_line_vars struct where relevant variables are stored. 217 */ 218 int dtop_dual_line_search(char *name, struct dtop_dual_line_vars *storage) 219 { 220 int i, j, k, n, sum, sum2; 221 char *data; 222 int *line_len = malloc(sizeof(int) * storage->line_count); 223 int *line_len2 = malloc(sizeof(int) * storage->line_count); 224 int read; 225 struct dt_procdict *dict, *prefix_dict; 226 struct dtop_data_point *data_points; 227 int dp_count = 0; 228 229 storage->line = malloc(storage->line_count * sizeof(*storage->line)); 230 storage->line2 = malloc(storage->line_count * sizeof(*storage->line2)); 231 for (i = 0; i < storage->line_count; i++) { 232 storage->line[i] = malloc(sizeof(char) * DTOP_DUAL_LINE); 233 storage->line2[i] = malloc(sizeof(char) * DTOP_DUAL_LINE); 234 } 235 dict = malloc(sizeof(struct dt_procdict) * (storage->line_count/2)); 236 prefix_dict = malloc(sizeof(struct dt_procdict) 237 * (storage->line_count/2)); 238 239 read = dt_read_file(name, &data, DTOP_DUAL_SIZE); 240 if (read == 0 || data == 0) 241 return DTOP_POLL_IO_ERR; 242 243 sum = 0; 244 sum2 = 0; 245 /* Assigns each line read from the file, a length */ 246 for (n = 0; n < storage->line_count; n++) { 247 line_len[n] = dt_read_line(storage->line[n], 248 DTOP_DUAL_LINE, data, 249 DTOP_DUAL_SIZE, sum); 250 line_len2[n] = dt_read_line(storage->line2[n], 251 DTOP_DUAL_LINE, data, 252 DTOP_DUAL_SIZE, sum2); 253 if (n <= (storage->line_count-2)) { 254 sum += (line_len[n] + 1); 255 sum2 += (line_len2[n] + 1); 256 } 257 258 } 259 260 /* Stores dp names and prefixes in dictionaries */ 261 for (i = 0; i < (storage->line_count/2); i++) 262 dt_parse_proc_dictionary(storage->line[2*i], line_len[2*i], 263 storage->line[(2*i)+1], line_len[(2*i)+1], &dict[i]); 264 265 for (i = 0; i < (storage->line_count/2); i++) 266 dt_parse_for_prefix(storage->line2[2*i], line_len2[2*i], 267 &prefix_dict[i]); 268 269 /* Finds how many data points were gathered from the file */ 270 for (j = 0; j < (storage->line_count/2); j++) { 271 for (i = 0; i < dict[j].max; i++) 272 dp_count++; 273 } 274 275 data_points = malloc(dp_count * sizeof(struct dtop_data_point)); 276 277 k = 0; 278 /* Creates a dtop_data_point struct for each dp found in the file */ 279 for (j = 0; j < (storage->line_count/2); j++) 280 for (i = 0; i < dict[j].max; i++) { 281 if (dict[j].val[i][0] == '-') 282 data_points[k].type = DTOP_LONG; 283 else 284 data_points[k].type = DTOP_ULONG; 285 data_points[k].name = dict[j].key[i]; 286 data_points[k].prefix = prefix_dict[j].val[i]; 287 data_points[k].skip = DO_NOT_SKIP; 288 data_points[k].initial_data_populated = NOT_POPULATED; 289 k++; 290 } 291 292 /* Calls dpg constructor, dpg will point to the dp struct */ 293 construct_dual_line_file_dpg(name, data_points, storage, dp_count); 294 295 free(line_len); 296 free(line_len2); 297 free(dict); 298 free(prefix_dict); 299 dt_free(&data); 300 301 return DTOP_POLL_OK; 302 } 303 304 /** 305 * @brief Calls dtop_search for a file with dual line pairs. 306 */ 307 void dtop_dual_line_init(char *name) 308 { 309 struct dtop_dual_line_vars *storage = malloc 310 (sizeof(struct dtop_dual_line_vars)); 311 storage->line_count = dtop_get_file_line_amount(name); 312 313 if (storage->line_count%2 != 0) { 314 printf("Dual line file, %s, contains error.\n", name); 315 printf("Data will not be collected from %s\n", name); 316 return; 317 } 318 dtop_dual_line_search(name, storage); 319 } 320