summaryrefslogblamecommitdiffstats
path: root/src/main/java/org/openslx/dnbd3/status/StatisticsGenerator.java
blob: c9e50e4236ee41f65a0ffbe18cdbfdeb498e47d9 (plain) (tree)
1
2
3
4
5
6
7
8



                                 


                                            
                                             





















                                                      
                                                                                                                                   

                                                                          

                                              



                                                                  
                                                              












                                                                                             

                                                                


                                                   

                                                      





                                                        
                                                                        




                                                                     




                                                                               
                                                    
                         


                                       
                                          




                                                                  
                                                                     








                                                                      

                                                                  
                                                        
                                                              
                                                  


                                                          



                                                                           
                                                     
                 
                                                                                    










































                                                                                                        
                                                  

                                 







                                                                              



                 
package org.openslx.dnbd3.status;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.openslx.dnbd3.status.output.EdgeSerializer;
import org.openslx.dnbd3.status.output.OutputMain;
import org.openslx.dnbd3.status.output.ServerStats;
import org.openslx.dnbd3.status.poller.ServerPoller;
import org.openslx.dnbd3.status.rpc.Client;
import org.openslx.dnbd3.status.rpc.Status;
import org.openslx.graph.ClientNode;
import org.openslx.graph.Edge;
import org.openslx.graph.Graph;
import org.openslx.graph.Node;
import org.openslx.graph.ServerNode;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class StatisticsGenerator
{
	private final List<ServerPoller> pollers;
	private volatile long lastUpdate = 0;
	private ExecutorService threadPool = new ThreadPoolExecutor( 3, 8, 1, TimeUnit.MINUTES, new SynchronousQueue<Runnable>() );
	private List<Future<Status>> futureStatusList = new ArrayList<>();
	private List<Status> statusList = new ArrayList<>();
	private final Gson exposedJsonBuilder;
	private final Gson defaultJsonBuilder;

	private final Graph graph = new Graph( "DNBD 3  Status" );
	private byte[] imgData = null;
	private final OutputMain output = new OutputMain();
	private final OutputMain newOutput = new OutputMain();

	public StatisticsGenerator( List<ServerPoller> pollers )
	{
		this.pollers = pollers;
		for ( ServerPoller poller : pollers ) {
			Node server = new ServerNode( poller.getAddress() );
			server.activate();
			graph.addNode( server );
		}
		// Prepare json serializer for graph
		final GsonBuilder gsonBuilder = new GsonBuilder();
		gsonBuilder.excludeFieldsWithoutExposeAnnotation();
		gsonBuilder.registerTypeHierarchyAdapter( Edge.class, new EdgeSerializer() );
		exposedJsonBuilder = gsonBuilder.create();
		defaultJsonBuilder = new GsonBuilder().create();
		output.graph = graph;
		output.servers = new ArrayList<>();
		output.timestamp = 0;
		newOutput.servers = new ArrayList<>();
		newOutput.timestamp = 0;
	}

	private synchronized void updateAll()
	{
		futureStatusList.clear();
		for ( final ServerPoller p : pollers ) {
			Callable<Status> task = new Callable<Status>() {
				@Override
				public Status call() throws Exception
				{
					return p.update();
				}
			};
			try {
				Future<Status> ret = threadPool.submit( task );
				futureStatusList.add( ret );
			} catch ( Exception e ) {
				e.printStackTrace();
			}
		}
		statusList.clear();
		output.servers.clear();
		newOutput.servers.clear();
		for ( Future<Status> future : futureStatusList ) {
			Status status;
			try {
				status = future.get();
			} catch ( Exception e ) {
				System.out.println("Future timeout");
				continue;
			}
			if ( status == null )
				continue;
			statusList.add( status );
			ServerStats srv = new ServerStats();
			srv.address = status.getAddress();
			srv.bytesReceived = status.getBytesReceived();
			srv.bytesSent = status.getBytesSent();
			srv.clientCount = status.getClientCount();
			srv.serverCount = status.getServerCount();
			srv.uptime = status.getUptime();
			srv.timestamp = status.getTimestamp();
			output.servers.add( srv );
			srv = srv.clone();
			srv.images = status.getImages();
			srv.clients = status.getClients();
			if (srv.clientCount == 0 && srv.serverCount == 0) {
				// For older dnbd3-server
				srv.clientCount = srv.clients.size();
			}
			newOutput.servers.add( srv );
		}
		newOutput.timestamp = output.timestamp = System.currentTimeMillis();
		synchronized ( graph ) {
			graph.decay();
			for ( Status status : statusList ) {
				String serverIp = status.getAddress();
				Node server = graph.getNode( serverIp );
				if ( server == null )
					server = new ServerNode( serverIp );
				server.activate();
				for ( Client client : status.getClients() ) {
					if ( client.getAddress() == null )
						continue;
					String ip = client.getAddress().replaceFirst( "\\:\\d+$", "" );
					Node n = graph.getNode( ip );
					if ( n == null )
						n = new ClientNode( ip );
					n.activate();
					graph.setEdge( server, n, ( client.getBytesSent() >> 12 ) + 1 );
				}
			}
			imgData = null;
		}
	}

	private synchronized void ensureUpToDate()
	{
		final long now = System.currentTimeMillis();
		if ( now - lastUpdate > 1900 ) {
			lastUpdate = now;
			updateAll();
		}
	}

	public byte[] getImagePng()
	{
		ensureUpToDate();
		synchronized ( graph ) {
			if ( imgData == null ) {
				imgData = graph.makeNextImage();
			}
		}
		return imgData;
	}

	public String getJson( boolean newFormat )
	{
		ensureUpToDate();
		if ( newFormat ) {
			synchronized ( newOutput ) {
				return defaultJsonBuilder.toJson( newOutput );
			}
		} else {
			synchronized ( output ) {
				return exposedJsonBuilder.toJson( output );
			}
		}
	}

}