1 /* $Id: mmstat.c,v 1.4 2003/04/27 19:48:04 mmondor Exp $ */
4 * Copyright (C) 2002-2003, Matthew Mondor
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software written by Matthew Mondor.
18 * 4. The name of Matthew Mondor may not be used to endorse or promote
19 * products derived from this software without specific prior written
22 * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 #include <sys/types.h>
40 #include <sys/socket.h>
52 #include <mmreadcfg.h>
58 MMCOPYRIGHT("@(#) Copyright (c) 2002-2003\n\
59 \tMatthew Mondor. All rights reserved.\n");
60 MMRCSID("$Id: mmstat.c,v 1.4 2003/04/27 19:48:04 mmondor Exp $");
65 /* PRIVATE PROTOTYPES */
67 static bool i_mmstat_send(struct log_entry
*, int);
74 static struct mmstat_config CONF
;
75 static bool mmstat_initialized
= FALSE
, connect_log
= TRUE
;
76 static int lsock
= -1;
77 static struct sockaddr_un laddr
;
84 /* Public API mmstat functions */
87 mmstat_init(mmstat_t
*mms
, bool persistant
, bool autoflush
)
91 if (mmstat_initialized
|| mmstat_initialize()) {
92 mms
->transaction
= FALSE
;
93 mms
->persistant
= persistant
;
94 mms
->autoflush
= autoflush
;
95 mms
->transact_pos
= 0;
104 mmstat(mmstat_t
*mms
, enum stat_type type
, int64_t value
, const char *fmt
, ...)
107 struct log_entry
*entry
;
110 if (type
== STAT_RESET
|| type
== STAT_UPDATE
|| type
== STAT_DELETE
) {
111 if (mms
->transact_pos
< MAX_TRANSACT
) {
112 /* In case transaction mode is active, make sure to not overflow
113 * buffer, and that we write next entry at the right offset.
114 * The mmstatd logger process only distinguishes transaction
115 * protected requests in that they are all sent in a single packet.
117 entry
= &(mms
->entries
[mms
->transact_pos
]);
119 /* Now simply fill new log entry */
120 mm_memclr(entry
, sizeof(struct log_entry
));
122 entry
->persistant
= mms
->persistant
;
123 entry
->autoflush
= mms
->autoflush
;
125 va_start(arg_ptr
, fmt
);
126 vsnprintf(entry
->key
, KEY_SIZE
- 1, fmt
, arg_ptr
);
129 if (type
== STAT_UPDATE
) entry
->un
.update
.modifier
= value
;
130 else if (type
== STAT_RESET
) entry
->un
.reset
.value
= value
;
134 if (ok
&& !mms
->transaction
) {
135 /* Not in transaction mode, flush packet to mmstatd immediately */
136 ok
= i_mmstat_send(mms
->entries
, 1);
137 mms
->transact_pos
= 0;
145 mmstat_transact(mmstat_t
*mms
, bool lock
)
150 if (!mms
->transaction
) {
151 /* Start transaction mode */
152 mms
->transaction
= TRUE
;
153 mms
->transact_pos
= 0;
157 if (mms
->transaction
) {
158 /* End transaction mode, flush transaction queue to mmstatd */
159 if (i_mmstat_send(mms
->entries
, mms
->transact_pos
)) ok
= TRUE
;
160 mms
->transaction
= FALSE
;
161 mms
->transact_pos
= 0;
170 mmstat_report(const char *fmt
, ...)
172 mmstatres_t
*res
= NULL
;
173 struct sockaddr_un sun
;
175 char key
[KEY_SIZE
], c
;
178 mm_memclr(key
, KEY_SIZE
);
179 va_start(arg_ptr
, fmt
);
180 vsnprintf(key
, KEY_SIZE
- 1, fmt
, arg_ptr
);
183 if (mmstat_initialized
|| mmstat_initialize()) {
184 if ((res
= malloc(sizeof(mmstatres_t
)))) {
185 if ((res
->fd
= socket(AF_LOCAL
, SOCK_STREAM
, 0)) != -1) {
186 mm_memclr(&sun
, sizeof(struct sockaddr_un
));
187 sun
.sun_family
= AF_UNIX
;
188 mm_strcpy(sun
.sun_path
, CONF
.STAT_SOCKET
);
189 if (connect(res
->fd
, (struct sockaddr
*)&sun
,
190 sizeof(struct sockaddr_un
)) != -1) {
191 if ((read(res
->fd
, &c
, 1) == 1) && (c
== '+')) {
192 if (write(res
->fd
, "s", 1) == 1 &&
193 write(res
->fd
, key
, KEY_SIZE
) == KEY_SIZE
)
209 mmstat_nextres(mmstatres_t
*res
)
211 struct pollfd fds
[] = {
216 if (poll(fds
, 1, -1) == 1) {
217 if (fds
[0].revents
& POLLIN
) {
218 if (read(res
->fd
, &res
->entry
, sizeof(mmstatent_t
)) ==
220 return (&res
->entry
);
231 mmstat_freeres(mmstatres_t
*res
)
241 mmstat_rotate(const char *pattern
, const char *prefix
)
243 struct sockaddr_un sun
;
245 char pat
[KEY_SIZE
], pre
[KEY_SIZE
], c
;
248 if (pattern
&& prefix
) {
249 mm_memclr(pat
, KEY_SIZE
);
250 mm_strncpy(pat
, pattern
, KEY_SIZE
- 1);
251 mm_memclr(pre
, KEY_SIZE
);
252 mm_strncpy(pre
, prefix
, KEY_SIZE
- 1);
254 if (mmstat_initialized
|| mmstat_initialize()) {
255 if ((fd
= socket(AF_LOCAL
, SOCK_STREAM
, 0)) != -1) {
256 mm_memclr(&sun
, sizeof(struct sockaddr_un
));
257 sun
.sun_family
= AF_UNIX
;
258 mm_strcpy(sun
.sun_path
, CONF
.STAT_SOCKET
);
259 if (connect(fd
, (struct sockaddr
*)&sun
,
260 sizeof(struct sockaddr_un
)) != -1) {
261 if ((read(fd
, &c
, 1) == 1) && (c
== '+')) {
262 if (write(fd
, "r", 1) == 1 &&
263 write(fd
, pat
, KEY_SIZE
) == KEY_SIZE
&&
264 write(fd
, pre
, KEY_SIZE
) == KEY_SIZE
)
277 /* Internal functions not available to the public mmstat API */
280 i_mmstat_send(struct log_entry
*entries
, int len
)
285 l
= sizeof(struct log_entry
) * len
;
288 if ((send(lsock
, entries
, l
, 0)) == l
)
296 /* Attempt to re-establish connection to mmstatd(8) */
297 syslog(LOG_NOTICE
, "mmstat - Re-establishing lost connection");
298 if (!mmstat_initialize())
308 mmstat_initialize(void)
310 char *conf_file
= "/etc/mmstatd.conf", *tmp
;
314 {CAT_STR
, 1, 31, CAS_UNTOUCHED
, "USER", CONF
.USER
},
315 {CAT_STR
, 1, 255, CAS_UNTOUCHED
, "GROUPS", CONF
.GROUPS
},
316 {CAT_STR
, 1, 31, CAS_UNTOUCHED
, "LOG_FACILITY", CONF
.LOG_FACILITY
},
317 {CAT_STR
, 1, 255, CAS_UNTOUCHED
, "PID_FILE", CONF
.PID_FILE
},
318 {CAT_STR
, 1, 255, CAS_UNTOUCHED
, "LOCK_FILE", CONF
.LOCK_FILE
},
319 {CAT_STR
, 1, 255, CAS_UNTOUCHED
, "LOG_SOCKET", CONF
.LOG_SOCKET
},
320 {CAT_STR
, 1, 255, CAS_UNTOUCHED
, "STAT_SOCKET", CONF
.STAT_SOCKET
},
321 {CAT_STR
, 1, 127, CAS_UNTOUCHED
, "ENV_DIR", CONF
.ENV_DIR
},
322 {CAT_STR
, 1, 31, CAS_UNTOUCHED
, "LOG_GROUP", CONF
.LOG_GROUP
},
323 {CAT_STR
, 1, 31, CAS_UNTOUCHED
, "STAT_GROUP", CONF
.STAT_GROUP
},
324 {CAT_VAL
, 1, 99999999, CAS_UNTOUCHED
, "SYNC_INTERVAL",
325 &CONF
.SYNC_INTERVAL
},
326 {CAT_VAL
, 0, 99999999, CAS_UNTOUCHED
, "SYNC_BYTES",
328 {CAT_VAL
, 1, 99999999, CAS_UNTOUCHED
, "MAX_LOGSIZE",
330 {CAT_VAL
, 1, 9999, CAS_UNTOUCHED
, "STATS_RATE", &CONF
.STATS_RATE
},
331 {CAT_VAL
, 1, 9999, CAS_UNTOUCHED
, "STATS_TIME", &CONF
.STATS_TIME
},
332 {CAT_END
, 0, 0, 0, NULL
, NULL
}
336 mm_strcpy(CONF
.USER
, "mmstatd");
337 mm_strcpy(CONF
.GROUPS
, "mmstat staff");
338 mm_strcpy(CONF
.LOG_FACILITY
, "LOG_AUTHPRIV");
339 mm_strcpy(CONF
.PID_FILE
, "/var/mmstatd/mmstatd.pid");
340 mm_strcpy(CONF
.LOG_SOCKET
, "/var/mmstatd/mmstatd_log.sock");
341 mm_strcpy(CONF
.STAT_SOCKET
, "/var/mmstatd/mmstatd_stat.sock");
342 mm_strcpy(CONF
.ENV_DIR
, "/var/mmstatd");
343 mm_strcpy(CONF
.LOG_GROUP
, "mmstat");
344 mm_strcpy(CONF
.STAT_GROUP
, "staff");
345 CONF
.SYNC_INTERVAL
= 1800;
346 CONF
.SYNC_BYTES
= 4096;
347 CONF
.MAX_LOGSIZE
= 1048576;
349 CONF
.STATS_TIME
= 10;
351 if ((tmp
= getenv("MMSTATCONF")))
353 if (mmreadcfg(conf_file
, cargs
, &cres
)) {
355 if ((lsock
= socket(AF_LOCAL
, SOCK_DGRAM
, 0)) != -1) {
356 mm_memclr(&laddr
, sizeof(struct sockaddr_un
));
357 mm_strncpy(laddr
.sun_path
, CONF
.LOG_SOCKET
, 100);
358 laddr
.sun_family
= AF_UNIX
;
359 if ((connect(lsock
, (struct sockaddr
*)&laddr
,
360 sizeof(struct sockaddr_un
))) == -1) {
363 syslog(LOG_NOTICE
, "mmstat_initialize() - connect(%s)",
367 syslog(LOG_NOTICE
, "mmstat_initialize() - socket()");
374 "mmstat_initialize() - mmreadcfg(/etc/mmstatd.conf)");
376 mmstat_initialized
= ok
;