Home | History | Annotate | Download | only in ioshark
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <fcntl.h>
     18 #include <stdio.h>
     19 #include <sys/types.h>
     20 #include <unistd.h>
     21 #include <stdlib.h>
     22 #include <string.h>
     23 #include <sys/stat.h>
     24 #include <sys/errno.h>
     25 #include "ioshark.h"
     26 #include "compile_ioshark.h"
     27 
     28 extern char *progname;
     29 
     30 static struct files_db_s *files_db_buckets[FILE_DB_HASHSIZE];
     31 static int current_fileno = 1;
     32 static int num_objects = 0;
     33 
     34 static int filename_cache_lookup(char *filename);;
     35 
     36 void
     37 files_db_write_objects(FILE *fp)
     38 {
     39 	int i;
     40 	struct ioshark_file_state st;
     41 
     42 	for (i = 0 ; i < FILE_DB_HASHSIZE ; i++) {
     43 		struct files_db_s *db_node, *s;
     44 
     45 		db_node = files_db_buckets[i];
     46 		while (db_node != NULL) {
     47 			st.fileno = db_node->fileno;
     48 			st.size = db_node->size;
     49 			st.global_filename_ix =
     50 				db_node->global_filename_ix;
     51 			if (fwrite(&st, sizeof(st), 1, fp) != 1) {
     52 				fprintf(stderr,
     53 					"%s Write error trace.outfile\n",
     54 					progname);
     55 				exit(EXIT_FAILURE);
     56 			}
     57 			s = db_node;
     58 			db_node = db_node->next;
     59 			free(s->filename);
     60 			free(s);
     61 		}
     62 	}
     63 }
     64 
     65 void *files_db_lookup(char *pathname)
     66 {
     67 	u_int32_t hash;
     68 	struct files_db_s *db_node;
     69 
     70 	hash = jenkins_one_at_a_time_hash(pathname, strlen(pathname));
     71 	hash %= FILE_DB_HASHSIZE;
     72 	db_node = files_db_buckets[hash];
     73 	while (db_node != NULL) {
     74 		if (strcmp(db_node->filename, pathname) == 0)
     75 			break;
     76 		db_node = db_node->next;
     77 	}
     78 	return db_node;
     79 }
     80 
     81 void *files_db_add(char *filename)
     82 {
     83 	u_int32_t hash;
     84 	struct files_db_s *db_node;
     85 
     86 	if ((db_node = files_db_lookup(filename)))
     87 		return db_node;
     88 	hash = jenkins_one_at_a_time_hash(filename, strlen(filename));
     89 	hash %= FILE_DB_HASHSIZE;
     90 	db_node = malloc(sizeof(struct files_db_s));
     91 	db_node->filename = strdup(filename);
     92 	db_node->global_filename_ix =
     93 		filename_cache_lookup(filename);
     94 	db_node->fileno = current_fileno++;
     95 	db_node->next = files_db_buckets[hash];
     96 	db_node->size = 0;
     97 	files_db_buckets[hash] = db_node;
     98 	num_objects++;
     99 	return db_node;
    100 }
    101 
    102 int
    103 files_db_get_total_obj(void)
    104 {
    105 	return num_objects;
    106 }
    107 
    108 static struct ioshark_filename_struct *filename_cache;
    109 static int filename_cache_num_entries;
    110 static int filename_cache_size;
    111 
    112 void
    113 init_filename_cache(void)
    114 {
    115 	static FILE *filename_cache_fp;
    116 	struct stat st;
    117 	int file_exists = 1;
    118 
    119 	if (stat("ioshark_filenames", &st) < 0) {
    120 		if (errno != ENOENT) {
    121 			fprintf(stderr, "%s Can't stat ioshark_filenames file\n",
    122 				progname);
    123 			exit(EXIT_FAILURE);
    124 		} else {
    125 			file_exists = 0;
    126 			filename_cache_num_entries = 0;
    127 		}
    128 	} else {
    129 		filename_cache_num_entries = st.st_size /
    130 			sizeof(struct ioshark_filename_struct);
    131 	}
    132 	if (file_exists) {
    133 		filename_cache_fp = fopen("ioshark_filenames", "r");
    134 		if (filename_cache_fp == NULL) {
    135 			fprintf(stderr, "%s Cannot open ioshark_filenames file\n",
    136 				progname);
    137 			exit(EXIT_FAILURE);
    138 		}
    139 	}
    140 	/* Preallocate a fixed size of entries */
    141 	filename_cache_size = filename_cache_num_entries + 1024;
    142 	filename_cache = calloc(filename_cache_size,
    143 				sizeof(struct ioshark_filename_struct));
    144 	if (filename_cache == NULL) {
    145 		fprintf(stderr, "%s Can't allocate memory - this is fatal\n",
    146 			__func__);
    147 		exit(EXIT_FAILURE);
    148 	}
    149 	if (fread(filename_cache,
    150 		  sizeof(struct ioshark_filename_struct),
    151 		  filename_cache_num_entries,
    152 		  filename_cache_fp) != (size_t)filename_cache_num_entries) {
    153 		fprintf(stderr, "%s Can't read ioshark_filenames file\n",
    154 			progname);
    155 		exit(EXIT_FAILURE);
    156 	}
    157 	if (file_exists)
    158 		fclose(filename_cache_fp);
    159 }
    160 
    161 static int
    162 filename_cache_lookup(char *filename)
    163 {
    164 	int ret;
    165 	int i;
    166 
    167 	for (i = 0 ; i < filename_cache_num_entries ; i++) {
    168 		if (strcmp(filename_cache[i].path, filename) == 0)
    169 			return i;
    170 	}
    171 	if (filename_cache_num_entries >= filename_cache_size) {
    172 		int newsize;
    173 
    174 		/* reallocate the filename cache up first */
    175 		filename_cache_size += 1024;
    176 		newsize = filename_cache_size *
    177 			sizeof(struct ioshark_filename_struct);
    178 		filename_cache = realloc(filename_cache, newsize);
    179 		if (filename_cache == NULL) {
    180 			fprintf(stderr,
    181 				"%s Can't allocate memory - this is fatal\n",
    182 				__func__);
    183 			exit(EXIT_FAILURE);
    184 		}
    185 	}
    186 	strcpy(filename_cache[filename_cache_num_entries].path,
    187 	       filename);
    188 	ret = filename_cache_num_entries;
    189 	filename_cache_num_entries++;
    190 	return ret;
    191 }
    192 
    193 void
    194 store_filename_cache(void)
    195 {
    196 	static FILE *filename_cache_fp;
    197 
    198 	filename_cache_fp = fopen("ioshark_filenames", "w+");
    199 	if (filename_cache_fp == NULL) {
    200 		fprintf(stderr, "%s Cannot open ioshark_filenames file\n",
    201 			progname);
    202 		exit(EXIT_FAILURE);
    203 	}
    204 	if (fwrite(filename_cache,
    205 		   sizeof(struct ioshark_filename_struct),
    206 		   filename_cache_num_entries,
    207 		   filename_cache_fp) != (size_t)filename_cache_num_entries) {
    208 		fprintf(stderr, "%s Can't read ioshark_filenames file\n",
    209 			progname);
    210 		exit(EXIT_FAILURE);
    211 	}
    212 	fclose(filename_cache_fp);
    213 	free(filename_cache);
    214 }
    215 
    216 
    217 
    218