/* This code is part of Freenet. It is distributed under the GNU General * Public License, version 2 (or at your option any later version). See * http://www.gnu.org/ for further details of the GPL. */ package freenet.node.simulator; import static java.util.concurrent.TimeUnit.DAYS; import java.io.File; import java.io.UnsupportedEncodingException; import freenet.client.HighLevelSimpleClient; import freenet.crypt.DummyRandomSource; import freenet.io.comm.PeerParseException; import freenet.io.comm.ReferenceSignatureVerificationException; import freenet.keys.CHKBlock; import freenet.keys.CHKDecodeException; import freenet.keys.CHKEncodeException; import freenet.keys.CHKVerifyException; import freenet.keys.ClientCHK; import freenet.keys.ClientCHKBlock; import freenet.node.FSParseException; import freenet.node.Node; import freenet.node.NodeInitException; import freenet.node.NodeStarter; import freenet.node.RequestStarter; import freenet.support.Executor; import freenet.support.Fields; import freenet.support.HexUtil; import freenet.support.Logger; import freenet.support.PooledExecutor; import freenet.support.Logger.LogLevel; import freenet.support.LoggerHook.InvalidThresholdException; import freenet.support.compress.InvalidCompressionCodecException; import freenet.support.compress.Compressor.COMPRESSOR_TYPE; import freenet.support.io.FileUtil; /** * Test a busy, bandwidth limited network. Hopefully this should reveal any serious problems with * load limiting and block transfer. * @author toad */ public class RealNodeBusyNetworkTest extends RealNodeRoutingTest { static final int NUMBER_OF_NODES = 25; static final int DEGREE = 5; static final short MAX_HTL = (short)8; static final int INSERT_KEYS = 50; static final boolean START_WITH_IDEAL_LOCATIONS = true; static final boolean FORCE_NEIGHBOUR_CONNECTIONS = true; static final boolean ENABLE_SWAPPING = false; static final boolean ENABLE_ULPRS = false; static final boolean ENABLE_PER_NODE_FAILURE_TABLES = false; static final boolean ENABLE_SWAP_QUEUEING = false; static final boolean ENABLE_PACKET_COALESCING = true; static final boolean ENABLE_FOAF = true; static final boolean FORK_ON_CACHEABLE = false; static final boolean REAL_TIME_FLAG = false; static final int TARGET_SUCCESSES = 20; //static final int NUMBER_OF_NODES = 50; //static final short MAX_HTL = 10; static final int DARKNET_PORT_BASE = 5008; static final int DARKNET_PORT_END = DARKNET_PORT_BASE + NUMBER_OF_NODES; public static void main(String[] args) throws FSParseException, PeerParseException, CHKEncodeException, InvalidThresholdException, NodeInitException, ReferenceSignatureVerificationException, InterruptedException, UnsupportedEncodingException, CHKVerifyException, CHKDecodeException, InvalidCompressionCodecException { String name = "realNodeRequestInsertTest"; File wd = new File(name); if(!FileUtil.removeAll(wd)) { System.err.println("Mass delete failed, test may not be accurate."); System.exit(EXIT_CANNOT_DELETE_OLD_DATA); } wd.mkdir(); //NOTE: globalTestInit returns in ignored random source //NodeStarter.globalTestInit(name, false, LogLevel.ERROR, "freenet.node.Location:normal,freenet.node.simulator.RealNode:minor,freenet.node.Insert:MINOR,freenet.node.Request:MINOR,freenet.node.Node:MINOR"); //NodeStarter.globalTestInit(name, false, LogLevel.ERROR, "freenet.node.Location:MINOR,freenet.io.comm:MINOR,freenet.node.NodeDispatcher:MINOR,freenet.node.simulator:MINOR,freenet.node.PeerManager:MINOR,freenet.node.RequestSender:MINOR"); //NodeStarter.globalTestInit(name, false, LogLevel.ERROR, "freenet.node.FNP:MINOR,freenet.node.Packet:MINOR,freenet.io.comm:MINOR,freenet.node.PeerNode:MINOR,freenet.node.DarknetPeerNode:MINOR"); NodeStarter.globalTestInit(name, false, LogLevel.ERROR, "", true); System.out.println("Busy network test (inserts/retrieves in quantity/stress test)"); System.out.println(); DummyRandomSource random = new DummyRandomSource(); //DiffieHellman.init(random); Node[] nodes = new Node[NUMBER_OF_NODES]; Logger.normal(RealNodeRoutingTest.class, "Creating nodes..."); Executor executor = new PooledExecutor(); for(int i=0;i<NUMBER_OF_NODES;i++) { nodes[i] = NodeStarter.createTestNode(DARKNET_PORT_BASE+i, 0, name, false, MAX_HTL, 20 /* 5% */, random, executor, 500*NUMBER_OF_NODES, (CHKBlock.DATA_LENGTH+CHKBlock.TOTAL_HEADERS_LENGTH)*100, true, ENABLE_SWAPPING, false, ENABLE_ULPRS, ENABLE_PER_NODE_FAILURE_TABLES, ENABLE_SWAP_QUEUEING, ENABLE_PACKET_COALESCING, 8000, ENABLE_FOAF, false, true, false, null); Logger.normal(RealNodeRoutingTest.class, "Created node "+i); } // Now link them up makeKleinbergNetwork(nodes, START_WITH_IDEAL_LOCATIONS, DEGREE, FORCE_NEIGHBOUR_CONNECTIONS, random); Logger.normal(RealNodeRoutingTest.class, "Added random links"); for(int i=0;i<NUMBER_OF_NODES;i++) { nodes[i].start(false); System.err.println("Started node "+i+"/"+nodes.length); } waitForAllConnected(nodes); waitForPingAverage(0.95, nodes, random, MAX_PINGS, 1000); System.out.println(); System.out.println("Ping average > 95%, lets do some inserts/requests"); System.out.println(); HighLevelSimpleClient[] clients = new HighLevelSimpleClient[nodes.length]; for(int i=0;i<clients.length;i++) { clients[i] = nodes[i].clientCore.makeClient(RequestStarter.IMMEDIATE_SPLITFILE_PRIORITY_CLASS, false, false); } // Insert 100 keys into random nodes ClientCHK[] keys = new ClientCHK[INSERT_KEYS]; String baseString = System.currentTimeMillis() + " "; for(int i=0;i<INSERT_KEYS;i++) { System.err.println("Inserting "+i+" of "+INSERT_KEYS); int node1 = random.nextInt(NUMBER_OF_NODES); Node randomNode = nodes[node1]; String dataString = baseString + i; byte[] data = dataString.getBytes("UTF-8"); ClientCHKBlock b; b = ClientCHKBlock.encode(data, false, false, (short)-1, 0, COMPRESSOR_TYPE.DEFAULT_COMPRESSORDESCRIPTOR, false); CHKBlock block = b.getBlock(); ClientCHK chk = b.getClientKey(); byte[] encData = block.getData(); byte[] encHeaders = block.getHeaders(); ClientCHKBlock newBlock = new ClientCHKBlock(encData, encHeaders, chk, true); keys[i] = chk; Logger.minor(RealNodeRequestInsertTest.class, "Decoded: "+new String(newBlock.memoryDecode(), "UTF-8")); Logger.normal(RealNodeRequestInsertTest.class,"CHK: "+chk.getURI()); Logger.minor(RealNodeRequestInsertTest.class,"Headers: "+HexUtil.bytesToHex(block.getHeaders())); // Insert it. try { randomNode.clientCore.realPut(block, false, FORK_ON_CACHEABLE, false, false, REAL_TIME_FLAG); Logger.error(RealNodeRequestInsertTest.class, "Inserted to "+node1); Logger.minor(RealNodeRequestInsertTest.class, "Data: "+Fields.hashCode(encData)+", Headers: "+Fields.hashCode(encHeaders)); } catch (freenet.node.LowLevelPutException putEx) { Logger.error(RealNodeRequestInsertTest.class, "Insert failed: "+ putEx); System.err.println("Insert failed: "+ putEx); System.exit(EXIT_INSERT_FAILED); } } // Now queue requests for each key on every node. for(int i=0;i<INSERT_KEYS;i++) { ClientCHK key = keys[i]; System.err.println("Queueing requests for "+i+" of "+INSERT_KEYS); for(int j=0;j<nodes.length;j++) { clients[j].prefetch(key.getURI(), DAYS.toMillis(1), 32768, null); } long totalRunningRequests = 0; for(int j=0;j<nodes.length;j++) { totalRunningRequests += nodes[j].clientCore.countQueuedRequests(); } System.err.println("Running requests: "+totalRunningRequests); } // Now wait until finished. How??? while(true) { long totalRunningRequests = 0; for(int i=0;i<nodes.length;i++) { totalRunningRequests += nodes[i].clientCore.countQueuedRequests(); } System.err.println("Running requests: "+totalRunningRequests); if(totalRunningRequests == 0) break; Thread.sleep(1000); } System.exit(0); } }