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 3 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, see <http://www.gnu.org/licenses/>. 19 */ 20 21#include "perf.h" 22 23extern sig_atomic_t keep_running; 24 25void fatal(char *msg) 26{ 27 perror(msg); 28 exit(1); 29} 30 31void add_key_raw(TDB_CONTEXT *db, char *keystring, void *databuf, size_t datasize, int flags) 32{ 33 TDB_DATA key, data; 34 35 key.dptr = keystring; 36 key.dsize = strlen(keystring); 37 data.dptr = databuf; 38 data.dsize = datasize; 39 40 tdb_store(db, key, data, flags); 41} 42 43void add_key(TDB_CONTEXT *db, char *keystring, char *datastring, int flags) 44{ 45 TDB_DATA key, data; 46 47 key.dptr = keystring; 48 key.dsize = strlen(keystring); 49 data.dptr = datastring; 50 data.dsize = strlen(datastring); 51 52 tdb_store(db, key, data, flags); 53} 54 55void make_key(char *buf, int buflen, int key_part1, char *key_part2) 56{ 57 memset(buf, 0, buflen); 58 if(key_part2 != NULL) 59 sprintf(buf, "%d%s", key_part1, key_part2); 60 else 61 sprintf(buf, "%d", key_part1); 62 63 return; 64} 65 66void usage(char *progname) 67{ 68 fprintf(stderr, "Usage: %s [-d] [-f <file_path>].\n", progname); 69 fprintf(stderr, "\t-d: run as a daemon.\n"); 70 fprintf(stderr, "\t-f <file_path>: path where the TDB files reside.\n"); 71 fprintf(stderr, "\t\tDEFAULT is /var/lib/samba/perfmon\n"); 72 exit(1); 73} 74 75void parse_flags(RuntimeSettings *rt, int argc, char **argv) 76{ 77 int flag; 78 79 while((flag = getopt(argc, argv, "df:")) != -1) 80 { 81 switch(flag) 82 { 83 case 'd': 84 { 85 rt->dflag = TRUE; 86 break; 87 } 88 case 'f': 89 { 90 memcpy(rt->dbDir, optarg, strlen(optarg)); 91 break; 92 } 93 default: 94 { 95 usage(argv[0]); 96 } 97 } 98 } 99 100 return; 101} 102 103void setup_file_paths(RuntimeSettings *rt) 104{ 105 int status; 106 107 if(strlen(rt->dbDir) == 0) 108 { 109 /* No file path was passed in, use default */ 110 sprintf(rt->dbDir, "/var/lib/samba/perfmon"); 111 } 112 113 sprintf(rt->nameFile, "%s/names.tdb", rt->dbDir); 114 sprintf(rt->counterFile, "%s/data.tdb", rt->dbDir); 115 116 mkdir(rt->dbDir, 0755); 117 rt->cnames = tdb_open(rt->nameFile, 0, TDB_CLEAR_IF_FIRST, O_RDWR | O_CREAT, 0644); 118 rt->cdata = tdb_open(rt->counterFile, 0, TDB_CLEAR_IF_FIRST, O_RDWR | O_CREAT, 0644); 119 120 if(rt->cnames == NULL || rt->cdata == NULL) 121 { 122 perror("setup_file_paths"); 123 exit(1); 124 } 125 126 return; 127} 128 129void sigterm_handler() 130{ 131 keep_running = FALSE; 132 return; 133} 134 135void daemonize(RuntimeSettings *rt) 136{ 137 pid_t pid; 138 int i; 139 int fd; 140 141 /* Check if we're already a daemon */ 142 if(getppid() == 1) 143 return; 144 pid = fork(); 145 if(pid < 0) 146 /* can't fork */ 147 exit(1); 148 else if(pid > 0) 149 { 150 /* we're the parent */ 151 tdb_close(rt->cnames); 152 tdb_close(rt->cdata); 153 exit(0); 154 } 155 156 /* get a new session */ 157 if(setsid() == -1) 158 exit(2); 159 160 /* Change CWD */ 161 chdir("/"); 162 163 /* close file descriptors */ 164 close(STDIN_FILENO); 165 close(STDOUT_FILENO); 166 close(STDERR_FILENO); 167 168 /* And reopen them as safe defaults */ 169 fd = open("/dev/null", O_RDONLY); 170 if(fd != 0) 171 { 172 dup2(fd, 0); 173 close(fd); 174 } 175 fd = open("/dev/null", O_WRONLY); 176 if(fd != 1) 177 { 178 dup2(fd, 1); 179 close(fd); 180 } 181 fd = open("/dev/null", O_WRONLY); 182 if(fd != 2) 183 { 184 dup2(fd, 2); 185 close(fd); 186 } 187 188 /* handle signals */ 189 signal(SIGINT, SIG_IGN); 190 signal(SIGHUP, SIG_IGN); 191 signal(SIGTERM, sigterm_handler); 192 193 return; 194} 195 196int get_counter_id(PERF_DATA_BLOCK *data) 197{ 198 data->counter_id += 2; 199 data->num_counters++; 200 201 return data->counter_id; 202} 203 204void init_perf_counter(PerfCounter *counter, 205 PerfCounter *parent, 206 unsigned int index, 207 char *name, 208 char *help, 209 int counter_type, 210 int record_type) 211{ 212 counter->index = index; 213 memcpy(counter->name, name, strlen(name)); 214 memcpy(counter->help, help, strlen(help)); 215 counter->counter_type = counter_type; 216 counter->record_type = record_type; 217 218 switch(record_type) 219 { 220 case PERF_OBJECT: 221 sprintf(counter->relationships, "p"); 222 break; 223 case PERF_COUNTER: 224 sprintf(counter->relationships, "c[%d]", parent->index); 225 break; 226 case PERF_INSTANCE: 227 sprintf(counter->relationships, "i[%d]", parent->index); 228 break; 229 default: 230 perror("init_perf_counter: unknown record type"); 231 exit(1); 232 } 233 234 return; 235} 236