1/* 2 * Unix SMB/CIFS implementation. 3 * Performance Counter Daemon 4 * 5 * Copyright (C) Marcin Krzysztof Porwit 2005 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 */ 21 22#include "perf.h" 23 24extern sig_atomic_t keep_running; 25 26void fatal(char *msg) 27{ 28 perror(msg); 29 exit(1); 30} 31 32void add_key_raw(TDB_CONTEXT *db, char *keystring, void *databuf, size_t datasize, int flags) 33{ 34 TDB_DATA key, data; 35 36 key.dptr = keystring; 37 key.dsize = strlen(keystring); 38 data.dptr = databuf; 39 data.dsize = datasize; 40 fprintf(stderr, "doing insert of [%x] with key [%s] into [%s]\n", 41 data.dptr, 42 keystring, 43 db->name); 44 45 tdb_store(db, key, data, flags); 46} 47 48void add_key(TDB_CONTEXT *db, char *keystring, char *datastring, int flags) 49{ 50 TDB_DATA key, data; 51 52 key.dptr = keystring; 53 key.dsize = strlen(keystring); 54 data.dptr = datastring; 55 data.dsize = strlen(datastring); 56 /* fprintf(stderr, "doing insert of [%s] with key [%s] into [%s]\n", 57 data.dptr, 58 keystring, 59 db->name);*/ 60 61 tdb_store(db, key, data, flags); 62} 63 64void make_key(char *buf, int buflen, int key_part1, char *key_part2) 65{ 66 memset(buf, 0, buflen); 67 if(key_part2 != NULL) 68 sprintf(buf, "%d%s", key_part1, key_part2); 69 else 70 sprintf(buf, "%d", key_part1); 71 72 return; 73} 74 75void usage(char *progname) 76{ 77 fprintf(stderr, "Usage: %s [-d] [-f <file_path>].\n", progname); 78 fprintf(stderr, "\t-d: run as a daemon.\n"); 79 fprintf(stderr, "\t-f <file_path>: path where the TDB files reside.\n"); 80 fprintf(stderr, "\t\tDEFAULT is /var/lib/samba/perfmon\n"); 81 exit(1); 82} 83 84void parse_flags(RuntimeSettings *rt, int argc, char **argv) 85{ 86 int flag; 87 88 while((flag = getopt(argc, argv, "df:")) != -1) 89 { 90 switch(flag) 91 { 92 case 'd': 93 { 94 rt->dflag = TRUE; 95 break; 96 } 97 case 'f': 98 { 99 memcpy(rt->dbDir, optarg, strlen(optarg)); 100 break; 101 } 102 default: 103 { 104 usage(argv[0]); 105 } 106 } 107 } 108 109 return; 110} 111 112void setup_file_paths(RuntimeSettings *rt) 113{ 114 int status; 115 116 if(strlen(rt->dbDir) == 0) 117 { 118 /* No file path was passed in, use default */ 119 sprintf(rt->dbDir, "/var/lib/samba/perfmon"); 120 } 121 122 sprintf(rt->nameFile, "%s/names.tdb", rt->dbDir); 123 sprintf(rt->counterFile, "%s/data.tdb", rt->dbDir); 124 125 mkdir(rt->dbDir, 0755); 126 rt->cnames = tdb_open(rt->nameFile, 0, TDB_CLEAR_IF_FIRST, O_RDWR | O_CREAT, 0644); 127 rt->cdata = tdb_open(rt->counterFile, 0, TDB_CLEAR_IF_FIRST, O_RDWR | O_CREAT, 0644); 128 129 if(rt->cnames == NULL || rt->cdata == NULL) 130 { 131 perror("setup_file_paths"); 132 exit(1); 133 } 134 135 return; 136} 137 138void sigterm_handler() 139{ 140 keep_running = FALSE; 141 return; 142} 143 144void daemonize(RuntimeSettings *rt) 145{ 146 pid_t pid; 147 int i; 148 int fd; 149 150 /* Check if we're already a daemon */ 151 if(getppid() == 1) 152 return; 153 pid = fork(); 154 if(pid < 0) 155 /* can't fork */ 156 exit(1); 157 else if(pid > 0) 158 { 159 /* we're the parent */ 160 tdb_close(rt->cnames); 161 tdb_close(rt->cdata); 162 exit(0); 163 } 164 165 /* get a new session */ 166 if(setsid() == -1) 167 exit(2); 168 169 /* Change CWD */ 170 chdir("/"); 171 172 /* close file descriptors */ 173 close(STDIN_FILENO); 174 close(STDOUT_FILENO); 175 close(STDERR_FILENO); 176 177 /* And reopen them as safe defaults */ 178 fd = open("/dev/null", O_RDONLY); 179 if(fd != 0) 180 { 181 dup2(fd, 0); 182 close(fd); 183 } 184 fd = open("/dev/null", O_WRONLY); 185 if(fd != 1) 186 { 187 dup2(fd, 1); 188 close(fd); 189 } 190 fd = open("/dev/null", O_WRONLY); 191 if(fd != 2) 192 { 193 dup2(fd, 2); 194 close(fd); 195 } 196 197 /* handle signals */ 198 signal(SIGINT, SIG_IGN); 199 signal(SIGHUP, SIG_IGN); 200 signal(SIGTERM, sigterm_handler); 201 202 return; 203} 204 205int get_counter_id(PERF_DATA_BLOCK *data) 206{ 207 data->counter_id += 2; 208 data->num_counters++; 209 210 return data->counter_id; 211} 212 213void init_perf_counter(PerfCounter *counter, 214 PerfCounter *parent, 215 unsigned int index, 216 char *name, 217 char *help, 218 int counter_type, 219 int record_type) 220{ 221 counter->index = index; 222 memcpy(counter->name, name, strlen(name)); 223 memcpy(counter->help, help, strlen(help)); 224 counter->counter_type = counter_type; 225 counter->record_type = record_type; 226 227 switch(record_type) 228 { 229 case PERF_OBJECT: 230 sprintf(counter->relationships, "p"); 231 break; 232 case PERF_COUNTER: 233 sprintf(counter->relationships, "c[%d]", parent->index); 234 break; 235 case PERF_INSTANCE: 236 sprintf(counter->relationships, "i[%d]", parent->index); 237 break; 238 default: 239 perror("init_perf_counter: unknown record type"); 240 exit(1); 241 } 242 243 return; 244} 245