package edu.uw.cse.netlab.testharness; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Timer; import java.util.TimerTask; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerListener; import org.gudy.azureus2.core3.download.DownloadManagerStats; import org.gudy.azureus2.core3.global.GlobalManagerDownloadRemovalVetoException; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.peer.PEPeerManager; import org.gudy.azureus2.core3.peer.PEPeerManagerListener; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerListener; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerResponse; import org.gudy.azureus2.ui.swt.StartServer; import org.gudy.azureus2.ui.swt.mainwindow.Initializer; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreComponent; import com.aelitis.azureus.core.AzureusCoreException; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreLifecycleListener; import com.aelitis.azureus.core.impl.AzureusCoreImpl; import edu.uw.cse.netlab.reputation.LocalIdentity; import edu.uw.cse.netlab.reputation.storage.ReputationDAO; public class CLI_Main { AzureusCore mCore; static CLI_Main mInst = null; public static CLI_Main get() { return mInst; } File mErr = null, mOut = null; public File getOut() { return mOut; } public File getErr() { return mErr; } public CLI_Main( String [] args ) { // try // { // mErr = File.createTempFile("ost", "err"); // mOut = File.createTempFile("ost", "out"); // // // skip this for now. //// System.out.println("tail -f " + mOut.getAbsolutePath()); //// System.out.println("tail -f " + mErr.getAbsolutePath()); //// //// System.setOut(new PrintStream( new FileOutputStream(mOut), true )); //// System.setErr(new PrintStream( new FileOutputStream(mErr), true )); // } // catch( IOException e ) // { // System.err.println("Couldn't redirect stdout, err. " + e); // e.printStackTrace(); // System.exit(-1); // } // this makes sure we're the only instance running on this machine. // DEBUG -- removed for local testing // (new Thread(new ReceiveOrders(4312))).start(); // final SendStatus status = new SendStatus("recycle.cs.washington.edu", 4312); final String [] args_shadow = args; List<byte []> torrent_bytes = new ArrayList<byte[]>(); boolean keep_last = false, keep_curr = false; int rate = 1024; // 1 MBps int wait_after_finished_secs = 0; // default is immediately quit double wait_after_ratio = Double.MAX_VALUE; boolean show_tray = false; String outfile = null; //COConfigurationManager.setParameter("dht.logging", false); try { for( int i=0; i<args.length; i++ ) { if( args[i].equals("-file") ) { FileInputStream fis = new FileInputStream(args[++i]); byte [] scratch_bytes = new byte[fis.available()]; fis.read(scratch_bytes); torrent_bytes.add(scratch_bytes); } else if( args[i].equals("-bytes") ) { byte [] scratch_bytes = args[++i].getBytes(); torrent_bytes.add(scratch_bytes); } else if( args[i].equals("-keep_last") ) { keep_last = true; } else if( args[i].equals("-keep_curr") ) { keep_curr = true; } else if( args[i].equals("-outfile") ) { outfile = args[++i]; } else if( args[i].equals("-rate") ) { rate = Integer.parseInt(args[++i]); } else if( args[i].equals("-stay") ) { wait_after_finished_secs = Integer.parseInt(args[++i]); } else if( args[i].equals("-ratio") ) { wait_after_ratio = Double.parseDouble(args[++i]); } else if( args[i].equals("-tray") ) { show_tray = true; } } } catch( IOException e ) { System.err.println("Couldn't load torrent: " + e); System.exit(-1); } COConfigurationManager.preInitialise(); impose_settings(rate); long start = System.currentTimeMillis(); mCore = AzureusCoreFactory.create(); System.out.println("starting core took: " + (System.currentTimeMillis()-start) + " ms"); final Object ready = new Object(); mCore.addLifecycleListener(new AzureusCoreLifecycleListener(){ public void componentCreated(AzureusCore core, AzureusCoreComponent component) { System.out.println("component created: " + component); } public boolean requiresPluginInitCompleteBeforeStartedEvent() { return false; } public boolean restartRequested(AzureusCore core) throws AzureusCoreException { return false; } public void started(AzureusCore core) { System.out.println("Core started"); // DEBUG -- removed for local testing //(new Thread(status)).start(); synchronized(ready) { ready.notifyAll(); } } public boolean stopRequested(AzureusCore core) throws AzureusCoreException { return false; } public void stopped(AzureusCore core) {} public void stopping(AzureusCore core) {} public boolean syncInvokeRequired() { return false; } }); mCore.start(); try { synchronized(ready) { while( mCore.isStarted() == false ) ready.wait(); } } catch( Exception e ) { System.err.println(e); e.printStackTrace(); System.exit(-1); } ReputationDAO.get(); // try { // SWTThread.createInstance(null); // } catch (SWTThreadAlreadyInstanciatedException e1) { // System.err.println(e1); // e1.printStackTrace(); // } // SystemTraySWT tray = new SystemTraySWT(); // Remove all existing download managers if they exist. for( DownloadManager dm : (DownloadManager[])(mCore.getGlobalManager().getDownloadManagers().toArray(new DownloadManager[0])) ) { if( keep_last == false ) { System.out.println("Removing existing download manager: " + dm); try { mCore.getGlobalManager().removeDownloadManager(dm); } catch( AzureusCoreException e ) { e.printStackTrace(); } catch( GlobalManagerDownloadRemovalVetoException e ) { e.printStackTrace(); } } /** * If there is some weirdness during torrent add (or out of program movement of torrent / data files), Azureus will simply fail * silently during DownloadManager recreation. Here we try to detect when things are weird. */ dm.addListener(new DownloadManagerListener() { public void completionChanged( DownloadManager manager, boolean completed ) {} public void downloadComplete( DownloadManager manager ) {} public void filePriorityChanged( DownloadManager download, DiskManagerFileInfo file ) {} public void positionChanged( DownloadManager download, int oldPosition, int newPosition ) {} public void stateChanged( DownloadManager manager, int state ) { System.out.println(manager + " state: " + state); if( state == DownloadManager.STATE_ERROR ) { try { mCore.getGlobalManager().removeDownloadManager(manager); } catch( AzureusCoreException e ) { e.printStackTrace(); } catch( GlobalManagerDownloadRemovalVetoException e ) { e.printStackTrace(); } } } }); } // make sure we have this in the CP.. LocalIdentity.get(); if( torrent_bytes.size() > 0 ) { for( byte [] bytes : torrent_bytes ) { start_distribution(bytes, keep_curr, outfile, wait_after_finished_secs, wait_after_ratio); } } else { System.out.println("Nothing to do explicitly... (next: watchdir)"); //MagicDirectoryManager.get(); try { // DEBUG -- removed for local testing // while( status.getTorrent() == null ) // Thread.sleep(1000); // DEBUG -- removed for local testing // System.out.println("got torrent bytes from coordinator, starting..."); // start_distribution(torrent_bytes); } catch( Exception e ) { System.err.println(e); e.printStackTrace(); } } if( show_tray ) { new Initializer(AzureusCoreImpl.getSingleton(), new StartServer(), new String[]{}); } } /** * @param args */ public static void main(String[] args) { mInst = new CLI_Main(args); } private static void start_distribution( byte[] torrent_bytes, boolean keep_curr, String outfile, final int wait_after_finished_secs, final double wait_after_ratio ) { try { File torrent = File.createTempFile("ost", "torrent"); FileOutputStream fos = new FileOutputStream(torrent); fos.write(torrent_bytes); fos.close(); if( keep_curr ) torrent.deleteOnExit(); File saved = null; if( outfile == null ) { saved = File.createTempFile("ost", "file"); if( keep_curr ) saved.deleteOnExit(); } else { saved = new File(outfile); } final DownloadManager dm = AzureusCoreFactory.getSingleton().getGlobalManager().addDownloadManager(torrent.getAbsolutePath(), saved.getAbsolutePath()); dm.addListener(new DownloadManagerListener() { long dist_start_time = System.currentTimeMillis(); public void completionChanged(DownloadManager manager, boolean completed) {} public void downloadComplete(DownloadManager manager) { System.out.println("dl_completion " + (System.currentTimeMillis() - dist_start_time)/1000); System.out.println("download completed. waiting: " + wait_after_finished_secs + " / ratio: " + wait_after_ratio); final long completion_time = System.currentTimeMillis(); (new Timer()).schedule(new TimerTask(){ public void run() { DownloadManagerStats stats = dm.getStats(); double ratio = (double)stats.getTotalDataBytesSent() / (double)stats.getTotalDataBytesReceived(); if( ratio > wait_after_ratio ) { System.out.println("ratio reached: " + ratio); exit(); } if( (System.currentTimeMillis() - completion_time) > wait_after_finished_secs*1000 ) { System.out.println("wait after time reached: " + wait_after_finished_secs ); exit(); } } }, 1000, 1000); } public void filePriorityChanged(DownloadManager download, DiskManagerFileInfo file) {} public void positionChanged(DownloadManager download, int oldPosition, int newPosition) {} public void stateChanged(final DownloadManager manager, int state) { System.out.println("State changed for: " + manager.getTorrentFileName() + " -- " + state); if( state == DownloadManager.STATE_DOWNLOADING ) { System.out.println("download manager initialized, adding listeners..."); manager.getPeerManager().addListener(new PEPeerManagerListener() { public void destroyed() {} public void peerAdded( PEPeerManager manager, PEPeer peer ) { System.out.println("got peer: " + peer); } public void peerRemoved( PEPeerManager manager, PEPeer peer ) {}}); manager.getTrackerClient().addListener(new TRTrackerAnnouncerListener() { public void receivedTrackerResponse( TRTrackerAnnouncerResponse response ) { System.out.println("Received tracker response: " + response.getStatus() + " peers: " + response.getPeers().length ); dist_start_time = System.currentTimeMillis(); } public void urlChanged( TRTrackerAnnouncer announcer, URL old_url, URL new_url, boolean explicit ) {} public void urlRefresh() {}}); (new Timer("Download status reporter", true)).schedule(new TimerTask(){ public void run() { DownloadManagerStats stats = manager.getStats(); System.out.println( " DL: " + stats.getDataReceiveRate()/1024 + " [" + stats.getTotalDataBytesReceived() / (1024) + "]" + " UL: " + stats.getDataSendRate()/1024 + " [" + stats.getTotalDataBytesSent() / (1024) + "]" + " Peers: " + manager.getPeerManager().getPeers().size() + " %: " + (double)((double)stats.getTotalGoodDataBytesReceived() / (double)manager.getSize()) * 100.0 + " MaxUL: " + COConfigurationManager.getIntParameter("Max Upload Speed KBs") ); } }, 1000, 5 * 1000); } } }); } catch( Exception e ) { System.err.println("Error downloading specified swarm: " + e ); e.printStackTrace(); } } private static void impose_settings(int rate) { COConfigurationManager.setParameter("Save Torrent Files", false); COConfigurationManager.setParameter("Max Upload Speed KBs", rate); System.out.println("rate is: " + rate); COConfigurationManager.setParameter("LAN Speed Enabled", false); COConfigurationManager.setParameter("Prioritize First Piece", true); COConfigurationManager.setParameter("Show Splash", false); COConfigurationManager.setParameter("Enable System Tray", true); // also, seed incremental file creation in the config defaults (modified a bunch of stuff there) System.out.println("default torrent dir is: " + COConfigurationManager.getStringParameter("General_sDefaultTorrent_Directory")); COConfigurationManager.addParameterListener("General_sDefaultTorrent_Directory", new ParameterListener(){ public void parameterChanged( String parameterName ) { System.out.println("changed********: " + parameterName); System.out.println("default torrent dir is: " + COConfigurationManager.getStringParameter("General_sDefaultTorrent_Directory")); } }); } public static void exit() { try { if( AzureusCoreImpl.isCoreAvailable() ) { System.out.println("Calling core stop"); AzureusCoreImpl.getSingleton().stop(); } } catch( Exception e ) { System.err.println("stop exception: " + e); e.printStackTrace(); System.exit(0); } } }