📄 mmstat.c
字号:
/* $Id: mmstat.c,v 1.3 2003/01/08 20:57:46 mmondor Exp $ *//* * Copyright (C) 2002-2003, Matthew Mondor * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software written by Matthew Mondor. * 4. The name of Matthew Mondor may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *//* HEADERS */#include <sys/types.h>#include <sys/socket.h>#include <sys/un.h>#include <sys/uio.h>#include <sys/poll.h>#include <stdlib.h>#include <unistd.h>#include <stdio.h>#include <stdarg.h>#include <syslog.h>#include <mmtypes.h>#include <mmstat.h>#include <mmreadcfg.h>#include <mmstring.h>MMCOPYRIGHT("@(#) Copyright (c) 2002-2003\n\\tMatthew Mondor. All rights reserved.\n");MMRCSID("$Id: mmstat.c,v 1.3 2003/01/08 20:57:46 mmondor Exp $");/* PRIVATE PROTOTYPES */static bool i_mmstat_send(struct log_entry *, int);/* GLOBALS */static struct mmstat_config CONF;static bool mmstat_initialized = FALSE, connect_log = TRUE;static int lsock = -1;static struct sockaddr_un laddr;/* FUNCTIONS *//* Public API mmstat functions */boolmmstat_init(MMSTAT *mms, bool persistant, bool autoflush){ bool ret = FALSE; if (mmstat_initialized || mmstat_initialize()) { mms->transaction = FALSE; mms->persistant = persistant; mms->autoflush = autoflush; mms->transact_pos = 0; ret = TRUE; } return (ret);}boolmmstat(MMSTAT *mms, enum stat_type type, int64_t value, char *fmt, ...){ bool ok = FALSE; struct log_entry *entry; va_list arg_ptr; if (type == STAT_RESET || type == STAT_UPDATE || type == STAT_DELETE) { if (mms->transact_pos < MAX_TRANSACT) { /* In case transaction mode is active, make sure to not overflow * buffer, and that we write next entry at the right offset. * The mmstatd logger process only distinguishes transaction * protected requests in that they are all sent in a single packet. */ entry = &(mms->entries[mms->transact_pos]); mms->transact_pos++; /* Now simply fill new log entry */ mm_memclr(entry, sizeof(struct log_entry)); entry->type = type; entry->persistant = mms->persistant; entry->autoflush = mms->autoflush; if (fmt) { va_start(arg_ptr, fmt); vsnprintf(entry->key, KEY_SIZE - 1, fmt, arg_ptr); va_end(arg_ptr); } if (type == STAT_UPDATE) entry->un.update.modifier = value; else if (type == STAT_RESET) entry->un.reset.value = value; ok = TRUE; } } if (ok && !mms->transaction) { /* Not in transaction mode, flush packet to mmstatd immediately */ ok = i_mmstat_send(mms->entries, 1); mms->transact_pos = 0; } return (ok);}boolmmstat_transact(MMSTAT *mms, bool lock){ bool ok = FALSE; if (lock) { if (!mms->transaction) { /* Start transaction mode */ mms->transaction = TRUE; mms->transact_pos = 0; ok = TRUE; } } else { if (mms->transaction) { /* End transaction mode, flush transaction queue to mmstatd */ if (i_mmstat_send(mms->entries, mms->transact_pos)) ok = TRUE; mms->transaction = FALSE; mms->transact_pos = 0; } } return (ok);}MMSTATRES *mmstat_report(char *fmt, ...){ MMSTATRES *res = NULL; struct sockaddr_un sun; va_list arg_ptr; char key[KEY_SIZE], c; if (fmt) { mm_memclr(key, KEY_SIZE); va_start(arg_ptr, fmt); vsnprintf(key, KEY_SIZE - 1, fmt, arg_ptr); va_end(arg_ptr); connect_log = FALSE; if (mmstat_initialized || mmstat_initialize()) { if ((res = malloc(sizeof(MMSTATRES)))) { if ((res->fd = socket(AF_LOCAL, SOCK_STREAM, 0)) != -1) { mm_memclr(&sun, sizeof(struct sockaddr_un)); sun.sun_family = AF_UNIX; mm_strcpy(sun.sun_path, CONF.STAT_SOCKET); if (connect(res->fd, (struct sockaddr *)&sun, sizeof(struct sockaddr_un)) != -1) { if ((read(res->fd, &c, 1) == 1) && (c == '+')) { if (write(res->fd, "s", 1) == 1 && write(res->fd, key, KEY_SIZE) == KEY_SIZE) return (res); } } close(res->fd); } free(res); } } } return (NULL);}MMSTATENT *mmstat_nextres(MMSTATRES *res){ struct pollfd fds[] = { {res->fd, POLLIN, 0} }; for (;;) { if (poll(fds, 1, -1) == 1) { if (fds[0].revents & POLLIN) { if (read(res->fd, &res->entry, sizeof(MMSTATENT)) == sizeof(MMSTATENT)) return (&res->entry); else break; } } } return (NULL);}MMSTATRES *mmstat_freeres(MMSTATRES *res){ close(res->fd); free(res); return (NULL);}boolmmstat_rotate(char *pattern, char *prefix){ struct sockaddr_un sun; int fd; char pat[KEY_SIZE], pre[KEY_SIZE], c; bool ok = FALSE; if (pattern && prefix) { mm_memclr(pat, KEY_SIZE); mm_strncpy(pat, pattern, KEY_SIZE - 1); mm_memclr(pre, KEY_SIZE); mm_strncpy(pre, prefix, KEY_SIZE - 1); connect_log = FALSE; if (mmstat_initialized || mmstat_initialize()) { if ((fd = socket(AF_LOCAL, SOCK_STREAM, 0)) != -1) { mm_memclr(&sun, sizeof(struct sockaddr_un)); sun.sun_family = AF_UNIX; mm_strcpy(sun.sun_path, CONF.STAT_SOCKET); if (connect(fd, (struct sockaddr *)&sun, sizeof(struct sockaddr_un)) != -1) { if ((read(fd, &c, 1) == 1) && (c == '+')) { if (write(fd, "r", 1) == 1 && write(fd, pat, KEY_SIZE) == KEY_SIZE && write(fd, pre, KEY_SIZE) == KEY_SIZE) ok = TRUE; } } close(fd); } } } return (ok);}/* Internal functions not available to the public mmstat API */static booli_mmstat_send(struct log_entry *entries, int len){ int l; bool ok = FALSE; l = sizeof(struct log_entry) * len; while (!ok) { if (lsock != -1) { if ((send(lsock, entries, l, 0)) == l) ok = TRUE; else { close(lsock); lsock = -1; } } if (!ok) { /* Attempt to re-establish connection to mmstatd(8) */ syslog(LOG_NOTICE, "mmstat - Re-establishing lost connection"); if (!mmstat_initialize()) break; } } return (ok);}boolmmstat_initialize(void){ char *conf_file = "/etc/mmstatd.conf", *tmp; bool ok = FALSE; CRES cres; CARG cargs[] = { {CAT_STR, 1, 31, CAS_UNTOUCHED, "USER", CONF.USER}, {CAT_STR, 1, 255, CAS_UNTOUCHED, "GROUPS", CONF.GROUPS}, {CAT_STR, 1, 31, CAS_UNTOUCHED, "LOG_FACILITY", CONF.LOG_FACILITY}, {CAT_STR, 1, 255, CAS_UNTOUCHED, "PID_FILE", CONF.PID_FILE}, {CAT_STR, 1, 255, CAS_UNTOUCHED, "LOCK_FILE", CONF.LOCK_FILE}, {CAT_STR, 1, 255, CAS_UNTOUCHED, "LOG_SOCKET", CONF.LOG_SOCKET}, {CAT_STR, 1, 255, CAS_UNTOUCHED, "STAT_SOCKET", CONF.STAT_SOCKET}, {CAT_STR, 1, 127, CAS_UNTOUCHED, "ENV_DIR", CONF.ENV_DIR}, {CAT_STR, 1, 31, CAS_UNTOUCHED, "LOG_GROUP", CONF.LOG_GROUP}, {CAT_STR, 1, 31, CAS_UNTOUCHED, "STAT_GROUP", CONF.STAT_GROUP}, {CAT_VAL, 1, 99999999, CAS_UNTOUCHED, "SYNC_INTERVAL", &CONF.SYNC_INTERVAL}, {CAT_VAL, 0, 99999999, CAS_UNTOUCHED, "SYNC_BYTES", &CONF.SYNC_BYTES}, {CAT_VAL, 1, 99999999, CAS_UNTOUCHED, "MAX_LOGSIZE", &CONF.MAX_LOGSIZE}, {CAT_VAL, 1, 9999, CAS_UNTOUCHED, "STATS_RATE", &CONF.STATS_RATE}, {CAT_VAL, 1, 9999, CAS_UNTOUCHED, "STATS_TIME", &CONF.STATS_TIME}, {CAT_END, 0, 0, 0, NULL, NULL} }; /* Set defaults */ mm_strcpy(CONF.USER, "mmstatd"); mm_strcpy(CONF.GROUPS, "mmstat staff"); mm_strcpy(CONF.LOG_FACILITY, "LOG_AUTHPRIV"); mm_strcpy(CONF.PID_FILE, "/var/mmstatd/mmstatd.pid"); mm_strcpy(CONF.LOG_SOCKET, "/var/mmstatd/mmstatd_log.sock"); mm_strcpy(CONF.STAT_SOCKET, "/var/mmstatd/mmstatd_stat.sock"); mm_strcpy(CONF.ENV_DIR, "/var/mmstatd"); mm_strcpy(CONF.LOG_GROUP, "mmstat"); mm_strcpy(CONF.STAT_GROUP, "staff"); CONF.SYNC_INTERVAL = 1800; CONF.SYNC_BYTES = 4096; CONF.MAX_LOGSIZE = 1048576; CONF.STATS_RATE = 5; CONF.STATS_TIME = 10; if ((tmp = getenv("MMSTATCONF"))) conf_file = tmp; if (mmreadcfg(conf_file, cargs, &cres)) { if (connect_log) { if ((lsock = socket(AF_LOCAL, SOCK_DGRAM, 0)) != -1) { mm_memclr(&laddr, sizeof(struct sockaddr_un)); mm_strncpy(laddr.sun_path, CONF.LOG_SOCKET, 100); laddr.sun_family = AF_UNIX; if ((connect(lsock, (struct sockaddr *)&laddr, sizeof(struct sockaddr_un))) == -1) { close(lsock); lsock = -1; syslog(LOG_NOTICE, "mmstat_initialize() - connect(%s)", CONF.LOG_SOCKET); } } else syslog(LOG_NOTICE, "mmstat_initialize() - socket()"); if (lsock != -1) ok = TRUE; } else ok = TRUE; } else syslog(LOG_NOTICE, "mmstat_initialize() - mmreadcfg(/etc/mmstatd.conf)"); mmstat_initialized = ok; return (ok);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -