You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
168 lines
7.8 KiB
168 lines
7.8 KiB
/**
|
|
* NetworkHistory
|
|
* Copyright 2014 by Michael Peter Christen
|
|
* First released 10.10.2014 at http://yacy.net
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program in the file lgpl21.txt
|
|
* If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
import java.io.IOException;
|
|
import java.text.ParseException;
|
|
import java.util.ArrayList;
|
|
import java.util.Date;
|
|
import java.util.HashMap;
|
|
import java.util.Iterator;
|
|
import java.util.LinkedHashSet;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
import net.yacy.cora.date.GenericFormatter;
|
|
import net.yacy.cora.document.encoding.ASCII;
|
|
import net.yacy.cora.protocol.RequestHeader;
|
|
import net.yacy.cora.util.ConcurrentLog;
|
|
import net.yacy.kelondro.blob.Tables.Row;
|
|
import net.yacy.search.Switchboard;
|
|
import net.yacy.server.serverObjects;
|
|
import net.yacy.server.serverSwitch;
|
|
import net.yacy.visualization.ChartPlotter;
|
|
import net.yacy.visualization.RasterPlotter;
|
|
|
|
|
|
public class NetworkHistory {
|
|
|
|
public static RasterPlotter respond(@SuppressWarnings("unused") final RequestHeader header, serverObjects post, final serverSwitch env) {
|
|
final Switchboard sb = (Switchboard) env;
|
|
|
|
if (post == null) post = new serverObjects();
|
|
|
|
final int maxtime = post.getInt("maxtime", 48); // hours
|
|
final int bottomscale = post.getInt("scale", 1); // 1h
|
|
final String[] columnsx = post.get("columns", "cC").split("\\|"); // new String[]{"aM", "aW", "aD", "aH", "cC", "cD", "cP", "cR", "cI"};
|
|
/*
|
|
aM activeLastMonth
|
|
aW activeLastWeek
|
|
aD activeLastDay
|
|
aH activeLastHour
|
|
cC countConnected (Active Senior)
|
|
cD countDisconnected (Passive Senior)
|
|
cP countPotential (Junior)
|
|
cR count of the RWI entries
|
|
cI size of the index (number of documents)
|
|
*/
|
|
final Set<String> columns = new LinkedHashSet<>();
|
|
for (String col: columnsx) columns.add(col);
|
|
// scan the database and put in values
|
|
List<Map<String, Long>> rows = new ArrayList<>(maxtime * 2);
|
|
long now = System.currentTimeMillis();
|
|
long timelimit = now - maxtime * 3600000L;
|
|
try {
|
|
Iterator<Row> rowi = sb.tables.iterator("stats", false);
|
|
Map <String, Long> statrow;
|
|
while (rowi.hasNext()) {
|
|
Row row = rowi.next();
|
|
String d = ASCII.String(row.getPK());
|
|
Date date = GenericFormatter.SHORT_MINUTE_FORMATTER.parse(d, 0).getTime();
|
|
if (date.getTime() < timelimit) break;
|
|
statrow = new HashMap<>();
|
|
for (String key: columns) {
|
|
byte[] x = row.get(key);
|
|
if (x != null) statrow.put(key, Long.parseLong(ASCII.String(x)));
|
|
}
|
|
statrow.put("time", date.getTime());
|
|
rows.add(statrow);
|
|
}
|
|
} catch (final IOException|ParseException e) {
|
|
ConcurrentLog.logException(e);
|
|
}
|
|
|
|
// find correct scale
|
|
int maxpeers = 100, minpeers = Integer.MAX_VALUE; // to be measured by pre-scanning the db
|
|
for (Map<String, Long> row: rows) {
|
|
for (String column: columns) {
|
|
Long v = row.get(column);
|
|
if (v != null) maxpeers = Math.max(maxpeers, (int) v.longValue());
|
|
if (v != null && v.longValue() > 0) minpeers = Math.min(minpeers, (int) v.longValue());
|
|
}
|
|
}
|
|
if (minpeers < 0) {
|
|
ConcurrentLog.warn("NetworkHistory", "Negative value in plot. columns:"+columns);
|
|
minpeers=0;
|
|
}
|
|
if (minpeers==maxpeers) {
|
|
minpeers=Math.max(0,minpeers-10);
|
|
maxpeers+=10;
|
|
}
|
|
if (maxpeers-minpeers > 2*minpeers) minpeers=0; // if we are close enough to zero, use zero as minimum
|
|
int order=(int)Math.log10(maxpeers-minpeers);
|
|
int scale=(int)Math.pow(10, order);
|
|
minpeers=(minpeers/scale)*scale;
|
|
maxpeers=((maxpeers/scale)+1)*scale;
|
|
if ((maxpeers-minpeers)/scale < 3) scale=Math.max(1,scale/2);
|
|
final int leftborder = 30;
|
|
final int rightborder = 10;
|
|
final int width = post.getInt("width", 768 + leftborder + rightborder);
|
|
final int hspace = width - leftborder - rightborder;
|
|
final int height = post.getInt("height", 240);
|
|
final int topborder = 20;
|
|
final int bottomborder = 20;
|
|
final int vspace = height - topborder - bottomborder;
|
|
final int leftscale = scale;
|
|
String timestr = maxtime + " HOURS";
|
|
if (maxtime > 24 && maxtime % 24 == 0) timestr = (maxtime / 24) + " DAYS";
|
|
if (maxtime == 168) timestr = "WEEK";
|
|
if (maxtime > 168 && maxtime % 168 == 0) timestr = (maxtime / 168) + " WEEKS";
|
|
String headline = "YACY NETWORK HISTORY";
|
|
if (columns.contains("aM")) headline += ", ACTIVE PEERS WITHIN THE LAST MONTH";
|
|
if (columns.contains("aW")) headline += ", ACTIVE PEERS WITHIN THE LAST WEEK";
|
|
if (columns.contains("aD")) headline += ", ACTIVE PEERS WITHIN THE LAST DAY";
|
|
if (columns.contains("aH")) headline += ", ACTIVE PEERS WITHIN THE LAST HOUR";
|
|
if (columns.contains("cC")) headline += ", ACTIVE SENIOR PEERS";
|
|
if (columns.contains("cD")) headline += ", PASSIVE SENIOR PEERS";
|
|
if (columns.contains("cP")) headline += ", POTENTIAL JUNIOR PEERS";
|
|
if (columns.contains("cI")) headline = "YACY PEER '" + sb.peers.myName().toUpperCase() + "' INDEX SIZE HISTORY: NUMBER OF DOCUMENTS";
|
|
if (columns.contains("cR")) headline = "YACY PEER '" + sb.peers.myName().toUpperCase() + "' INDEX SIZE HISTORY: NUMBER OF RWI ENTRIES";
|
|
ChartPlotter chart = new ChartPlotter(width, height, 0xFFFFFFl, 0x000000l, 0xAAAAAAl, leftborder, rightborder, topborder, bottomborder, headline, "IN THE LAST " + timestr);
|
|
long pps = (long)hspace * (long)bottomscale / maxtime;
|
|
int pixelperscale = Math.max(8, (int)pps );
|
|
chart.declareDimension(ChartPlotter.DIMENSION_BOTTOM, bottomscale, pixelperscale, -maxtime, 0x000000l, 0xCCCCCCl, "TIME/HOURS");
|
|
pps = (long)vspace * (long)leftscale / (maxpeers-minpeers);
|
|
pixelperscale = Math.max(8, (int)pps );
|
|
chart.declareDimension(ChartPlotter.DIMENSION_LEFT, leftscale, pixelperscale, minpeers, 0x008800l, null , columns.contains("cI") ? "DOCUMENTS" : columns.contains("cR") ? "RWIs" : "PEERS");
|
|
|
|
// write the data
|
|
float x0, x1;
|
|
int y0, y1;
|
|
Long time;
|
|
for (String column: columns) {
|
|
x0 = 1.0f; y0 = 0;
|
|
for (Map<String, Long> row: rows) {
|
|
time = row.get("time");
|
|
if (time == null) continue;
|
|
Long v = row.get(column);
|
|
if (v == null) continue;
|
|
x1 = (time - now) / 3600000.0f;
|
|
y1 = (int) v.longValue();
|
|
chart.setColor(0x228822);
|
|
chart.chartDot(ChartPlotter.DIMENSION_BOTTOM, ChartPlotter.DIMENSION_LEFT, x1, y1, 2, null, 315);
|
|
chart.setColor(0x008800);
|
|
if (x0 < 0.0f) chart.chartLine(ChartPlotter.DIMENSION_BOTTOM, ChartPlotter.DIMENSION_LEFT, x0, y0, x1, y1);
|
|
x0 = x1; y0 = y1;
|
|
}
|
|
}
|
|
return chart;
|
|
}
|
|
}
|