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