From: root Date: Wed, 4 Apr 2007 10:14:07 +0000 (+0200) Subject: Add lots of TG06 graph stuff. X-Git-Url: https://git.sesse.net/?p=nms;a=commitdiff_plain;h=9b525f6032627f2d79ae65f9e2b1a97bbad587c0 Add lots of TG06 graph stuff. --- diff --git a/web/ext/comparegraph.cpp b/web/ext/comparegraph.cpp new file mode 100644 index 0000000..5beb37d --- /dev/null +++ b/web/ext/comparegraph.cpp @@ -0,0 +1,172 @@ +#include +#include +#include +#include +#include +#include +#include +#include "graph.h" +#include "flowpusher.h" +#include "flowutil.h" + +namespace pqxx { + template<> + void from_string(const char *from, long long &to) + { + to = atoll(from); + } +} + + +int main(int argc, char **argv) +{ + int width = 1000, height = 500; + pqxx::connection conn05("dbname=nms05 host=localhost user=nms password=seesahS4"); + pqxx::connection conn("dbname=nms host=localhost user=nms password=seesahS4"); + + std::vector flow, total_flow, total_flow05; + FlowPusher fp(flow); + int last_port = -1; + + mallopt(M_TRIM_THRESHOLD, -1); + + int num_total = 0; + pqxx::work t(conn, "fetch_all"); + pqxx::icursorstream::icursorstream cstream(t, "select port,extract(epoch from time) as time,bytes_in,bytes_out from polls natural join switches where ((switchtype='es3024' and port < 25) or (switchtype='summit400' and port > 1)) order by switch,port,time", "fetch_all", 500); + + for ( ;; ) { + pqxx::result res; + + cstream >> res; + if (res.empty()) + break; + + for (unsigned i = 0; i < res.size(); ++i) { + int port = res[i][0].as(); + double x = res[i][1].as(); + unsigned long long y1 = res[i][2].as(), y2 = res[i][3].as(); + + if (port != last_port) { + if (last_port != -1) { + total_flow = sum_flows(total_flow, flow); + fprintf(stderr, "%u (%u)\n", last_port, ++num_total); + } + + // reset + last_port = port; + fp.reset(x, y1, y2); + continue; + } + + fp.push(x, y1, y2); + } + } + total_flow = sum_flows(total_flow, flow); + + unsigned long long min_y = 0; + unsigned long long max_y = 10000000; + + for (unsigned i = 0; i < total_flow.size(); ++i) { + flow_element fe = total_flow[i]; + + min_y = std::min(min_y, fe.y1); + max_y = std::max(max_y, fe.y1); + + min_y = std::min(min_y, fe.y2); + max_y = std::max(max_y, fe.y2); + } + + printf("06 done.\n"); + + num_total = 0; + pqxx::work t05(conn05, "fetch_all"); + pqxx::icursorstream::icursorstream cstream05(t05, "select port,extract(epoch from (time + interval '1 year 20 days')) as time,bytes_in,bytes_out from polls natural join switches where (switchtype='es3024' and port < 25) order by switch,port,time", "fetch_all", 500); + + last_port = -1; + + for ( ;; ) { + pqxx::result res; + + cstream05 >> res; + if (res.empty()) + break; + + for (unsigned i = 0; i < res.size(); ++i) { + int port = res[i][0].as(); + double x = res[i][1].as(); + unsigned long long y1 = res[i][2].as(), y2 = res[i][3].as(); + + if (port != last_port) { + if (last_port != -1) { + total_flow05 = sum_flows(total_flow05, filter_flow(flow)); + fprintf(stderr, "TG05: %u (%u)\n", last_port, ++num_total); + } + + // reset + last_port = port; + fp.reset(x, y1, y2); + continue; + } + + fp.push(x, y1, y2); + } + } + total_flow05 = sum_flows(total_flow05, filter_flow(flow)); + + for (unsigned i = 0; i < total_flow05.size(); ++i) { + flow_element fe = total_flow05[i]; + + min_y = std::min(min_y, fe.y1); + max_y = std::max(max_y, fe.y1); + + min_y = std::min(min_y, fe.y2); + max_y = std::max(max_y, fe.y2); + } + + double min_x = std::min(total_flow[0].x, total_flow05[0].x); + double max_x = std::max(total_flow[total_flow.size() - 1].x, total_flow05[total_flow05.size() - 1].x); + + graph *g = mygraph_new(width, height); + g = mygraph_make_graph(g, min_x, max_x, min_y, max_y, 5); + + // PLOT FIRST + int *x = new int[total_flow.size()]; + unsigned long long *y1 = new unsigned long long[total_flow.size()]; + unsigned long long *y2 = new unsigned long long[total_flow.size()]; + + // de-interleave + for (unsigned i = 0; i < total_flow.size(); ++i) { + x[i] = total_flow[i].x; + y1[i] = total_flow[i].y1; + y2[i] = total_flow[i].y2; + } + + mygraph_plot_series(g, x, y1, total_flow.size(), 1.0f, 0.0f, 0.0f); + mygraph_plot_series(g, x, y2, total_flow.size(), 0.0f, 0.0f, 1.0f); + + delete[] x; + delete[] y1; + delete[] y2; + + // PLOT SECOND + x = new int[total_flow05.size()]; + y1 = new unsigned long long[total_flow05.size()]; + y2 = new unsigned long long[total_flow05.size()]; + + // de-interleave + for (unsigned i = 0; i < total_flow05.size(); ++i) { + x[i] = total_flow05[i].x; + y1[i] = total_flow05[i].y1; + y2[i] = total_flow05[i].y2; + } + + mygraph_plot_series(g, x, y1, total_flow05.size(), 0.0f, 1.0f, 0.0f); + mygraph_plot_series(g, x, y2, total_flow05.size(), 1.0f, 0.0f, 1.0f); + + delete[] x; + delete[] y1; + delete[] y2; + + mygraph_to_file(g, "comparative.png"); + mygraph_cleanup(g); +} diff --git a/web/ext/flowpusher.cpp b/web/ext/flowpusher.cpp new file mode 100644 index 0000000..7bcbf6a --- /dev/null +++ b/web/ext/flowpusher.cpp @@ -0,0 +1,87 @@ +#include +#include +#include +#include +#include +#include "flowpusher.h" + +FlowPusher::FlowPusher(std::vector &flow) : flow(flow) +{ +} + +void FlowPusher::find_diff(double x, double &prev_x, unsigned long long y1, unsigned long long prev_y1, unsigned long long y2, unsigned long long prev_y2, + unsigned long long &yf1, unsigned long long &yf2) +{ + // Heuristics: if last reading was more than ten minutes away, and both + // readings went down from last reading, we assume the counters + // were zeroed. If not, we assume wraparound. + bool over_10mins = (x - prev_x >= 600); + bool y1_wrapped = ((prev_y1 == 0 && y1 == 0) || y1 < prev_y1); + bool y2_wrapped = ((prev_y2 == 0 && y2 == 0) || y2 < prev_y2); + bool both_zero = (y1 == 0 && y2 == 0); + bool any_wide = (prev_y1 > 4294967296ULL || prev_y2 > 4294967296ULL); + + if ((over_10mins && (y1_wrapped || y2_wrapped)) || both_zero || (any_wide && (y1_wrapped || y2_wrapped))) { + prev_y1 = 0; + prev_y2 = 0; + + // our best estimate for when it was zeroed :-) + prev_x = (prev_x + x) / 2; + } + + if (y1 < prev_y1) { + yf1 = (unsigned long long)(((unsigned long long)y1 + 4294967296ULL) - prev_y1); + } else { + yf1 = (unsigned long long)(y1 - prev_y1); + } + + if (y2 < prev_y2) { + yf2 = (unsigned long long)(((unsigned long long)y2 + 4294967296ULL) - prev_y2) / (x - prev_x); + } else { + yf2 = (unsigned long long)(y2 - prev_y2); + } +} + +void FlowPusher::push(double x, unsigned long long y1, unsigned long long y2) +{ + unsigned long long yf1, yf2; + + find_diff(x, prev_x, y1, prev_y1, y2, prev_y2, yf1, yf2); + yf1 /= (x - prev_x); + yf2 /= (x - prev_x); + + flow_element fe; + fe.x = unsigned((prev_x + x)*0.5); + fe.y1 = yf1; + fe.y2 = yf2; + + min_x = std::min(min_x, fe.x); + max_x = std::max(max_x, fe.x); + + min_y = std::min(min_y, fe.y1); + max_y = std::max(max_y, fe.y1); + + min_y = std::min(min_y, fe.y2); + max_y = std::max(max_y, fe.y2); + + flow.push_back(fe); + + prev_x = x; + prev_y1 = y1; + prev_y2 = y2; +} + +void FlowPusher::reset(double x, unsigned long long y1, unsigned long long y2) +{ + flow.resize(0); + + min_y = 0; + max_y = 10000000; + + max_x = time(NULL); + min_x = max_x - 86400; + + prev_x = x; + prev_y1 = y1; + prev_y2 = y2; +} diff --git a/web/ext/flowpusher.h b/web/ext/flowpusher.h new file mode 100644 index 0000000..a16f7b1 --- /dev/null +++ b/web/ext/flowpusher.h @@ -0,0 +1,31 @@ +#ifndef _FLOWPUSHER_H +#define _FLOWPUSHER_H 1 + +struct flow_element { + unsigned x; + unsigned long long y1, y2; +}; + +class FlowPusher +{ +private: + std::vector &flow; + unsigned min_x, max_x; + long long unsigned min_y, max_y; + double prev_x; + unsigned long long prev_y1, prev_y2; + +public: + FlowPusher(std::vector &flow); + void reset(double x, unsigned long long y1, unsigned long long y2); + void push(double x, unsigned long long y1, unsigned long long y2); + static void find_diff(double x, double &prev_x, unsigned long long y1, unsigned long long prev_y1, unsigned long long y2, unsigned long long prev_y2, + unsigned long long &yf1, unsigned long long &yf2); + + unsigned get_min_x() { return min_x; } + unsigned get_max_x() { return max_x; } + unsigned get_min_y() { return min_y; } + unsigned get_max_y() { return max_y; } +}; + +#endif /* !defined(_FLOWPUSHER_H) */ diff --git a/web/ext/flowutil.cpp b/web/ext/flowutil.cpp new file mode 100644 index 0000000..9df12dc --- /dev/null +++ b/web/ext/flowutil.cpp @@ -0,0 +1,128 @@ +#include +#include +#include +#include +#include +#include +#include "graph.h" +#include "flowutil.h" + +std::vector sum_flows(const std::vector &a, const std::vector &b) +{ + std::vector ret; + std::vector::const_iterator ia = a.begin(), ib = b.begin(); + + double last_xa = 0.0, last_y1a = 0.0, last_y2a = 0.0; + double last_xb = 0.0, last_y1b = 0.0, last_y2b = 0.0; + + while (ia != a.end() && ib != b.end()) { + if (ia->x == ib->x) { + flow_element fea = *ia, feb = *ib, fe; + + last_xa = fea.x; + last_y1a = fea.y1; + last_y2a = fea.y2; + + last_xb = feb.x; + last_y1b = feb.y1; + last_y2b = feb.y2; + + fe.x = fea.x; + fe.y1 = fea.y1 + feb.y1; + fe.y2 = fea.y2 + feb.y2; + + ret.push_back(fe); + + ++ia, ++ib; + } else if (ia->x < ib->x) { + flow_element fe = *ia; + + last_xa = fe.x; + last_y1a = fe.y1; + last_y2a = fe.y2; + + double t = (fe.x - last_xb) / (ib->x - last_xb); + fe.y1 += last_y1b + t * (ib->y1 - last_y1b); + fe.y2 += last_y2b + t * (ib->y2 - last_y2b); + + ret.push_back(fe); + + ++ia; + } else { + flow_element fe = *ib; + + last_xb = fe.x; + last_y1b = fe.y1; + last_y2b = fe.y2; + + double t = (fe.x - last_xa) / (ia->x - last_xa); + fe.y1 += last_y1a + t * (ia->y1 - last_y1a); + fe.y2 += last_y2a + t * (ia->y2 - last_y2a); + + ret.push_back(fe); + ++ib; + } + } + + while (ia != a.end()) { + ret.push_back(*ia); + ++ia; + } + while (ib != b.end()) { + ret.push_back(*ib); + ++ib; + } + + return ret; +} + +std::vector filter_flow(const std::vector &flow) +{ + unsigned long long last_y1 = 0, last_y2 = 0; + std::vector ret; + + for (std::vector::const_iterator i = flow.begin(); i != flow.end(); ++i) { +/* if ((i->y1 > 100000 && last_y1 < 10000 && i->y2 > 100000 && last_y2 < 1000) || + (last_y1 > 10000 && last_y2 > 10000 && i->y1 / last_y1 > 10 && i->y2 / last_y2 > 10)) { + printf("yoyo: %llu %llu (%llu %llu)\n", i->y1, i->y2, last_y1, last_y2); + } else { + ret.push_back(*i); + last_y1 = i->y1; + last_y2 = i->y2; + } */ + if (!(i->x >= 1145056800 && i->x <= 1145070800)) { + ret.push_back(*i); + } + } + + return ret; +} + +void make_graph(int port, unsigned width, unsigned height, unsigned min_x, unsigned max_x, unsigned long long min_y, unsigned long long max_y, std::vector &flow) +{ + char filename[256]; + graph *g = mygraph_new(width, height); + g = mygraph_make_graph(g, min_x, max_x, min_y, max_y, 5); + + int *x = new int[flow.size()]; + unsigned long long *y1 = new unsigned long long[flow.size()]; + unsigned long long *y2 = new unsigned long long[flow.size()]; + + // de-interleave + for (unsigned i = 0; i < flow.size(); ++i) { + x[i] = flow[i].x; + y1[i] = flow[i].y1; + y2[i] = flow[i].y2; + } + + mygraph_plot_series(g, x, y1, flow.size(), 1.0f, 0.0f, 0.0f); + mygraph_plot_series(g, x, y2, flow.size(), 0.0f, 0.0f, 1.0f); + sprintf(filename, "port-%u-500-250.png", port); + mygraph_to_file(g, filename); + mygraph_cleanup(g); + + delete[] x; + delete[] y1; + delete[] y2; +} + diff --git a/web/ext/flowutil.h b/web/ext/flowutil.h new file mode 100644 index 0000000..235ebc9 --- /dev/null +++ b/web/ext/flowutil.h @@ -0,0 +1,11 @@ +#ifndef _FLOWUTIL_H +#define _FLOWUTIL_H 1 + +#include +#include "flowpusher.h" + +std::vector sum_flows(const std::vector &a, const std::vector &b); +std::vector filter_flow(const std::vector &flow); +void make_graph(int port, unsigned width, unsigned height, unsigned min_x, unsigned max_x, unsigned long long min_y, unsigned long long max_y, std::vector &flow); + +#endif /* !defined(_FLOWUTIL_H) */ diff --git a/web/ext/graph.cpp b/web/ext/graph.cpp new file mode 100755 index 0000000..a516b31 --- /dev/null +++ b/web/ext/graph.cpp @@ -0,0 +1,240 @@ +#include "graph.h" + +int tz_local_offset() { return 7200; } // riktig? + + +void +mygraph_fill_background(graph *mygraph); + +void +mygraph_draw_graph (cairo_t *cr, + int x, + int y ); + +graph * +mygraph_new (int width, int height) +{ + graph *mygraph; + mygraph = (graph *)malloc(sizeof(graph)); + mygraph->width = width; + mygraph->height = height; + + + int stride = width * 4; + unsigned char *image; + image = (unsigned char *) malloc (sizeof(unsigned char) * stride * height); + + mygraph->surface = cairo_image_surface_create_for_data (image, CAIRO_FORMAT_ARGB32, + width, height, stride); + mygraph->cr = cairo_create (mygraph->surface); + + cairo_set_source_rgb (mygraph->cr, 1.0, 1.0, 1.0); + mygraph_fill_background (mygraph); + + cairo_select_font_face (mygraph->cr, "Sans", CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_font_size (mygraph->cr, 10); + + cairo_set_antialias(mygraph->cr, CAIRO_ANTIALIAS_NONE); + cairo_set_line_width (mygraph->cr, 1.0); + + return mygraph; +} + +graph * +mygraph_make_graph (graph *mygraph, double min_x, double max_x, + double min_y, double max_y, int tickgran) +{ + int xoffset = 70; + cairo_text_extents_t extents; + + mygraph->xoffset = xoffset; + mygraph->min_x = min_x; + mygraph->max_x = max_x; + mygraph->min_y = min_y; + mygraph->max_y = max_y; + +/* cairo_t *cr; */ +/* cairo_surface_t *surface; */ + + double xs = ((double)mygraph->width - (double)(xoffset+2)) / + (double)(max_x - min_x); + + double ys = ((double)mygraph->height - 33.) / (double)(min_y - max_y); + + mygraph->xs = xs; + mygraph->ys = ys; + + double starthour = fmod((min_x + (double)tz_local_offset()) / 3600., 24.); + double diff, center, begin, end; + + char string[20]; + + int i; + for (i = 0; i<240; i++) + { // Hour marks and text + if ((i % 2) == 0) + cairo_set_source_rgb (mygraph->cr, 1.0, 1.0, 1.0); + else + cairo_set_source_rgb (mygraph->cr, 0.90, 0.90, 1.0); + + diff = (double)i - starthour; + begin = (diff * 3600.) * xs; + end = ((double)(i+1) - starthour) * 3600.0 * xs; + center = (begin + end) / 2.; + + if (begin < 0.0) + continue; + if (begin > ((double)mygraph->width - ((double)xoffset))) + continue; + + cairo_rectangle (mygraph->cr, xoffset+begin, 0, + end - begin, mygraph->height); + + cairo_fill (mygraph->cr); + + if (begin <= 0.0 || end >= mygraph->width - (xoffset)) + continue; + + cairo_set_source_rgb (mygraph->cr, 0.0, 0.0, 0.0); + + sprintf(string, "%d", i % 24); +// printf("showing string %s @ %fx%f\n", string, xoffset + center - (extents.width/2), (mygraph->height - extents.height - 2)); + + cairo_text_extents (mygraph->cr, string, &extents); + cairo_move_to (mygraph->cr, xoffset + center - + (extents.width/2), + (mygraph->height - extents.height - 2)); + + cairo_show_text (mygraph->cr, string); + + } + + cairo_set_source_rgb (mygraph->cr, 0.4, 0.4, 0.4); + long long ytick; + do + { + ytick = ((long long)max_y - (long long)min_y) / 11; + ytick = (long long)(ceil (ytick / tickgran) * tickgran); + tickgran /= 10; + } while (((long long)max_y - (long long)min_y) / ytick < 4); + + int y; + unsigned long long traf; + for (i = -11; i<12; i++) + { + y = (int)((i * ytick - (long long)max_y) * ys + 10); + if (y < 2 || y > mygraph->height - 18) + continue; + +/* printf("draw line at %d\n", y); */ + + cairo_move_to (mygraph->cr, xoffset, y); + cairo_line_to (mygraph->cr, mygraph->width-1, y); + + if (i == 0) + { + + cairo_set_source_rgb (mygraph->cr, 0.0, 0.0, 1.0); + cairo_stroke (mygraph->cr); + cairo_set_source_rgb (mygraph->cr, 0.6, 0.6, 0.6); + } + else + cairo_stroke (mygraph->cr); + + // draw text + traf = 8 * ((unsigned long long)i * ytick); +/* printf("traffic: %d\n", traf); */ + + if (traf >= 500000000) + sprintf (string, "%.1f Gbit", ((double)traf/1000000000)); + else if (traf >= 500000) + sprintf (string, "%.1f Mbit", ((double)traf/1000000)); + else + sprintf (string, "%.1f kbit", ((double)traf/1000)); + + cairo_text_extents (mygraph->cr, string, &extents); + +/* if (y - (extents.height/2) < 2 || + y + (extents.height/2) > mygraph->height - (extents.height + 2)) + continue; */ + + cairo_move_to (mygraph->cr, + xoffset - 4 - extents.width, + y + (extents.height/2)); + + cairo_show_text (mygraph->cr, string); + } + + cairo_rectangle (mygraph->cr, xoffset, 0, mygraph->width-xoffset-1, mygraph->height-1); + + cairo_set_source_rgb (mygraph->cr, 0.0, 0.0, 0.0); + cairo_stroke (mygraph->cr); + + return mygraph; +} + +void +mygraph_plot_series (graph *mygraph, int *xvals, unsigned long long *yvals, int n_vals, + double r, double g, double b) +{ + int x, i; + unsigned long long y; + x = xvals[0]; + y = yvals[0]; + + cairo_set_antialias(mygraph->cr, CAIRO_ANTIALIAS_DEFAULT); + cairo_set_source_rgb (mygraph->cr, r, g, b); + + int xp = (int)((x - mygraph->min_x) * mygraph->xs + mygraph->xoffset + 1); + int yp = (int)((y - mygraph->max_y) * mygraph->ys + 10); + + cairo_move_to (mygraph->cr, xp, yp); + +/* printf("Plotting from:\n"); + printf("(%d, %d) %d (%d, %d)
\n", + x, y, (int)((double)(x - (int)mygraph->min_x) * mygraph->xs + (double)(mygraph->xoffset + 1)) , + (int)((double)(x - (int)mygraph->min_x) * mygraph->xs + (double)(mygraph->xoffset + 1)), + (int)((double)(y - (int)mygraph->max_y) * mygraph->ys + 10.)); */ + + int last_xp = xp, last_yp = yp; + + for (i = 1; i < n_vals; i++) + { + x = xvals[i]; + y = yvals[i]; + + int xp = (int)((x - mygraph->min_x) * mygraph->xs + mygraph->xoffset + 1); + int yp = (int)((y - mygraph->max_y) * mygraph->ys + 10); + + if (abs(xp - last_xp) < 2 && yp > last_yp) + continue; + + cairo_line_to (mygraph->cr, xp, yp); + last_xp = xp; + last_yp = yp; + } + + cairo_stroke(mygraph->cr); +} + +void +mygraph_to_file (graph *mygraph, char *filename) +{ + cairo_surface_write_to_png (mygraph->surface, filename); +} + +void +mygraph_cleanup (graph *self) +{ + cairo_destroy (self->cr); + cairo_surface_destroy (self->surface); +} + +void +mygraph_fill_background (graph *mygraph) +{ + cairo_rectangle (mygraph->cr, 0, 0, mygraph->width, mygraph->height); + cairo_fill (mygraph->cr); +} + diff --git a/web/ext/graphall.cpp b/web/ext/graphall.cpp new file mode 100644 index 0000000..a21fc45 --- /dev/null +++ b/web/ext/graphall.cpp @@ -0,0 +1,75 @@ +#include +#include +#include +#include +#include +#include +#include "graph.h" +#include "flowpusher.h" +#include "flowutil.h" + +int main(int argc, char **argv) +{ + bool total_only = false; + int width = 500, height = 250; + + std::vector flow, total_flow; + FlowPusher fp(flow); + int last_port = -1; + + mallopt(M_TRIM_THRESHOLD, -1); + + if (argc == 2 && strcmp(argv[1], "--total-only") == 0) { + width = 1000; + height = 500; + total_only = true; + } + + int num_total = 0; + + for ( ;; ) { + int port; + double x; + unsigned long long y1, y2; + + if (scanf("%d %lf %llu %llu", &port, &x, &y1, &y2) != 4) + break; + + if (port != last_port) { + if (last_port != -1) { + if (!total_only) + make_graph(last_port, width, height, fp.get_min_x(), fp.get_max_x(), fp.get_min_y(), fp.get_max_y(), flow); + total_flow = sum_flows(total_flow, flow); + fprintf(stderr, "%u (%u)\n", last_port, ++num_total); + } + + // reset + last_port = port; + fp.reset(x, y1, y2); + continue; + } + + fp.push(x, y1, y2); + } + + // last graph + if (!total_only) + make_graph(last_port, width, height, fp.get_min_x(), fp.get_max_x(), fp.get_min_y(), fp.get_max_y(), flow); + total_flow = sum_flows(total_flow, flow); + + // total graph + unsigned long long min_y = 0; + unsigned long long max_y = 10000000; + + for (unsigned i = 0; i < total_flow.size(); ++i) { + flow_element fe = total_flow[i]; + + min_y = std::min(min_y, fe.y1); + max_y = std::max(max_y, fe.y1); + + min_y = std::min(min_y, fe.y2); + max_y = std::max(max_y, fe.y2); + } + + make_graph(65535, width, height, total_flow[0].x, total_flow[total_flow.size() - 1].x, min_y, max_y, total_flow); +} diff --git a/web/ext/totalcount.cpp b/web/ext/totalcount.cpp new file mode 100644 index 0000000..bb4b1c0 --- /dev/null +++ b/web/ext/totalcount.cpp @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include +#include +#include +#include "graph.h" +#include "flowpusher.h" +#include "flowutil.h" + +namespace pqxx { + template<> + void from_string(const char *from, long long &to) + { + to = atoll(from); + } +} + +int main(int argc, char **argv) +{ + int width = 1000, height = 500; + unsigned long long traffic = 0ULL; + pqxx::connection conn("dbname=nms host=localhost user=nms password=seesahS4"); + + std::vector flow; + int last_port = -1; + + mallopt(M_TRIM_THRESHOLD, -1); + + int num_total = 0; + pqxx::work t(conn, "fetch_all"); +// pqxx::icursorstream::icursorstream cstream(t, "select port,extract(epoch from time) as time,bytes_in,bytes_out from polls natural join switches where ((switchtype='es3024' and port < 25) or (switchtype='summit400' and port > 1)) order by switch,port,time", "fetch_all", 500); + pqxx::icursorstream::icursorstream cstream(t, "select port,extract(epoch from time) as time,bytes_in,bytes_out from polls natural join switches where switch=1447 order by switch,port,time", "fetch_all", 500); + + double prev_x; + unsigned long long prev_y1, prev_y2; + + for ( ;; ) { + pqxx::result res; + + cstream >> res; + if (res.empty()) + break; + + for (unsigned i = 0; i < res.size(); ++i) { + int port = res[i][0].as(); + double x = res[i][1].as(); + unsigned long long y1 = res[i][2].as(), y2 = res[i][3].as(); + + if (port != last_port) { + if (last_port != -1) { + fprintf(stderr, "%.2f TB (%u)\n", traffic / double(1024.0 * 1024.0 * 1024.0 * 1024.0), ++num_total); + } + + // reset + last_port = port; + prev_x = x; + prev_y1 = y1; + prev_y2 = y2; + continue; + } + + unsigned long long yf1, yf2; + FlowPusher::find_diff(x, prev_x, y1, prev_y1, y2, prev_y2, yf1, yf2); + traffic += 0.5 * (yf1 + yf2); + + prev_x = x; + prev_y1 = y1; + prev_y2 = y2; + } + } + fprintf(stderr, "%.2f TB\n", traffic / double(1024.0 * 1024.0 * 1024.0 * 1024.0)); +} diff --git a/web/ext/totalgraph.cpp b/web/ext/totalgraph.cpp new file mode 100644 index 0000000..f1301d2 --- /dev/null +++ b/web/ext/totalgraph.cpp @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include +#include +#include +#include "flowpusher.h" +#include "flowutil.h" + +namespace pqxx { + template<> + void from_string(const char *from, long long &to) + { + to = atoll(from); + } +} + + +int main(int argc, char **argv) +{ + int width = 1000, height = 500; + pqxx::connection conn("dbname=nms host=localhost user=nms password=seesahS4"); + + std::vector flow, total_flow; + FlowPusher fp(flow); + int last_port = -1; + + mallopt(M_TRIM_THRESHOLD, -1); + + int num_total = 0; + pqxx::work t(conn, "fetch_all"); + pqxx::icursorstream::icursorstream cstream(t, "select port,extract(epoch from time) as time,bytes_in,bytes_out from polls natural join switches where (switchtype='es3024' and port < 25) or (switchtype='summit400' and port > 1) order by switch,port,time", "fetch_all", 500); + + for ( ;; ) { + pqxx::result res; + + cstream >> res; + if (res.empty()) + break; + + for (unsigned i = 0; i < res.size(); ++i) { + int port = res[i][0].as(); + double x = res[i][1].as(); + unsigned long long y1 = res[i][2].as(), y2 = res[i][3].as(); + + if (port != last_port) { + if (last_port != -1) { + total_flow = sum_flows(total_flow, flow); + fprintf(stderr, "%u (%u)\n", last_port, ++num_total); + } + + // reset + last_port = port; + fp.reset(x, y1, y2); + continue; + } + + fp.push(x, y1, y2); + } + } + + unsigned long long min_y = 0; + unsigned long long max_y = 10000000; + + for (unsigned i = 0; i < total_flow.size(); ++i) { + flow_element fe = total_flow[i]; + + min_y = std::min(min_y, fe.y1); + max_y = std::max(max_y, fe.y1); + + min_y = std::min(min_y, fe.y2); + max_y = std::max(max_y, fe.y2); + } + + make_graph(65535, width, height, total_flow[0].x, total_flow[total_flow.size() - 1].x, min_y, max_y, total_flow); +}