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