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
files_db_write_objects(FILE * fp)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 
files_db_lookup(char * pathname)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 
files_db_add(char * filename)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
files_db_get_total_obj(void)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
init_filename_cache(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
filename_cache_lookup(char * filename)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
store_filename_cache(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