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