Home | History | Annotate | Download | only in src
      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