--- /dev/null
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <malloc.h>
+#include <vector>
+#include <algorithm>
+#include <pqxx/pqxx>
+#include "graph.h"
+#include "flowpusher.h"
+#include "flowutil.h"
+
+namespace pqxx {
+ template<>
+ void from_string<long long>(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_element> 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<int>();
+ double x = res[i][1].as<double>();
+ unsigned long long y1 = res[i][2].as<long long>(), y2 = res[i][3].as<long long>();
+
+ 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<int>();
+ double x = res[i][1].as<double>();
+ unsigned long long y1 = res[i][2].as<long long>(), y2 = res[i][3].as<long long>();
+
+ 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);
+}
--- /dev/null
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <malloc.h>
+#include <vector>
+#include "flowpusher.h"
+
+FlowPusher::FlowPusher(std::vector<flow_element> &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;
+}
--- /dev/null
+#ifndef _FLOWPUSHER_H
+#define _FLOWPUSHER_H 1
+
+struct flow_element {
+ unsigned x;
+ unsigned long long y1, y2;
+};
+
+class FlowPusher
+{
+private:
+ std::vector<flow_element> &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_element> &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) */
--- /dev/null
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <malloc.h>
+#include <vector>
+#include <algorithm>
+#include "graph.h"
+#include "flowutil.h"
+
+std::vector<flow_element> sum_flows(const std::vector<flow_element> &a, const std::vector<flow_element> &b)
+{
+ std::vector<flow_element> ret;
+ std::vector<flow_element>::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<flow_element> filter_flow(const std::vector<flow_element> &flow)
+{
+ unsigned long long last_y1 = 0, last_y2 = 0;
+ std::vector<flow_element> ret;
+
+ for (std::vector<flow_element>::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_element> &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;
+}
+
--- /dev/null
+#ifndef _FLOWUTIL_H
+#define _FLOWUTIL_H 1
+
+#include <vector>
+#include "flowpusher.h"
+
+std::vector<flow_element> sum_flows(const std::vector<flow_element> &a, const std::vector<flow_element> &b);
+std::vector<flow_element> filter_flow(const std::vector<flow_element> &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_element> &flow);
+
+#endif /* !defined(_FLOWUTIL_H) */
--- /dev/null
+#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)<br/>\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);
+}
+
--- /dev/null
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <malloc.h>
+#include <vector>
+#include <algorithm>
+#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_element> 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);
+}
--- /dev/null
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <malloc.h>
+#include <vector>
+#include <algorithm>
+#include <pqxx/pqxx>
+#include "graph.h"
+#include "flowpusher.h"
+#include "flowutil.h"
+
+namespace pqxx {
+ template<>
+ void from_string<long long>(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_element> 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<int>();
+ double x = res[i][1].as<double>();
+ unsigned long long y1 = res[i][2].as<long long>(), y2 = res[i][3].as<long long>();
+
+ 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));
+}
--- /dev/null
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <malloc.h>
+#include <vector>
+#include <algorithm>
+#include <pqxx/pqxx>
+#include "flowpusher.h"
+#include "flowutil.h"
+
+namespace pqxx {
+ template<>
+ void from_string<long long>(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_element> 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<int>();
+ double x = res[i][1].as<double>();
+ unsigned long long y1 = res[i][2].as<long long>(), y2 = res[i][3].as<long long>();
+
+ 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);
+}