+++ /dev/null
-@include@ @includel@../build.mk@includel@
-
-.PHONY: all
-all: graphing.so nterfacer_graphing.so dump
-
-graphing.so: graphing.o fsample.o
-
-nterfacer_graphing.so: nterfacer_graphing.o
-
-dump: dump.o fsample.o
- $(CC) $(CFLAGS) -o $@ @srcs@
+++ /dev/null
-#include "graphing.h"
-#include <stdio.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-int dump(fsample_m *f, fsample_t start, fsample_t stop) {
- int i, j;
-
- for(i=start;i<stop;i++) {
- printf("%2d ", i);
- for(j=0;j<f->pos;j++) {
- fsample_t t;
- int moo = fsget_m(f, j, i, &t);
-
- if(!moo) {
- int moo2 = fsget_mr(f, j, i, &t);
- printf("X%2d(%2d) ", t, moo2);
- } else {
- printf(" %2d(%2d) ", t, moo);
- }
- }
- printf("\n");
- }
-
- return 0;
-}
-
-
-int main(int cargc, char **cargv) {
- fsample_m *f;
- int stop = time(NULL) / GRAPHING_RESOLUTION;
- struct stat sb;
-
- if(cargc < 2) {
- puts("insufficient args");
- return 1;
- }
-
- if(stat(cargv[1], &sb) == -1) {
- puts("file doesn't exist");
- return 2;
- }
-
- f = fsopen_m(0, cargv[1], SAMPLES, NULL, NULL);
- if(!f)
- return 3;
-
- dump(f, stop - 100, stop);
-
- fsclose_m(f);
-
- return 0;
-}
-
+++ /dev/null
-#include "fsample.h"
-
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-
-static fsample_t version = 1;
-
-static void fscorefree(void *arg) {
- fsample *f = (fsample *)arg;
- munmap(f->header, f->len);
-}
-
-fsample *fsopen(char *filename, size_t samples, CoreHandlerAddFn chafn, CoreHandlerDelFn chdfn) {
- int flags = 0;
- int new = 0;
- fsample *f = (fsample *)malloc(sizeof(fsample));
- if(!f)
- return NULL;
-
- f->len = samples * sizeof(struct fsample_p) + sizeof(struct fsample_header);
- f->fd = open(filename, O_RDWR|O_CREAT, 0600);
-
- if(!lseek(f->fd, 0, SEEK_END))
- new = 1;
-
- if((f->fd == -1) || (lseek(f->fd, f->len - 1, SEEK_SET) == -1)) {
- free(f);
- return NULL;
- }
- write(f->fd, "", 1);
-
- flags = MAP_SHARED;
-#ifdef MAP_NOCORE
- flags|=MAP_NOCORE;
-#endif
-
- f->header = mmap(NULL, f->len, PROT_READ|PROT_WRITE, flags, f->fd, 0);
- if(f->header == MAP_FAILED) {
- close(f->fd);
- free(f);
- return NULL;
- }
-
- if(!new && (memcmp(f->header->magic, "FSAMP", sizeof(f->header->magic)) || (version != f->header->version))) {
- munmap(f->header, f->len);
- close(f->fd);
- free(f);
- return NULL;
- }
-
- if(chafn && chdfn) {
- f->corehandler = chafn(fscorefree, f);
- f->corehandlerdel = chdfn;
- } else {
- f->corehandler = NULL;
- f->corehandlerdel = NULL;
- }
-
- memcpy(f->header->magic, "FSAMP", sizeof(f->header->magic));
- f->header->version = version;
-
- f->m = (struct fsample_p *)(f->header + 1);
- f->samples = samples;
-
- if(f->header->iteration == 0)
- f->header->iteration = 1;
-
- return f;
-}
-
-void fsclose(fsample *f) {
- munmap(f->header, f->len);
- close(f->fd);
-
- if(f->corehandlerdel && f->corehandler)
- (f->corehandlerdel)(f->corehandler);
-
- free(f);
-}
-
-int fsadd_m(fsample_m *f, char *filename, size_t freq, DeriveValueFn derive, void *tag) {
- fsample_m_entry *p = &f->entry[f->pos];
-
- p->f = fsopen(filename, f->samples / freq, f->chafn, f->chdfn);
- if(!p->f)
- return 0;
-
- p->freq = freq;
- p->derive = derive;
- p->tag = tag;
- f->pos++;
- return 1;
-}
-
-fsample_m *fsopen_m(size_t count, char *filename, size_t samples, CoreHandlerAddFn chafn, CoreHandlerDelFn chdfn) {
- fsample_m *n = (fsample_m *)malloc(sizeof(fsample_m) + (count + 1) * sizeof(fsample_m_entry));
- if(!n)
- return NULL;
-
- n->samples = samples;
- n->pos = 0;
- n->chafn = chafn;
- n->chdfn = chdfn;
-
- if(!fsadd_m(n, filename, 1, NULL, 0)) {
- free(n);
- return NULL;
- }
-
- return n;
-}
-
-void fsset_m(fsample_m *f, fsample_t pos, fsample_t value) {
- int i;
-
- for(i=0;i<f->pos;i++) {
- fsample_t v;
-
- if((pos + 1) % f->entry[i].freq != 0)
- continue;
-
- if(f->entry[i].derive) {
- v = (f->entry[i].derive)(f, i, pos, f->entry[i].tag);
- } else {
- v = value;
- }
-
- fsset(f->entry[i].f, pos / f->entry[i].freq, v);
- }
-}
-
-void fsclose_m(fsample_m *f) {
- int i;
-
- for(i=0;i<f->pos;i++)
- fsclose(f->entry[i].f);
- free(f);
-}
-
-fsample_t fsamean(fsample_m *f, int entry, fsample_t pos, void *tag) {
- fsample_t c = 0;
- long samples = (long)tag;
- int count = 0;
- int rpos = pos / f->entry[0].freq;
- int i;
- fsample_t t;
-
- for(i=0;i<samples;i++) {
- if(__fsget_m(f, 0, rpos - i, &t)) {
- c+=t;
- count++;
- } else {
-/* printf("bad :(\n");*/
- }
- }
-
- if(count == 0)
- return 0;
-
- return c / count;
-}
-
-fsample_t fsapmean(fsample_m *f, int entry, fsample_t pos, void *tag) {
- fsample_t c = 0;
- long samples = (long)tag;
- int count = 0;
- int rpos = pos / f->entry[entry - 1].freq;
- int i;
- fsample_t t;
-
- for(i=0;i<=samples;i++) {
- if(__fsget(f->entry[entry - 1].f, rpos - i, &t)) {
- c+=t;
- count++;
- } else {
- /*printf("bad :(\n");*/
- }
- }
-
- if(count == 0)
- return 0;
-
- return c / count;
-}
+++ /dev/null
-#ifndef __FSAMPLE_H
-#define __FSAMPLE_H
-
-#include <sys/types.h>
-
-typedef u_int32_t fsample_t;
-
-typedef struct fsample fsample;
-
-/* nice loss of type safety here... */
-typedef void *(*CoreHandlerAddFn)(void *handler, void *arg);
-typedef void (*CoreHandlerDelFn)(void *);
-
-/* single sample functions */
-fsample *fsopen(char *filename, size_t samples, CoreHandlerAddFn chafn, CoreHandlerDelFn chdfn);
-void fsclose(fsample *f);
-
-struct fsample_m;
-typedef fsample_t (*DeriveValueFn)(struct fsample_m *v, int entry, fsample_t pos, void *tag);
-
-typedef struct fsample_m_entry {
- size_t freq;
- fsample *f;
- void *tag;
- DeriveValueFn derive;
-} fsample_m_entry;
-
-typedef struct fsample_m {
- size_t pos, samples;
- CoreHandlerAddFn chafn;
- CoreHandlerDelFn chdfn;
- struct fsample_m_entry entry[];
-} fsample_m;
-
-/* multiple sample functions */
-fsample_m *fsopen_m(size_t count, char *filename, size_t samples, CoreHandlerAddFn chafn, CoreHandlerDelFn chdfn);
-void fsclose_m(fsample_m *f);
-int fsadd_m(fsample_m *f, char *filename, size_t freq, DeriveValueFn derive, void *tag);
-void fsset_m(fsample_m *f, fsample_t pos, fsample_t value);
-
-/* aggregates */
-fsample_t fsamean(fsample_m *f, int entry, fsample_t pos, void *tag);
-fsample_t fsapmean(fsample_m *f, int entry, fsample_t pos, void *tag);
-
-struct fsample_p {
- fsample_t v;
- unsigned char iteration;
-};
-
-struct fsample_header {
- char magic[4];
- fsample_t version;
- unsigned char iteration;
- fsample_t lastpos;
-};
-
-struct fsample {
- struct fsample_p *m;
- int fd;
- size_t samples, len;
- struct fsample_header *header;
- void *corehandler;
- CoreHandlerDelFn corehandlerdel;
-};
-
-static inline unsigned char previteration(fsample *f) {
- unsigned char p = f->header->iteration - 1;
- if(p == 0)
- p = 255;
- return p;
-}
-
-/* doesn't support writing to negative numbers... */
-static inline void fsset(fsample *f, fsample_t pos, fsample_t value) {
- fsample_t actualpos = pos % f->samples;
- struct fsample_p *p = &f->m[actualpos];
-
- if(f->header->lastpos > actualpos) {
- f->header->iteration++;
- if(f->header->iteration == 0)
- f->header->iteration = 1;
- }
-
- f->header->lastpos = actualpos;
-
- p->iteration = f->header->iteration;
- p->v = value;
-}
-
-static inline fsample_t mmod(int x, int y) {
-#if -5 % 3 == -2
- int v = x % y;
- if(v < 0)
- v = v + y;
- return v;
-#else
-#error Unknown modulo operator function.
-#endif
-}
-
-/* API functions only have access to positive indicies */
-static inline fsample_t __fsget(fsample *f, int pos, fsample_t *t) {
- struct fsample_p *p = &f->m[mmod(pos, f->samples)];
-
- if(p->iteration != f->header->iteration) {
- unsigned char prev = previteration(f);
-
- if(prev != p->iteration || (pos <= f->header->lastpos)) {
- /*printf("bad: prev: %d p->iteration: %d, pos: %d lastpos: %d\n", prev, p->iteration, pos, f->header->lastpos);*/
- return 0;
- }
- }
-
- *t = p->v;
- return p->iteration;
-}
-
-static inline fsample_t fsget_r(fsample *f, fsample_t pos, fsample_t *t) {
- struct fsample_p *p = &f->m[mmod(pos, f->samples)];
-
- *t = p->v;
- return p->iteration;
-}
-
-static inline fsample_t fsget(fsample *f, fsample_t pos, fsample_t *t) {
- return __fsget(f, pos, t);
-}
-
-static inline fsample_t __fsget_m(fsample_m *f, int entry, int pos, fsample_t *t) {
- return __fsget(f->entry[entry].f, pos / f->entry[entry].freq, t);
-}
-
-static inline fsample_t fsget_m(fsample_m *f, int entry, fsample_t pos, fsample_t *t) {
- return fsget(f->entry[entry].f, pos / f->entry[entry].freq, t);
-}
-
-static inline fsample_t fsget_mr(fsample_m *f, int entry, fsample_t pos, fsample_t *t) {
- return fsget_r(f->entry[entry].f, pos / f->entry[entry].freq, t);
-}
-
-#endif
+++ /dev/null
-#include <string.h>
-#include <stdio.h>
-
-#include "../core/hooks.h"
-#include "../core/config.h"
-#include "../usercount/usercount.h"
-#include "../lib/sstring.h"
-#include "../core/schedule.h"
-#include "../core/error.h"
-#include "../lib/sha1.h"
-#include "../lib/hmac.h"
-
-#include "graphing.h"
-
-static void gr_newserver(int hook, void *arg);
-static void gr_lostserver(int hook, void *arg);
-static void tick(void *arg);
-static void openserver(int servernum);
-static void closeserver(int servernum);
-
-fsample_m *servergraphs[MAXSERVERS];
-static void *sched;
-
-static sstring *path;
-
-void _init(void) {
- int i;
-
- memset(servergraphs, 0, sizeof(servergraphs));
-
- path = getcopyconfigitem("graphing", "path", "", 100);
- if(!path || !path->content || !path->content[0]) {
- Error("graphing", ERR_WARNING, "Path not set, not loaded.");
- return;
- }
-
- for(i=0;i<MAXSERVERS;i++)
- openserver(i);
-
- registerhook(HOOK_SERVER_NEWSERVER, gr_newserver);
- registerhook(HOOK_SERVER_LOSTSERVER, gr_lostserver);
-
- sched = schedulerecurring(time(NULL), 0, 1, tick, NULL);
-}
-
-void _fini(void) {
- int i;
- if(sched)
- deleteschedule(sched, tick, NULL);
-
- for(i=0;i<MAXSERVERS;i++)
- if(servermonitored(i))
- closeserver(i);
-
- freesstring(path);
-
- deregisterhook(HOOK_SERVER_NEWSERVER, gr_newserver);
- deregisterhook(HOOK_SERVER_LOSTSERVER, gr_lostserver);
-}
-
-int servermonitored(int servernum) {
- return servergraphs[servernum] != NULL;
-}
-
-static char *appendsuffix(char *prefix, char *suffix) {
- static char buf[1024];
-
- snprintf(buf, sizeof(buf), "%s%s", prefix, suffix);
-
- return buf;
-}
-
-static void openserver(int servernum) {
- unsigned char digest[SHA1_DIGESTSIZE];
- char filename[512], hexdigest[sizeof(digest)*2 + 1];
- FILE *f;
- SHA1_CTX sha;
- fsample_m *m;
-
- if(servermonitored(servernum))
- return;
-
- if(serverlist[servernum].linkstate == LS_INVALID)
- return;
-
- SHA1Init(&sha);
- SHA1Update(&sha, (unsigned char *)serverlist[servernum].name->content, serverlist[servernum].name->length);
- SHA1Final(digest, &sha);
-
- snprintf(filename, sizeof(filename), "%s/%s", path->content, hmac_printhex(digest, hexdigest, sizeof(digest)));
-
- f = fopen(appendsuffix(filename, ".name"), "w");
- if(!f) {
- Error("graphing", ERR_WARNING, "Unable to create name file for %s (%s.name)", serverlist[servernum].name->content, filename);
- return;
- }
-
- fprintf(f, "%s\n", serverlist[servernum].name->content);
- fclose(f);
-
- /* 0: seconds
- 1: minutes
- 2: hours
- 3: days
- 4: weeks
- 5: months
- */
-
- m = fsopen_m(GRAPHING_DATASETS, appendsuffix(filename, ".0"), SAMPLES, (CoreHandlerAddFn)registercorehandler, (CoreHandlerDelFn)deregistercorehandler);
- if(!m) {
- Error("graphing", ERR_WARNING, "Unable to create main backing store for %s (%s.0)", serverlist[servernum].name->content, filename);
- return;
- }
-/*
- if(!fsadd_m(m, appendsuffix(filename, ".1"), PERMINUTE, fsapmean, (void *)PERMINUTE) ||
- !fsadd_m(m, appendsuffix(filename, ".2"), PERMINUTE * 24, fsapmean, (void *)(PERMINUTE * 24)) ||
- !fsadd_m(m, appendsuffix(filename, ".3"), PERMINUTE * 24 * 7, fsapmean, (void *)(PERMINUTE * 24 * 7)) ||
- !fsadd_m(m, appendsuffix(filename, ".4"), PERMINUTE * 24 * 7 * 4, fsapmean, (void *)(PERMINUTE * 24 * 7 * 4)) ||
- !fsadd_m(m, appendsuffix(filename, ".5"), PERMINUTE * 24 * 7 * 4 * 12, fsapmean, (void *)(PERMINUTE * 24 * 7 * 4 * 12)))
- {
- Error("graphing", ERR_WARNING, "Unable to create main side store for %s (%s.X)", serverlist[servernum].name->content, filename);
- fsclose_m(m);
- return;
- }
-*/
- servergraphs[servernum] = m;
-}
-
-static void closeserver(int servernum) {
- if(!servermonitored(servernum))
- return;
-
- fsclose_m(servergraphs[servernum]);
- servergraphs[servernum] = NULL;
-}
-
-static void gr_newserver(int hook, void *arg) {
- long num = (long)arg;
-
- openserver(num);
-}
-
-static void gr_lostserver(int hook, void *arg) {
- long num = (long)arg;
-
- closeserver(num);
-}
-
-static void tick(void *arg) {
- time_t t = time(NULL);
- int i;
-
- if(t % GRAPHING_RESOLUTION != 0)
- return;
-
- for(i=0;i<MAXSERVERS;i++)
- if(servermonitored(i))
- fsset_m(servergraphs[i], t / GRAPHING_RESOLUTION, servercount[i]);
-}
-
-
+++ /dev/null
-#ifndef __GRAPHING_H
-#define __GRAPHING_H
-
-#include "../server/server.h"
-#include "../graphing/fsample.h"
-
-extern fsample_m *servergraphs[MAXSERVERS];
-int servermonitored(int servernum);
-
-#define GRAPHING_DATASETS 5
-#define GRAPHING_RESOLUTION 5
-
-#define PERMINUTE (60 / GRAPHING_RESOLUTION)
-#define SAMPLES PERMINUTE * 60 * 24 * 7 * 4 * 12
-
-#endif
+++ /dev/null
-#include "../nterfacer/library.h"
-#include "../nterfacer/nterfacer.h"
-
-#include "graphing.h"
-
-#include <time.h>
-
-#define ERR_SERVER_NOT_MONITORED 0x01
-#define ERR_BAD_PARAMETERS 0x02
-#define ERR_BAD_ENTRY 0x03
-
-int handle_servernames(struct rline *li, int argc, char **argv);
-int handle_serverdata(struct rline *li, int argc, char **argv);
-
-static struct service_node *g_node;
-
-void _init(void) {
- g_node = register_service("graphing");
- if(!g_node)
- return;
-
- register_handler(g_node, "servernames", 0, handle_servernames);
- register_handler(g_node, "serverdata", 3, handle_serverdata);
-}
-
-void _fini(void) {
- if(g_node)
- deregister_service(g_node);
-}
-
-int handle_servernames(struct rline *li, int argc, char **argv) {
- int i;
-
- for(i=0;i<MAXSERVERS;i++) {
- if((serverlist[i].linkstate != LS_INVALID) && servermonitored(i)) {
- if(ri_append(li, "%d:%s", i, serverlist[i].name->content) == BF_OVER)
- return ri_error(li, BF_OVER, "Buffer overflow");
- }
- }
-
- return ri_final(li);
-}
-
-int handle_serverdata(struct rline *li, int argc, char **argv) {
- int servernum = atoi(argv[0]);
- unsigned int entry = atoi(argv[1]);
- fsample_t count = atoi(argv[2]);
- time_t t = time(NULL) / GRAPHING_RESOLUTION;
- int i, ret;
- fsample_m *m;
-
- if(!servermonitored(servernum))
- return ri_error(li, ERR_SERVER_NOT_MONITORED, "Server not monitored");
-
- m = servergraphs[servernum];
-
- if(entry > m->pos) /* not inclusive as 0 is used for for the base index */
- return ri_error(li, ERR_BAD_PARAMETERS, "Bad parameters");
-
- for(i=0;i<count;i++) {
- fsample_t v;
- if(fsget_m(m, entry, t - m->entry[entry].freq * i, &v)) {
- ret = ri_append(li, "%d", v);
- } else {
- ret = ri_append(li, "-1", v);
- }
- if(ret == BF_OVER)
- return ri_error(li, BF_OVER, "Buffer overflow");
- }
-
- return ri_final(li);
-}
-