78a99fef494df0e4058799e2aa1892fa6828ede7
[ira/wip.git] / examples / perfcounter / perf_writer_util.c
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
24 extern sig_atomic_t keep_running;
25
26 void fatal(char *msg)
27 {
28   perror(msg);
29   exit(1);
30 }
31
32 void 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
48 void 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
64 void 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
75 void 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
84 void 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
112 void 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
138 void sigterm_handler()
139 {
140     keep_running = FALSE;
141     return;
142 }
143
144 void 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
205 int 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
213 void 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 }