commit 2a56a66bb99d83ed9323f40c0e3a2df9396aa94b Author: Olaf Rempel Date: Tue Jun 13 21:34:36 2006 +0200 Initial Version diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..960d78f --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.o +*.so +*.d +sammler +sammler.log diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..093c6e0 --- /dev/null +++ b/AUTHORS @@ -0,0 +1 @@ +Olaf Rempel diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..60549be --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ab7c353 --- /dev/null +++ b/Makefile @@ -0,0 +1,30 @@ +# Toplevel Makefile + +SAMMLER_SRC := sammler.c config.c logging.c rrdtool.c plugins.c +PLUGIN_SRC := $(wildcard p_*.c) +CFLAGS := -O2 -Wall +LDFLAGS := -ldl -lrrd -rdynamic + +# ############################ + +all: sammler $(PLUGIN_SRC:%.c=%.so) + +sammler: $(SAMMLER_SRC:%.c=%.o) + $(CC) $(LDFLAGS) $^ -o $@ + +%.d: %.c + $(CC) $(CFLAGS) -MM -c $< -o $@ + +%.o: %.c + $(CC) $(CFLAGS) -o $@ -c $< + +%_sh.o: %.c + $(CC) $(CFLAGS) -fPIC -o $@ -c $< + +%.so: %_sh.o + $(LD) -shared -o $@ $< + +clean: + rm -rf *.d *.o *.so sammler + +#-include $(SAMMLER_SRC:.c=.d) $(PLUGIN_SRC:.c=.d) diff --git a/config.c b/config.c new file mode 100644 index 0000000..f36fed6 --- /dev/null +++ b/config.c @@ -0,0 +1,182 @@ +/*************************************************************************** + * Copyright (C) 06/2006 by Olaf Rempel * + * razzor@kopf-tisch.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include +#include + +#include "list.h" + +#include "config.h" +#include "logging.h" + +static LIST_HEAD(config_list); + +static struct conf_section * config_add_section(char *name) +{ + struct conf_section *section; + + if (!name) + return NULL; + + section = malloc(sizeof(struct conf_section)); + if (section) { + INIT_LIST_HEAD(§ion->list); + INIT_LIST_HEAD(§ion->tupel); + + strncpy(section->name, name, sizeof(section->name)); + list_add_tail(§ion->list, &config_list); + } + return section; +} + +static int config_add_tupel(struct conf_section *section, char *option, char *parameter) +{ + struct conf_tupel *tupel; + + if (!section || !option || !parameter) + return 0; + + if (!(tupel = malloc(sizeof(struct conf_tupel)))) + return 0; + + INIT_LIST_HEAD(&tupel->list); + + tupel->option = strdup(option); + tupel->parameter = strdup(parameter); + + list_add_tail(&tupel->list, §ion->tupel); + return 1; +} + +static void config_free(void) +{ + struct conf_section *section, *section_tmp; + struct conf_tupel *tupel, *tupel_tmp; + + list_for_each_entry_safe(section, section_tmp, &config_list, list) { + list_for_each_entry_safe(tupel, tupel_tmp, §ion->tupel, list) { + list_del(&tupel->list); + free(tupel->option); + free(tupel->parameter); + free(tupel); + } + list_del(§ion->list); + free(section); + } +} + +int config_parse(char *config) +{ + struct conf_section *section = NULL; + FILE *fz; + int i = 0, ret = 1; + char *row, *tok, *tok2; + + if (!config) + return 0; + + if (!(row = malloc(1024))) + return 0; + + if (!(fz = fopen(config, "r"))) { + log_print(LOG_ERROR, "config_parse(): %s", config); + return 0; + } + + while (fgets(row, 1024, fz)) { + i++; + + if (row[0] == '#' || row[0] <= ' ') { + continue; + + } else if (row[0] == '[') { + tok = strtok(row +1, " ]\n"); + section = config_add_section(tok); + if (!section) { + log_print(LOG_WARN, "config_parse(): invalid section in row %d", i); + ret = 0; + break; + } + continue; + + } else if (!section) { + log_print(LOG_WARN, "config_parse(): missing section in row %d", i); + ret = 0; + break; + } + + if ((tok = strtok(row, " \n")) && (tok2 = strtok(NULL, " \n"))) + if (!config_add_tupel(section, tok, tok2)) + log_print(LOG_WARN, "config_parse(): invalid row %d", i); + } + + fclose(fz); + free(row); + + if (atexit(config_free) != 0) { + log_print(LOG_ERROR, "config_parse(): atexit()"); + return 0; + } + + return ret; +} + +struct conf_section * config_get_section(char *name) +{ + struct conf_section *section; + + list_for_each_entry(section, &config_list, list) { + if (!strcmp(section->name, name)) + return section; + } + return NULL; +} + +char * config_get_parameter(struct conf_section *section, char *option) +{ + struct conf_tupel *tupel; + + list_for_each_entry(tupel, §ion->tupel, list) { + if (!strcmp(tupel->option, option)) + return tupel->parameter; + } + return NULL; +} + +char * config_get_string(char *section, char *option, char *def) +{ + struct conf_section *tmp; + char *ret; + + tmp = config_get_section(section); + if (tmp && (ret = config_get_parameter(tmp, option))) + return ret; + + return def; +} + +int config_get_int(char *section, char *option, int def) +{ + char *ret; + + ret = config_get_string(section, option, NULL); + return ret ? atoi(ret) : def; +} diff --git a/config.h b/config.h new file mode 100644 index 0000000..1f0131f --- /dev/null +++ b/config.h @@ -0,0 +1,24 @@ +#ifndef _CONFIG_H_ +#define _CONFIG_H_ + +#include "list.h" + +struct conf_section { + struct list_head list; + char name[32]; + struct list_head tupel; +}; + +struct conf_tupel { + struct list_head list; + char *option; + char *parameter; +}; + +int config_parse(char *config); +struct conf_section * config_get_section(char *name); +char * config_get_parameter(struct conf_section *section, char *option); +char * config_get_string(char *section, char *option, char *def); +int config_get_int(char *section, char *option, int def); + +#endif /* _CONFIG_H_ */ diff --git a/list.h b/list.h new file mode 100644 index 0000000..61f8d93 --- /dev/null +++ b/list.h @@ -0,0 +1,268 @@ +#ifndef _LIST_H_ +#define _LIST_H_ + +/* + * stolen from linux kernel 2.6.11 (http://kernel.org/) + * linux/include/linux/stddef.h (offsetoff) + * linux/include/linux/kernel.h (container_of) + * linux/include/linux/list.h (*list*) + * linux/include/linux/netfilter_ipv4/listhelp.h (LIST_FIND) + * + * modified by Olaf Rempel + */ +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) + +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/* + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/* + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head * prev, struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/* + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is + * in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = NULL; + entry->prev = NULL; +} + +/* + * list_del_init - deletes entry from list and reinitialize it. + * entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/* + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +/* + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/* + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +static inline void __list_splice(struct list_head *list, + struct list_head *head) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +/* + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(struct list_head *list, struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head); +} + +/* + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head); + INIT_LIST_HEAD(list); + } +} + +/* + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/* + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/* + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; pos != (head); pos = pos->prev) + +/* + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/* + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/* + * list_for_each_entry_reverse - iterate backwards over list of given type. + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_reverse(pos, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member)) + +/* + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + + +/* Return pointer to first true entry, if any, or NULL. A macro + required to allow inlining of cmpfn. */ +#define LIST_FIND(head, cmpfn, type, args...) \ +({ \ + const struct list_head *__i, *__j = NULL; \ + \ + list_for_each(__i, (head)) \ + if (cmpfn((const type)__i , ## args)) { \ + __j = __i; \ + break; \ + } \ + (type)__j; \ +}) + +#endif /* _LIST_H_ */ diff --git a/logging.c b/logging.c new file mode 100644 index 0000000..521c2be --- /dev/null +++ b/logging.c @@ -0,0 +1,103 @@ +/*************************************************************************** + * Copyright (C) 06/2006 by Olaf Rempel * + * razzor@kopf-tisch.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include + +#include "logging.h" + +#define BUFSIZE 8192 + +static FILE *log_fd = NULL; +static char *buffer = NULL; + +void log_print(int prio, const char *fmt, ...) +{ + va_list az; + int len; + + if (buffer == NULL) { + buffer = malloc(BUFSIZE); + if (buffer == NULL) { + fprintf(stderr, "log_print: out of memory\nBailing out!\n"); + exit(-1); + } + } + + va_start(az, fmt); + len = vsnprintf(buffer, BUFSIZE, fmt, az); + va_end(az); + + if (len >= BUFSIZE) { + log_print(LOG_ERROR, "log_print: arguments too long"); + errno = 0; + return; + } + + if (errno) { + strncpy(buffer + len, ": ", BUFSIZE - len); + len += 2; + strncpy(buffer + len, strerror(errno), BUFSIZE - len); + } + + if (log_fd) { + char tbuf[64]; + time_t tzgr; + + time(&tzgr); + strftime(tbuf, sizeof(tbuf), "%b %d %H:%M:%S :", localtime(&tzgr)); + + fprintf(log_fd, "%s %s\n", tbuf, buffer); + fflush(log_fd); + + } else { + fprintf(stderr, "%s\n", buffer); + } + + errno = 0; +} + +static void log_close(void) +{ + if (buffer) + free(buffer); + + fclose(log_fd); +} + +int log_init(char *logfile) +{ + log_fd = fopen(logfile, "a"); + if (log_fd == NULL) { + log_print(LOG_ERROR, "log_open('%s'): %s", logfile); + return 0; + } + + if (atexit(log_close) != 0) { + log_print(LOG_ERROR, "log_open(): atexit()"); + return 0; + } + + log_print(LOG_EVERYTIME, "=========================="); + return 1; +} diff --git a/logging.h b/logging.h new file mode 100644 index 0000000..c6e32c0 --- /dev/null +++ b/logging.h @@ -0,0 +1,16 @@ +#ifndef _LOGGING_H_ +#define _LOGGING_H_ + +#define LOG_DEBUG 5 +#define LOG_INFO 4 +#define LOG_NOTICE 3 +#define LOG_WARN 2 +#define LOG_ERROR 1 +#define LOG_CRIT 0 + +#define LOG_EVERYTIME 0 + +int log_init(char *logfile); +void log_print(int prio, const char *fmt, ... ); + +#endif /* _LOGGING_H_ */ diff --git a/p_ctstat.c b/p_ctstat.c new file mode 100644 index 0000000..2974bcc --- /dev/null +++ b/p_ctstat.c @@ -0,0 +1,105 @@ +/*************************************************************************** + * Copyright (C) 06/2006 by Olaf Rempel * + * razzor@kopf-tisch.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include + +#include "plugins.h" + +#define BUFSIZE 1024 + +struct sammler_plugin plugin; + +static char *ds_def[] = { + "DS:entries:GAUGE:%d:0:U", + "DS:searched:DERIVE:%d:0:U", + "DS:found:DERIVE:%d:0:U", + "DS:new:DERIVE:%d:0:U", + "DS:invalid:DERIVE:%d:0:U", + "DS:ignore:DERIVE:%d:0:U", + "DS:delete:DERIVE:%d:0:U", + "DS:delete_list:DERIVE:%d:0:U", + "DS:insert:DERIVE:%d:0:U", + "DS:insert_failed:DERIVE:%d:0:U", + "DS:drop:DERIVE:%d:0:U", + "DS:early_drop:DERIVE:%d:0:U", + "DS:icmp_error:DERIVE:%d:0:U", + "DS:expect_new:DERIVE:%d:0:U", + "DS:expect_create:DERIVE:%d:0:U", + "DS:expect_delete:DERIVE:%d:0:U", + NULL +}; + +static char ** get_ds(int ds_id) +{ + return ds_def; +} + +static void probe(void) +{ + FILE *fp; + char *buffer, *val[16], filename[16]; + unsigned long long arr[16]; + int i, cpu = 0; + + buffer = malloc(BUFSIZE); + if (buffer == NULL) { + log_print(LOG_WARN, "plugin ctstat: out of memory"); + return; + } + + fp = fopen("/proc/net/stat/ip_conntrack", "r"); + if (fp == NULL) { + log_print(LOG_WARN, "plugin ctstat"); + free(buffer); + return; + } + + while (fgets(buffer, BUFSIZE, fp) != NULL) { + if (!strncmp(buffer, "entries", 7)) + continue; + + if (strsplit(buffer, val, 16) != 16) + continue; + + for (i = 0; i < 16; i++) + arr[i] = strtoll(val[i], NULL, 16); + + snprintf(filename, sizeof(filename), "ctstat-%d.rrd", cpu); + + probe_submit(&plugin, filename, 0, + "%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu", + arr[0], arr[1], arr[2], arr[3], + arr[4], arr[5], arr[6], arr[7], + arr[8], arr[9], arr[10], arr[11], + arr[12], arr[13], arr[14], arr[15]); + + cpu++; + } + fclose(fp); + free(buffer); +} + +struct sammler_plugin plugin = { + .name = "ctstat", + .version = 1, + .probe = &probe, + .get_ds = &get_ds, +}; diff --git a/p_load.c b/p_load.c new file mode 100644 index 0000000..9876f15 --- /dev/null +++ b/p_load.c @@ -0,0 +1,70 @@ +/*************************************************************************** + * Copyright (C) 06/2006 by Olaf Rempel * + * razzor@kopf-tisch.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include + +#include "plugins.h" + +struct sammler_plugin plugin; + +static char *ds_def[] = { + "DS:1min:GAUGE:%d:0:U", + "DS:5min:GAUGE:%d:0:U", + "DS:15min:GAUGE:%d:0:U", + NULL +}; + +static char ** get_ds(int ds_id) +{ + return ds_def; +} + +static void probe(void) +{ + FILE *fp; + char buffer[32]; + char *val[3]; + + fp = fopen("/proc/loadavg", "r"); + if (fp == NULL) { + log_print(LOG_WARN, "plugin load"); + return; + } + + if (fgets(buffer, sizeof(buffer), fp) == NULL) { + log_print(LOG_WARN, "plugin load"); + fclose(fp); + return; + } + + fclose(fp); + + if (strsplit(buffer, val, 3) != 3) + return; + + probe_submit(&plugin, "load.rrd", 0, "%s:%s:%s", val[0], val[1], val[2]); +} + +struct sammler_plugin plugin = { + .name = "load", + .version = 1, + .probe = &probe, + .get_ds = &get_ds, +}; diff --git a/p_memory.c b/p_memory.c new file mode 100644 index 0000000..8115236 --- /dev/null +++ b/p_memory.c @@ -0,0 +1,125 @@ +/*************************************************************************** + * Copyright (C) 06/2006 by Olaf Rempel * + * razzor@kopf-tisch.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include + +#include "plugins.h" + +#define BUFSIZE 1024 + +#define DS_MEMORY 1 +#define DS_SWAP 2 + +struct sammler_plugin plugin; + +static char *mem_ds_def[] = { + "DS:total:GAUGE:%d:0:U", + "DS:free:GAUGE:%d:0:U", + "DS:buffers:GAUGE:%d:0:U", + "DS:cached:GAUGE:%d:0:U", + NULL +}; + +static char *swap_ds_def[] = { + "DS:total:GAUGE:%d:0:U", + "DS:free:GAUGE:%d:0:U", + NULL +}; + +static char ** get_ds(int ds_id) +{ + switch (ds_id) { + case DS_MEMORY: + return mem_ds_def; + + case DS_SWAP: + return swap_ds_def; + + default: + return NULL; + } +} + +struct meminfo_ { + unsigned long long memtotal; + unsigned long long memfree; + unsigned long long buffers; + unsigned long long cached; + unsigned long long swaptotal; + unsigned long long swapfree; +}; + +static void probe(void) +{ + FILE *fp; + char *buffer; + struct meminfo_ meminfo; + + buffer = malloc(BUFSIZE); + if (buffer == NULL) { + log_print(LOG_WARN, "plugin memory: out of memory"); + return; + } + + fp = fopen("/proc/meminfo", "r"); + if (fp == NULL) { + log_print(LOG_WARN, "plugin memory"); + free(buffer); + return; + } + + while (fgets(buffer, BUFSIZE, fp) != NULL) { + if (!strncmp(buffer, "MemTotal:", 9)) + meminfo.memtotal = atoll(buffer + 10); + + else if (!strncmp(buffer, "MemFree:", 8)) + meminfo.memfree = atoll(buffer + 9); + + else if (!strncmp(buffer, "Buffers:", 8)) + meminfo.buffers = atoll(buffer + 9); + + else if (!strncmp(buffer, "Cached:", 7)) + meminfo.cached = atoll(buffer + 8); + + else if (!strncmp(buffer, "SwapTotal:", 10)) + meminfo.swaptotal = atoll(buffer + 11); + + else if (!strncmp(buffer, "SwapFree:", 9)) + meminfo.swapfree = atoll(buffer + 10); + } + + probe_submit(&plugin, "memory.rrd", DS_MEMORY, "%llu:%llu:%llu:%llu", + meminfo.memtotal, meminfo.memfree, + meminfo.buffers, meminfo.cached); + + probe_submit(&plugin, "swap.rrd", DS_SWAP, "%llu:%llu", + meminfo.swaptotal, meminfo.swapfree); + + fclose(fp); + free(buffer); +} + +struct sammler_plugin plugin = { + .name = "memory", + .version = 1, + .probe = &probe, + .get_ds = &get_ds, +}; diff --git a/p_mount.c b/p_mount.c new file mode 100644 index 0000000..a5dfb83 --- /dev/null +++ b/p_mount.c @@ -0,0 +1,106 @@ +/*************************************************************************** + * Copyright (C) 06/2006 by Olaf Rempel * + * razzor@kopf-tisch.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include +#include +#include + +#include "plugins.h" + +struct sammler_plugin plugin; + +static char *ds_def[] = { + "DS:block_total:GAUGE:%d:0:U", + "DS:block_free:GAUGE:%d:0:U", + NULL +}; + +static char ** get_ds(int ds_id) +{ + return ds_def; +} + +static void probe(void) +{ + FILE *fp; + struct mntent *mnt; + struct statfs fs; + char *slash, filename[64]; + int len; + + fp = setmntent("/etc/mtab", "r"); + if (fp == NULL) { + log_print(LOG_WARN, "plugin mount"); + return; + } + + while ((mnt = getmntent(fp)) != NULL) { + if (!strcmp(mnt->mnt_fsname, "none")) + continue; + + if (!strcmp(mnt->mnt_fsname, "proc")) + continue; + + if (!strcmp(mnt->mnt_fsname, "sysfs")) + continue; + + if (!strcmp(mnt->mnt_fsname, "udev")) + continue; + + if (!strcmp(mnt->mnt_fsname, "devpts")) + continue; + + if (!strcmp(mnt->mnt_type, "nfs")) + continue; + + if (statfs(mnt->mnt_dir, &fs) == -1) { + log_print(LOG_WARN, "plugin mount: statfs(%s)", mnt->mnt_dir); + continue; + } + + if (fs.f_blocks == 0) + continue; + + slash = mnt->mnt_fsname; + while (slash && (slash = strchr(slash, '/'))) { + slash = strchr(slash, '/'); + *slash++ = '_'; + } + + len = snprintf(filename, sizeof(filename), "mount%s.rrd", mnt->mnt_fsname); + if (len >= sizeof(filename)) { + log_print(LOG_WARN, "plugin mount: file name too long", mnt->mnt_fsname); + continue; + } + + probe_submit(&plugin, filename, 0, "%lu:%lu", + fs.f_blocks * (fs.f_bsize /1024), + fs.f_bfree * (fs.f_bsize /1024)); + } + endmntent(fp); +} + +struct sammler_plugin plugin = { + .name = "mount", + .version = 1, + .probe = &probe, + .get_ds = &get_ds, +}; diff --git a/p_netdev.c b/p_netdev.c new file mode 100644 index 0000000..c62ff68 --- /dev/null +++ b/p_netdev.c @@ -0,0 +1,93 @@ +/*************************************************************************** + * Copyright (C) 06/2006 by Olaf Rempel * + * razzor@kopf-tisch.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include + +#include "plugins.h" + +#define BUFSIZE 1024 + +struct sammler_plugin plugin; + +static char *ds_def[] = { + "DS:byte_in:COUNTER:%d:0:U", + "DS:byte_out:COUNTER:%d:0:U", + "DS:pkt_in:COUNTER:%d:0:U", + "DS:pkt_out:COUNTER:%d:0:U", + NULL +}; + +static char ** get_ds(int ds_id) +{ + return ds_def; +} + +static void probe(void) +{ + FILE *fp; + char *buffer, *stats, *device; + char *val[16], filename[32]; + + buffer = malloc(BUFSIZE); + if (buffer == NULL) { + log_print(LOG_WARN, "plugin netdev: out of memory"); + return; + } + + fp = fopen("/proc/net/dev", "r"); + if (fp == NULL) { + log_print(LOG_WARN, "plugin netdev"); + free(buffer); + return; + } + + while (fgets(buffer, BUFSIZE, fp) != NULL) { + + if (!(stats = strchr(buffer, ':'))) + continue; + + *stats++ = '\0'; + + device = buffer; + while (*device == ' ') + device++; + + if (*device == '\0') + continue; + + if (strsplit(stats, val, 16) != 16) + continue; + + snprintf(filename, sizeof(filename), "net-%s.rrd", device); + + probe_submit(&plugin, filename, 0, "%s:%s:%s:%s", + val[0], val[8], val[1], val[9]); + } + fclose(fp); + free(buffer); +} + +struct sammler_plugin plugin = { + .name = "netdev", + .version = 1, + .probe = &probe, + .get_ds = &get_ds, +}; diff --git a/p_random.c b/p_random.c new file mode 100644 index 0000000..37a42c2 --- /dev/null +++ b/p_random.c @@ -0,0 +1,68 @@ +/*************************************************************************** + * Copyright (C) 06/2006 by Olaf Rempel * + * razzor@kopf-tisch.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include + +#include "plugins.h" + +struct sammler_plugin plugin; + +static char *ds_def[] = { + "DS:entropy:GAUGE:%d:0:U", + NULL +}; + +static char ** get_ds(int ds_id) +{ + return ds_def; +} + +static void probe(void) +{ + FILE *fp; + char buffer[32]; + char *val[1]; + + fp = fopen("/proc/sys/kernel/random/entropy_avail", "r"); + if (fp == NULL) { + log_print(LOG_WARN, "plugin random"); + return; + } + + if (fgets(buffer, sizeof(buffer), fp) == NULL) { + log_print(LOG_WARN, "plugin random"); + fclose(fp); + return; + } + + fclose(fp); + + if (strsplit(buffer, val, 1) != 1) + return; + + probe_submit(&plugin, "random.rrd", 0, "%s", val[0]); +} + +struct sammler_plugin plugin = { + .name = "random", + .version = 1, + .probe = &probe, + .get_ds = &get_ds, +}; diff --git a/p_rtstat.c b/p_rtstat.c new file mode 100644 index 0000000..0612d14 --- /dev/null +++ b/p_rtstat.c @@ -0,0 +1,106 @@ +/*************************************************************************** + * Copyright (C) 06/2006 by Olaf Rempel * + * razzor@kopf-tisch.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include + +#include "plugins.h" + +#define BUFSIZE 1024 + +struct sammler_plugin plugin; + +static char *ds_def[] = { + "DS:entries:GAUGE:%d:0:U", + "DS:in_hit:DERIVE:%d:0:U", + "DS:in_slow_tot:DERIVE:%d:0:U", + "DS:in_slow_mc:DERIVE:%d:0:U", + "DS:in_no_route:DERIVE:%d:0:U", + "DS:in_brd:DERIVE:%d:0:U", + "DS:in_martian_dst:DERIVE:%d:0:U", + "DS:in_martian_src:DERIVE:%d:0:U", + "DS:out_hit:DERIVE:%d:0:U", + "DS:out_slow_tot:DERIVE:%d:0:U", + "DS:out_slow_mc:DERIVE:%d:0:U", + "DS:gc_total:DERIVE:%d:0:U", + "DS:gc_ignored:DERIVE:%d:0:U", + "DS:gc_goal_miss:DERIVE:%d:0:U", + "DS:gc_dst_overflow:DERIVE:%d:0:U", + "DS:in_hlist_search:DERIVE:%d:0:U", + "DS:out_hlist_search:DERIVE:%d:0:U", + NULL +}; + +static char ** get_ds(int ds_id) +{ + return ds_def; +} + +static void probe(void) +{ + FILE *fp; + char *buffer, *val[17], filename[16]; + unsigned long long arr[17]; + int i, cpu = 0; + + buffer = malloc(BUFSIZE); + if (buffer == NULL) { + log_print(LOG_WARN, "plugin rtstat: out of memory"); + return; + } + + fp = fopen("/proc/net/stat/rt_cache", "r"); + if (fp == NULL) { + log_print(LOG_WARN, "plugin rtstat"); + free(buffer); + return; + } + + while (fgets(buffer, BUFSIZE, fp) != NULL) { + if (!strncmp(buffer, "entries", 7)) + continue; + + if (strsplit(buffer, val, 17) != 17) + continue; + + for (i = 0; i < 17; i++) + arr[i] = strtoll(val[i], NULL, 16); + + snprintf(filename, sizeof(filename), "rtstat-%d.rrd", cpu); + + probe_submit(&plugin, filename, 0, + "%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu", + arr[0], arr[1], arr[2], arr[3], + arr[4], arr[5], arr[6], arr[7], + arr[8], arr[9], arr[10], arr[11], + arr[12], arr[13], arr[14], arr[15], + arr[16]); + cpu++; + } + fclose(fp); + free(buffer); +} + +struct sammler_plugin plugin = { + .name = "rtstat", + .version = 1, + .probe = &probe, + .get_ds = &get_ds, +}; diff --git a/p_stat.c b/p_stat.c new file mode 100644 index 0000000..4104994 --- /dev/null +++ b/p_stat.c @@ -0,0 +1,142 @@ +/*************************************************************************** + * Copyright (C) 06/2006 by Olaf Rempel * + * razzor@kopf-tisch.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include + +#include "plugins.h" + +#define BUFSIZE 1024 + +#define DS_CPU 1 +#define DS_PROC 2 + +struct sammler_plugin plugin; + +static char *cpu_ds_def[] = { + "DS:user:COUNTER:%d:0:U", + "DS:nice:COUNTER:%d:0:U", + "DS:syst:COUNTER:%d:0:U", + "DS:idle:COUNTER:%d:0:U", + "DS:wait:COUNTER:%d:0:U", + "DS:intr:COUNTER:%d:0:U", + "DS:sitr:COUNTER:%d:0:U", + NULL +}; + +static char *proc_ds_def[] = { + "DS:intr:COUNTER:%d:0:U", + "DS:ctxt:COUNTER:%d:0:U", + "DS:fork:COUNTER:%d:0:U", + NULL +}; + +static char ** get_ds(int ds_id) +{ + switch (ds_id) { + case DS_CPU: + return cpu_ds_def; + + case DS_PROC: + return proc_ds_def; + + default: + return NULL; + } +} + +struct proc_ { + unsigned long long intr; + unsigned long long ctxt; + unsigned long long fork; +}; + +static void probe(void) +{ + FILE *fp; + char *buffer; + struct proc_ proc; + + buffer = malloc(BUFSIZE); + if (buffer == NULL) { + log_print(LOG_WARN, "plugin stat: out of memory"); + return; + } + + fp = fopen("/proc/stat", "r"); + if (fp == NULL) { + log_print(LOG_WARN, "plugin stat"); + free(buffer); + return; + } + + while (fgets(buffer, BUFSIZE, fp) != NULL) { + if (!strncmp(buffer, "cpu", 3)) { + char *val[9], filename[16]; + int numfields, cpu; + + if ((buffer[3] >= '0') && (buffer[3] <= '9')) { + cpu = atoi(buffer +3); + snprintf(filename, sizeof(filename), "cpu-%d.rrd", cpu); + + } else { + strncpy(filename, "cpu.rrd", sizeof(filename)); + } + + numfields = strsplit(buffer, val, 9); + if (numfields < 5) + continue; + + if (numfields >= 8) { + probe_submit(&plugin, filename, DS_CPU, + "%s:%s:%s:%s:%s:%s:%s", + val[1], val[2], val[3], val[4], + val[5], val[6], val[7]); + + } else { + probe_submit(&plugin, filename, DS_CPU, + "%s:%s:%s:%s:0:0:0", + val[1], val[2], val[3], val[4]); + } + + } else if (!strncmp(buffer, "intr", 4)) { + proc.intr = atoll(buffer + 5); + + } else if (!strncmp(buffer, "ctxt", 4)) { + proc.ctxt = atoll(buffer + 5); + + } else if (!strncmp(buffer, "processes", 9)) { + proc.fork = atoll(buffer + 10); + } + } + + probe_submit(&plugin, "proc.rrd", DS_PROC, "%llu:%llu:%llu", + proc.intr, proc.ctxt, proc.fork); + + fclose(fp); + free(buffer); +} + +struct sammler_plugin plugin = { + .name = "stat", + .version = 1, + .probe = &probe, + .get_ds = &get_ds, +}; diff --git a/p_uptime.c b/p_uptime.c new file mode 100644 index 0000000..946b365 --- /dev/null +++ b/p_uptime.c @@ -0,0 +1,69 @@ +/*************************************************************************** + * Copyright (C) 06/2006 by Olaf Rempel * + * razzor@kopf-tisch.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include + +#include "plugins.h" + +struct sammler_plugin plugin; + +static char *ds_def[] = { + "DS:uptime:GAUGE:%d:0:U", + "DS:idletime:GAUGE:%d:0:U", + NULL +}; + +static char ** get_ds(int ds_id) +{ + return ds_def; +} + +static void probe(void) +{ + FILE *fp; + char buffer[32]; + char *val[2]; + + fp = fopen("/proc/uptime", "r"); + if (fp == NULL) { + log_print(LOG_WARN, "plugin uptime"); + return; + } + + if (fgets(buffer, sizeof(buffer), fp) == NULL) { + log_print(LOG_WARN, "plugin uptime"); + fclose(fp); + return; + } + + fclose(fp); + + if (strsplit(buffer, val, 2) != 2) + return; + + probe_submit(&plugin, "uptime.rrd", 0, "%s:%s", val[0], val[1]); +} + +struct sammler_plugin plugin = { + .name = "uptime", + .version = 1, + .probe = &probe, + .get_ds = &get_ds, +}; diff --git a/p_vmstat.c b/p_vmstat.c new file mode 100644 index 0000000..8fcd009 --- /dev/null +++ b/p_vmstat.c @@ -0,0 +1,101 @@ +/*************************************************************************** + * Copyright (C) 06/2006 by Olaf Rempel * + * razzor@kopf-tisch.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include + +#include "plugins.h" + +#define BUFSIZE 1024 + +struct sammler_plugin plugin; + +static char *ds_def[] = { + "DS:pgalloc_high:DERIVE:%d:0:U", + "DS:pgalloc_normal:DERIVE:%d:0:U", + "DS:pgalloc_dma:DERIVE:%d:0:U", + "DS:pgfree:DERIVE:%d:0:U", + "DS:pgfault:DERIVE:%d:0:U", + NULL +}; + +static char ** get_ds(int ds_id) +{ + return ds_def; +} + +struct vmstat_ { + unsigned long long pgalloc_high; + unsigned long long pgalloc_normal; + unsigned long long pgalloc_dma; + unsigned long long pgfree; + unsigned long long pgfault; +}; + +static void probe(void) +{ + FILE *fp; + char *buffer; + struct vmstat_ vmstat; + + buffer = malloc(BUFSIZE); + if (buffer == NULL) { + log_print(LOG_WARN, "plugin vmstat: out of memory"); + return; + } + + fp = fopen("/proc/vmstat", "r"); + if (fp == NULL) { + log_print(LOG_WARN, "plugin vmstat"); + free(buffer); + return; + } + + while (fgets(buffer, BUFSIZE, fp) != NULL) { + if (!strncmp(buffer, "pgalloc_high", 12)) + vmstat.pgalloc_high = atoll(buffer + 13); + + else if (!strncmp(buffer, "pgalloc_normal", 14)) + vmstat.pgalloc_normal = atoll(buffer + 15); + + else if (!strncmp(buffer, "pgalloc_dma", 11)) + vmstat.pgalloc_dma = atoll(buffer + 12); + + else if (!strncmp(buffer, "pgfree", 6)) + vmstat.pgfree = atoll(buffer + 7); + + else if (!strncmp(buffer, "pgfault", 7)) + vmstat.pgfault = atoll(buffer + 8); + } + + probe_submit(&plugin, "vmstat.rrd", 0, "%llu:%llu:%llu:%llu:%llu", + vmstat.pgalloc_high, vmstat.pgalloc_normal, + vmstat.pgalloc_dma, vmstat.pgfree, vmstat.pgfault); + + fclose(fp); + free(buffer); +} + +struct sammler_plugin plugin = { + .name = "vmstat", + .version = 1, + .probe = &probe, + .get_ds = &get_ds, +}; diff --git a/plugins.c b/plugins.c new file mode 100644 index 0000000..e27d97a --- /dev/null +++ b/plugins.c @@ -0,0 +1,166 @@ +/*************************************************************************** + * Copyright (C) 06/2006 by Olaf Rempel * + * razzor@kopf-tisch.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include + +#include "list.h" + +#include "plugins.h" +#include "config.h" +#include "logging.h" +#include "rrdtool.h" + +#define BUFSIZE 1024 + +static LIST_HEAD(plugin_list); + +static void plugin_load(char *filename) +{ + struct sammler_plugin *plugin = NULL; + static char *plugin_dir; + + char *buffer; + void *tmp; + int len; + + if (plugin_dir == NULL) + plugin_dir = config_get_string("global", "plugin_dir", "."); + + buffer = malloc(BUFSIZE); + if (buffer == NULL) { + log_print(LOG_ERROR, "plugin_load: out of memory"); + return; + } + + len = snprintf(buffer, BUFSIZE, "%s/%s", plugin_dir, filename); + if (len >= BUFSIZE) { + log_print(LOG_ERROR, "plugin_load: file name too long: %s/%s", plugin_dir, filename); + free(buffer); + return; + } + + dlerror(); + tmp = dlopen(buffer, RTLD_NOW); + if (tmp == NULL) { + log_print(LOG_ERROR, "plugin_load: dlopen: %s", dlerror()); + free(buffer); + return; + } + + plugin = dlsym(tmp, "plugin"); + if (plugin == NULL) { + log_print(LOG_ERROR, "plugin_load: failed to load '%s'", filename); + dlclose(tmp); + free(buffer); + return; + } + + log_print(LOG_INFO, "Plugin '%s' (v%d) loaded", plugin->name, plugin->version); + + list_add_tail(&plugin->list, &plugin_list); + + free(buffer); + return; +} + +void plugin_load_all() +{ + struct conf_section *section; + struct conf_tupel *tupel; + + section = config_get_section("global"); + if (section) { + list_for_each_entry(tupel, §ion->tupel, list) + if (!strcmp(tupel->option, "plugin")) + plugin_load(tupel->parameter); + } +} + +void plugins_probe(void) +{ + struct sammler_plugin *plugin; + + list_for_each_entry(plugin, &plugin_list, list) + plugin->probe(); +} + +char ** plugins_get_ds(char *name, int version, int ds_id) +{ + struct sammler_plugin *plugin; + list_for_each_entry(plugin, &plugin_list, list) { + if (strcmp(plugin->name, name)) + continue; + + if (plugin->version != version) + continue; + + return plugin->get_ds(ds_id); + } + return NULL; +} + +void probe_submit(struct sammler_plugin *plugin, char *filename, int ds_id, const char *fmt, ... ) +{ + va_list az; + char *buffer; + int len; + + buffer = malloc(BUFSIZE); + if (buffer == NULL) { + log_print(LOG_ERROR, "probe_submit: out of memory"); + return; + } + + va_start(az, fmt); + len = vsnprintf(buffer, BUFSIZE, fmt, az); + va_end(az); + + if (len >= BUFSIZE) { + log_print(LOG_ERROR, "probe_submit: %s arguments too long", plugin->name); + free(buffer); + return; + } + + rrd_submit(plugin->name, plugin->version, filename, ds_id, buffer); +// net_submit(plugin->name, plugin->version, filename, ds_id, buffer); + + free(buffer); +} + + + +int strsplit(char *string, char **fields, size_t size) +{ + size_t i = 0; + char *ptr = string; + + while ((fields[i] = strtok(ptr, " \n\t")) != NULL) { + ptr = NULL; + i++; + + if (i >= size) + break; + } + return i; +} diff --git a/plugins.h b/plugins.h new file mode 100644 index 0000000..c2e604d --- /dev/null +++ b/plugins.h @@ -0,0 +1,25 @@ +#ifndef _PLUGINS_H_ +#define _PLUGINS_H_ + +#include "list.h" +#include "logging.h" + +struct sammler_plugin { + struct list_head list; + char *name; + int version; + void (*probe) (void); + char ** (*get_ds) (int ds_id); +}; + +void plugin_load_all(void); + +void plugins_probe(void); + +char ** plugins_get_ds(char *plugin, int version, int ds_id); + +void probe_submit(struct sammler_plugin *plugin, char *filename, int ds_id, const char *fmt, ... ); + +int strsplit(char *string, char **fields, size_t size); + +#endif /* _PLUGINS_H_ */ diff --git a/rrdtool.c b/rrdtool.c new file mode 100644 index 0000000..2f06aeb --- /dev/null +++ b/rrdtool.c @@ -0,0 +1,316 @@ +/*************************************************************************** + * Copyright (C) 06/2006 by Olaf Rempel * + * razzor@kopf-tisch.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include + +#include + +#include "list.h" + +#include "logging.h" +#include "config.h" +#include "plugins.h" + +#define DEFAULT_STEP 10 + +#define ARGCMAX 64 +#define ARGVSIZE 1024 + +#define RRDTOOL_CREATE 1 +#define RRDTOOL_UPDATE 2 + +#define BUFSIZE 1024 + +static int append_rra_config(char *buffer, int size, int *pos) +{ + struct conf_section *section; + struct conf_tupel *tupel; + + int len, rra_cnt = 0; + + section = config_get_section("global"); + if (section == NULL) { + log_print(LOG_ERROR, "append_ds_config: conf-section 'global' not found"); + return -1; + } + + list_for_each_entry(tupel, §ion->tupel, list) { + if (strcmp(tupel->option, "rra")) + continue; + + len = snprintf(buffer + *pos, size - *pos, "%s ", tupel->parameter); + if (len >= size - *pos) { + log_print(LOG_ERROR, "append_ds_config: arguments too long"); + return -1; + } + + *pos += len; + rra_cnt++; + } + return rra_cnt; +} + +static int append_ds_config(char *buffer, int size, int *pos, int heartbeat, char **ds_def) +{ + int len, ds_cnt = 0; + char *dsbuild; + + dsbuild = malloc(BUFSIZE); + if (dsbuild == NULL) { + log_print(LOG_ERROR, "append_ds_config: out of memory"); + return -1; + } + + while (*ds_def != NULL) { + len = snprintf(dsbuild, BUFSIZE, *ds_def, heartbeat); + if (len >= BUFSIZE) { + log_print(LOG_ERROR, "append_ds_config: arguments too long"); + free(dsbuild); + return -1; + } + + len = snprintf(buffer + *pos, size - *pos, "%s ", dsbuild); + if (len >= size - *pos) { + log_print(LOG_ERROR, "append_ds_config: arguments too long"); + free(dsbuild); + return -1; + } + + *pos += len; + *ds_def++; + ds_cnt++; + } + free(dsbuild); + + return ds_cnt; +} + +static int do_rrd(int mode, char *cmd) +{ + int argc; + char *argv[ARGCMAX]; + + argc = strsplit(cmd, argv, ARGCMAX -1); + argv[argc] = NULL; + + optind = 0; + rrd_clear_error(); + + if (mode == RRDTOOL_CREATE) { + if (rrd_create(argc, argv) == -1) { + errno = 0; + log_print(LOG_ERROR, "rrd_create failed: %s: %s", + argv[2], rrd_get_error()); + return -1; + } + + } else if (mode == RRDTOOL_UPDATE) { + if (rrd_update(argc, argv) == -1) { + errno = 0; + log_print(LOG_ERROR, "rrd_update failed: %s: %s", + argv[2], rrd_get_error()); + return -1; + } + } + return 0; +} + +static int rrd_create_file(char *filename, char **ds_def) +{ + int pos, step, heartbeat, retval; + char *buffer; + + buffer = malloc(ARGVSIZE); + if (buffer == NULL) { + log_print(LOG_ERROR, "append_ds_config: out of memory"); + return -1; + } + + step = config_get_int("global", "step", DEFAULT_STEP); + heartbeat = (step * 2) + (step / 2); + + pos = snprintf(buffer, ARGVSIZE, "create %s -s %d ", filename, step); + if (pos >= ARGVSIZE) { + log_print(LOG_ERROR, "rrd_create_file: arguments too long"); + free(buffer); + return -1; + } + + if (append_rra_config(buffer, ARGVSIZE, &pos) <= 0) { + free(buffer); + return -1; + } + + if (append_ds_config(buffer, ARGVSIZE, &pos, heartbeat, ds_def) <= 0) { + free(buffer); + return -1; + } + + retval = do_rrd(RRDTOOL_CREATE, buffer); + free(buffer); + + return retval; +} + +static int rrd_update_file(char *filename, char *values) +{ + int pos, retval; + char *buffer; + + buffer = malloc(ARGVSIZE); + if (buffer == NULL) { + log_print(LOG_ERROR, "append_ds_config: out of memory"); + return -1; + } + + pos = snprintf(buffer, ARGVSIZE, "update %s %lu:%s", filename, time(NULL), values); + if (pos >= ARGVSIZE) { + log_print(LOG_ERROR, "rrd_update_file: arguments too long"); + free(buffer); + return -1; + } + + retval = do_rrd(RRDTOOL_UPDATE, buffer); + free(buffer); + + return retval; +} + +static int check_create_dir(char *dir) +{ + struct stat statbuf; + if (stat(dir, &statbuf) == -1) { + if (errno == ENOENT) { + errno = 0; + if (mkdir(dir, 0755) == -1) { + log_print(LOG_ERROR, "check_create_dir: mkdir(%s)", dir); + return -1; + } + + } else { + log_print(LOG_ERROR, "check_create_dir: stat(%s)", dir); + return -1; + } + + } else if (!S_ISDIR (statbuf.st_mode)) { + log_print(LOG_ERROR, "check_create_dir: stat(%s): Not a directory!", dir); + return -1; + } + return 0; +} + +static int create_parent_dirs(char *filename) +{ + char *lastslash, *nextslash = filename; + + lastslash = strrchr(filename, '/'); + if (lastslash == NULL) { + log_print(LOG_ERROR, "create_parent_dirs: invalid file name"); + return -1; + } + + *lastslash = '\0'; + + while (1) { + if (strchr(nextslash, '/') == NULL) { + if (*lastslash == '\0') + *lastslash = '/'; + else + break; + } + nextslash = strchr(nextslash, '/'); + + *nextslash = '\0'; + if (filename != nextslash) { + if (check_create_dir(filename) == -1) { + *nextslash = '/'; + *lastslash = '/'; + return -1; + } + } + *nextslash++ = '/'; + } + return 0; +} + +void rrd_submit(char *plugin, int version, char *filename, int ds_id, char *data) +{ + struct stat statbuf; + static char *rrd_dir = NULL; + + char *fullfile, **ds_def; + int len; + + if (rrd_dir == NULL) + rrd_dir = config_get_string("global", "rrd_dir", "."); + + fullfile = malloc(BUFSIZE); + if (fullfile == NULL) { + log_print(LOG_ERROR, "rrd_submit: out of memory"); + return; + } + + len = snprintf(fullfile, BUFSIZE, "%s/%s", rrd_dir, filename); + if (len >= BUFSIZE) { + log_print(LOG_ERROR, "rrd_submit: arguments too long"); + free(fullfile); + return; + } + + if (stat(fullfile, &statbuf) == -1) { + if (errno == ENOENT) { + errno = 0; + + if (create_parent_dirs(fullfile) == -1) { + free(fullfile); + return; + } + + ds_def = plugins_get_ds(plugin, version, ds_id); + if (ds_def == NULL) { + log_print(LOG_ERROR, "No vaild DS found (%s v%d %d)", plugin, version, ds_id); + free(fullfile); + return; + } + + if (rrd_create_file(fullfile, ds_def) == -1) { + free(fullfile); + return; + } + + } else { + log_print(LOG_ERROR, "rrd_submit: stat(%s):", fullfile); + free(fullfile); + return; + } + + } else if (!S_ISREG (statbuf.st_mode)) { + log_print(LOG_ERROR, "rrd_submit: stat(%s): Not a regular file!", fullfile); + free(fullfile); + return; + } + + rrd_update_file(fullfile, data); + free(fullfile); +} diff --git a/rrdtool.h b/rrdtool.h new file mode 100644 index 0000000..047b7a4 --- /dev/null +++ b/rrdtool.h @@ -0,0 +1,6 @@ +#ifndef _RRDTOOL_H_ +#define _RRDTOOL_H_ + +void rrd_submit(char *plugin, int version, char *filename, int ds_id, char *data); + +#endif /* _RRDTOOL_H_ */ diff --git a/sammler.c b/sammler.c new file mode 100644 index 0000000..823cba4 --- /dev/null +++ b/sammler.c @@ -0,0 +1,102 @@ +/*************************************************************************** + * Copyright (C) 06/2006 by Olaf Rempel * + * razzor@kopf-tisch.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "logging.h" +#include "plugins.h" + +#define DEFAULT_CONFIG "sammler.conf" +#define DEFAULT_LOGFILE "sammler.log" + +static struct option opts[] = { + {"config", 1, 0, 'c'}, + {"debug", 0, 0, 'd'}, + {"help", 0, 0, 'h'}, + {0, 0, 0, 0} +}; + +int main(int argc, char *argv[]) +{ + char *config = DEFAULT_CONFIG; + int code, arg = 0, debug = 0; + + do { + code = getopt_long(argc, argv, "c:dh", opts, &arg); + + switch (code) { + case 'c': /* config */ + config = optarg; + break; + + case 'd': /* debug */ + debug = 1; + break; + + case 'h': /* help */ + printf("Usage: sammler [options]\n" + "Options: \n" + " --config -c configfile use this configfile\n" + " --debug -d do not fork and log to stderr\n" + " --help -h this help\n" + "\n"); + exit(0); + break; + + case '?': /* error */ + exit(-1); + break; + + default: /* unknown / all options parsed */ + break; + } + } while (code != -1); + + /* parse config file */ + if (!config_parse(config)) + exit(-1); + + /* check logfile */ + char *logfile = config_get_string("global", "logfile", DEFAULT_LOGFILE); + if (logfile && !debug) { + /* start logging */ + if (!log_init(logfile)) + exit(-1); + + /* zum daemon mutieren */ + daemon(-1, 0); + } + + log_print(LOG_EVERYTIME, "sammler started"); + + plugin_load_all(); + + while (1) { + plugins_probe(); + sleep (10); + } + + return 0; +} diff --git a/sammler.conf b/sammler.conf new file mode 100644 index 0000000..f714ba3 --- /dev/null +++ b/sammler.conf @@ -0,0 +1,35 @@ +[global] +logfile sammler.log + +plugin_dir . + +plugin p_stat.so +plugin p_load.so +plugin p_memory.so +plugin p_vmstat.so +plugin p_uptime.so +plugin p_netdev.so +plugin p_mount.so +#plugin p_ctstat.so +plugin p_rtstat.so +plugin p_random.so + +rrd_dir rrd + +step 10 + +# 1h(10s), 48h(1min), 7d(5min), 4w(30min) +rra RRA:MIN:0.1:1:360 +rra RRA:MIN:0.1:6:2880 +rra RRA:MIN:0.1:30:2016 +rra RRA:MIN:0.1:180:1344 + +rra RRA:AVERAGE:0.1:1:360 +rra RRA:AVERAGE:0.1:6:2880 +rra RRA:AVERAGE:0.1:30:2016 +rra RRA:AVERAGE:0.1:180:1344 + +rra RRA:MAX:0.1:1:360 +rra RRA:MAX:0.1:6:2880 +rra RRA:MAX:0.1:30:2016 +rra RRA:MAX:0.1:180:13446