2014-10-10 14:16:16 +02:00
/ * *
* 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 ;
2014-11-10 18:52:01 +01:00
import java.util.Iterator ;
2014-10-29 13:21:35 +01:00
import java.util.LinkedHashSet ;
2014-10-10 14:16:16 +02:00
import java.util.List ;
import java.util.Map ;
2014-10-29 13:21:35 +01:00
import java.util.Set ;
2014-10-10 14:16:16 +02:00
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
2014-10-29 13:21:35 +01:00
final String [ ] columnsx = post . get ( " columns " , " cC " ) . split ( " \\ | " ) ; // new String[]{"aM", "aW", "aD", "aH", "cC", "cD", "cP", "cR", "cI"};
2014-10-10 14:16:16 +02:00
/ *
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 )
* /
2014-10-29 13:21:35 +01:00
final Set < String > columns = new LinkedHashSet < > ( ) ;
for ( String col : columnsx ) columns . add ( col ) ;
2014-10-10 14:16:16 +02:00
// scan the database and put in values
List < Map < String , Long > > rows = new ArrayList < > ( maxtime * 2 ) ;
long now = System . currentTimeMillis ( ) ;
2014-10-29 13:21:35 +01:00
long timelimit = now - maxtime * 3600000L ;
2014-10-10 14:16:16 +02:00
try {
2014-11-10 18:52:01 +01:00
Iterator < Row > rowi = sb . tables . iterator ( " stats " , false ) ;
2014-10-10 14:16:16 +02:00
Map < String , Long > statrow ;
2014-11-10 18:52:01 +01:00
while ( rowi . hasNext ( ) ) {
Row row = rowi . next ( ) ;
2014-10-10 14:16:16 +02:00
String d = ASCII . String ( row . getPK ( ) ) ;
Date date = GenericFormatter . SHORT_MINUTE_FORMATTER . parse ( d ) ;
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
2014-10-29 21:41:41 +01:00
int maxpeers = 100 , minpeers = Integer . MAX_VALUE ; // to be measured by pre-scanning the db
2014-10-10 14:16:16 +02:00
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 ( ) ) ;
2014-10-29 21:41:41 +01:00
if ( v ! = null & & v . longValue ( ) > 0 ) minpeers = Math . min ( minpeers , ( int ) v . longValue ( ) ) ;
2014-10-10 14:16:16 +02:00
}
}
2014-10-29 21:41:41 +01:00
maxpeers = 10 * ( ( maxpeers / 9 * 10 ) / 10 ) ;
minpeers = 10 * ( ( minpeers * 9 / 10 ) / 10 ) ;
2014-10-29 13:37:44 +01:00
final int leftborder = 30 ;
2014-10-10 14:16:16 +02:00
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 ;
2014-10-29 21:41:41 +01:00
final int leftscale = 10 * ( maxpeers / 100 ) ;
2014-10-29 13:21:35 +01:00
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 " ;
2014-10-29 21:41:41 +01:00
if ( columns . contains ( " cI " ) ) headline = " YACY PEER ' " + sb . peers . myName ( ) + " ' INDEX SIZE HISTORY: NUMBER OF DOCUMENTS " ;
if ( columns . contains ( " cR " ) ) headline = " YACY PEER ' " + sb . peers . myName ( ) + " ' INDEX SIZE HISTORY: NUMBER OF RWI ENTRIES " ;
2014-10-29 13:21:35 +01:00
ChartPlotter chart = new ChartPlotter ( width , height , 0xFFFFFFl , 0x000000l , 0xAAAAAAl , leftborder , rightborder , topborder , bottomborder , headline , " IN THE LAST " + timestr ) ;
2014-11-07 18:12:09 +01:00
int pixelperscale = hspace / ( maxtime / bottomscale ) ;
if ( pixelperscale > 0 ) chart . declareDimension ( ChartPlotter . DIMENSION_BOTTOM , bottomscale , pixelperscale , - maxtime , 0x000000l , 0xCCCCCCl , " TIME/HOURS " ) ;
pixelperscale = 10 * ( ( vspace * leftscale / ( maxpeers - minpeers ) ) / 10 ) ;
if ( pixelperscale > 0 ) chart . declareDimension ( ChartPlotter . DIMENSION_LEFT , leftscale , pixelperscale , minpeers , 0x008800l , null , columns . contains ( " cI " ) ? " DOCUMENTS " : columns . contains ( " cR " ) ? " RWIs " : " PEERS " ) ;
2014-10-10 14:16:16 +02:00
// 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 ;
}
}